VIVADO中单bit信号的跨时钟域处理
同步触发器的约束,确保软件布局布线时把同步的触发器放到同一个SLICE中
目录
前言
本文介绍了两种单bit信号快时钟的脉冲到慢时钟的同步的方法。两种方法均可以把快时钟的脉冲同步到慢时钟。除此之外还在考虑线延迟的情况下结合仿真图片说明了组合逻辑输出不加触发器会带来的风险,文字加仿真图片可以帮助读者理解电路。最后还介绍了同步触发器的约束,确保软件布局布线时把同步的触发器放到同一个SLICE中,以降低MTBF(平均无故障时间)。
提示:创作不易,有帮助请一键三连!
一、快时钟的脉冲到慢时钟的同步方法一
1、正确结果
显然快时钟的脉冲的周期比慢时钟的脉冲的周期小,一个很直接的想法就是对源时钟的脉冲信号展宽为宽脉冲,然后在目的时钟域打拍进行同步。这个思路是对的,但是需要注意在源时钟展宽时和在目的时钟形成脉冲时要用时序电路!(原因继续往下文阅读),还有就是扩宽的脉冲尽量比目的时钟的宽度宽1.5倍,这样既覆盖了目的时钟的一个周期,又保持了足够的裕量。
先贴出正确的代码、电路图和仿真结果。快时钟的周期为10ns,慢时钟的周期为12ns。
module pulse_fast2slow(
input clk1, //快时钟
input clk2, //慢时钟
input in_pulse,
output reg out_pulse
);
reg pulse_buf1;
reg pulse_buf2;
reg wide_pulse;
always @(posedge clk1)
begin
pulse_buf1 <= in_pulse;
pulse_buf2 <= pulse_buf1;
wide_pulse <= pulse_buf1 | pulse_buf2;
end
reg new_pulse_buf1;
reg new_pulse_buf2;
reg new_pulse_buf3;
always @(posedge clk2)
begin
new_pulse_buf1 <= wide_pulse;
new_pulse_buf2 <= new_pulse_buf1;
new_pulse_buf3 <= new_pulse_buf2;
out_pulse <= ~new_pulse_buf3 & new_pulse_buf2;
end
endmodule
电路图太大,拆成两部分,如下,标红框的地方一定要用时序电路,不可直接将或门或者与门输出的信号不经过触发器直接给后级电路,可能会有风险。(解释见下文)
以上是正确的结果,可见源时钟脉冲扩宽, 目的时钟采样后成功同步了脉冲。
2、源时钟脉冲展宽组合逻辑输出不加触发器的风险
如图所示,即去掉或门后面触发器,直接将或门输出接到另外一个时钟域,会有风险。
对应代码变化如下:
reg pulse_buf1;
reg pulse_buf2;
wire wide_pulse;
always @(posedge clk1)
begin
pulse_buf1 <= in_pulse;
pulse_buf2 <= pulse_buf1;
end
assign wide_pulse = pulse_buf1 | pulse_buf2;
考虑走线的延时,如下图所示,pulse_buf1_reg和pulse_buf2_reg的Q端到或门的输入I0和I1的延时不一致时,或门的输出就是下图倒数第二个信号的两个高电平夹着一个低电平,如果将或门的输出接了触发器,就是下图最后一个信号的正确波形。所以这就是为什么前文提到要用时序电路的原因,如果或门输出不接触发器,目的时钟直接采样,就有可能采到中间凹下去的那个低电平,甚至还有可能造成亚稳态。
3、目的时钟采样组合逻辑输出不加触发器的风险
如图所示,即去掉与门后面触发器,直接将与门输出接到输出,会有风险,分析和前面的一样。
图中第一个画圈处new_pulse_buf2_reg的Q端延时2ns到与门输入的I1端,第2个画圈处new_pulse_buf3_reg的Q端延时3ns到与门输入的I0端,对比与门的输出和与门后接触发器的输出,可见与门直接输出脉冲宽度只有75-62=13ns,比时钟周期多了一个ns,而触发器的输出84-72=12ns和周期12ns刚好对的上。这种延时下与门直接输出比时钟周期多1个ns,其实如果后面的电路都是这个clk2时钟区域的话,倒不会有风险,因为即使脉宽是13ns,后级电路不管是上升沿还是下降沿采样都只能采到一次高电平。
下面改了延时的大小。图中第一个画圈处new_pulse_buf2_reg的Q端延时7ns到与门输入的I1端,第2个画圈处new_pulse_buf3_reg的Q端延时1ns到与门输入的I0端,对比与门的输出和与门后接触发器的输出,可见与门直接输出脉冲宽度只有73-67=6ns,比时钟周期少了6ns,而触发器的输出84-72=12ns和周期12ns刚好对的上。这种情况下如果后级电路是下降沿采样就不能到高电平了。
所以说,目的时钟采样组合逻辑输出也最好加一级触发器,不然电路可能会有风险。综上所述,快时钟的脉冲同步到慢时钟时最好是组合电路的输出加一级触发器。
二、快时钟的脉冲到慢时钟的同步方法二
方法一这种脉冲扩展方法的有效性取决于快时钟(CLKA)和慢时钟(CLKB)之间的频率关系。如果两者的时钟周期比例发生变动,原先设计的脉冲宽度可能无法满足要求。若未同步调整扩展逻辑,则可能导致信号捕获失败或亚稳态风险,就需要重新修改代码。还有一种方法是源时钟域将脉冲信号转化为电平信号,目的时钟域去检测电平信号的变化,从而恢复脉冲,这种方法就不会受快时钟(CLKA)和慢时钟(CLKB)之间的频率关系的影响。显然这种方法也适用于慢时钟的脉冲到块时钟的同步。
正确的代码、电路图和仿真结果如下。快时钟的周期为10ns,慢时钟的周期为12ns。注意代码最后是异或^,方法一是&。
module pulse_fast2slow(
input clk1, //快时钟
input clk2, //慢时钟
input in_pulse,
output reg out_pulse
);
//////方法二
reg wide_pulse=0;
always @(posedge clk1)
begin
if(in_pulse)
wide_pulse <= !wide_pulse;
end
reg new_pulse_buf1;
reg new_pulse_buf2;
reg new_pulse_buf3;
always @(posedge clk2)
begin
new_pulse_buf1 <= wide_pulse;
new_pulse_buf2 <= new_pulse_buf1;
new_pulse_buf3 <= new_pulse_buf2;
out_pulse <= new_pulse_buf3 ^ new_pulse_buf2;
end
endmodule
可见,快时钟的脉冲成功同步到了慢时钟。从功耗的角度来说,应该采用方法一,从资源的角度来说,应该采用方法二。两种方法都是正确的,自己看哪种适合就用哪种吧!
三、约束打拍触发器
经过前面的分析,可以得出一个结论,那就是同步器中的触发器延迟越小越好,毫无疑问,同一个SLICE中的两个触发器走线肯定是最短的,所以我们希望软件布局布线时把同步的触发器放到同一个SLICE中,这样可以降低MTBF(平均无故障时间)。如果不加约束,new_pulse_buf1,new_pulse_buf2,new_pulse_buf3不是放到同一个SLICE中,如下图所示。
施加约束,即
(* ASYNC_REG="TRUE" *)reg new_pulse_buf1,new_pulse_buf2,new_pulse_buf3;
这样new_pulse_buf1,new_pulse_buf2,new_pulse_buf3就是放到同一个SLICE中的了。ASYNC_REG属性的作用对象为寄存器,寄存器添加该属性后,即表明寄存器的数据输入口D接收的是来自异步时钟触发器的数据或是该寄存器在一个同步链中属于同步寄存器。ASYNC_REG在异步跨时钟域中经常被使用。
需要注意的是在附加了ASYNCREG属性后,在综合的过程中将不会优化该寄存器及其周边逻辑。所以会发现加了约束的WNS是18.739,比没加约束的WNS18.758要小一点。
总结
本文介绍了两种单bit信号快时钟的脉冲到慢时钟的同步的方法。两种方法均可以把快时钟的脉冲同步到慢时钟。