基于ISE的FIFO IP核使用
FIFO经常用在异步时钟的数据传输当中,本次就是使用FIFO做为通信的读写接口。
具体案例为FIFO的环回实验,对FIFO的使用进行验证。
操作系统:*Window 10*
操作平台:*ISE 14.7*
第三方编写软件:*Visual Studio Code*
FIFO IP设置
步骤1:
接口类型选择Native类型的,AXI4是与DMA或与其他有AXI4接口通信时使用的。
步骤2:
选择异步时钟,FIFO的主要功能就是用在异步时钟域作为缓存,所以选择独立时钟的模式使用范围更广。
Memory Type :常用的有Block Ram 和 Distrubtion RAM ,前者使用片上ROM作为缓存,后者使用LUT逻辑资源搭建RAM缓存,如果使用FIFO不大,或者资源充足的情况下,使用Block RAM。
步骤3:
如上图所示 ,Read Mode 选择First-word Fall-Through , First-word Fall-Through 与 Stanbdard FIFO 的区别就是, Stanbdard FIFO 模式下,read data 会将数据延迟一个Clock ,这里选择 First-word Fall-Through(FIFO先进先出)。
Data port parameters (数据接口长度),根据自己的要求设置位宽和深度,至于深度需要根据异步时钟差去设置,具体的请使用搜索引擎搜索。
步骤4:
这里的接口是几乎总是空与几乎总是满(块接近最大深度),根据自身需求选择。
步骤5:
Programmable Full/Empty Type 根据时钟实时刷新可以作为一个阈值判断。
步骤6:
Data Count是对FIFO中已有的数据进行计数,从data count 中可以得到可读或可写的的数据量。
程序
Verilog 程序
`timescale 1ns / 1ps
module FIFO(
input rst ,
input wr_clk ,
input rd_clk ,
input [7 : 0] din ,
input wr_en ,
input rd_en ,
output [7 : 0] dout ,
output full ,
output empty ,
output [9 : 0] rd_data_count ,
output [9 : 0] wr_data_count ,
output prog_full ,
output prog_empty
);
fifo u_fifo (
.rst (rst ), // input rst
.wr_clk (wr_clk ), // input wr_clk
.rd_clk (rd_clk ), // input rd_clk
.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
.rd_data_count(rd_data_count), // output [9 : 0] rd_data_count
.wr_data_count(wr_data_count), // output [9 : 0] wr_data_count
.prog_full (prog_full ), // output prog_full
.prog_empty (prog_empty ) // output prog_empty
);
endmodule
仿真脚本程序
`timescale 1ns / 1ps
module tb_FIFO;
// Inputs
reg rst ;
wire wr_clk ;
wire rd_clk ;
reg [7:0] din ;
reg wr_en ;
reg rd_en ;
// Outputs
wire [7:0] dout ;
wire full ;
wire empty ;
wire [9:0] rd_data_count ;
wire [9:0] wr_data_count ;
wire prog_full ;
wire prog_empty ;
// Instantiate the Unit Under Test (UUT)
FIFO uut (
.rst (rst ),
.wr_clk (wr_clk ),
.rd_clk (rd_clk ),
.din (din ),
.wr_en (wr_en ),
.rd_en (rd_en ),
.dout (dout ),
.full (full ),
.empty (empty ),
.rd_data_count (rd_data_count ),
.wr_data_count (wr_data_count ),
.prog_full (prog_full ),
.prog_empty (prog_empty )
);
initial begin
// Initialize Inputs
rst = 1;
din = 0;
wr_en = 0;
rd_en = 0;
// Wait 100 ns for global reset to finish
#100 rst = 0 ;
end
//define reg
reg sys_clk = 0 ;
reg [1 : 0] state = 0 ;
reg [9 : 0] cnt0 = 0 ;
always #10 sys_clk = ~sys_clk ;
assign wr_clk = sys_clk ;
assign rd_clk = sys_clk ;
always @(posedge sys_clk ) begin
case (state)
0:begin
rd_en <= 0 ;
if (!full) begin
state <= state + 1 ;
wr_en <= 1 ;
cnt0 <= cnt0 + 1 ;
din <= cnt0 ;
end
else begin
state <= state ;
wr_en <= 0 ;
cnt0 <= cnt0 ;
din <= din ;
end
end
1:begin
cnt0 <= cnt0 ;
wr_en <= 0 ;
if (!empty) begin
state <= 0 ;
rd_en <= 1 ;
end
else begin
state <= state ;
rd_en <= 0 ;
end
end
default: state <= state ;
endcase
end
endmodule
仿真
。