我在互联网上找到了以下代码,同时寻找良好的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
Run Code Online (Sandbox Code Playgroud)
您在这里看到的是所谓的双列同步器.如前所述,这是一个异步FIFO.这意味着FIFO的读写侧不在同一时钟域上.
如您所知,触发器需要满足设置和保持时序要求才能正常工作.当您从一个时钟域驱动信号到另一个时钟域时,在一般情况下无法保证此要求.
当你违反这些要求时,FF会进入所谓的"元稳定"状态,在这种情况下,有一段时间不确定,然后(或多或少)随机地转到1或0.他们这样做(这很重要)在不到一个时钟周期内.
这就是为什么这两层失败的原因.第一个有机会进行元稳定,但应该及时解决,以便第二组翻牌保持干净利落.
它本身并不足以跨时钟域传递多位值(地址指针).如果同时有多个位发生变化,则无法确定转换在另一侧是否清洁.所以在这些情况下你经常看到的是FIFO指针将通过灰色编码.这意味着计数器的每个增量一次最多改变一位.
例如,而不是00 - > 01 - > 10 - > 11 - > 00 ...它将是00 - > 01 - > 11 - > 10 - > 00 ...
时钟域穿越是一个深刻而微妙的主题.即使是经验丰富的设计师也经常在没有仔细思考的情
BTW普通的Verilog仿真不会显示我刚才在零延迟模拟中所描述的内容.您需要使用实时模型进行带注释的SDF模拟.