3

I found the following piece of code in the internet , while searching for good FIFO design. From the linkSVN Code FIFO -Author Clifford E. Cummings . I did some research , I was not able to figure out why there are three pointers in the design ?I can read the code but what am I missing ?

 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
4

2 回答 2

9

您在这里看到的是所谓的双列同步器。正如您提到的,这是一个异步 FIFO。这意味着 FIFO 的读取端和写入端不在同一个时钟域上。

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

当您违反这些要求时,FF 会进入所谓的“亚稳定”状态,其中有一小段时间是不确定的,然后(或多或少)随机变为 1 或 0。但他们会这样做(这很重要)在不到一个时钟周期内。

这就是为什么这里有两层翻牌。第一个有机会进入亚稳定状态,但应该及时解决以被第二组翻牌干净地捕获。

这本身不足以跨时钟域传递多位值(地址指针)。如果不止一个位在同一时间发生变化,那么您无法确定另一侧的过渡是否干净。因此,在这些情况下,您经常会看到 FIFO 指针将采用格雷编码。这意味着计数器的每个增量一次最多更改一位。

例如,而不是 00 -> 01 -> 10 -> 11 -> 00 ... 它将是 00 -> 01 -> 11 -> 10 -> 00 ...

时钟域交叉是一个深刻而微妙的主题。即使是经验丰富的设计师也经常在没有仔细考虑的情况下把它们搞砸。

顺便说一句,普通的 Verilog 模拟不会显示我刚刚在零延迟模拟中描述的任何内容。您需要使用真实时序模型进行带注释的 SDF 仿真。

于 2013-04-12T16:24:11.103 回答
2

在此示例中,地址通过移位寄存器传递,以使其延迟一个时钟周期。本来可以有更多的“指针”来进一步延迟输出。

通常,如果您对设计进行仿真并查看波形,则更容易理解发生了什么以及为什么。

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

  1. Xilinx FIFO 发生器 IP 内核
  2. Altera 的单/双时钟 FIFO
  3. OpenCores 通用 FIFO

希望能帮助到你。祝你好运!

于 2013-04-12T13:08:35.830 回答