当前位置:   article > 正文

跨时钟域信号如何处理(一、单bit信号)_跨时钟域信号如何处理(一) luoai_2666

跨时钟域信号如何处理(一) luoai_2666

背景

一颗芯片上会有许多不同的信号工作在不同的时钟频率下。比如SOC芯片中的CPU通常会工作在一个频率上,总线信号(比如DRAM BUS)会工作在另一个时钟频率下,而普通的信号又会工作在另外的时钟频率下。这3个不同时钟(频率)下工作的信号往往需要相互沟通和传递信号。

不同时钟域下的信号传递就涉及到跨时钟域信号处理,因为相互之间的频率、相位不一样,如果不做处理或者处理不当,如下图所示的时钟域CLK_A的数据信号A可能无法满足时钟域CLK_B的setup/hold时间,可能导致:
1.数据丢失,无法采到预期中的信号;
2.亚稳态的产生。

各大FPGA厂家的FPGA编译工具(这是习惯性叫法)在逻辑综合以及实现之后都会出一个时序报告,里面就有跨时钟域的报告,在里面你可以看到你有哪些信号进行了跨时钟域。如下图为Vivado工具的报告位置:
在这里插入图片描述
对于这些跨时钟域的情况,一般我们要在逻辑设计的时候就解决,之后的时序约束中设置为false path,即让综合工具不要机关算尽般去布局布线让时序满足要求(这会拖慢编译时间,当然时序也不会成功),设置为false path或者时钟组之后,工具默认不对其进行时序分析(因为设计中已经解决了跨时钟域的问题,这也就是为什么输跨时钟域问题是设计解决的,而不是约束解决的)。

两级DFF同步器

参考资料
https://mp.weixin.qq.com/s/ld466c-zJQWev_Py3HE2Ew
http://blog.sina.com.cn/s/blog_679686370102wn5f.html
场景:慢时钟域到快时钟域
图片

从时钟域A(CLKA)传过来的信号a_in, 直接用时钟域B CLKB采用很容易产生亚稳态,用两级DFF 敲过后再使用就可以把亚稳态概率降到一个合理的值。

很多人可能会问,为什么是两级DFF呢?一级或者三级DFF行不行呢?这里有一个平均失效间隔时间MTBF(Mean Time Between Failure)的考虑。MTBF时间越长,出现亚稳态的概率就越小,但是也不能完全避免亚稳态。注意采样时钟频率越高,MTBF可能会迅速减小。

有文献给出的数据:对于一个采样频率为200Mhz的系统,如果不做同步MTBF是2.5us,一级DFF同步的MTBF大概是23年,两级DFF同步的大约MTBF大概是640年,MTBF越长出错的概率越小。所以一级看上去不太稳,二级差不多够用了,至于三级可能会影响到系统的性能,而且增加面积,所以看上去没什么必要。

module sync_method_1( signal_in_clk1, signal_out_clk2, CLK2);

input              signal_in_clk1;    //时钟域CLK1里的信号
output	reg        signal_out_clk2;  //时钟域CLK2里的信号
input              CLK2;                  //时钟CLK2

reg signal_r1;
always @(posede CLK2)begin
	signal_r1 <= signal_in_clk1;
	signal_out_clk2 <= signal_out1;
end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注意事项:
错误1 :时钟域A的组合逻辑信号直接敲两级DFF同步到时钟域B

如下图(1)所示虽然时钟域A的逻辑信号c0 传输到时钟域B的时候,也用了两级DFF 同步器,但我们知道组合逻辑电路各个输入信号的不一致性以及组合逻辑内部路径的延时时间不一样,运算后的信号存在毛刺如图(2),而我们又无法预先知道CLKB 的上升沿何时会到来,CLKB 采样到的信号就无法预知,这显然不是我们想要的结果。
图片

因此,要想CLKB 能采到稳定的信号,时钟域A的信号必须是在CLKA打一拍,在一个时钟周期内是稳定的信号,如图(3)所示:

图片
错误2 : Clock-gating enable 信号没有经过异步处理
(暂时没遇到;这en信号不也是一个跨时钟域信号么?直接打两拍处理行不行?)

在下图中a_in 信号经过CLKA的DFF敲过,再送到两级DFF 同步器处理,完全没毛病。但是F2的使能信号EN是从时钟域A来的,当EN信号变化的时候,由于时钟域不一样,无法保证使能之后的CLKB信号采样数据时满足setup/hold time 要求,这时F2输出信号也就变得无法预测了。

图片
两级同步器处理单比特信号虽然比较简单,但还是要注意它的使用方法,不要犯上面的错误哦。

脉冲展宽同步

参考:https://mp.weixin.qq.com/s/mS3JMVDjEu3cvg-oSleeUw
场景:快速时钟域同步到慢速时钟域
为什么不能直接“打两拍”:慢速时钟域的时钟clkb根本就采集不到快速时钟域clka下的Signal_a脉冲信号,会漏掉数据。
在这里插入图片描述
思路:

  1. 让signal_a展宽:每当快速时钟域clka检测到Signal_a脉冲信号为高时,让src_state信号取反,使得Signal_a的第一个脉冲变为src_state信号的上升沿,Signal_a的第二个脉变为wide_a信号的下降沿。
    这样就使快速时钟域clka的脉冲信号Signal_a展宽之后在慢速时钟域clkb中能够被采集到
  2. wide_a打两拍同步到慢速时钟域clkb
  3. 将wide_b2再转换为脉冲信号:双边沿检测。wide_b1信号可能是不稳定的,而wide_b2信号是稳定的,所以需要将wide_b2信号再打一拍,产生wide_b3信号,再边沿检测,这就是为什么看到一共打了三拍的原因。
    这里用组合逻辑实现边沿检测,如果用时序逻辑会延时一拍。
    在这里插入图片描述
always@(posedge clka) begin
	if(signal_a) wide_a <= ~wide_a;
end 

always@(posedge clkb) begin
	wide_b1 <= wide_a;
	wide_b2 <= wide_b1;
	wide_b3 <= wide_b2;
end

assign signal_b = wide_b2 ^ wide_b3;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

问题:输入脉冲的间隔至少是两个同步器时钟(clkb)周期才行,否则wide_a不够两个clkb周期,wide_b只能维持一个时钟,最终signal_b区分不开signal_a的两个脉冲
需要用握手信号的方法来进一步改进
在这里插入图片描述

握手协议

握手信号法
场景:快速时钟域同步到慢速时钟域
例. 一个系统有两个时钟域的电路,其时钟频率分别为fClka=64MHz和fClkb=20MHz。Clka时钟域驱动一个脉冲信号pulse_a(位宽1bit),传输到Clkb时钟域的电路中,用于触发b模块的某些动作。电路模型和关键时序如下图。请写出a2b模块的rtl代码,并给出评估,你的设计大约用了多少个寄存器?设计中请用异步低复位。(大华FPGA)
在这里插入图片描述
所谓握手,即通信双方使用双向控制信号进行状态指示。这个信号既有发送域给接收域的,也有接收域给发送域的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
注:握手信号法其实也用到了脉冲展宽的方法,只是展宽信号的变化条件不同。因为如果不对脉冲进行展宽慢速时钟域的时钟很有可能无法采集到快速时钟域的信号。
缺点就是延时比较久,而且不能对过近的脉冲进行完美的同步。
在这里插入图片描述
如果距离足够远,就可以完美同步:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/387455
推荐阅读
相关标签
  

闽ICP备14008679号