前言
FIFO(First Input First Output),即先进先出队列。在FPGA中的作用是为了实现两个模块之间通信的速率不统一的问题,起到缓存数据的作用。本教程为入门教程,将从最简单的FIFO开始学习。
一、ISE中FIFO的IP核配置
接下来保持默认设置,然后生成IP文件。打开文件模板得到例化端口
ip_fifo your_instance_name (
.clk(clk), // input clk
.rst(rst), // input rst
.din(din), // input [7 : 0] din
.wr_en(wr_en), // input wr_en
.rd_en(rd_en), // input rd_en
.dout(dout), // output [7 : 0] dout
.full(full), // output full
.empty(empty) // output empty
);
特别注意,FIFO的IP核文件的复位使能和PLL(分频器)IP核 的RST是一样的,都是低电平使能模块。
二、FIFO功能验证
实验方法:往FIFO中装载数据并读取数据,查看各个端口的信号变化。
实验1
思想方法:
设置一个位宽为10的计数变量cnt,复位之前cnt为0,当复位结束以后开始从【0:1023】循环计数,在【0:1023】之间选取两个时钟段,在时钟段1,往FIFO中装载数据,当在时间段2,从FIFO中读取数据。
代码
`timescale 1ns / 1ps
module fifo_tst(
input sys_clk,
input sys_rst_n,
output [ 7: 0 ] fifo_rd_data,
output fifio_empty,
output fifo_full,
output reg fifo_rdrdy
);
reg [ 7: 0 ] fifio_data_in;
reg wr_en; //fifo的写使能
reg rd_en; //fifo的读使能
reg [ 9: 0 ] cnt;
/* 时间戳产生 */
always@( posedge sys_clk or negedge sys_rst_n )
begin
if ( !sys_rst_n )
cnt <= 0;
else
cnt <= cnt + 1;
end
/* FIFO的写入与读出操作 */
always@( posedge sys_clk or negedge sys_rst_n )
begin
if ( !sys_rst_n )
begin
wr_en <= 0;
rd_en <= 0;
fifio_data_in <= 0;
end
/* 数据写入 */
else if ( ( cnt > 50 ) && ( cnt < 116 ) )
begin
wr_en <= 1;
rd_en <= 0;
fifio_data_in <= cnt + 10;
end
/* 数据读出 */
else if ( ( cnt > 150 ) && ( cnt < 216 ) )
begin
wr_en <= 0;
rd_en <= 1;
fifio_data_in <= 0;
end
else
begin
wr_en <= 0;
rd_en <= 0;
fifio_data_in <= 0;
end
end
/* fifo_rdrdy延后rd_en一个时钟周期,代表读出的数据有效 */
always@( posedge sys_clk or negedge sys_rst_n )
begin
if ( !sys_rst_n )
fifo_rdrdy <= 0;
else
fifo_rdrdy <= rd_en;
end
ip_fifo my_fifo (
.clk( sys_clk ), // input clk
.rst( ~sys_rst_n ), // input rst
.din( fifio_data_in ), // input [7 : 0] din
.wr_en( wr_en ), // input wr_en
.rd_en( rd_en ), // input rd_en
.dout( fifo_rd_data ), // output [7 : 0] dout
.full( fifo_full ), // output full
.empty( fifio_empty ) // output empty
);
endmodule
实验1仿真
把FIFO的输入与输出的完整的一个周期分成了4个时间段。
时间段1:
时间段2:
时间段3:
时间段4:
从上边的实验数据中可以得到以下的结论:
- 从阶段1和阶段2的实验数据对比可以发现,FIFO中存放的第一个数据是WR_EN由低变高以后第一个时钟周期的数据。 fifo的empty信号在FIFO为空的时候会被置为高电平,当写入第一个数据后的时钟上升沿,empty信号会被拉低同时发生。
- 最后一个数据输入以后,full信号拉高,FIFO记满数据。
- 3.读第一个数据,rd_en拉高后的第二的时钟,数据输出和full拉低同时发生。
- 最后一个数据读出和empty信号由低变高同时发生,但是最后一个数据的re_en是低电平,所以充分验证了读出的数据要滞后re_en一个时钟周期。
附:
单时钟的FIFIO实现同时读取数据与接收数据。