异步FIFO的异步复位顺序与复位释放顺序?

本文探讨异步FIFO的复位顺序及复位释放顺序的重要性,详细解析为何先复位读端口能有效避免RAM读写冲突,并阐述先释放读端口对于防止FIFO溢出的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异步FIFO的异步复位顺序与复位释放顺序?

如下图所示,FIFO所用的存储结构为1R1W的双端口RAM,RAM存在读写冲突问题时,读出的数据会是不稳定状态,即当读操作和写操作同时发生且读写地址相同则RAM会发生读写冲突。

注意:在FIFO正常工作状态,内部存储RAM是不会发生读写冲突的,只有当不合理复位操作才会导致FIFO内部RAM发生读写冲突。

图中的两个复位:wrst_n和rrst_n均为异步复位


1、那么在FIFO初始化过程中,是先复位写端口(wrst_n=0)还是先复位读端口(rrst_n=0)呢?

先复位读端口,后复位写端口,能够有效避免FIFO内部RAM读写冲突。

这里有朋友困惑了,为什么先复位写端口会出现读写冲突呢?

请看下图:

假设FIFO深度为8,则写地址waddr为3位,则在写地址产生模块(FIFOwptr)中waddr[2:0]则对应3个寄存器,每个寄存器的复位信号的延时不完全一致,所以存在有些复位信号早到达,有些晚到达,造成在写时钟采样沿发生非理想跳变,如waddr从3’b110跳变到3’b010,从而RAM输入的写地址从3’b110跳变到3’b010。

 

如图所示,waddr[2]对应的复位信号早于其他地址位到达,且在时钟采样沿前跳变,本应写入RAM的地址应该为3'b110,应为复位信号的影响,现在跳变为了3'b010,若此时读端口的地地址为3'b010,此时发生RAM读写冲突,读出的数据不确定。此时的不确定数据会先后级传递,造成不确定的电路异常。

而在FIFO正常状态(FIFO中有数据的情况),写数据waddr一直大于读地址raddr,因而不会发生读写冲突。

先复位读端口则写地址大于读地址,则不会发生读写冲突。

2、在复位释放时,先释放读端口还是先释放写端口?

先释放读端口,后释放写端口,能够避免FIFO溢出但是没有上报的情况。

在芯片初始化完成后,芯片内部各模块是处于复位状态,因此需要依次复位释放,其中就包含了FIFO的复位释放。

 在IC设计中,我们是不允许FIFO溢出的,但是一旦有溢出必须有中断上报机制。

在一些FIFO设计中,读端口非空即读,且读时钟频率大于写时钟,此种情况下,在正常工作状态,FIFO不会溢出,因此此类FIFO没有反压流控和溢出中断上报机制。

若先复位释放写端口,则数据会不断写入到FIFO中,而此时读端口没有释放,这段时间内可能会发生FIFO溢出并且没有任何信息上报,因此不合理。

### 实现异步FIFO复位同步的方法 对于异步FIFO而言,由于其操作在两个不同的时钟域之间,因此复位机制需要特别处理以确保系统的稳定性和可靠性。为了防止因跨时钟域传输而导致的“毛刺”或亚稳态现象,复位信号会被分别同步至读/写时钟域[^1]。 #### 复位信号扩展 考虑到异步FIFO的特点,简单的单周期脉冲复位可能会引发潜在的问题。为了避免这些问题的发生,通常建议将复位信号延长几个时钟周期,即所谓的多周期复位使能。这种做法可以有效减少由短暂复位引起的不稳定状态,从而提高整个系统的鲁棒性[^3]。 #### 使用双寄存器级联消除亚稳态 一种常见的解决办法是在接收方采用两级触发器来捕获来自另一时钟域的状态变化。这种方法被称为“打两拍”,它能够显著降低发生亚稳态的概率,进而保障数据的有效传递[^2]。 以下是具体实现代码: ```verilog module async_fifo_reset_sync ( input wire rst_n, // 异步复位低电平有效 input wire clk_w, // 写时钟 output reg sync_rst_w // 同步后的写时钟域复位信号 ); // 扩展复位宽度为N个clk_w周期 (此处假设N=4) reg [3:0] ext_rst_cnt; always @(posedge clk_w or negedge rst_n) begin if (!rst_n) begin ext_rst_cnt <= 4'b1111; // 设置计数器初始值为全高 end else if (&ext_rst_cnt) begin ext_rst_cnt <= {ext_rst_cnt[2:0], 1'b0}; // 计数值减一直至清零 end end assign sync_rst_w = |ext_rst_cnt; // 双寄存器级联用于消除亚稳态影响 reg meta_reg1, meta_reg2; wire synced_rst; always_ff @(posedge clk_w or negedge rst_n) begin if (~rst_n) begin meta_reg1 <= 1'b0; meta_reg2 <= 1'b0; end else begin meta_reg1 <= ~synced_rst; meta_reg2 <= meta_reg1; end end assign synced_rst = &meta_reg2 ? 'b0 : sync_rst_w; endmodule ``` 此模块展示了如何通过计数器延展原始复位脉宽,并利用双重锁存技术完成从全局异步复位到特定时钟域内同步复位转换的过程。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值