【FIFO】Standard / FWFT FIFO设计实现(一)——同步时钟

在这里插入图片描述

标准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下载。

<think>嗯,用户问的是FIFOStandard模式和First Word Fall Through(FWFT)有什么区别。首先,我需要确认自己对这两种模式的理解是否正确。Standard FIFO通常是在写入数据后,需要读使能信号来触发数据的输出,而FWFT则是在数据写入后,即使没有读使能,数据也会自动出现在输出端,只要FIFO不为空。这可能涉及到内部结构的差异,比如FWFT可能没有输出寄存器,或者控制逻辑不同。 然后,用户可能是在设计中使用FIFO时遇到了问题,比如数据延迟或者控制信号的处理。他们可能想知道这两种模式各自的优缺点,以及适用场景。比如在需要立即获取数据的场合,FWFT可能更合适,而Standard模式可能在需要严格同步控制时更好。 接下来,我需要考虑如何组织回答。首先明确两者的定义,然后对比它们的工作机制、时序差异、应用场景等。可能需要用例子或者波形图来说明,但在文本中需要用文字描述清楚。比如Standard模式下,数据在读使能后下个周期才有效,而FWFT则在有效时数据已经出现在输出端。 还要注意用户可能的背景,他们可能是FPGA工程师或数字电路设计者,因此需要技术细节,但也要确保解释清晰易懂。可能需要提到FIFO的空满标志处理,因为FWFT模式下的empty信号行为可能与Standard不同,比如在FWFT中,empty变低后数据立即可用,而不需要等待读使能。 另外,用户可能关心如何在实际项目中选择这两种模式,是否需要修改现有代码或配置。比如在使用Xilinx Vivado的IP核时,配置FIFO时会有个选项选择模式,这时候了解两者的区别很重要。 最后,需要检查是否有遗漏点,比如延迟的影响、资源占用是否不同,或者是否存在兼容性问题。确保回答全面,帮助用户做出正确选择。</think>在数字电路设计中,FIFO(First-In-First-Out)的**Standard模式**和**First Word Fall Through(FWFT)模式**是两种关键工作方式,其核心差异体现在数据输出时序和控制逻辑上。以下是系统性对比分析: --- ### **、工作机制对比** #### 1. **Standard FIFO** - **输出触发条件**:必须通过`rd_en`信号主动拉高才能输出数据 - **数据延迟特性**: - 写入数据后,输出端口**保持原值不变** - `rd_en`有效后,数据在**下时钟周期**出现在输出端 - **空满标志行为**: - `empty`标志为低时,仅表示FIFO有数据,但输出端口尚未更新 - 需要`rd_en`脉冲才能将数据传递到输出 #### 2. **FWFT FIFO** - **输出触发机制**:数据**自动前推**到输出端(无需`rd_en`) - **数据延迟特性**: - 写入数据后,若FIFO非空,数据**立即出现在输出端** - `rd_en`用于**确认消费**当前数据并推进下个数据 - **空满标志行为**: - `empty`标志为低时,输出端口数据**已有效可用** - `rd_en`拉高后,下个数据在**同时钟周期**更新(若存在) --- ### **二、时序波形对比** #### 标准模式时序(假设时钟上升沿有效): ``` 时钟周期 | 1 2 3 4 操作 | 写A 写B 读使能 无操作 输出数据 | X X A B empty | 1→0 0 0 1(读完B后) ``` *注:第3周期`rd_en`有效后,第4周期才能看到B数据* #### FWFT模式时序: ``` 时钟周期 | 1 2 3 4 操作 | 写A 写B 读使能 无操作 输出数据 | A B B C(若存在) empty | 0 0 0→1(当B被读取且无新数据) ``` *注:A在写入后立即输出,第3周期`rd_en`有效时B已在输出端* --- ### **三、结构差异** #### 1. **Standard FIFO内部结构** ``` [存储阵列] → [输出寄存器](由`rd_en`控制锁存) ``` - 输出寄存器**隔离**存储阵列与外部接口 - 需要额外控制逻辑管理寄存器更新 #### 2. **FWFT FIFF结构** ``` [存储阵列前端直接连接输出端口] ``` - 省去输出寄存器层 - 控制逻辑直接管理存储阵列指针 --- ### **四、应用场景选择** | 特性 | Standard FIFO | FWFT FIFO | |---------------------|-----------------------------|----------------------------| | **延迟敏感度** | 可容忍1周期延迟 | 要求零周期延迟 | | **控制复杂度** | 需精确控制`rd_en`时序 | 自动推进,控制更简单 | | **典型应用** | 跨时钟同步 | 实时数据流处理 | | **资源占用** | 略多(含输出寄存器) | 更少 | --- ### **五、深度技术细节** #### 1. **Empty信号行为差异** - **Standard**:`empty`为低仅表示FIFO有数据,但输出端尚未有效 - **FWFT**:`empty`为低时,输出数据**已稳定可用** #### 2. **满标志(full)的相同性** 两种模式在`full`标志行为上完全致:当存储达到容量上限时拉高 #### 3. **Xilinx FPGA的特殊实现** 在VivadoFIFO Generator中: - FWFT模式通过`Almost Empty`标志提前预警数据耗尽 - 可通过`PROGRAMMABLE_EMPTY`特性优化FWFT性能 --- ### **六、代码实例对比** #### Standard模式读取流程: ```verilog always @(posedge clk) begin if (!fifo_empty) begin rd_en <= 1'b1; // 需主动触发读取 data_out <= fifo_dout; // 下个周期生效 end end ``` #### FWFT模式读取流程: ```verilog always @(posedge clk) begin if (!fifo_empty) begin rd_en <= 1'b1; // 确认当前数据已使用 // data_out已包含有效数据,无需赋值 end end ``` --- ### **七、选择建议** - **优先FWFT**:当需要最小化延迟(如DMA传输、实时信号处理) - **选择Standard**:在需要严格对齐控制信号的流水线设计- **混合使用**:在多层次FIFO系统中,可搭配使用两种模式实现最优时序 通过理解这两种模式的本质差异,可以显著优化数据路径设计,避免因FIFO行为误解导致的时序违例或功能错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjh776a68

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值