FWFT FIFO


打个小广告: 艾伦耶格尔的数字小店

1. FWFT FIFO介绍

1.1 FIFO 基础回顾

在深入 FWFT FIFO 之前,先回顾 FIFO 的基本概念:

  • FIFO(First-In-First-Out):一种按写入顺序读出数据的缓冲区。
  • 核心应用场景
    • 解决数据生产者和消费者的速度不匹配
    • 跨时钟域通信
    • 数据流缓冲

1.2 FWFT FIFO 的独特特性

FWFT(First-Word Fall-Through) 是一种特殊的 FIFO 工作模式,其核心特点

  • 数据提前暴露:FIFO 非空时,第一个有效数据自动出现在输出端口(dout)。
  • 读操作简化
    • rd_en 信号作用变为"确认消费当前数据"
    • 读操作后下一个数据(如果有)立即出现在 dout
  • 低延迟优势:省去标准 FIFO 中 rd_endout 的延迟周期

1.3 FWFT FIFO vs 标准 FIFO

行为标准 FIFOFWFT FIFO
初始状态dout 无效(例如空)若 FIFO 非空,dout 直接有效
读操作触发rd_en 拉高后下一周期输出rd_en 拉高后立即更新数据
空标志行为最后一个数据读出后生效最后一个数据读出时生效

2. 实现原理

这里我们使用寄存器代替存储器,主要是因为FIFO在不需要缓冲非常大的容量时可以使用寄存器作为载体。若需要存储器,只需添加地址转换逻辑。
FWFT FIFO

3. FWFT FIFO 时序示例

假设已写入数据 A, B, C

时钟周期操作doutempty说明
T1无操作A0数据 A 自动暴露
T2rd_en=1B0读 A,B 立即出现
T3rd_en=1C0读 B,C 立即出现
T4rd_en=1无效1读 C,FIFO 变空

4. 设计考量

  • 空标志逻辑:最后一个数据被读出时立即生效
  • 接口设计
    • dout 始终有效(除非 FIFO 为空)
    • 下游模块需根据 empty 判断数据有效性
  • 资源优化:现代 FPGA Block RAM 原生支持 FWFT 模式

5.RTL 实现


/**********************************************************************
	File: fwft_fifo.v 
	Author:艾伦耶格尔【咸鱼】
	Purpose:
	An small  First Word Fall Through FIFO. The code will use LUTs
	and  optimized for low LUTs utilization.
	Salted Fish Link: 【闲鱼】https://m.tb.cn/h.6dWD3XF?tk=PNtBeuDxgv4 CZ356点击链接直接打开
*******************************************************************/

`include "../define.v"
`timescale 1ns/1ps
module fwft_fifo #(
		parameter WIDTH = 1,
		parameter MAX_DEPTH_BITS = 2
	)
	(
		input [WIDTH-1:0] din,     // Data in
		input          wr_en,   // Write enable
		input          rd_en,   // Read the next word
		output reg [WIDTH-1:0]  dout,    // Data out
		output         full,
		output         nearly_full,
		output 			recieve_more_than_0,
		output 			recieve_more_than_1,
		input          reset,
		input          clk
	
	);
	
	
	
	`LOG2
	
	localparam DEPTH_WIDTH = log2(MAX_DEPTH_BITS +1);
	
	wire 	[MAX_DEPTH_BITS-2 	: 	0]	mux_in	[WIDTH-1		:0];
	wire	[DEPTH_WIDTH-1			:	0] mux_sel;
	wire 	[WIDTH-1					:	0] mux_out;
	
	wire 										empty;
	reg	[MAX_DEPTH_BITS-2 	: 	0]	shiftreg [WIDTH-1		:0];
	reg	[DEPTH_WIDTH-1			:	0]	depth;
	
	wire out_sel ;
	wire out_ld ;
	wire [WIDTH-1					:	0]  dout_next;
	
	
	genvar i;
	generate 
		for(i=0;i<WIDTH; i=i+1) begin : lp
			if(MAX_DEPTH_BITS>2) begin 
				always @(posedge clk ) begin 
					//if (reset) begin 
					//	shiftreg[i] <= {MAX_DEPTH_BITS{1'b0}};
					//end else begin
						if(wr_en) shiftreg[i] <= {shiftreg[i][MAX_DEPTH_BITS-3 	: 	0]	,din[i]};
					//end
				end
			end else begin
				always @(posedge clk ) begin 
					//if (reset) begin 
					//	shiftreg[i] <= {MAX_DEPTH_BITS{1'b0}};
					//end else begin
						if(wr_en) shiftreg[i] <= din[i];
					//end
				end //always
			end //else
			assign mux_in[i] 	= shiftreg[i];
			assign mux_out[i]	= mux_in[i][mux_sel];
			assign dout_next[i] = (out_sel) ? mux_out[i] : din[i]; 	
		end //for
	endgenerate
	
	
	always @(posedge clk) begin
		if (reset) begin
			 depth  <= {DEPTH_WIDTH{1'b0}};
		end else begin
			 if (wr_en & ~rd_en) depth <=
						// synthesis translate_off
						#1
						// synthesis translate_on
						depth + 1'h1;
			else if (~wr_en & rd_en) depth <=
						// synthesis translate_off
						#1
						// synthesis translate_on
						depth - 1'h1;
			
		end
	end//always
	
	
	always @(posedge clk or posedge reset) begin
		if (reset) begin
			 dout  <= {WIDTH{1'b0}};
		end else begin
			 if (out_ld) dout <= dout_next;
		end
	end//always
	
		
assign full 						= depth == MAX_DEPTH_BITS;
assign nearly_full 				= depth >= MAX_DEPTH_BITS-1;
assign empty 						= depth == 'h0;
assign recieve_more_than_0 	= ~ empty;
assign recieve_more_than_1 	= ~( depth == 0 ||  depth== 1 );
assign out_sel 					= (recieve_more_than_1)	 ? 1'b1 : 1'b0;
assign out_ld 						= (depth !=0 )?  rd_en : wr_en;
assign mux_sel 					= depth-2'd2;	
	
	 // synthesis translate_off
   always @(posedge clk)
   begin
      if (wr_en && full) begin
         $display("%t ERROR: Attempt to write to full FIFO: %m", $time);
      end
      if (rd_en && !recieve_more_than_0) begin
         $display("%t ERROR: Attempt to read an empty FIFO: %m", $time);
      end
   end // always @ (posedge clk)
   // synthesis translate_on
	





endmodule	
	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值