电子说
什么是同步器
如图1所示电路结构就叫同步器。左边为时钟域clk1,右边两个FF为时钟域clk2,蓝色的为CDC(clock domain cross)路径。这种电路结构常用于两个不同的时钟域数据传输。其实前面讲的异步复位同步释放本质上也是同步器,只是前面的复位信号是复位端口产生的,不是某个寄存器打拍过来的,异步复位信号也可以视作一个不同时钟域的信号。由此你也可以知道同步器的作用之一就是消除亚稳态。
图1. 同步器跨时钟域图
用更直观的代码告诉大家,就是如下verilog代码:
reg [ 1:0] d1;
reg [ 1:0] ql;
reg [ 1:0] q2;
always@(posedge clk1)
begin
if(rst == 1'b1) d1 <= 2'h0;
else d1 <= din;
end
always@(posedge clk2)
begin
if(rst == 1'b1) ql <= 2'h0;
else q1 <= d1
end
always@(posedge clk2)
begin
if(rst == 1'b1) q2 <= 2'h0;
else q2 <= q1;
end
亚稳态及其传播
重点!
通过两级寄存器,即使产生亚稳态也在两个寄存器之间,降低传递到后级的概率,从而减轻亚稳态对后级影响。
理论上,亚稳态产生后持续时长是随机的,意味着永远持续下去也是可能的,然而由于实际电路中存在的噪声和能量变化等一定会让亚稳态很快产生不平衡,迅速向0或者1靠拢。举个例子,就像笔尖上放一个圆球,理论上可以找一个位置永远平衡,然而实际上由于一点点的震动都会导致圆球迅速掉下去。如图2所示,在时钟发射沿到来后,亚稳态产生后持续时间为Tmet,在捕获沿到来时,dout的亚稳态已经消除,这样亚稳态就不会往后级传播,也就是说亚稳态在一个时钟周期内稳定就可以防止往下一级传播。实际中亚稳态的稳定都很快。而同步器打2拍就是为了在时钟频率很高的时候,捕获沿采到亚稳态向下一级传播的时候,还有一级寄存器隔离,然亚稳态在一个时钟周期内稳定下来。
假设,亚稳态在一个时钟周期内稳定不下来的概率为P,0
图2. 亚稳态产生过程
同步器同步n bit数据
当n=1时,参见上面的亚稳态传播,1bit数据产生亚稳态以后就算错了也是变成0或者1第二拍也会正确,所以同步1bit数据可以采后面几拍的数据,这样就能保证采集过来的数据是正确的,后面会试验给大家看。当然,要实现这点首先是快时钟必须是慢时钟的好几倍才行,至少2倍。
多bit数据传输和1bit数据唯一的区别就是多路对齐,保证每一路数据延迟一致 ,这样就和传输1bit数据一样了。下面给大家推荐一个约束set_bus_skew,可以约束一条总线上每根线的延迟相差不大。
命令用法——set_bus_skew [-from 寄存器名] [-to 寄存器名] xx ns。比如在图3中约束src_gray_ff_reg到dest_graysync_ff_reg之间的两根线延迟保持一致,完整命令如下,保证两根线延迟都在2.5ns,一个快时钟域周期:
set_bus_skew -from [get_cells src_gray_ff_reg[ ]] -to [get_cells {dest_graysync_ff_reg[0][ ]}] 2.500
图3. 寄存器图
同步器传输数据的情景分析
情景1
同步器只能正确处理同源的两个时钟域之间的信号,如果不同源,很可能出现发射沿打出的数据还没稳定就被捕获沿采集到,这样数据就会出错。
情景2
两个时钟域的频率不能太接近,且快时钟最好是慢时钟的整数倍,这样保证边沿不会出现捕获沿不在数据不稳定的时候出现,不然会采错数据。
下图是100M和96.34M时钟用同步器采集的结果,err和err1为高电平都是代表数据有错的时候。可以发现数据出错频繁,而且间隔不均等,本质上就是因为两个时钟的相位关系不是像整数倍一样规律,很可能出现捕获沿采集不稳定数据。其实小数倍的时候,小数位数越多越容易出现这种问题。
图4. 时钟频率不匹配导致错误
情景3
快时钟最好是慢时钟的整数倍的时候,不加约束也可以有方法比较稳定的正确抓取数据 。
下图是50M时钟到200M时钟跨时钟域同步的结果,没有加约束,大家可以看到数据在从0x4ef到0x4f0过度的时候第一拍出错了,出现了1个0x4f1,而后面的三拍数据是对的,看后面出错的数据也是这样,也就是说,每采集到的4个数里面,用出现次数多的数覆盖次数少的数就可以了,因为原本是4倍关系,所以理论上连续的4个数是要一致的。
如下图在两个位置的总线都加了set_bus_skew约束5ns后,采集的数据一直没有出错,也根本不用覆盖的方法去剔除错误数据了。
正确传输条件总结:
全部0条评论
快来发表一下你的评论吧 !