异步FIFO设计

时间:2013-04-12 10:24:05

标签: verilog fifo

我在互联网上找到了以下代码,同时寻找良好的FIFO设计。来自链接SVN Code FIFO -Author Clifford E. Cummings。我做了一些研究,我无法弄清楚为什么设计中有三个指针?我可以阅读代码,但我错过了什么?

 module sync_r2w #(parameter ADDRSIZE = 4)
 (output reg [ADDRSIZE:0] wq2_rptr,
 input [ADDRSIZE:0] rptr,
 input wclk, wrst_n);
 reg [ADDRSIZE:0] wq1_rptr;
 always @(posedge wclk or negedge wrst_n)
 if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
 else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
endmodule


module sync_w2r #(parameter ADDRSIZE = 4)
 (output reg [ADDRSIZE:0] rq2_wptr,
 input [ADDRSIZE:0] wptr,
 input rclk, rrst_n);
 reg [ADDRSIZE:0] rq1_wptr;
 always @(posedge rclk or negedge rrst_n)
 if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
 else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
endmodule

2 个答案:

答案 0 :(得分:9)

您在这里看到的是所谓的双列同步器。如前所述,这是一个异步FIFO。这意味着FIFO的读写侧不在同一个时钟域。

如您所知,触发器需要满足设置和保持时序要求才能正常工作。当您从一个时钟域驱动信号到另一个时钟域时,在一般情况下无法保证这一要求。

当你违反这些要求时,FF会进入所谓的“元稳定”状态,在这种情况下,一段时间内存在不确定性,然后(或多或少)随机地转为1或0.他们会这样做(而且这个很重要)在不到一个时钟周期内。

这就是为什么这两层失败的原因。第一个有机会进入稳定状态,但应该及时解决,以便第二组翻牌保持干净利落。

它本身并不足以跨时钟域传递多位值(地址指针)。如果同时有多个位发生变化,那么您无法确定另一侧的转换是否干净。所以在这些情况下你经常看到的是FIFO指针将通过灰色编码。这意味着计数器的每个增量一次最多改变一位。

e.g。而不是00 - &gt; 01 - &gt; 10 - &gt; 11 - &gt; 00 ...它将是00 - &gt; 01 - &gt; 11 - &gt; 10 - &gt; 00 ...

时钟域穿越是一个深刻而微妙的主题。即使是经验丰富的设计师也经常在没有仔细考虑的情况下弄乱他们。

BTW普通的Verilog仿真不会显示我刚才在零延迟模拟中所描述的内容。您需要使用实时模型进行带注释的SDF模拟。

答案 1 :(得分:2)

在此示例中,地址通过shift register传递,以便将其延迟一个时钟周期。可能会有更多的“指针”,以便更多地延迟输出。

通常,如果您模拟设计并查看波形,则更容易理解发生了什么以及为什么会这样做。

此外,您可以查看以下一些优秀的FIFO实现:

  1. Xilinx FIFO Generator IP Core
  2. Altera's single/double-clock FIFOs
  3. OpenCores Generic FIFOs
  4. 希望它有所帮助。祝你好运!