标准FIFO
本文使用位扩展的方式实现标准FIFO,原理可参考【AXIS】AXI-Stream FIFO设计实现(一)——基本模式,核心代码如下:
logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_r = 'd0, wr_ptr_r = 'd0;
always_ff @(posedge clk) begin
if (wr_en & ~wfull) begin
wr_ptr_r <= wr_ptr_r + 1;
end
end
always_ff @(posedge clk) begin
if (rd_en & ~rempty) begin
rd_ptr_r <= rd_ptr_r + 1;
end
end
assign wfull = (wr_ptr_r[FIFO_DEPTH_WIDTH] != rd_ptr_r[FIFO_DEPTH_WIDTH]) && (wr_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0] == rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]);
assign rempty = rd_ptr_r == wr_ptr_r;
logic [TDATA_WIDTH - 1 : 0] ram[FIFO_DEPTH - 1 : 0];
always @(posedge clk) begin
if (wr_en & ~wfull) begin
ram[wr_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]] <= m_axis_tdata;
end
end
always @(posedge clk) begin
if (rd_en & ~rempty) begin
s_axis_tdata <= ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
end
end
FWFT FIFO简单实现
基于标准FIFO,引入FWFT机制。一种简单做法即将ram输出改为组合逻辑输出,这种方式实现的FWFT延时最低。
always_comb begin
// if (rd_en & ~rempty) begin
s_axis_tdata = ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
// end
end
FWFT FIFO优化
然而,在FPGA中所有存储资源如(BRAM、URAM)均具有一个周期的读延时,在构造大容量fifo时,为了让综合工具将FIFO存储RAM综合为BRAM / URAM,更合适的做法为添加寄存器slice,这种方式会增加1个周期的延迟:
initial rempty = 1'b1;
assign wfull = sfifo_wfull;
always_ff @(posedge clk) begin
if (~sfifo_rempty & (rempty | rd_en)) begin
s_axis_tdata <= ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
end
end
assign sfifo_rd_en = (rempty | rd_en);
always @(posedge clk) begin
if (~sfifo_rempty) begin
rempty <= 1'b0;
end else if (rd_en) begin
rempty <= 1'b1;
end
end
完整代码
完整工程代码可在同名微信公众号回复SYNC_FIFOs下载。