8.3 多周期路径
在某些情况下,两个触发器之间的数据路径可能需要一个以上的时钟周期才能传播通过逻辑。在这种情况下,这条组合逻辑路径会被定义为多周期路径(multicycle path)。虽然数据还是会在每个时钟沿上都被捕获触发器捕获,但我们需要告知 STA 在指定数量的时钟周期之后才会出现有效的捕获时钟沿。
图 8-14 是一个示例。由于数据路径最多需要三个时钟周期,因此应指定三个周期的多周期建立时间检查。为此需要指定如下的多周期建立时间约束:
图 8-14
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。
现在,我们来检查一下多周期路径上的保持时间检查。在最常见的情况下,我们希望保持时间检查保持不变(与单周期路径一致),如图 8-14 所示,这样可使数据在三个时钟周期之内任意进行改变。只有指定多周期保持时间为 2,才可以获得与单周期建立时间检查情况相同的保持时间检查。这是因为在没有这样的多周期保持时间约束的情况下,默认的保持时间检查是在建立时间捕获沿的前一个有效时钟沿上执行的,这显然不是我们希望的。
我们需要将执行保持时间检查的时钟沿移动到默认时钟沿之前的两个周期,因此指定了多周期保持时间为 2。预期的检查如图 8-15 所示,通过多周期保持时间约束,数据路径的最小延迟可以小于一个时钟周期。
图 8-15
- set_multicycle_path 2 -hold -from [get_pins UFF0/Q] -to [get_pins UFF1/D]
多周期保持时间约束命令中的周期数指定了从默认保持时间检查沿(建立时间捕获沿之前的一个有效沿)需要移回多少个时钟周期。以下是一份保持时间检查的路径报告:
由于此路径的多周期建立时间约束为 3,因此其默认保持时间检查是在建立时间捕获沿之前的有效时钟沿上执行的。在大多数设计中,如果最大路径(或建立时间)需要 N 个时钟周期,则大于(N-1)个时钟周期的最小路径约束是不可行的。通过指定两个周期的多周期保持时间约束,可以将保持时间检查时钟沿移回到数据发起沿处(即 0ns 处),如上面的路径报告中所示。
因此在大多数设计中,指定为 N(周期)的多周期建立时间约束应伴随着指定为 N-1(周期)的多周期保持时间约束。
如果指定了 N 个周期的多周期建立时间约束,但缺少了相应的 N-1 个周期的多周期保持时间约束,会发生什么情况呢?在这种情况下,会在建立时间捕获沿之前的一个周期时钟沿上执行保持时间检查。图 8-16 显示了仅约束多周期建立时间为 3 个周期时,进行这种保持时间检查的情况。
图 8-16
如图所示,这规定了数据只能在建立时间捕获沿之前的一个周期内进行改变。因此,数据路径必须具有至少两个时钟周期的最小延迟才能满足此要求。以下是这种情况的路径报告:
从路径报告中注意到,在捕获沿之前的一个时钟沿对保持时间进行了检查,这导致了较大的保持时间违例。实际上,该保持时间检查将要求组合逻辑中的最小延迟至少为两个时钟周期。
跨时钟域
让我们考虑在周期相同的两个不同时钟之间存在多周期路径的情况。(时钟周期也不同的情况将在本章后面进行介绍)
例子 1:
create_clock -name CLKM -period 10 -waveform {0 5} [get_ports CLKM]
create_clock -name CLKP -period 10 -waveform {0 5} [get_ports CLKP]
多周期建立时间约束指定了给定路径的时钟周期数,如图 8-17 所示。默认建立时间捕获沿总是与发起沿相隔一个时钟周期,约束多周期建立时间为 2 会使建立时间捕获沿与发起沿相隔 2 个时钟周期。
图 8-17
多周期保持时间约束指定了保持时间检查应该在建立时间捕获沿之前几个时钟周期的时钟沿处执行,无论建立时间发起沿在何处,如图 8-18 所示。默认的保持时间检查是在建立时间捕获沿之前一个周期的时钟沿处执行的。约束多周期保持时间为 1 会将保持时间检查放置于默认保持时间检查之前一个周期的时钟沿处,因此变为建立时间捕获沿之前两个周期的时钟沿处。
图 8-18
假设有如下多周期路径约束:
- set_multicycle_path 2 -from [get_pins UFF0/CK] -to [get_pins UFF3/D]
由于没有 -hold 选项,因此将默认为 -setup 选项。以上约束指定多周期建立时间为 2 且多周期保持时间为 0。对应建立时间检查的路径报告如下所示:
注意,路径报告中所打印出的路径组(Path Group)始终是捕获触发器的路径组,在这种情况下为 CLKP。
接下来是保持时间检查的路径报告。由于多周期保持时间约束默认为 0,因此将在建立时间捕获沿(20ns)之前一个时钟周期的 10ns 处进行保持时间检查。
以上报告报出了保持时间违例,这可以通过将多周期保持时间约束指定为 1 来消除,下面的另一个示例对此进行了说明。
例子 2:
set_multicycle_path 2 -from [get_pins UFF0/CK] -to [get_pins UFF3/D] -setup
set_multicycle_path 1 -from [get_pins UFF0/CK] -to [get_pins UFF3/D] -hold
以下是多周期建立时间约束为 2 时建立时间检查的路径报告:
以下是多周期保持时间约束为 1 时保持时间检查的路径报告:
请注意,本节中建立时间检查和保持时间检查的示例报告是针对同一工艺角(corner)的。通常,在最坏情况的慢速工艺角下,建立时间检查最难满足(裕量最小),而在最佳情况的快速工艺角下,保持时间检查最难满足(裕量最小)。
8.4 伪路径
当设计的功能运行时,某些时序路径可能不真实(或不可能)存在。在执行 STA 时可以将这些路径设置为伪路径(false path),这样就可以关闭这些路径,那么 STA 就不会对这些伪路径去进行分析了。
伪路径可能是从一个时钟域到另一个时钟域、从触发器的时钟引脚到另一触发器的输入引脚、通过一个单元的引脚、通过多个单元的引脚或这些情况的组合 。当通过单元的引脚指定了伪路径后,通过该引脚的所有路径都将被忽略,无需进行时序分析。辨别出伪路径的好处在于减少了分析空间,从而使分析可以专注于真实存在的路径,这同样有助于减少分析时间。但是,过多使用 -through 选项去指定伪路径同样会降低分析的速度。
可以使用 set_false_path 命令来约束伪路径,以下是一些例子:
set_false_path -from [get_clocks SCAN_CLK] -to [get_clocks CORE_CLK]
set_false_path -through [get_pins UMUX0/S]
set_false_path -through [get_pins SAD_CORE/RSTN]
set_false_path -to [get_ports TEST_REG*]
set_false_path -through UINV/Z -through UAND0/Z
下面给出了一些关于设置伪路径的建议。要在两个时钟域之间设置伪路径,请使用:
- set_false_path -from [get_clocks clockA] -to [get_clocks clockB]
而不要使用:
- set_false_path -from [get_pins {regA_ * }/CK] -to [get_pins {regB_ * }/D]
后者这种方式要慢得多。
另一个建议是尽可能少使用 -through 选项,因为它增加了运行时不必要的复杂性。仅在绝对有必要且没有替代方法可以指定该伪路径的情况下,才可以使用 -through 选项。
从优化的角度来看,还有一个建议是不要将一条多周期路径约束为伪路径。如果需要在已知或可预测的时刻对信号进行采样,则无论时间间隔多大,都应使用多周期路径约束,以使路径具有一定的约束条件并进行优化以满足多周期约束。如果把一条许多时钟周期后进行采样的路径指定为了伪路径,则对设计中其余逻辑路径的优化可能会使该路径变长,甚至超出所需的时间。
8.5 半周期路径
如果设计中同时具有负边沿触发的触发器(有效时钟沿为下降沿)和正边沿触发的触发器(有效时钟沿为上升沿),则设计中可能存在半周期路径(half-cycle path)。半周期路径可能是从一个触发器的上升沿到另一个触发器的下降沿,或者反过来。图 8-19 给出了一个示例,其中数据的发起沿在触发器 UFF5 的时钟下降沿,而数据的捕获沿在触发器 UFF3 的时钟上升沿。
图 8-19
以下是建立时间检查的路径报告:
请注意起点(Startpoint)和终点(Endpoint)中的边沿说明。时钟 CLKP 的下降沿出现在 6ns,上升沿出现在 12ns。因此,数据需要在半个周期 6ns 内到达捕获触发器的输入引脚。
虽然在建立时间检查时数据路径仅有半个时钟周期,但额外的半个周期可用于保持时间检查。以下是保持时间检查的路径报告:
保持时间检查通常是在捕获沿之前一个周期的捕获沿上执行的。由于捕获沿是在 12ns 处,因此前一个捕获沿在 0ns 处,故将在 0ns 处检查保持时间。这为保持时间检查有效地增加了半个时钟周期的裕量,因此可以看见保持时间检查有较大的正裕量(slack)。
8.6 撤销时间检查
撤销时间检查(removal timing check)可确保在有效时钟沿与释放异步控制信号之间有足够的时间。该检查可确保有效时钟沿不带来影响,因为异步控制信号将保持有效状态,直到有效时钟沿之后一段撤销时间为止。换句话说,异步控制信号会在有效时钟沿之后被释放(变为无效),因此该时钟沿不会产生任何影响,如图 8-20 所示。该检查基于的是触发器异步引脚上指定的撤销时间。以下是单元库中与撤销时间检查有关的描述片段:
图 8-20
与保持时间检查一样,该检查也是针对最小路径的,不过是在触发器的异步引脚上。
终点(Endpoint)表明这是撤销时间检查,且在触发器 UFF6 的异步引脚 CDN 上。该触发器的撤销时间在报告中显示为 library removal time,值为 0.19ns。
所有异步时序检查均被分配给了 async_default 路径组。
8.7 恢复时间检查
恢复时间检查(recovery timing check)可确保异步信号变为无效状态的时刻与下一个有效时钟沿之间的时间间隔大于一个最小值。换句话说,此检查可确保在异步信号变为无效状态之后,有足够的时间恢复,以便下一个有效时钟沿可以生效。例如,考虑从异步复位变为无效的时刻到触发器有效时钟沿之间的时间间隔。如果该时间间隔太短即有效时钟沿在复位释放后太早出现,则触发器可能进入未知的状态。恢复时间检查如图 8-21 所示。该检查基于的是触发器异步引脚上指定的恢复时间,单元库文件中与恢复时间有关的描述片段如下:
图 8-21
与建立时间检查一样,该检查也是针对最大路径的,不过是在触发器的异步引脚上。
以下是一份恢复时间检查的路径报告:
终点(Endpoint)表明这是恢复时间检查,并且触发器 UFF6 的恢复时间在报告中显示为 library recovery time,值为 0.09ns。恢复时间检查也属于 async_default 路径组。
8.8 跨时钟域的时序
8.8.1 慢速时钟域到快速时钟域
让我们来对一条从慢速时钟域到快速时钟域的路径来进行建立时间与保持时间检查,如图 8-22 所示。
图 8-22
这是以上示例的时钟定义:
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]
当数据发起触发器和捕获触发器的时钟频率不同时,STA 会首先确定一个公共基本周期(common base period)。下面给出了在具有上述两个时钟的设计中执行 STA 时打印出的信息。较快的时钟会被延拓,以便获得一个公共周期。
图 8-23
图 8-23 中为建立时间检查。默认情况下,将使用最严格的建立时间边沿去检查,在本例中为 5ns 处的时钟沿。以下是此时建立时间检查的路径报告:
请注意,发起时钟沿为 0ns,而捕获时钟沿为 5ns。
如前所述,保持时间检查与建立时间检查有关,并确保由当前时钟沿发起的数据不会干扰先前数据的捕获。这是保持时间检查的报告:
在上面的示例中,我们可以看到发起的数据在捕获时钟的第四个周期可用。让我们假设该设计的目的不是在 CLKP 的下一个有效沿上就捕获数据,而是在每第 4 个捕获沿上捕获数据。该假设给触发器之间的组合逻辑路径提供了 4 个 CLKP 周期的时间,即 20ns。我们可以通过设置以下多周期路径约束来做到这一点:
- set_multicycle_path 4 -setup -from [get_clocks CLKM] -to [get_clocks CLKP] -end
图 8-24
-end 选项指定了多周期 4 是用于终点(endpoint)或捕获时钟的。此多周期路径约束将建立时间和保持时间检查更改为了图 8-24 中所示。以下是这种情况下建立时间检查的路径报告:
上图 8-24 中也说明了保持时间检查,请注意,保持时间检查是根据建立时间检查而决定的,默认为当前数据捕获沿之前的一个周期。以下是保持时间检查的路径报告。注意,保持时间捕获沿为 15ns,比建立时间捕获沿(20ns)早一个周期(5ns)。
在大多数设计中,这不是理想的时序检查,应将保持时间检查一直移回到数据发起沿所在位置。因此,我们可以约束多周期保持时间为 3。
- set_multicycle_path 3 -hold -from [get_clocks CLKM] -to [get_clocks CLKP] -end
3 是指将保持时间检查沿向后移三个 CLKP 时钟周期,即 0ns 时刻处。与多周期建立时间约束的区别在于:在多周期建立时间约束中,建立时间捕获沿会从默认的建立时间捕获沿向前移动指定的周期数;而在多周期保持时间约束中,保持时间检查沿会从默认的保持时间检查沿向后移动指定的周期数。-end 选项意味着我们想将终点(或捕获边沿)移回指定的周期数,即捕获时钟的周期数。代替 -end 的另一种选项 -start 指定了要移动的发起时钟周期数,-end 选项指定了要移动的捕获时钟周期数。-end 是多周期建立时间约束的默认值,-start 是多周期保持时间约束的默认值。
图 8-25
使用多周期保持时间约束,可以将保持时间检查的时钟沿往回移,检查效果如图 8-25 所示。具有多周期保持时间约束的保持时间检查路径报告如下:
总之,如果指定了 N 个周期的多周期建立时间,那么很可能还应指定 N-1 个周期的多周期保持时间。对于慢速到快速时钟域之间的路径,多周期路径约束的一个好经验是使用 -end 选项。使用此选项,可以根据快速时钟的时钟周期来调整建立时间和保持时间检查。
8.8.2 快速时钟域到慢速时钟域
在本小节中,我们考虑数据路径从快速时钟域到慢速时钟域的示例。使用以下时钟定义时,默认的建立时间和保持时间检查如图 8-26 所示。
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]
图 8-26
总共可能有四种建立时间检查,请参阅图 8-26 中的 Setup1,Setup2,Setup3 和 Setup4。其中,最严格的是 Setup4 检查。以下是此最严格检查的路径报告。请注意,数据发起时钟沿为 15ns,捕获时钟沿为 20ns。
与建立时间检查类似,总共也可能有四种保持时间检查。图 8-26 中所示为最严格的保持时间检查,该检查可确保 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
在这种情况下,图 8-27 中为用于建立时间和保持时间检查的时钟沿。-start 选项指定周期数的单位(在这种情况下为 2)是发起时钟周期(在这种情况下为 CLKP)。约束多周期建立时间为 2 会将发起沿移动到默认发起沿之前的一个时钟沿,即在 10ns 而不是默认的 15ns 处。多周期保持时间约束确保了在 0ns 处发起沿发起的数据,不会被 0ns 处的捕获沿捕获到。
图 8-27
以下是建立时间检查的路径报告。与预期一样,发起时钟沿为 10ns,捕获时钟沿为 20ns。
以下是保持时间检查的路径报告。保持时间检查是在 0ns 处执行的,此时捕获时钟和发起时钟均为上升沿。
与从慢速时钟域到快速时钟域的路径不同,在从快速时钟域到慢速时钟域的路径中,多周期路径约束的一个好经验是使用 -start 选项,然后再根据快速时钟调整建立时间和保持时间检查。