前一篇文章:STA 静态时序分析 第八章——时序检查(1)
目录
8.3 多周期路径
某些情况下,两个触发器之间的组合逻辑路径需要多于一个时钟周期来传播,这就是多周期路径。即使捕获寄存器的在每个有效时钟边沿都捕获了数据,但是我们仍需告诉STA在特定数目的周期才会出现有效(相关)的时钟边沿。
下图中例子,数据路径需要3个时钟周期才能传播,建立时间多周期检查,应当被指定为3周期。多周期建立时间约束,如下所示。
create_clock -name CLKM -period 10 [get_ports CLKM]
set_multicycle_path 3 -setup \
-from [get_pins UFF0/Q] \
-to [get_pins UFF1/D]
"设置多周期约束"指定了从 UFF0/CK 到 UFF1/D 的路径完成需要最多三个时钟周期。这意味着设计每隔三周期才会使用来自 UFF1/Q 的数据,而不是每个周期都使用。
报告中的30ns意味着,三个周期才会使用一次数据。不要将其想象为流水线,中间不是分阶段的。
下面进行保持时间检查。 在大多数情况下,我们想让他如同在单周期路径中一样去检查他,就像上面的电路图所示。这样可以保证数据在三个时钟周期的时间里可以自由改变。只有指定多周期保持时间为2,才可以获得与单周期建立时间检查情况相同的保持时间检查。这是因为若没有这个多周期保持时间的设定,默认的保持时间检查将在建立时间检查有效边沿前一周期的有效沿处进行,这不是我们想要的。需要将保持时间检查移动至默认保持时间检查沿的前两个时钟周期,因此多周期保持时间指定为2。预想的行为如下图所示。有了多周期保持时间,数据路径的最小延迟可以比一个时钟周期更短。
set_multicycle_path 2 -hold -from [get_pins UFF0/Q] \
-to [get_pins UFF1/D]
多周期保持(multicycle hold)中标示的周期数指定了从默认的保持检查边缘(即在设置捕获边缘之前的一个有效边缘)向回推移多少个时钟周期。以下是路径报告。
在这个时序报告中,注意到保持时间检查在捕获沿的前一有效时钟沿进行,导致了很大的违例。实际上,保持时间检查要求组合逻辑电路的时延要在两个时钟周期及以上。
时钟域的交叉
如果存在周期相同的两个时钟之间的多周期路径。
create_clock -name CLKM \
-period 10 -waveform {0 5} [get_ports CLKM]
create_clock -name CLKP \
-period 10 -waveform {0 5} [get_ports CLKP]
setup multicycle multiplier 代表了对于一条给定的路径上的时钟周期数。
hold multicycle multiplier 代表了在建立捕获有效沿之前的时钟周期数,此时不管发射的有效边沿。默认的边沿总是在捕获沿的前一个,如果设置为1,就将默认边沿前推一个周期,因此就会领先捕获有效沿两个周期,如下图所示。
下面是建立时间检查所对应的时序报告。
PathGroup中指定的时钟,永远是捕获触发器所使用的时钟,也就是CLKP。
下面是保持时间检查的报告,由于指定的值为0,所以保持时间检查,在捕获有效边沿的前一个周期处进行。
上面的报告中展示了,出现了违例,这可以通过设置保持多周期的值为 1 来避免。
另一个例子
下面是跨时钟域的多周期路径的另一个例子,在这里显式地指出了建立时间多周期为2,保持时间多周期为1。
保持时间检查的时序报告
下面是保持时间检查的时序报告
可以注意到上一个保持时间检查的报告中,CLKP的Incr列为10.00,这是因为默认只向前推了一个时钟周期,但是再推一个时钟周期之后(也就是显式指定 1 的代码),相对于建立时钟边沿就没有延迟了,所以为0。注意:这个小节中的检查都使用的是同一个工艺角,但我们建立时间检查通常用延时最大的工艺角;保持时间检查通常用延时最小的工艺角。
8.4 伪路径
设计中的有些时序路径不是真实存在的。这些路径可以通过设置为伪路径从而在STA期间关闭。这样STA就可以忽略它。
虚假路径的示例包括从一个时钟域到另一个时钟域、从触发器的时钟引脚到另一个触发器的输入、通过一个单元的引脚、通过多个单元的引脚,或者这些情况的组合。当通过一个单元的引脚指定虚假路径时,所有经过该引脚的路径都会被忽略,进行时序分析时不考虑它们。指定虚假路径的好处在于,它可以减少分析的空间,从而使分析只集中在真实路径上。这有助于缩短分析时间。然而,使用through 选项方式标记过多虚假路径可能会导致分析速度变慢。
set_false_path -from [get_clocks SCAN_CLK] \
-to [get_clocks CORE_CLK]
# Any path starting from the SCAN_CLK domain to the
# CORE_CLK domain is a false path.
set_false_path -through [get_pins UMUX0/S]
# Any path going through this pin is false.
set_false_path \
-through [get_pins SAD_CORE/RSTN]]
# The false path specifications can also be specified to,
# through, or from a module pin instance.
set_false_path -to [get_ports TEST_REG*]
# All paths that end in port named TEST_REG* are false paths.
set_false_path -through UINV/Z -through UAND0/Z
# Any path that goes through both of these pins
# in this order is false.
推荐的使用方法如下
set_false_path -from [get_clocks clockA] \
-to [get_clocks clockB]
不要使用:
set_false_path -from [get_pins {regA_*}/CP] \
-to [get_pins {regB_*}/D]
第二个方法会更慢。另一个推荐的方法就是尽量少使用带有through选项的语句,只有当必须使用through的时候,再去用它。
从优化的角度分析,我们另外推荐,不要将多周期路径设置为伪路径。如果一个信号在已知或可预测的时间被采样,无论这个时间间隔有多长,都应该使用多周期路径规范(multicycle path specification),这样该路径会有一些约束,并且会经过优化以满足多周期约束。如果在一个信号被采样的多个时钟周期后使用虚假路径,则剩余逻辑的优化可能会不可避免地减慢该路径,甚至可能会超过实际所需的优化程度。
设置成伪路径说明该路径真的不存在,时序分析中永远不会考虑了。设置成多周期,时序报告中仍会进行分析。
8.5 半周期路径
如果在一个设计中,存在上升沿触发的触发器,也存在下降沿触发的触发器,那么很有可能在这个设计中,存在半周期路径。一个半周期路径可以是从一个上升沿触发的触发器到一个下降沿触发的触发器,反之亦然。下图中的例子,发射触发器,在下降边沿触发;捕获触发器,在上升边沿触发。
下面是时序报告
在上面的例子中,下降沿在6ns,上升沿在12ns。所以数据只有6ns的时间从发射触发器传播到捕获触发器。然而在建立时间检查中,虽然数据只有半个周期的时间可以用来传播;但是在保持时间检查中,会有多出来的半个周期可用。下面是保持时间检查的时序报告:
保持时间检查总是在捕获边沿的前一个周期进行。因为捕获时钟边沿只在12ns的时候发生,前一个边沿是0ns,因此会在0ns处进行保持时间检查,这会导致出现将近半个周期的裕度。
8.6 移除(撤销)时间检查
撤销时间检查保证在时钟有效边沿和释放异步控制信号之间有足够的时间。这项检查保证时钟的有效边沿没有影响,因为异步控制信号将会一直保持有效直到有效边沿过后一段时间为止。另,异步控制信号在时钟的有效边沿过去后,才会是非活跃状态。所以时钟的有效边沿不会带来影响。下面是单元库中对于撤销时间检查的一段描述代码:
pin(CDN) {
. . .
timing() {
related_pin : "CK";
timing_type : removal_rising;
. . .
}
}
和保持时间检查一样,撤销时间检查也是最小时序路径检查,唯一不同是在触发器的异步引脚上进行。
Endpoint 终点选项显示出来他是一个撤销时间检查,它是在UFF6触发器的异步引脚CDN。所有的异步时序检查,时序组都是async default。
library removal time 可以理解为hold检查的变形,因为是数据的最早变化时间。希望数据改变的越晚越好,所以在时序报告中,是加上了0.19ns的库撤销时间。
8.7 恢复时间检查
恢复时间检查保证,在失效的异步控制信号,和下一个有效时钟边沿之间有最短的时间。另一句话来说,这项检查保证,异步控制信号不活跃后,有着充足的时间去恢复,从而下个时钟边沿可以变为有效的。举例来说,考虑异步复位信号失效,以及触发器的有效时钟边沿。如果在异步复位信号失效后,很快就来了时钟的有效边沿,触发器的状态很可能是未知。
pin(RSN) {
. . .
timing() {
related_pin : "CK";
timing_type : recovery_rising;
. . .
}
}
就像建立时间检查一样,这个检查最大延时检查。唯一的不同就是检查的是异步信号。
从Endpoint 终点可以看出,这是一个恢复时间检查。恢复时间检查同样也属于async default 路径组。
8.8 跨时钟域的时序问题
8.8.1 慢-快时钟域
当有一条路径从慢时钟域开始,结束于快时钟域,我们来进行建立时间检查以及保持时间检查。
该例子的时钟定义的代码为
create_clock -name CLKM \
-period 20 -waveform {0 10} [get_ports CLKM]
create_clock -name CLKP \
-period 5 -waveform {0 2.5} [get_ports CLKP]
很明显,CLKM周期大,速度慢;CLKP周期小,速度快。这时候STA将会找到一个共同的基础周期。更快的时钟,周期将会被扩大,从而获得一个公共基本周期(common base period)。
Expanding clock 'CLKP' to base period of 20.00 (old period was 5.00, added 6 edges).
默认来说,使用的是最严格的建立边沿关系。也就是说,将会在下一个捕获边沿,进行建立时间检查。
注意到,发射时钟在0ns,而捕获时钟在5ns。
就像之前讨论的,保持时间检查与建立时间检查相关。保证时钟边沿发送的数据,不会影响之前的捕获。下面是保持时间检查的时序报告。
前面的例子中可以看出,发射的数据,在捕获时钟,每四个周期有效一次。我们可以设想,不在每个CLKP的时钟边沿捕获数据而是在每四个时钟边沿捕获一次数据。这个假设将会给到两个触发器间的组合逻辑四个周期去传播。
set_multicycle_path 4 -setup \
-from [get_clocks CLKM] -to [get_clocks CLKP] -end
-end 选项指定了多周期4指向的是终止点或捕获时钟。该多周期路径约束改变了建立时间和保持时间检查为下图。以下是建立时间检查时序报告。
上面的波形图,同样也展示了保持时间的检查。要注意保持时间的检查边沿,在捕获有效边沿的前一个周期,对应的时间也就是15ns。
保持时间检查在15ns进行的后果就是数据到来的太早,造成严重的违例。因此我们需要设置如下代码,将保持时间检查进行的边沿,挪至发射时钟的边沿进行检查。
set_multicycle_path 3 -hold \
-from [get_clocks CLKM] -to [get_clocks CLKP] -end
这样将保持时间检查的捕获沿向前移动了三个周期到了0ns处。与多周期建立时间的不同之处是,在建立时间检查中其捕获沿向时间轴右移动指定数目的周期时间,而在保持时间检查中其捕获沿向时间轴左移动指定数目的周期时间(从建立时间检查捕获沿的前一周期开始)。-end选项意味着我们想将终点(或捕获边沿)移回指定的周期数,即捕获时钟的周期数。代替-end的另一种选项-start指定了要移动的发起时钟周期数,-end选项指定了要移动的捕获时钟周期数。-end是多周期建立时间约束的默认值,-start是多周期保持时间约束的默认值。
通过如上代码的指定,可以得到下图。
总的来说,如果指定了一个建立多周期为N,则保持多周期应指定为N-1.非常建议使用-end选项,使用这个指令,保持时间和建立时间将会依照更快的那个时钟进行调整。
8.8.2 快-慢时钟域
现在我们考虑一条从快时钟域开始,结束于慢时钟域的路径。默认的建立、保持时间检查如下图所示。并且使用了如下的时钟定义。
create_clock -name CLKM \
-period 20 -waveform {0 10} [get_ports CLKM]
create_clock -name CLKP \
-period 5 -waveform {0 2.5} [get_ports CLKP]
这里有四个可能进行的建立时间检查,但是,条件最严格的一个是setup4这个建立时间检查。下面是针对于setup4的路径时序报告。注意到发射时钟边沿在15ns而捕获时钟边沿是在20ns。
与建立时间检查类似,这里有四个可能得保持时间检查,下面的时序报告是针对于0ns的捕获边沿的,从而保证其不会捕获在0ns发射的数据,报告如下。
总的来说,一个设计者,可能会指定一个从快时钟域到慢时钟域的数据路径为多周期路径,如果将数据路径的建立时间检查放松到对于快速时钟域的两个时钟周期,以下指定将包含在多周期路径的设置当中:
set_multicycle_path 2 -setup \
-from [get_clocks CLKP] -to [get_clocks CLKM] -start
set_multicycle_path 1 -hold \
-from [get_clocks CLKP] -to [get_clocks CLKM] -start
# The -start option refers to the launch clock and is the default for a multicycle hold.
上图中展示了建立时间检查、保持时间检查所使用的边沿。-start 选项指定了周期数量的单位是发射时钟的周期,也就是CLKP。建立时间多周期为2,也就是将发射边沿从默认的发射边沿向前移动了一个周期,也就是在10ns的位置而不是在15ns的位置。保持时间多周期保证0ns的捕获边沿,只会捕获先前周期的数据,而不会捕获在0ns发射的数据。
下面是建立时间的时序报告:
接下来的是保持时间检查报告,在0ns处进行保持时间检查,这里捕获时钟、发射时钟都有上升沿。
不同于第一小节中讲到的从慢时钟域到快时钟域, 在快时钟域到慢时钟域的情况下,更推荐使用-start选项。此时建立检查、保持检查都是基于快的时钟。
部分内容翻译自“Static Timing Analysis for Nanometer Designs A Practical Approach” 欢迎指正!