本文介绍了 FIFO 常见的作用,通过一步步配置,再到例程和 testbench 实现一个 FIFO IP 核的调用 。
xilinx 的 FIFO generator core 支持 Native interface FIFOs, AXI Memory Mapped interface FIFOs 和 AXI4-Stream interface FIFOs。
AXI Memory Mapped 和 AXI4-Stream interface FIFOs 是由 Native interface FIFO 衍生出来的。
目录
FIFO 的用处
Native interface FIFOs 可用于数据宽度转换、跨时钟域处理。
数据宽度转换:例如从8位宽的数据变换到 16 位宽的数据,即输入 8 位宽数据,输出补成 16 位宽。
跨时钟域处理:例如数据采集时钟为 20 MHz,而数据处理时钟为 100 MHz,则可通过 FIFO 将数据从 20 MHz 转换到 100 MHz。
FIFO 各端口含义
输入端口:
wr_clk 写时钟
rd_clk 读时钟
din 输入数据
wr_en 写使能
rd_en 读使能
输出端口:
dout 输出数据
full 满标记
wr_ack 写应答
empty 空标记
valid 输出有效标记
rd_data_count 读计数
wr_data_count 写计数
almost_full 快满标记
overflow 写溢出标记
almost_empty 快空标记
underflow 读溢出标记
具体使用FIFO 的配置中会说明。
FIFO 的配置及仿真结果
配置
④ 具体选哪种资源看情况,下表列出对比
⑤ standard mode 和 First Word Fall Through的仿真对比见仿真部分
⑥ 当我们选 write depth 为16时,后面接着一句 actual write depth : 15,意味着实际上的写深度为15,这在仿真结果也可以看到。
配置好后点生成 IP 核。
仿真
⑤ standard mode 和 First Word Fall Through
⑦ 可选信号及可配置标记位
wr_ack :wr_en 为高电平,立即写入 din 的第一个数据,这点可以从dout的第一个数据开出。在 wr_en 拉高后的下一个写时钟上升沿,wr_ack 拉高,表明上一周期写入成功。
almost full 、full、overflow :写入 15个数据后 full 拉高,在第14个数据时 almost full 拉高,若写满后 wr_en 仍为高电平(继续写入),则 overflow 拉高,表示溢出。改代码使写满后wr_en为低电平,则 overflow 始终为低电平,见下两图对比 。
此 FIFO 设置深度时设为 16,实际上,从仿真结果看,仅写入15个数据就满了。
将可配置满标记阈值设为 10,由仿真结果,当 wr_data_count 数到10时,prog_full 拉高,实际上,wr_data_count 有两个时钟周期的延迟,因此,此时写入的是第12个数据
almost empty、 empty 、underflow:rd_en 为高电平时,并没有立即开始读出,这点与写入不同,直到下一个读时钟周期,dout 才输出读的第一个数据,同时 valid 拉高,读到第14个数据,empty 拉高,表示读空了,第13个数据时 almost empty 拉高,若读空后rd_en仍为高电平(继续读出),则 underflow 电平拉高,表示溢出。类似于 overflow ,当读空时 rd_en 为低电平,则underflow始终为低电平。
此 FIFO 设置深度时设为 16,写入了 15 个数据,实际上,从仿真结果看,仅读出 14 个数据就空了。
将可配置空标记阈值设为 5,由仿真结果,当 rd_data_count 为5时,prog_empty 拉高。
FIFO 的调用、代码
在 sources 里的 IP sources ,打开.veo文件,划到最后,可以看到 FIFO 的例化,直接复制使用即可。
在代码中定义端口并例化 FIFO
module t1(
input wire rst,
input wire wr_clk,
input wire rd_clk,
input wire [4 : 0] din,
input wire wr_en,
input wire rd_en,
output wire [4 : 0] dout,
output wire full,
output wire wr_ack,
output wire empty,
output wire valid,
output wire [3 : 0] rd_data_count,
output wire [3 : 0] wr_data_count,
output wire almost_full,
output wire overflow,
output wire almost_empty,
output wire underflow
);
fifo_generator_0 fifo_inst2 (
.rst(rst), // input wire rst
.wr_clk(wr_clk), // input wire wr_clk
.rd_clk(rd_clk), // input wire rd_clk
.din(din), // input wire [4 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [4 : 0] dout
.full(full), // output wire full
.wr_ack(wr_ack), // output wire wr_ack
.empty(empty), // output wire empty
.valid(valid), // output wire valid
.rd_data_count(rd_data_count), // output wire [3 : 0] rd_data_count
.wr_data_count(wr_data_count), // output wire [3 : 0] wr_data_count
.almost_full(almost_full), // output wire almost_full
.overflow(overflow), // output wire overflow
.almost_empty(almost_empty), // output wire almost_empty
.underflow(underflow) // output wire underflow
// .wr_rst_busy(wr_rst_busy), // output wire wr_rst_busy
// .rd_rst_busy(rd_rst_busy) // output wire rd_rst_busy
);
endmodule
写测试文件
`timescale 1ns/1ps
module test_tb();
reg rst;
reg wr_clk;
reg rd_clk;
reg [4 : 0] din;
wire wr_en;
wire rd_en;
wire [4 : 0] dout;
wire full;
wire wr_ack;
wire empty;
wire valid;
wire [3 : 0] rd_data_count;
wire [3 : 0] wr_data_count;
wire almost_full;
wire overflow;
wire almost_empty;
wire underflow;
//读时钟
initial rd_clk = 1;
always#5 rd_clk = ~rd_clk;
//写时钟
initial wr_clk = 1;
always#25 wr_clk = ~wr_clk;
//读使能、写使能
assign wr_en = ((~rd_en) && (~full));
assign rd_en = ((~wr_en) && (~empty));
//写数据
always @ ( posedge wr_clk ) begin
if ( rst )
din <= 5'd1;
else if ( wr_en )
din <= din + 1'b1;
end
initial begin
rst = 1;
#11;
rst = 0;
end
//例化
t1 t1_inst(
.rst ( rst ),
.wr_clk ( wr_clk ),
.rd_clk ( rd_clk ),
.din ( din ),
.wr_en ( wr_en ),
.rd_en ( rd_en ),
.dout ( dout ),
.full ( full ),
.wr_ack ( wr_ack ),
.empty ( empty ),
.valid ( valid ),
.rd_data_count ( rd_data_count ),
.wr_data_count ( wr_data_count ),
.almost_full (almost_full ),
.overflow (overflow ),
.almost_empty (almost_empty ),
.underflow (underflow )
);
endmodule