面试题12–跨时钟域的信号处理技术


一.定义:

对于沿触发的触发器来说,其输出存在两个有效的状态,即高和低(或者说逻辑1和逻辑0)。触发器的建立时间和保持时间在时钟上升沿左右定义了一个时间窗口,如果触发器数据输入端口上的数据在这个时间窗口内发生变化(或者数据更新),那么就会产生时序违规。存在这个时序违规是因为建立时间要求和保持时间要求被违反了,此时触发器内部的某个节点可能会在一个电压范围内浮动,无法稳定在逻辑0或者逻辑1状态。换句话说,如果数据在上述窗口中被采集,触发器中的晶体管不能可靠地设置为逻辑0或者逻辑1对应的电平上。所以,此时的晶体管并未处于饱和区对应的高或者低电平,而是在稳定到一个确定电平之前,徘徊在一个中间电平状态(这个中间电平或许是一个正确值,也许不是)。
在这里插入图片描述

图2-3所示就是所谓的亚稳态,图中“??”表示该处数据是处于一种未知或无效状态。如图2-3的波形所示,信号的跳变发生在建立时间和保持时间边界组成的时间窗口内,或者说时钟2刚好在数据1发生变化的时刻对其进行采样,这意味着第二个寄存器的输出不会是逻辑0或逻辑1对应的确定电平,而是它们之间的一个中间电平。输出保持亚稳态的时间是随机的,甚至可能在整个时钟周期内都保持亚稳态。那么,如果这个亚稳态值输人到组合逻辑,根据逻辑门电路的切换门檻,就可能会发生错误的操作。从时序收敛的角度来说,两个触发器之间的组合逻辑延时都要求要小于最小的时钟周期,但这种亚稳态信号保持亚稳态的时间,本身就是变相地增加了逻辑延时。显然,一个亚稳态信号会给设计带来致命的功能故障,使得该信号在俩个时钟域相邻的时钟沿上无法获得相同的状态,但是跨过时钟域之后的第二个时钟上升沿时刻,数据应该能够稳定下来。

1.1处理亚稳态的经典办法一一双触发

设计中使用的任何寄存器都会指定一个建立和保持时间,在时钟上升沿前后的这个时间内输人数据被禁止发生任何变动。所有器件中的寄存器都要指定这个精确参数,就是为了防止数据信号两次变化发生的时间间隔太过靠近,从而导致其输出陷入亚稳态

当需要在两个时钟域传输信号的时候,需要考虑一个重要的问题是:是否需要采样从一个时钟域传输到另一个时钟域的这个信号的每一个值?通过思考这个问题可以发现,在跨时钟边界存在跨时钟域传输数据允许丢失部分采样值跨时钟域传输数据不允许丢失任何信号采样值两种情况,而且确认设计到底属于哪种情况则变得非常重要。这两种情况中,跨时钟域信号都需要被同步到其接收时钟域之中。

最常见的同步器就是使用两级寄存器,即使用寄存器打两拍的方式进行同步。所谓的同步器就是采样一个异步信号,采样输出能够同步到本地或采样时钟的模块。这种最简单也是使用最普遍的两级寄存的同步器如图2-4所示。
在这里插入图片描述
异步信号同步化:这样理解,一个信号在一个时钟域上满足这个时钟域的建立时间和保持时间;该信号与下一个时钟域同步的意思就是也满足下一个时钟域的建立时间和保持时间。

当然,仍然有可能级联的第二个寄存器输出还会表现为非稳定状态,但是这种双寄存同步器已经可以解决大部分这类亚稳态问题。在设计这种同步器的时候应当注意遵循以下原则:
【1】级联的寄存器必须使用同一个采样时钟;
【2】发送端时钟域寄存器输出和接收端异步时钟域级联寄存器输入之间不能有任何其他组合逻辑;
【3】同步器中级联的寄存器中除了最后一个寄存器外所有的寄存器只能有一个扇出,即其只能驱动下一级寄存器的输入
在这里插入图片描述

图2-5就展示了不符合上述第一个原则的情况,即接收时钟域两个级联寄存器使用了不同的时钟沿进行触发。这样处理大大增加了无法有效解决第一个寄存器亚稳态输出的风险,因为级联寄存器中的第二个寄存器很可能没有足够的时间(两级寄存器之间只有半个时钟周期,而非整个时钟周期)来处理。
在这里插入图片描述

图2-6则展现了不符合上述第二个原则的情况,即发送时钟域寄存器输出和接收时钟域寄存器输入之间存在不合理的组合逻辑。由于组合逻辑会产生毛刺,这样同步器很有可能采样到不需要的数据。此外,组合逻辑输出的额外切换也增加了亚稳态的风险。

同步器中寄存器链的长度就是符合上述三个原则的寄存器个数,上述提到的典型的同步器长度是2,即两级寄存器。另外,只要同步器中寄存器链处于同一个时钟域,那么寄存器链中寄存器路径之间是可以存在组合逻辑的。图2-7所示即为这样的一个例子。
在这里插入图片描述

1.2使用三级触发器对亚稳态进行同步处理

平均故障间隔时间(MeanTime Between Failure, MTBF) 。这是衡量一个产品,尤其是电子产品的可靠性指标。显然, 在计算MTBF时, 大的MTBF值要好于小的MTBF值。MTB T值大表示两次故障间隔的时间长;相反,则表示两次故障间隔的时间短。上文提到有时候同步器中两级寄存器未必足够,是指在一些高速设计中需要再额外加人一级寄存器来增加MTBF, 也即同步器中两级寄存器的MTBF太短。图2-8即为某些高速设计中使用的三级触发器同步器。
在这里插入图片描述

1.3如何同步快速信号到慢速时钟域

跨时钟域信号当跨越两个时钟域之间的边界时,如果不允许丢失任何数值,那么同步技术或信号的宽度就显得非常重要。设计者可能会面临这样一个问题,即信号在发送时钟域被采样之前可能会出现数值的两次变化,因为发送时钟域的时钟频率高于接收时钟域的时钟频率,如此跨时钟域信号就有可能在跨越时钟域边界之前经历了两次发送时钟域时钟的上升沿。这种可能性在信号从一个时钟域传递到另一个时钟域的任何时候都必须认真考虑,而且必须要考虑在这种情况下丢失信号对设计来说是否有问题。如果丢失信号采样值对于设计来说是不允许的,那么有两种通用的应对方法可以解决这个问题:一个是开环解决方案,确保信号在无须确认的情况下可以被采集;另一个是闭环解决方案,即在跨时钟域边界时,信号需要接收端的反馈确认

如果快速时钟域的时钟频率是慢速时钟域的1.5倍以上,那么同步较慢的控制信号到一快速时钟域通常来说不会有问题,因为快速时钟域的时钟信号将会采样慢速跨时钟域信号一次甚至更多次。因此,跨时钟域信号从低速时钟域跨越到高速时钟域比其从高速时钟域跨越到低速时钟域产生更少的潜在问题,只需采用前面介绍的双触发同步器在跨时钟边界来传递单个跨时钟域信号即可

下面来讨论跨时钟域信号从高速时钟域跨越到低速时钟域可能会产生的问题。首先,以一个比较极端的例子来说明问题。在这个例子中发送时钟域的时钟频率高于接收时钟域的时钟频率,而跨时钟域的信号脉冲宽度正好等于发送端时钟的一个时钟周期。那么,当只有一个高速时钟周期宽的跨时钟域信号传递到低速时钟域时,被低速时钟采样后,该信号有可能为高,也可能为低。也就是说,该信号有可能会被低速时钟采集,也可能不会被采集,如图2-9所示,该信号在跨时钟边界时丢失数值。
在这里插入图片描述
再来看一个不太极端的例子。如图2-10所示,从发送时钟域(快速时钟)发送的信号脉宽稍微大于接收时钟域(低速时钟)时钟周期。在大部分情况下,该信号是能被低速时钟采样并传递,但是在实际应用中该跨时钟域信号有很小概率的情况下,脉冲改变发生在离接收时钟域同步器两个时钟上升沿太近,如此第一个时钟沿处建立时间无法得到满足,第二个时钟沿处保持时间得不到满足,从而无法得到预期的信号脉冲。前面提到有两种方法可以解决上述问题,首先来看第一种方法,即开环方案。这种方案还是采取之前介绍的同步器来采样跨时钟域信号,但是前提是需要先将目标信号展宽,如:
在这里插入图片描述
图2-11所示,需要将目标信号展宽到至少少超过接收时钟域的时钟周期。最佳的脉宽是至少为采样时钟周期的1.5倍,这样跨时钟域信号将会被接收时钟域的时钟至少稳定地采样一次。开环解决方案,多用于相关时钟频率固定且时钟信号能够被正确分析。这种方案的好
处是能在无须接收时钟域的握手信号的情青况下最快地将信号传递通过跨时钟域边界。该方案的缺点是,容易让其他设计者误以为当前解决方案为通用解决方案,或者说当设计要求发生改变的时候,设计者容易忘记重新分析之前的“开环”解决方案。
在这里插入图片描述

下面讨论第二种解决方案,即“闭环”解决方案。这种解决方案是在发送时钟域将控制信号当使能信号传递,并将其同步到接收时钟域,然后接收时钟域收到使能控制信号之后,将同步的控制信号反馈到发送时钟域,发生时钟域通过另外一个同步器接收此反馈回来的控制信号,并以它作为信号正确接收的握手信号。如图2-12所示,这种方案的好处是反馈信号当使能信号传递。回来的同步信号可以非常安全地确认第一个使能控制信号已经被接收时钟域正确识别和采样。其缺点也是显而易见的,即这种信号传递方式存在相当大的延时,因为信号未被接收时钟域正确接收之前是不能被释放的,也即在被正确接收之前目标信号不能改变数值,也就无法传递信号的下一个数值。

在这里插入图片描述

二.多比特信号跨时钟域同步处理

当在时钟域之间传递多比特数据时,普通的同步器并不能保证数据传递的安全性。在多时钟设计中,工程师往往容易犯一个错误,即同一事务处理含有需要从一个时钟域向另一个时钟域传递的多位跨时钟数据,并忽略了同步采样这些跨时钟位的重要性。跨时钟域传递多比特信号的问题是,在同步多个信号到一个时钟域时将可能偶发数据变化歪斜(Skew) , 这种数据歪斜最终会在第二个时钟域的不同时钟上升沿上被采集。即便能够完美地控制和匹配这些多比特信号的走线长度,随着芯片衬底工艺不同,上升和下降的时间也会不一样,这些因素都会产生足够的歪斜导致在精心匹配的多条信号上采样失败。为了避免这种多比特跨时钟域信号上的采样歪斜,需要掌握一些不一样的策略。这些策略大致可以分为三种:
【1】多比特信号融合策略,即在可能的情况下,将多比特跨时钟域信号融合成单比特跨时钟域信号;
【2】多周期路径规划策略,即使用同步加载信号来安全地传递多比特跨时钟域信号;
【3】使用格雷码传递多比特跨时钟域信号;

2.1多比特信号融合

只要有可能,就要将跨时钟域的多比特信号融合到单比特跨时钟域信号。设计中在碰到多比特需要跨时钟域时,可以先考虑是否真的需要多比特来控制逻辑跨越时钟边界?

下面通过一个例子来说明,只是简单地对多比特跨时钟域信号使用同步器并不一定是足够好的一种解决方案。如果这些控制信号的顺序或排列对于设计非常重要,那么设计者必须非常小心地将这些信号传递到新的时钟域。这一节给出的所有例子都比较简单,但它们所模仿的都是实际设计中出现的情况。
在这里插入图片描述

首先来看第一个例子,如图2-13所示,在接收时钟域有一个寄存器,它需要一个加载(Load) 信号和一个使能(Enable) 信号来加载一个数值到寄存器。如果加载和使能信号在发送时钟域的同一个时钟沿被驱动有效(即两个控制信号需要同时有效),那么这两个控制信号之间就有可能存在产生一个小歪斜的机会,这就可能导致在接收时钟域中这两个信号被同步到不同的时钟周期。在这种情况下,数据是不能被加载到寄存器的。解决图2-13所示问题的方法非常简单,就是将加载和使能两个控制信号融合成一个单 比特控制信号(这两个控制信号本身相同,且同时有效),如图2-14所示。单比特控制信号同步到接收时钟域后作为一个“加载使能”信号同时驱动寄存器的加载和使能输入端口,如此即可消除图2-13所示的潜在问题。
在这里插入图片描述

2.2多周期路径规划

多周期路径规划是一种通用的安全传递多比特跨时钟域信号技术。多周期路径规划是指在传输非同步数据到接收时钟域时配上的一个同步的控制信号,数据和控制信号被同时发送到接收时钟域,同时控制信号在接收时钟域使用俩级寄存器同步到接收时钟域,使用此同步后的控制信号来加载数据,数据可以在目的的寄存器被安全加载。使用这种技术的好处是:
【1】在时钟域值之间发送数据的时候无需计算对应脉冲宽度;
【2】发送时钟域值只需要切换一个使能到接收时钟域来显示数据已经被传递且以经准备被加载,使能信号无需返回到原始状态;

使用这种方式传递多比特时钟域信号时,数据不需要同步,只需要传递一个同步的使能信号到接收时钟域即可。接收时钟域在同步使能信号通过同步方式传递到接收时钟域之前不允许采集数据。

这种方式之所以被称为多周期路径规划,是由于非同步的数据字直接传造到接收时钟域并在接收时钟域保持多个时钟周期,只有在一个使能信号被同步到接收时钟域并被识别以后才允许该非同步数据字发生变化。

正是因为非同步数据传递到接收时钟域并在多个时钟周期内保持稳定,所以数据的传递是安全的,数据值并无陷入亚稳态的危险

这种方式非常类似在单时钟域中经常采用的“数据有效”技术,比如读、写FIFO的读有效和写有效等,只是这里谈论的是跨时钟域。有效信号一般是和数据对齐的,那么在传递数据和使能(或有效)信号到下一个时钟域的时候,只需要同步使能信号。图2-17所示为一种常用的跨时钟域传递使能控制信号处理方法。将使能信号经过同步器同步后传递到一个同步脉冲发生器,然后产生一个指示信号用于指示非同步多周期数据,即可在下一个接收时钟上升沿进行采集
在这里插入图片描述
上图所示,关键的一点在于产生同步使能脉冲时,输入信号的极性并不重要,土中输入信号d从低切换到高,在第七个时钟上升沿在从高切换到低,看到只要输入信号d发生变化都能产生同步使能信号脉冲,所以输入信号的每次切换都对应依次数据的变化。

在单时钟域应用设计当中,经常使用类似的技术来产生数据有效信号。上图使用的是异或门,该技术的缺点是在脉冲的上升沿和下降沿都会产生一个同步脉冲,当只需要一个同步脉冲,或者说检测脉冲上升沿的时侯,可以使用q3取反后与q2相与即可得到一个单一的同步脉冲,也即只会在上升沿处产生产生一个同步脉冲。

2.3使用FIFO结构处理多比特跨时钟域信号

跨时钟域传输数据用得最多的方法就是使用先入先出(FIFO)结构FIFO可以用于在两个异步时钟域之间传输多比特信号。通常看到的FIFO应用包括在两个标准总线之间传输数据,以及从可突发访问的存储器中读出数据或者对其写入数据。。在很多不同的应用中,FIFO都一种非常有用的数据结构,不过这里仅关注其处理跨时钟域突发数据的能力。

如图2-18所示,一个FIFO被用于缓存数据,这样在设备中就形成了一个数据序列。
在这里插入图片描述
通过使用异步FIFO,数据发送端可以随意地间隔发送数据,而接收端也可以其固有的带宽从数据序列里取出数据并进行处理。由于任何由FIFO实现的数据序列的长度都不能无限制,所以需要一些控制来防止FIFO溢出。这时有两种选项可以采用:
【1】事先定义好的发送速率(可突发或不可突发)、最小接收速率以及对应最大的序列尺寸;
【2】握手控制。
注意,发送设备的时钟频率没有必要高于接收端设备,否则容易造成溢出。以较慢的频 率将数据送入FIFO,那么数据写人FIFO的时钟周期数要少于接收端将要处理数据的时钟周期数。那么,如果不采取握手控制,就必需要理解以上描述会产生溢出的最坏的情况。

在任何一段时间内,假设数据发送写FIFO的速率大于接收处理数据的速率,那么很轻易地使系统无法维持。因为没有任何存储设备可以存得下无限的数据,这种问题需要在系统结构层级才能解决。通常来说,突发发送一般是以小周期性或非周期性发生。所以FIFO的最大尺寸要大于或等于(具体还要根据数据接收器的属性)突发的尺寸。

在很多例子中,不管是突发尺寸还是数据到达的分配都无法很好地定义。这种时候,就有必要使用握手控制来防止FIFO产生数据溢出。如图2-19所示,这种握手控制通常由些标志信号来实现。这些标志信号,一个是发送侧的满标志,用于提示FIFO已没有多余空间存储数据;另一个则是空标志,用于提示接收侧FIFO中已没有数据需要处理。管理这些握手信号可能还需要一个状态机,正如图2-19所示。
在这里插入图片描述

FIFO在FPGA内一般是通过封装一个双口RAM来实现。表面上看来微不足道的标志信号(如空和满指示等),实际上实现起来反而比较困难。原因就在于输入控制常常需要依据输出来产生,同样输出控制也常常需要依据输入来产生。例如,驱动输入的逻辑必须要知道FIFO是否已满,而这只能通过获取从输出端读出的数据数量才能得知。同样的道理,在输出侧从FIFO读数据的逻辑必需要了解FIFO中是否还有数据(即FIFO是否已空),而这只能通过输入端口的写指针才能判决。

这里探讨使用FIFO在两个异步时钟域之间传输数据,不过同样会面临实现FIFO本身时遇到的握手标志问题。为了在两个时钟域之间传递必要的信号,必须重回到的打两拍技术。下面以图2-20所示的简单异步FIFO框图为例进行阐述。
在这里插入图片描述

图2-20中,在产生空和满信号时,写地址和读地址都必须是异步传递到对方时钟域中。这样,在重新同步多比特地址总线时问题就出现了,即根据各比特的不同走线,总线中某些比特可能会比其他比特晚一个时钟周期。换句话说,由于两个时钟域异步的自然属性,使得地址总线有些比特在一个时钟沿上被采集,而另一些比特却在下一个时钟沿上被采集,当然这取决于数据是否在第一个触发器的时钟沿到达之前提前足够长时间有效。如果上述情况发生,那么会给系统带来严重后果,因为二进制地址中有些位变化有些位却没有,因此接收逻辑将会得到一个完全无效的地址,这个地址既不是当前地址也不是上一个地址。这个问题可以通过将二进制地址转换为格雷码的方式解决。格雷码是一种非常特殊的计数器,两个相邻地址中只有一个比特是不同的。所以当地址改变时,只需要改变地址中的个比特即可,这样就可以避免上面提到的问题。如果发生变化的那个比特并没有被下一个时钟正确采集,地址线上会“同步地”保留旧的地址。那么任何不正确的地址(既不是当前地址也不是旧地址)操作都会被消除。所以格雷码常用来在异步时钟域之间传递多比特计数值,且多用于FIFO内

需要额外注意的是,由于读写地址需要在异步时钟域之间传递,所以地址就有可能比预想的晚一个时钟周期,同时意味着空或者满标志位晚一个时钟周期,但是这并不表示错误导致了数据溢出的情况。如果这种情况在传递地址到读时钟域时,读逻辑将简单地认为数据没有写入,且将认为FIFO已空,尽管FIFO已经被写入了一个数据。这只会对吞吐量有一些小的影响,但是不会导致下溢(即读已空的FIFO)状况发生。同样,传递地址到写时钟域时,如果写地址被延时了,那么写逻辑就会认为FIFO里面没有多余空间,尽管FIFO还未满。这只会对吞吐量有一些小的影响,但是不会导致上溢(即写已满的FIFO)状况发生。

参考文献:
【1】FPGA设计实战演练(高级技巧篇)