在搜索好的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发布于 2013-04-13 00:24:11
你在这里看到的是所谓的双秩同步器。正如您所提到的,这是一个异步FIFO。这意味着FIFO的读写侧不在同一时钟域上。
如你所知,触发器需要满足设置和保持时序要求,才能正常工作。当您将一个信号从一个时钟域驱动到另一个时钟域时,在一般情况下无法保证这一要求。
当你违反这些要求时,FF进入所谓的“亚稳定”状态,在这种状态下,有一小段时间是不确定的,然后(或多或少)随机到1或0。不过,它们在不到一个时钟周期内就做到了这一点(这一点很重要)。
这就是为什么这里的两层失败。第一个有机会变得亚稳定,但应该及时解决,以便被第二组flops干净地捕获。
这本身不足以跨时钟域传递多位值(地址指针)。如果多个比特同时发生变化,那么您不能确保在另一端的转换是干净的。因此,在这些情况下,您经常会看到FIFO指针将被格雷编码。这意味着计数器的每个增量一次最多改变一位。
例如,而不是00 -> 01 -> 10 -> 11 -> 00 ...将会是00 -> 01 -> 11 -> 10 -> 00...
时钟域交叉是一个深奥而微妙的课题。即使是经验丰富的设计师也经常会在没有仔细考虑的情况下把它们搞砸。
顺便说一句,普通的Verilog模拟不会显示我刚才在零延迟sim中描述的任何内容。您需要使用真实的计时模型进行带注释的SDF模拟。
发布于 2013-04-12 21:08:36
在本例中,地址通过shift register传递,以便将其延迟一个时钟周期。本可以有更多的“指针”,以使输出延迟更多。
通常,如果您模拟设计并查看波形,就更容易理解发生了什么以及原因。
另外,这里有一些很好的FIFO实现,你可以看看:
希望能有所帮助。祝好运!
https://stackoverflow.com/questions/15968912
复制相似问题