数字电路中的Single-Bit跨时钟域设计
- 同步时钟&异步时钟的定义
- Metastable(亚稳态)
- Metastable的产生原因
- Setup / Hold Requirement的真正原因
- Metastable造成的问题
- 跨时钟域同步设计
- 跨时钟域处理目标
- Single-bit的Clock Domin Crossing (CDC) 电路
- Single-bit CDC电路设计的注意事项
- 跨时钟域电路的仿真验证
- 跨时钟域电路的时序约束
同步时钟&异步时钟的定义
在数字芯片的设计当中,我们经常要处理基于不同时钟域的电路之间的信号传输。例如,在一块芯片当中,接口的时钟是固定的,而CPU Core的时钟可能会与接口的时钟不同。在百兆的速度下,Ethernet接口频率为25MHz,而Cortex-m3最高工作频率可以达到72MHz。为了将数字信号完整的从一个时钟域传输到另一个时钟域,我们就需要用到跨时钟域技术。
我们首先定义一下同步时钟和异步时钟的概念。
同步时钟指的不仅仅是时钟频率相同的两个或多个时钟域,而是指能够明确多个时钟间如下关系的时钟源:
- 时钟频率;
- 时钟高电平/低电平的持续时间;
- 各个时钟的相位(各个时钟第一个上升沿的时间);
- 时钟的输入latency;
- …
当我们能够明确多个时钟源间的以上关系的时候,EDA工具就可以自动补全优化不同时钟源之间的电路,不需要设计者主动设计特殊电路。
当我们不能够明确多个时钟源之间的关系,特别是时钟源之间的相位关系的时候,我们将其称为异步时钟。
Metastable(亚稳态)
Metastable翻译过来是亚稳态,它指的是触发器无法在规定的时间段内达到一个可以确定的状态(“1”或“0”)。当一个触发器进入亚稳态的时候,在一段时间内既无法预测该Cell的输出电平,也不能预测什么时候该Cell输出能稳定在一个确定的电平上。
Metastable的产生原因
以一个D Flip-Flop (DFF)为例,如下图所示,当D端的电平保持时间满足了setup/hold requirement,在clock上升沿处将抓取D端的电平状态经过延时送往Q端。在这时,Q端的输出电平可以稳定状态(“1”或“0”)。
当D端电平的setup time或者hold time不满足要求的时候,如下图所示,Q端输出的输出电平无法预测,输出电平何时稳定也无法预测,会导致CK->Q的延时时间更长。
Setup / Hold Requirement的真正原因
下图是DFF的其中一种电路结构,D指的是D端,Q指的是Q端,φ连接的是Clock端。真正的电路结构分析比较复杂,这里简化一下,认为信号从D端传递到Q端需要一定的时间,当时间不能满足的话,Q端不能正确的输出D端信号。
因为DFF的电路结构,D端的电平保持时间必须保证setup/hold time。在这里我们提出另外三个问题:
- 第一个问题:在cell library中,一个DFF cell的setup requirement可以为0吗?
结论是可以的,只需要在Clock端加一个buffer,效果是将时钟信号延迟。这个时候,将如下图的整个电路package为一个大的cell。如此,这个大的DFF cell的setup requirement实际上是可以满足的。
- 第二个问题:在cell library中,一个DFF cell的hold requirement可以为0吗?
结论也是可以的。同理,在D端加一个buffer,效果是将D端输入信号延迟,满足了hold requirement。
- 第三个问题:在cell library中,一个DFF cell的setup/hold requirement可以同时为0吗?
结论是不可以的。上面两种方法本质是拉长setup/hold创建的时间窗口。如果如上所述,同时在clock端和D端加上delay buffer,效果与同时不加delay buffer是一样的。所以setup/hold requirement不可以同时为0。
Metastable造成的问题
就像上文所说的,Metastable最主要造成的问题有两个:
- DFF的输出端不稳定,可能是“1”也有可能是“0”;
- 比cell library里面的CK->Q延迟时间更长;
那么这里我们又出现了一个问题,Metastable所造成的CK->Q延迟时间最长可以达到多长的时间。根据经验,在小于0.13μm的制程工艺中,metastable time最长可以达到大概1ns时间。
面对异步时钟域之间的信号传输问题,为了避免出现metastable,我们采用了特殊的跨时钟域同步技术处理。
跨时钟域同步设计
跨时钟域处理目标
在跨时钟域同步设计中,我们需要达到的主要目标就是 100% 确保数据(事件)在跨时钟域当中的完整性。数据(事件)的完整性包括了:
- 数据(事件)的值不能错;
- 数据(事件)的顺序不能错;
- 数据(事件)的个数不能错;
- 在跨时钟域同步设计中,不能出现metastable现象。
Single-bit的Clock Domin Crossing (CDC) 电路
这里我们提出一种最简单的跨时钟域电路设计,单比特的跨时钟域电路设计,Single-bit的Clock Domin Crossing电路设计,如下图所示。
我们可以看到,图中输入信号din经过第一个DFF输出了d_async信号。d_async信号从一个时钟域 (clk0) 传递到另一个时钟域 (clk1),通过两级DFF,最后输出一个稳定的d_sync1信号。我们发现,当d_async信号第一次被clk1上升沿捕捉到的时候,恰好处在上升沿,它不能满足DFF的setup requirement,产生了metastable亚稳态。所以,这里我们将d_async信号做了一个delay,使得clk1可以在d_async信号满足setup/hold requirement的情况下捕捉输入信号。为了防止极端情况出现,即第一级DFF输出d_sync0信号也不能满足setup/hold requirement,导致metastable的传播,我们设置了第二级DFF,将d_sync0延迟,被clk1捕捉,输出d_sync1信号。第二级DFF基本可以保证metastable被消除。
上图展示了Single-bit CDC电路的两种情况。case0指的是当metastable出现的时候,d_sync0捕捉到的信号与输入信号状态一致,case1则是反之。所以在CDC电路设计中,打两拍后的信号可能会晚一个cycle出现,需要注意这种可能。
这种通过设置两级DFF(在工作中也俗称为打两拍)的电路设计不是所有条件下都可以达到消除metastable的目的,需要满足一些特定的条件。
-
输入信号 (din)保持时间 必须足够长,保证另一个时钟域的DFF可以捕捉到这个信号。输入信号的保持时间应该满足以下条件:另一个时钟域 (clk1) 一个时钟周期 + 第一级DFF的setup required time + 第一级DFF的hold required time。
-
我们在课堂上,老师会教授我们打两拍的方法可以在很大程度上消除metastable现象,但不能百分之一百的保证metastable不出现。面对metastable问题,我们在实际生产当中,不可能在设计的时候就设计可能出现问题的电路。我们在Metastable造成的问题一节中提到过,metastable time最长为1ns,指的是大概在1ns之后Q端一定会输出一个确定的电平。举个例子,当我们设计的clk1时钟周期为2ns,时钟频率为1000MHz,且DFF cell的setup/hold requirement小于1ns,那么我们第二级的DFF输入端信号一定会满足setup/hold requirement,也就是说完全消除了metastable现象。
Single-bit CDC电路设计的注意事项
在实际生产中,这种电路设计不可能独立存在,有可能会和一些组合逻辑电路连接。那么就会遇到以下三种情况:
-
在不同时钟域传输中间加设组合逻辑电路。如下图所示。
这种电路设计是不正确的。因为在组合逻辑电路中,不同的输入信号从输入到输出所经历的时间可能是不一样的,所以d_async信号在输出的过程中会出现unwanted glitch。当这些unwanted glitch被clk1抓取到的时候,就会输出不正确的电平状态,导致最后输出的数据(事件)不能保证完整性。 -
在两级DFF中间加设组合逻辑电路。如下图所示。
这种电路设计也是不正确的。因为在cell library当中,EDA工具的STA会对d_sync0的输出有一个预测,如下图所示。但当第一级DFF输出Q端信号与其他寄存器输出信号生成组合逻辑电路输出的话,真实的d_sync0可能会与预测的信号相比有一个delay延迟,导致了setup/hold requirement不能被满足,造成了d_sync1信号出现metastable现象。
-
在两级DFF输出稳定电平之后加设组合逻辑电路
这种电路设计是正确的,不影响消除metastable现象。
跨时钟域电路的仿真验证
每当我们设计完一个电路之后,我们都想将其进行仿真验证,在设计阶段就防止出现bug。但CDC通过RTL仿真是不能验证其正确性的,因为在RTL仿真当中,tool不会检查reg寄存器的setup/hold requirement,所以一定不会出现metastable现象。那么我们可以通过带delay的gate level后仿验证CDC电路的正确性吗?这种验证方法也是很难完整的验证CDC电路的。因为,第一,信号的翻转率可能不够。在同步电路的设计中,我们会将信号翻转,从“0”到“1”,从“1”到“0”,用于验证function的正确性。但在异步跨时钟域的电路中,我们不仅要验证function的正确,我们还要考虑在任意timing的条件下,这个CDC电路是否都正确完成指定的目标;第二,仿真时间不够长,没有把clk间的关系全部覆盖。跨时钟域电路的不同时钟源之间的关系是复杂的,比如时钟的频率、时钟的相位关系、时钟输入的latency等等。如果仿真时间不够长的话,clk间的关系没有覆盖完全,设计出来的电路也是有风险的;第三,在gate level后仿验证中,我们一般默认CDC电路会出现metastable现象,所以在第一级DFF的D pin上,我们不会进行timing check,即不会检查它的setup/hold requirement。如果DFF在cell library中的CK->Q延迟比较大,显示出来的最后Q pin输出了一个稳定的电平,我们也不能保证这个的电平是没有产生metastable现象的。
那么我们应该怎样保证CDC电路的正确性呢?第一,我们可以通过设计的电路结构保证,即grant by design;第二,通过工具检查CDC电路结构是否正确,比如:spyglass。这些工具会检查电路是否为同步电路,电路结构是否正确,是否在错误的位置放置了组合逻辑电路或时序逻辑电路。
跨时钟域电路的时序约束
在STA中,我们需要约束CDC电路的时序,保证综合过后的电路工作正常。首先在Timing约束中,我们可以不对第一级DFF D pin进行timing check,如上图在clk0到第一级DFF中的D pin线路中。因为我们设计CDC电路就是考虑到会出现Metastable现象并解决metastable现象,所以取消D pin的timing check。使用下面这行命令进行取消:
set_false_path -from clk0 -to clk1
对于一些高速电路(>=500MHz)设计,我们需要更加仔细的进行时序约束。
因为在真实电路中,会出现metastable现象,cell library中的第一级DFF CK->Q延迟时间会小于真实的CK->Q延迟时间。所以如上图所示,我们需要手动设计第一级DFF的Q pin到第二级DFF的D pin之间的最大延迟,set_maximal_delay。使用下面这行命令进行设置:
set_maximal_delay -from d_sync0 -to d_sync1 $dly_val
通常来说,$dly_val可以设置成clk1的0.4到0.5个时钟周期。