使用Vivado中的FIFO IP核
Vivado FIFO IP核
1、创建同步FIFO IP核
1.2 设置同步FIFO IP核相关参数
1.2.1 Basic选项卡
Native
类型用于非SOC逻辑设计,其它两种用于SOC逻辑设计,通常选择Native
类型。1.2.2 Native Ports选项卡
Read Mode
处用于设置读FIFO时的读模式。当FIFO配置为单时钟块RAM时,选择Standard FIFO
时的仿真波形如图2.2.1所示。选择First Word Fall Through
时的仿真波形如图2.2.2所示。即选择Standard FIFO
时当读使能信号rd_en拉高时,下一个时钟周期才会输出数据,而选择First Word Fall Through
时,当读使能信号rd_en拉高时,数据就会输出,不用等待一个时钟周期。Data Port Parameters
处用于设置读写端口的数据总线的宽度以及FIFO的深度。从上到下依次是写数据宽度、写数据深度、读数据宽度 、读数据深度(自动生成)。Reset Pin
处为是否采用复位引脚。Reset Type
处为是否为异步复位。Full Flags Reset Value
处为复位时Full Flags的状态为0还是为1。Dout Reset Value
处为复位时Dout数据线的状态。图2.2.1

图2.2.2

1.2.3 Status Flags选项卡
1.2.4 Data Counts选项卡
1.2.5 Summary选项卡
1.3 生成FIFO
1.4 例化FIFO
1.4.1 打开.veo文件
1.4.2 复制例化模板
1.5、编写testbench文件对同步fifo仿真
`timescale 1ns / 1ps
module tb();
parameter PERIOD = 20;
reg clk;
reg rst_n;
reg wr_en;
reg rd_en;
wire full;
wire empty;
reg [1:0] din;
wire [1:0] dout;
initial begin
clk = 0;
forever begin
#(PERIOD / 2) clk = ~clk;
end
end
initial begin
rst_n = 0;
#(PERIOD) rst_n = 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
din <= 2'd0;
end
else begin
din <= din + 1;
end
end
initial begin
wr_en = 0;
#(PERIOD *2 + PERIOD / 2) wr_en = 1;
end
initial begin
rd_en = 0;
#(PERIOD *4 + PERIOD / 2) rd_en = 1;
end
fifo_generator_0 your_instance_name (
.clk(clk), // input wire clk
.srst(~rst_n), // input wire srst
.din(din), // input wire [1 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [1 : 0] dout
.full(full), // output wire full
.empty(empty) // output wire empty
);
endmodule
仿真结果如下图所示:
2、创建异步FIFO IP核
2.2 设置异步FIFO IP核相关参数
2.2.1 Basic选项卡
2.2.2 Native Ports选项卡
同上述同步fifo设置。
2.2.3 Status Flags选项卡
同上述同步fifo设置。
2.2.4 Data Counts选项卡
此处勾选了两个计数器来分别计算写入和读出了多少个数据。
2.2.5 Summary选项卡
同上述同步fifo设置。
2.3 生成FIFO
同上述同步fifo设置。
2.4 例化FIFO
同上述同步fifo设置。
2.5、编写testbench文件对异步fifo仿真
module tb();
parameter PERIOD = 2;
reg clk ;
reg rst_n ;
reg wr_en ;
reg rd_en ;
reg [17:0] din ;
wire full ;
wire empty ;
wire [17:0] dout ;
wire [9:0] rd_data_count ;
wire [9:0] wr_data_count ;
wire wr_rst_busy ;
wire rd_rst_busy ;
initial begin
clk = 0;
forever begin
#(PERIOD / 2) clk = ~clk;
end
end
initial begin
rst_n = 0;
#(PERIOD * 2) rst_n = 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
din <= 18'd0;
end
else begin
din <= din + 1;
end
end
initial begin
wr_en = 0;
#(PERIOD *30 + PERIOD / 2) wr_en = 1;
end
initial begin
rd_en = 0;
#(PERIOD *40 + PERIOD / 2) rd_en = 1;
end
fifo_generator_0 your_instance_name (
.rst(~rst_n), // input wire rst
.wr_clk(clk), // input wire wr_clk
.rd_clk(clk), // input wire rd_clk
.din(din), // input wire [17 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [17 : 0] dout
.full(full), // output wire full
.empty(empty), // output wire empty
.rd_data_count(rd_data_count), // output wire [9 : 0] rd_data_count
.wr_data_count(wr_data_count), // output wire [9 : 0] wr_data_count
.wr_rst_busy(wr_rst_busy), // output wire wr_rst_busy
.rd_rst_busy(rd_rst_busy) // output wire rd_rst_busy
);
endmodule
仿真结果如下图所示:
如上图所示,复位完成后,wr_rst_busy和rd_rst_busy会有短暂的拉高过程,需要等待wr_rst_busy和rd_rst_busy均拉低时才能进行正常的读写。
如上图所示,在wr_en拉高后,empty信号会有几个周期的延时,如果在empty拉低之前就拉高读使能信号,则数据只会在empty拉低后才输出。如下图所示,在empty拉低之后拉高读使能信号,则数据在读使能信号拉高的下一个周期便输出了出来。