理论参考:
异步FIFO—Verilog实现
异步FIFO——结构、Verilog代码实现与仿真
FPGA逻辑设计回顾(6)多比特信号的CDC处理方式之异步FIFO有空满判断详细说明
引用红色闪电007的评论:
异步FIFO使用格雷码的唯一目的就是"即使在亚稳态进行读写指针抽样也能进行正确的空满状态判断"。 在异步的FIFO中,采用格雷码进行计数,相邻的数据仅仅只有1bit变化,这样在两个时钟域同步的时候仅仅可能只有1bit产生亚稳态,通过同步以后,亚稳态可以消除,最坏的情况是这1bit采错,但是即使是采错地址也只是相差1个,这对判断空满标志不会产生影响。 如果是采用10十进制进行编码,则相邻的数据可能有很多位同时进行变化,那么如果多位同时产生亚稳态而且同时采错数据,会对寄存器的空满标志做出严重错误的判断,会丢失数据或者读出无用的数据,使系统出错。 结论:个人认为格雷码的作用不能表述为消除亚稳态。
引用wulsong的评论:
【个人的一点理解】所谓的“虚满”、“虚空”概念并不那么重要。以“虚满”为例:写速率大于读速率时,会产生“满”标志,它是由读指针read_ptr转换为格雷码后同步到写时钟域进行判断生成的,相当于慢时钟同步到快时钟(empty也是,这是异步fifo能够正常工作的潜在原因)。慢时钟的读指针经过两级延时(wr_clk)同步到写时钟域,之间延时是写时钟的两个周期。又因为这种情况下读指针大于写指针,因此full可能会提前1~2个周期(写时钟),这对所有的读写频率差都是如此。所以,所谓的“虚满”只是在快时钟域的2级延时,属于正常现象,对FIFO本身没有影响。
module asys_fifo#(
parameter DATA_WIDTH = 16,
parameter DATA_DEPTH = 256,
parameter ADDR_WIDTH = 8
)
(
input rst,
input wr_clk,
input wr_en,
input [DATA_WIDTH-1:0] din,
input rd_clk,
input rd_en,
output reg valid,
output reg [DATA_WIDTH-1:0] dout,
output full,
output empty
);
reg [ADDR_WIDTH:0] wr_addr_ptr;//地址指针,比地址多一位
reg [ADDR_WIDTH:0] rd_addr_ptr;
wire [ADDR_WIDTH-1:0] wr_addr;
wire [ADDR_WIDTH-1:0] rd_addr;
wire [A