本文转载自:孤独的单刀的CSDN博客
1、概述
跨时钟域设计(CDC)是个老生常谈的问题,各种笔面试都很喜欢考。其场景很多很杂,其中一个比较为人熟知的就是单bit信号从慢时钟到快时钟所采用的两级寄存器处理的场景,俗称“打两拍”,打两拍可以有效的减少亚稳态的发生的概率。
比如下面的电路就是一个典型的打两拍电路:
发送端的信号是时钟域1的信号,而接受端的时钟则是时钟域2,两者为异步信号,发送端的异步输入信号被接受端采用两级寄存器采样的方式做了跨时钟域处理。
上面的电路转化成代码(仅部分代码),一般就是下面这种形式:
reg reg1,reg2;
always @(posedge clk)begin
if(rst)begin
reg1 <= 1'b0;
reg2 <= 1'b0;
end
else begin
reg1 <= in;
reg2 <= reg1;
end
end
在布局布线过程中,我们当然希望用来做CDC的两个寄存器可以尽量放在一起,这样可以减少寄存器之间的时延,从而增大MTBF,提高系统的稳定性。但是天不遂人愿,综合工具(vivado)在某些情况(比如资源使用较多的情况)下可能并不会这么智能,两个寄存器往往放置不到一起。
这时我们就可以使用vivado的提供的综合属性----ASYNC_REG 来解决这一问题。
2、用法
ASYNC_REG 属性一般用于跨时钟域的数据同步上,该属性指定:
在执行仿真时,若发生时序违例,则寄存器的默认行为是输出X或不定态,这可能引发在多个路径上传输不定态。在这种情况下,所有器件的输入会变成“X”,而自身则会变成不定态。这一情况会顺着设计链条传播,从而使设计的大部分或全部都进入不定态,且无法自行恢复。ASYNC_REG能够使得在发生时许违例时输出上次的已知值,从而解决这一问题。
ASYNC_REG属性使得vivado在综合时不会将其自身或周边逻辑优化,同时也通过影响优化、布局、布线的方式来提高MTBF。当应用了ASYNC_REG属性后,vivado会尽可能地将同步上的同步寄存器放置在一起来提高MTBF。被设置了ASYNC_REG属性的同一组直接相连的寄存器会被布局到 同一个SLICE/CLB。
ASYNC_REG属性可以用在RTL代码或XDC约束两个阶段。下面是一个RTL中使用的例子:
在定义寄存器 sync_0和sync_1的语句前面加上 (* ASYNC_REG = "TRUE" *) 就可以了 ,“TURE” 表示应用了 ASYNC_REG 属性,ASYNC_REG 的默认状态是 “FALSE”。
应用了该属性后,综合工具就会把两个寄存器放置在一起了:
下图是在XDC中使用的例子(这个用得不多,了解下就行了)
3、总结与参考
ASYNC_REG本质上是一个“优化向”的属性,它的作用是告诉综合工具vivado----被其标记的寄存器可以接收异步信号,且这些寄存器都是一个同步链上的同步寄存器,所以需要将其放置的尽可能靠近----也就是同一个SLICE/CLB,这样可以减少时延、有效提高MTBF。
参考资料:
Xilinx,ug912,Vivado Design Suite Properties Reference Guide
Xilinx,ug901,Vivado Design Suite User Guide Synthesis