本章描述了静态时序分析中执行的检查。这些检查旨在彻底验证待分析设计的时序。
两个主要的检查为建立时间检查(setup check)和保持时间检查(hold check)。一旦触发器时钟引脚的时钟确定了,就会自动对触发器进行这两项检查。时序检查通常会在多种情况下进行,包括最坏-慢(worst case slow)情况以及最好-快(best case fast)情况。通常来说,慢情况对于建立时间检查更严苛,快情况对于保持时间检查更严苛。这章节的例子,都假设了网络延时(net delay)是0。这是为了简便起见,不会对之前解释的核心原理有影响。
目录
8.1 建立时间检查
建立时间检查检查触发器时钟引脚和数据引脚之间的时序关系,去满足特定的需求。换句话说,就是要保证在触发器锁存数据之前,数据已经准备好了。在边沿到来之前,数据需要保持稳定的一段时间就成为建立时间。下图展示了这个概念。
通常,存在一个 发射触发器(launch flip-flop)——负责发射数据的触发器,以及一个 捕获触发器(capture flip-flop)——负责捕获数据的触发器,捕获触发器的建立时间必须得到满足。建立时间检查(setup check)验证从发射触发器到捕获触发器的最长路径(或最大路径)。这两个触发器的时钟可以是相同的,也可以是不同的。建立时间检查,是从发射触发器的第一个有效边沿到捕获寄存器最近的一个有效边沿。这可以保证前一个时钟周期发送的数据,经过一个周期后,准备好了被捕获。
上图中的例子。发射触发器,捕获触发器,有着相同的时钟。CLKM时钟的第一个上升沿,在经过Tlaunch时间后,出现在发射寄存器UFF0的引脚上。由这个时钟边沿所发送的数据,在经过了Tlaunch+Tck2q+Tdp 的时间后,出现在捕获寄存器UFF1的D引脚处。这时钟的第二个上升沿,经过Tcycle+Tcapture之后,出现在捕获寄存器UFF1的引脚处。这两个表达式所表示的时间的差值,必须大于触发器的建立时间,这样才能保证捕获寄存器有效的捕捉到数据。可以如下表示:
- Tlaunch 是发射触发器 UFF0 时钟树的延迟。就是上图中的那个小三角形。
- Tdp 是组合逻辑数据路径的延迟。
- Tcycle 是时钟周期。
- Tcapture 是捕获触发器 UFF1 时钟树的延迟。也是图中的小三角。
因为这个建立时间检查设置了一个最大约束(max constraint),建立时间检查总是会使用时间最长的路径。所以,这个检查通常在慢工艺角(slow corner)进行,因为这个工作条件下延迟是最大的。
8.1.1 触发器到触发器的路径
这是一个时序检查的报告。
在这个报告中,发射触发器名为UFF0,并且被时钟CLKM的上升沿触发。捕获触发器名为UFF1,也是被CLKM的上升沿触发。
- PathGroup:表示它属于CLKM的路径组。设计中所有路径都会被分到不同的路径组,不同的路径组是由捕获寄存器时钟决定的。
- PathType:表示在这份报告中都是最大路径延时,也就表明了这是建立时间检查。这是因为建立时间检查,要查最大的延时。相反的,保持时间检查,就是要检查设计中的最小延时。
- Incr:显示了指定端口或引脚的单元或网络延迟增量。这指的是某个特定端口或引脚相对于前一个端口的延迟,通常是在时序分析中使用来表示电路或信号路径的延迟变化。
- Path:显示了数据实际到达和需要到达的路径累积延迟。它是指信号从源头(例如时钟源)到目标(例如接收端口)所经过的路径的总延迟。
create_clock -name CLKM -period 10 -waveform {0 5} \
[get_ports CLKM]
set_clock_uncertainty -setup 0.3 [all_clocks]
set_clock_transition -rise 0.2 [all_clocks]
set_clock_transition -fall 0.15 [all_clocks]
数据发射路径需要经过0.26ns的延时,才能到达UFF1触发器的D引脚,这是捕获触发器的输入的到达时间。捕获边沿(距离一个周期,因为这是建立时间检查)在10ns。这个时钟的不确定度指定为0.3ns,因此这个时钟的周期由于不确定度而减少了0.3ns。时钟的不确定度包括由于时钟源抖动引起的周期变化以及用于分析的任何其它时序裕量。触发器的建立时间被设为0.04ns(library setup time),从捕获路径中被减去,因此所需的时间变为了9.66ns。因为到达时间为0.26ns,所以在时序路径上有9.41ns的正裕量(positive slack)。所需到达时间和实际到达时间之差可能看起来是9.40ns,但是实际值是出现在报告中的9.41ns。之所以存在差异,是因为表中仅显示小数点后两位数字,而内部计算和存储的值比所报告的精度更高。
什么是时钟网络延时(clock network delay)以及为什么他有“理想(ideal)”的标签。说明了时钟树是理想的,任何时钟路径上的缓冲(buffer)都认为是0延时的。一旦时钟树建立了以后,时钟网络就会被标记为"传播(propagated)",此时时钟路径就会展示出真正的延时(下一个时序报告中显示出来了)。0.11ns的延时是发射时钟的时钟网络延时,0.12ns是捕获时钟的时钟网络延时。
时序路径报告可以有选择地包含扩充的时序路径,他们带有明确显示的时钟树。下面是例子。
注意·上面报告中的缓冲器UCKBUF0,UCKBUF1,UCKBUF2,提供了时钟树延迟是如何计算得到的。
第一个时钟单元UCKBUF0的延迟是如何计算得到的呢?就如前几个章节所说,单元的延时是基于输入转换时间以及输出电容来计算的。因此问题转化成,在时钟树中的第一个单元的输入,使用的是怎样的转换时间。这个转换时间可以直接用set_input_transition指令指定。
set_input_transition -rise 0.3 [get_ports CLKM]
set_input_transition -fall 0.45 [get_ports CLKM]
上面指定了输入的上升和下降的转换时间。如果没有明显的指定,那么就认为是理想压摆,转换时间为0.
后面跟的 r f 的字样的表示的是时钟信号或数据信号的上升沿(或下降沿)。先前的时序报告中,一条路径从UFF0/Q的下降沿开始,到UFF1/D的上升沿结束。由于UFF1/D不是0就是1,所以也可以在这个端口以下降沿结束。下面就是一个例子。
什么是时钟源延迟(clock source latency)。这也被称为插入延时(insertion delay),定义为时钟从源到时钟定义点传播所需要的时间。如下图所示,这与时钟树在设计之外的延迟相对应。例如,如果该设计是较大模块的一部分,则时钟源延迟是指直到待分析设计时钟引脚(在这里指的就是CLKM)为止的时钟树延迟。可以使用set_clock_latency进行指定。
set_clock_latency -source -rise 0.7 [get_clocks CLKM]
set_clock_latency -source -fall 0.65 [get_clocks CLKM]
如果没有这个指令的话,我们就认为延迟为0。这是早期路径报告中使用的假设。请注意,源延时并不会对设计内部的路径产生任何影响,并且它们具有相同的发起时钟和捕获时钟。这是因为,相同的延时,会同样加到发射时钟路径以及捕获时钟路径。(我的理解是,两者没有一个相对的延时,因为加的部分是一样的)。但是这个延时确实会影响那些经过待分析设计输入输出端口的路径。
如果没有source这个选项,set_clock_latency指令定义的就是网络延时(clock network latency)。这个延时定义为从时钟的定义点到触发器引脚所用的时间。他用于在建立时钟树之前(即在时钟树综合之前)对通过时钟路径的延迟进行建模。一旦建立了时钟树并标记为了“已传播”(propagated),便会忽略此时钟网络延迟约束。这个指令可以用于从主时钟到衍生时钟延时的建模,也可以用于片外时钟延时的建模(时钟产生逻辑不是设计的一部分)。
8.1.2 输入到触发器的路径
下面的时序报告:输入到触发器的路径,另有图片展示了原理图以及时钟波形。
input port clocked by VIRTUAL_CLKM:认为是假想的触发器,驱动输入端口的INA。这个假想触发器的时钟是VIRTUAL_CLKM。此外,从假想触发器的时钟引脚 到 INA引脚的最大延时被指定为2.55ns。这在报告中呈现为输入内部延时(input external delay)。都使用下面的SDC指令进行指定。
create_clock -name VIRTUAL_CLKM -period 10 -waveform {0 5}
set_input_delay -clock VIRTUAL_CLKM \
-max 2.55 [get_ports INA]
请注意,虚拟时钟 VIRTUAL_CLKM 的定义没有与设计中的任何引脚关联;这是因为它被认为是在设计外部定义的(即它是虚拟的)。输入延迟的指定语句,set_input_delay指定了有关于虚拟时钟的延迟。
输入路径从INA开始,如何计算与INA输入端口连接的第一个单元UINV1的延时呢?一种方法就是指定输入端口INA的驱动单元。有了驱动单元就有了驱动强度、压摆,然后就可以用来计算UINV1延时。在缺少对于INA输入端口任何有关于压摆的设定时,转换时间我们认为是理想的,也就是0ns。
set_driving_cell -lib_cell BUFF \
-library lib013lwc [get_ports INA]
上图也展示了建立时间检查是如何完成的。数据必须在9.85ns之前到达UFF2/D,但是数据很早地在2.65ns就到了,所以呈现出了7.2ns的裕度。
存在实际时钟的输入路径
输入到达时间也可以与实际时钟对应,并不必须与虚拟时钟对应。实际时钟的例子有:设计内部引脚的时钟,或输入端口。下图中在输入端口CIN上进行有关于CLKP时钟的约束。
set_input_delay -clock CLKP -max 4.3 [get_ports CIN]
下面是时序报告。
8.1.3 从触发器到输出路径
与之前描述的类似,一个输出端口,可以形成与虚拟时钟、设计内部时钟、输入时钟端口或者输出时钟端口有关的约束。这个例子展示了ROUT约束于一个虚拟时钟。
set_output_delay -clock VIRTUAL_CLKP \
-max 5.1 [get_ports ROUT]
set_load 0.02 [get_ports ROUT]
为了确定与输出端口所连接的最后一个单元,我们需要制定这个端口的负载。使用set_load这个指令去指定负载。我们需要注意有可能ROUT端口可能存在DUA内部的负载,而我们使用指令指定的负载是外部负载。如果没有写这个指定的语句,我们就假定外部负载为0,但是这不太可能,因为该设计很可能会用于其他设计当中。
输出延时以output external delay指定,表现为外部虚拟寄存器的建立时间。
8.1.4 输入到输出的路径
设计中,可能存在组合逻辑路径从输入端口直到输出端口。这个路径也可以被约束并且进行时序分析。我们使用了虚拟时钟对输入、输出端口进行时序约束。
set_input_delay -clock VIRTUAL_CLKM \
-max 3.6 [get_ports INB]
set_output_delay -clock VIRTUAL_CLKM \
-max 5.8 [get_ports POUT]
下面的时序报告,从输入端口INB到输出端口POUT。注意到如果存在任何的内部时钟延迟,对于路径时序报告没有任何影响。
8.1.5 频率直方图
如果绘制一个典型设计的建立时间余量(setup slack)与路径数量的频率直方图,它将像下图。根据设计的状态(无论是否已优化),对于未优化的设计,零余量线会偏向右侧,而对于已优化的设计,零余量线则会偏向左侧。对于没有时序违例的设计,也就是没有负余量的路径,整个曲线将位于零余量线的右侧。
下面的直方图以文本形式呈现,通常可以由静态时序分析工具得到。
前两个索引表示裕度范围,第三个索引表示在该裕度范围内的路径数量。例如,表示在 410ps 到 415ps 的余量范围内有 941 条路径。该直方图表明,这个设计没有失败的路径,也就是说所有路径的裕度都是正值,并且最关键的路径的裕度在 375ps 到 380ps 之间。
对于那些难以满足时序要求的设计,直方图的峰值会偏向左侧,也就是说,会有很多路径的余量接近零。通过观察频率直方图,还可以判断设计是否能进一步优化以达到零余量,即,判断满足时序的难度。如果失败路径的数量很小且负余量也很小,则表明该设计相对接近满足所需的时序。然而,如果失败路径的数量很大且负余量的幅度也很大,则意味着该设计需要付出大量的努力才能满足所需的时序要求。
8.2 保持时间检查
保持时间检查确保触发器改变中的输出值不会传递至捕获触发器,并在捕获触发器有机会捕获其原始值前重写(overwrite)。这项检查是基于触发器的捕获要求。它要求正在被锁存的数据,应该在时钟的有效边沿过去后,仍保持一段时间的稳定。见下图。
就像建立时间检查,保持时间检查是在发射触发器-捕获触发器两者之间进行的。两个触发器的时钟可以相同或不同。保持时间检查,是从发射触发器的时钟的一个有效边沿 到 捕获触发器的一个相同的时钟边沿。因此保持时间检查与周期无关。在捕获寄存器的每个有效时钟边沿都会进行保持时间检查。
考虑CLKM的第二个有效边沿。由时钟上升沿发起的数据经过 Tlaunch + Tck2q + Tdp 的时间到达捕获触发器的D引脚。相同的时钟边沿,经过了 Tcapture 的时间到达捕获触发器的时钟引脚。我们的目的是发射触发器的数据,被捕获触发器在下一个时钟周期被捕获。如果数据在相同的时钟周期被捕获,那么就会涉及重写的问题。保持时间检查,就是为了防止重写的问题。保持时间检查,保证两个时间(数据到达时间 & 时钟到达时间)之差,必须大于捕获触发器的保持时间。这样的话,就不会发生重写的问题。如下公式:
其中:
- Tlaunch:发射触发器时钟树的延迟。
- Tdp:组合逻辑数据路径的延迟。
- Tcapture:捕获触发器时钟树的延迟
保持时间检查,是对于到达捕获触发器路径的最短时间约束,也就是设置了下限。因此,保持时间检查总是检查最快的路径,或者是最短的路径。因此,保持时间检查总是在最快的时序工艺角下面进行。
有时候即使设计中只有一个时钟,时钟树也可能导致时钟到达发射触发器和捕获触发器的到达时间存在显著差异。为了保证数据被有效地捕获,捕获触发器的时钟边沿,必须在数据变化之前到达。保持时间时序检查可以保证:
- 当前数据发起时钟沿(Setup launch edge)的下一个(subsequent)时钟沿发起的数据不被当前数据捕获时钟沿(Setup receiving edge)所捕获;
- 当前数据发起时钟沿发起的数据不被当前数据捕获时钟沿的前一个捕获时钟沿(Preceding receiving edge)所捕获;
上面的两项检查是相同的(发射、捕获触发器在相同的时钟域)。但是,如果这两个时钟频率不同,或者在不同的时钟域。以上的两种情况就可能产生不同的约束。这种情况下,通常会报告最差的保持时间检查。
上图中,UFF0 是发射触发器,UFF1 是捕获触发器。下一个数据发起时钟沿(Subsequent launch edge)不能传播数据过快导致数据捕获时钟沿(Setup receiving edge)没有时间去可靠捕获数据。此外,数据发起时钟沿(Setup launch edge)也不能够传播数据太快导致前一数据捕获时钟沿(Preceding receiving edge)没有机会捕获其应当捕获的数据。最坏保持时间(worst hold check)对应的是最严格的保持时间检查。
后面将会讲到如何从建立时间检查中推断出保持时间检查。虽然建立时间违例会导致设计的工作频率降低,但保持时间违例会“杀死”(kill)设计,即设计在任何频率下都无法运行。
8.2.1 触发器到触发器的路径
使用下图的例子,进行了保持时间分析,并且得到了报告。
- PathType:min,意味着使用了单元所有最短路径的延时进行保持时间检查。
- library hold time:指定了UFF1的保持时间(之前也解释了,为什么保持时间可以是负值)
- rise edge: 发射、捕获触发器使用的都是上升沿。
时序报告显示, 数据到达,并且保证前一周期数据被安全捕获的时间为0.19ns。由于新的数据在0.33ns到的,所以有0.14ns的裕度。如下图可以看出。
保持时间裕度计算
在建立时间检查和保持时间检查中,裕度计算方法有不同。建立时间检查中,裕度是要求到达时间-实际到达时间;保持时间检查中,裕度是实际到达时间-要求到达时间。保持时间检查中,负裕度意味着满足了保持时间检查,正裕度意味着不满足。
8.2.2 输入到触发器的路径
输入端口上的最小延时使用,使用一个虚拟时钟来指定。
set_input_delay -clock VIRTUAL_CLKM \
-min 1.1 [get_ports INA]
下面是保持时间检查的报告:
set_input_delay 指令在报告中以 input external delay 的形式呈现。保持时间检查,在0时刻的 VIRTUAL_CLKM 上升沿与 CLKM 上升沿之间进行。最早的,数据可以到达UFF2的时间为0.25ns(不违背检查的前提下),然而数据在1.2ns才到达,所以有一个正裕度为0.95ns。
8.2.3 触发器到输出的路径
输出端口的最小延迟使用以下来指定。
set_output_delay -clock VIRTUAL_CLKP \
-min 2.5 [get_ports ROUT]
输出延迟的指定,关联了一个虚拟时钟,报告如下。
set_output_delay在报告中以output external delay的形式呈现。这里解释一下为什么Incr列为负数,因为是向回推的。
从触发器到输出的路径(存在真实时钟)
set_output_delay -clock CLKP -min 3.5 [get_ports QOUT]
set_load 0.55 [get_ports QOUT]
由上面的报告中可以看出有4.46ns的裕度。
8.2.4 输入到输出的路径
由INB到POUT,使用以下代码来指定:
set_load -pin_load 0.15 [get_ports POUT]
set_output_delay -clock VIRTUAL_CLKM \
-min 3.2 [get_ports POUT]
set_input_delay -clock VIRTUAL_CLKM \
-min 1.8 [get_ports INB]
set_input_transition 0.8 [get_ports INB]
在上面的时序报告中,经过1.8ns的外部延时,再经过0.32ns的内部延时,到达POUT的时候已经产生了2.12ns的延时,对于同一个时钟沿,输出外部延时为3.2ns,加上不确定度的因素,最早可以-3.15ns到达,但是数据2.12ns才到,所以有5ns多的裕度。
部分内容翻译自“Static Timing Analysis for Nanometer Designs A Practical Approach” 欢迎指正!