赞
踩
它们与D触发器的内部结构有关系。D触发器的内部是一个主从锁存器(master-slave latch),一个常见的D触发器结构如下图所示
Latch能够存储住状态,靠的是上面的背靠背的反相器。而这个背靠背的反相器能够锁住状态是需要时间的。由此,我们可以分析出
setup time: 在clk的上升沿到来之前,D要传输到Z的时间。因为当Z的值还没有稳定的时候,D如果变化,那么这个背靠背的反相器就无法锁住值。
hold time: 第一个传输门关闭需要的时间,在传输门关闭期间,D->W要保持稳定,这样在传输门关闭之后,W稳定才不会导致背靠背反相器锁住的值发生变化。
所以我们可以看出,当D在setup/hold time window内发生变化,锁存器可能无法锁住一个稳定的值,会发生的结果是
注意我们并不是说Q最后的值不是稳定的1或者0, Q的值最后一定会稳定下来,稳定在高电平或者低电平,这是由于背靠背的反相器会产生正反馈,最终一定会稳定下来。但是当这个稳定的时间超出了clk-to-q的限制,我们就说产生了亚稳态。
在这里要澄清的一点是,亚稳态的出现并导致逻辑错误并且芯片失效是一个概率事件,而不是一个100%会发生的确定性事件
芯片一旦出现CDC的问题,可能会导致以下后果
关于MTBF,还有一个误区需要澄清,就是MTBF只要大于产品的设计使用寿命就可以了,这其实是不严谨的。因为一个产品可能由多个系统组成,每个系统又是由多个子系统组成,每个子系统可能细分下去是由更小的单元组成。整个产品不发生失效的概率是所有部分不发生失效概率的乘积。所以越是小的单元,越要保证MTBF越高,这样才能不会导致整个产品的MTBF 有显著下降。
例如下图所示:adata第一次变高,只碰到了bclk的2个沿,就可能导致bdata根本没有看到这个pulse,而第二次adata变高,持续了3个沿,这样bdata就能够确保也可以变高了。
所以如果bclk的频率是1.5倍的aclk频率以上,即使adata是aclk域的一个短pulse,也可以保证3edge要求。
如果没有这样频率的关系,那就得对adata有要求了,adata的变化不能很迅速,要稳定足够长的时间,这样才不会让bclk域错过值,具体怎么做呢?
我是不是要将adata的每一次翻转都同步到bclk呢?
其实这个问题应该是在考虑要将一个信号跨到另一个时钟域的时候首先要问自己的问题。大多数情况下,回答都是肯定的,也就是说adata变化了,bclk这边的信号也要变化。但是也有些时候,即使漏了adata的变化,可能也没关系,这就是和设计的要求相关了.
如果必须要求adata的每一次翻转都同步到bclk,一个办法就是利用反馈。也就是说信号从aclk域同步到bclk域,再同步回aclk域。aclk的data只有看到同步回来的值之后才能再翻转。如下图所示
但是这样做的缺点也很明显,就是将aclk的data进行了扩展,两次的同步也增加了延时,这是为了达到每次变化都同步而付出的代价。大多数时候,设计者知道adata变化的频率很低,比如是一个软件配置位,配置好之后可能不轻易更改;比如是一个中断信号,中断发生之后可能需要很长时间才会被软件清除,这些时候就没有必要设计反馈电路了。
最后再讲两个知识点,也是非常关键的知识点。
第一,利用double flop,bdata发生变化可能是在adata翻转之后1个周期,也可能是2个周期,这是由于第一级flop的metastable可能会resolve在不同的值。如果第一级flop 稳定在和adata相同的值,那么就只需要1个周期就能看到bdata翻转。而如果第一级flop 稳定在和adata相反的值,那么则需要再多一个周期。所以在设计和仿真验证中,不能假定bdata一定会在2个周期之后发生变化,而是将这个因素随机在仿真中,有的时候真的会暴露出设计中的问题。
第二,我们说的单bit信号,有人可能会说,组合逻辑的输出可不可以用double flop呢?比如一个AND门的输出,不也是单bit吗?答案很简单,不可以。原因就是组合逻辑的输出可能会有毛刺,这些毛刺会增大第一级flop产生metastable的概率,进而影响整个synchronizer的MTBF。所以对于任何单bit信号,在跨时钟域之前一定要先寄存(flop),只有flop的输出才能经过synchronizer. 下面的图就是不flop的情形。
由于pulse只持续一个周期,2flop synchronizer可能会miss掉pulse,那我们想个办法让产生过pulse这个之前发生过的事件记录在那里不就好了吗?这就是破解这个问题的思路:
其中的关键就是图中所示的Toggle Flop。可以看到当输入是一个单周期的pulse时,里面Toggle flop的输出只会翻转一下。
这样我们就把一个pulse转化成为了level,这个level信号直到下一个pulse来之前都是稳定的,于是我们就可以利用2flop synchronizer来将这个level信号同步到bclk时钟域,然后我们再借助一个XOR和一个flop来重新创造出一个pulse
我们继续看,既然这个pulse synchronizer中+间利用了2flop,那么2flop的3edge要求就必须要满足,换句话说,我们转化成为的level的信号Tq要足够长。如果Tq不满足bclk的3edge要求,那么这个level信号我们就无法同步过去,也就无法产生bclk的pulse了。而Tq每次变化是由于aclk来了一个新的pulse,这也就是要求aclk的连续两个pulse之间的间隔要足够大,要满足bclk的3edge要求。
如果你回答出来了这个pulse synchronizer的局限性,那么面试官很可能会接着问,如果我不知道下一个pulse是什么时间来怎么办呢?老李当年还就真被这么问到过,把老李差点整懵逼了。我们先来看,aclk时钟域最接近的两个pulse能靠多近呢,显然就是两个pulse中间只有一个aclk周期,这其实就是将aclk进行了2分频。那么相应的,Tq就是对aclk进行了4分频,每个Tq的level持续时间是2个aclk cycle,这2个cycle需要满足bclk的3edge要求,如果满足,那么就可以保证bclk域也可以产生每个cycle的pulse的要求。
本质思路就是我们不能让aclk域的pulse产生得很快,而是要等到pulse同步到bclk之后才能继续产生下一个pulse,于是我们要将b_p重新synchronize回到aclk域,作为放行下一个pulse的条件。
可是这个反馈的办法要求每个pulse产生都要同步回来,这样做的效率不高,有没有更快的办法呢?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。