赞
踩
一颗芯片上会有许多不同的信号工作在不同的时钟频率下。比如SOC芯片中的CPU通常会工作在一个频率上,总线信号(比如DRAM BUS)会工作在另一个时钟频率下,而普通的信号又会工作在另外的时钟频率下。这3个不同时钟(频率)下工作的信号往往需要相互沟通和传递信号。
不同时钟域下的信号传递就涉及到跨时钟域信号处理,因为相互之间的频率、相位不一样,如果不做处理或者处理不当,如下图所示的时钟域CLK_A的数据信号A可能无法满足时钟域CLK_B的setup/hold时间,可能导致:
1.数据丢失,无法采到预期中的信号;
2.亚稳态的产生。
各大FPGA厂家的FPGA编译工具(这是习惯性叫法)在逻辑综合以及实现之后都会出一个时序报告,里面就有跨时钟域的报告,在里面你可以看到你有哪些信号进行了跨时钟域。如下图为Vivado工具的报告位置:
对于这些跨时钟域的情况,一般我们要在逻辑设计的时候就解决,之后的时序约束中设置为false path,即让综合工具不要机关算尽般去布局布线让时序满足要求(这会拖慢编译时间,当然时序也不会成功),设置为false path或者时钟组之后,工具默认不对其进行时序分析(因为设计中已经解决了跨时钟域的问题,这也就是为什么输跨时钟域问题是设计解决的,而不是约束解决的)。
参考资料
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 :时钟域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脉冲信号,会漏掉数据。
思路:
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;
问题:输入脉冲的间隔至少是两个同步器时钟(clkb)周期才行,否则wide_a不够两个clkb周期,wide_b只能维持一个时钟,最终signal_b区分不开signal_a的两个脉冲
需要用握手信号的方法来进一步改进
握手信号法
场景:快速时钟域同步到慢速时钟域
例. 一个系统有两个时钟域的电路,其时钟频率分别为fClka=64MHz和fClkb=20MHz。Clka时钟域驱动一个脉冲信号pulse_a(位宽1bit),传输到Clkb时钟域的电路中,用于触发b模块的某些动作。电路模型和关键时序如下图。请写出a2b模块的rtl代码,并给出评估,你的设计大约用了多少个寄存器?设计中请用异步低复位。(大华FPGA)
所谓握手,即通信双方使用双向控制信号进行状态指示。这个信号既有发送域给接收域的,也有接收域给发送域的。
注:握手信号法其实也用到了脉冲展宽的方法,只是展宽信号的变化条件不同。因为如果不对脉冲进行展宽慢速时钟域的时钟很有可能无法采集到快速时钟域的信号。
缺点就是延时比较久,而且不能对过近的脉冲进行完美的同步。
如果距离足够远,就可以完美同步:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。