《静态时序分析实用方法》第七章翻译

第 7 章 配置 STA 环境(Configuring the STA Environment)

第 7 章是后续章节的先决条件。它描述了如何配置时序分析环境。第 7 章描述了指定时钟、IO 特性、伪路径和多周期路径的方法。

        本章节描述了如何为静态时序分析建立环境。正确约束的说明对于分析STA结果非常重要。应准确指定设计环境,以便STA分析能够识别设计中的所有时序问题。STA的准备包括设置时钟、指定IO定时特性以及指定伪路径和多周期路径。在继续下一章关于时间验证之前,彻底理解本章非常重要。  

7.1 什么是STA环境?(What is the STA Environment?)

        大多数数字设计都是同步的,从上一个时钟周期计算的数据锁存在活动时钟边缘的触发器中。考虑图7-1所示的典型同步设计,假设分析设计(DUA)与其他同步设计相互作用。这意味着DUA从时钟触发器接收数据,并将数据输出到DUA外部的另一个时钟触发器。

        要在此设计上执行STA,需要指定触发器的时钟,以及通向设计的所有路径和退出设计的所有路径的时序约束。 

         图7-1中的示例假设只有一个时钟,C1、C2、C3、C4和C5表示组合块。组合块C1和C5不在所分析的设计范围内。

        在典型设计中,从一个时钟域到另一个时钟域可以有多个时钟,具有多条路径。以下各节介绍如何在此类场景中指定环境。 

7.2 指定时钟(Specifying Clocks)

        要定义时钟,我们需要提供以下信息:

  • 时钟源(Clock source):它可以是设计的端口,也可以是设计内部单元的引脚(通常是时钟生成逻辑的一部分)。
  • 周期(Period):时钟的周期。
  • 占空比(Duty cycle):高电平持续时间(正相位)和低电平持续时间(负相位)。
  • 边沿时间(Edge times):上升沿和下降沿的时刻。

         图7-2显示了基本定义。通过定义时钟,所有内部时序路径(所有触发器到触发器路径)都受到约束;这意味着所有内部路径都可以仅使用时钟规格进行分析。时钟规范规定触发器到触发器的路径必须占用一个周期。我们将在后面描述如何放宽这一要求(一个周期时间)。

        以下是一个基本的时钟约束规范:

create_clock \
-name SYSCLK \
-period 20 \
-waveform {0 5} \
[get_ports2SCLK]

         时钟的名称为SYSCLK,在端口SCLK处定义。SYSCLK的周期指定为20个单位-如果未指定,则默认时间单位为纳秒(通常,时间单位指定为技术库的一部分。)波形中的第一个参数指定上升沿出现的时间,第二个参数指定下降沿出现的时间。

       waveform选项中可以指定任意数量的边。但是,所有边缘必须在一个周期内。沿时间从时间零点后的第一个上升沿开始交替,然后是下降沿,然后是上升沿,依此类推。这意味着waveform列表中的所有时间值必须是单调递增的。

-waveform {time_rise time_fall time_rise time_fall ...}

        此外,必须指定偶数条边。 waveform选项指定一个时钟周期内的波形,然后该时钟周期自身重复。 

        如果未指定waveform选项,默认值为:

-waveform {0, period/2}

        这里是一个没有波形规范的时钟规范示例(见图7-3)。 

create_clock -period 5 [get_ports SCAN_CLK]

        在此约束中,由于未指定-name选项,因此时钟的名称与端口的名称相同,即SCAN_CLK。 

        以下是时钟约束的另一个示例,其中波形的边沿在一个周期的中间位置(见图7-4)。 

create_clock -name BDYCLK -period 15 \
-waveform {5 12} [get_ports GBLCLK]

         时钟的名称为BDYCLK,在端口GBLCLK处定义。实际上,保持时钟名称与端口名称相同是一个好主意。

 这里有更多的时钟约束示例。

# See Figure 7-5(a):
create_clock -period 10 -waveform {5 10} [get_ports FCLK]
# Creates a clock with the rising edge at 5ns and the
# falling edge at 10ns.
# See Figure 7-5(b):
create_clock -period 125 \
-waveform {100 150} [get_ports ARMCLK]
# Since the first edge has to be rising edge,
# the edge at 100ns is specified first and then the
# falling edge at 150ns is specified. The falling edge
# at 25ns is automatically inferred.

# See Figure 7-6(a):
create_clock -period 1.0 -waveform {0.5 1.375} MAIN_CLK
# The first rising edge and the next falling edge
# is specified. Falling edge at 0.375ns is inferred
# automatically.
# See Figure 7-6(b):
create_clock -period 1.2 -waveform {0.3 0.4 0.8 1.0} JTAG_CLK
# Indicates a rising edge at 300ps, a falling edge at 400ps,
# a rising edge at 800ps and a falling edge at 1ns, and this
# pattern is repeated every 1.2ns.
create_clock -period 1.27 \
-waveform {0 0.635} [get_ports clk_core]
create_clock -name TEST_CLK -period 17 \
-waveform {0 8.5} -add [get_ports {ip_io_clk[0]}]
# The -add option allows more than one clock
# specification to be defined at a port.

锁相环PLL(Phase-locked loop):在专用集成电路中常用来产生高频时钟 。

         除上述属性外,还可以选择指定时钟源处的转换时间。在某些情况下,例如某些PLL模型的输出或输入端口,该工具无法自动计算过渡时间。在这种情况下,明确指定时钟源处的转换时间非常有用。这是使用set_clock_transition命令指定的。

set_clock_transition -rise 0.1 [get_clocks CLK_CONFIG]
set_clock_transition -fall 0.12 [get_clocks CLK_CONFIG]

        这个约束仅适用于理想时钟,一旦构建了时钟树就将其忽略,因为此时将会使用时钟引脚上的实际过渡时间。如果在输入端口上定义了时钟,也可以使用set_input_transition命令(参见7.7节)来约束时钟的转换。 

7.2.1 时钟不确定性(Clock Uncertainty)

        可以使用 set_clock_uncertainty 约束指定时钟周期的时序不确定性。不确定性可用于模拟可以减少有效时钟周期的各种因素。这些因素可以是时钟抖动和任何其他可能希望用于时序分析的悲观因素。

set_clock_uncertainty -setup 0.2 [get_clocks CLK_CONFIG]
set_clock_uncertainty -hold 0.05 [get_clocks CLK_CONFIG]

         注意,建立时间检查的时钟不确定度将减少可用的有效时钟周期,如图7-7所示。对于保持时间检查,时钟不确定度将用作需要满足的额外时序裕量。

         以下命令可用于指定跨时钟边界路径上的时钟不确定度,称为时钟间不确定度(inter-clock uncertainty)。

set_clock_uncertainty -from VIRTUAL_SYS_CLK -to SYS_CLK \
-hold 0.05
set_clock_uncertainty -from VIRTUAL_SYS_CLK -to SYS_CLK \
-setup 0.3
set_clock_uncertainty -from SYS_CLK -to CFG_CLK -hold 0.05
set_clock_uncertainty -from SYS_CLK -to CFG_CLK -setup 0.1

         图 7-8 显示了两个不同时钟域 SYS_CLK 和 CFG_CLK 之间的路径。根据上述时钟间不确定性约束,100ps 用作建立时间检查的不确定性,50ps 用作保持时间检查的不确定性。

7.2.2 时钟延迟(Clock Latency)

         可以使用set_clock_latency命令指定时钟的延迟。

# Rise clock latency on MAIN_CLK is 1.8ns:
set_clock_latency 1.8 -rise [get_clocks MAIN_CLK]
# Fall clock latency on all clocks is 2.1ns:
set_clock_latency 2.1 -fall [all_clocks]
# The -rise, -fall refer to the edge at the clock pin of a
# flip-flop.

         时钟延迟有两种类型:网络延迟(network latency)和源延迟(source latency)。网络延迟是从时钟定义点 (create_clock) 到触发器时钟引脚的延迟。源延迟,也称为插入延迟(insertion delay),是从时钟源到时钟定义点的延迟。源延迟可以代表片上或片外延迟。图 7-9 显示了这两种情况。触发器时钟引脚的总时钟延迟是源延迟和网络延迟的总和。

        下面是一些指定源和网络延迟的示例命令。 

# Specify a network latency (no -source option) of 0.8ns for
# rise, fall, max and min:
set_clock_latency 0.8 [get_clocks CLK_CONFIG]
# Specify a source latency:
set_clock_latency 1.9 -source [get_clocks SYS_CLK]
# Specify a min source latency:
set_clock_latency 0.851 -source -min [get_clocks CFG_CLK]
# Specify a max source latency:
set_clock_latency 1.322 -source -max [get_clocks CFG_CLK]

         源延迟和网络延迟之间的一个重要区别是:一旦为设计建立了时钟树,就可以忽略网络延迟(假设指定了set_propagated_clock命令)。但是,即使在建立时钟树之后,源延迟也会保留。网络延迟是在进行时钟树综合(Clock Tree Synthesis)之前对时钟树延迟的估计值。在时钟树综合完成后,从时钟源到触发器时钟引脚的总时钟延迟是源延迟加上时钟树从时钟定义点到触发器的实际延迟。

         生成时钟在下一节中描述,虚拟时钟在 7.9 节中描述。

7.3 生成时钟(Generated Clocks)

         生成时钟是从主时钟派生的时钟。主时钟是使用 create_clock 命令定义的时钟。

         在基于主时钟的设计中生成新时钟时,可以将新时钟定义为生成时钟。例如,如果时钟有一个 3 分频电路,则可以在该电路的输出端定义一个生成时钟。这个定义是必需的,因为 STA 不知道分频逻辑输出端的时钟周期已经改变,更重要的是新的时钟周期是什么。图 7-10 显示了生成时钟的示例,该时钟是主时钟 CLKP 的 2 分频。   

create_clock -name CLKP 10 [get_pins UPLL0/CLKOUT]
# Create a master clock with name CLKP of period 10ns
# with 50% duty cycle at the CLKOUT pin of the PLL.

create_generated_clock -name CLKPDIV2 -source UPLL0/CLKOUT \
-divide_by 2 [get_pins UFF0/Q]

# Creates a generated clock with name CLKPDIV2 at the Q
# pin of flip-flop UFF0. The master clock is at the CLKOUT
# pin of PLL. And the period of the generated clock is double
# that of the clock CLKP, that is, 20ns.

         可以在触发器的输出端口定义一个新时钟是主时钟,而非生成时钟吗?答案是肯定的,这确实是可能的,但是它也有一些缺点。定义主时钟而不是生成时钟会创建一个新的时钟域。通常这不是问题,除了在设置STA约束时需要处理更多的时钟域外。相反,将新时钟定义为生成时钟不会创建新的时钟域,并且生成时钟会被认为与其主时钟同相,生成时钟不需要进行额外的约束。因此,尽量将内部新生成的时钟定义为生成时钟,而不是将其声明为另一个主时钟。

         主时钟和生成时钟之间的另一个重要区别是时钟源的概念。在主时钟中,时钟的源点位于主时钟的定义点。在生成时钟中,时钟源是主时钟的源,而不是生成时钟的源。这意味着在时钟路径报告中,时钟路径的起点始终是主时钟定义点。这是生成时钟相对于定义新主时钟的一大优势,因为对于新主时钟的情况不会自动包含源延迟。

        图 7-11 显示了一个多路复用器的示例,其两个输入都有时钟。在这种情况下,无需在多路复用器的输出上定义时钟。如果选择信号设置为常数,多路复用器的输出会自动获得正确的时钟传播。如果多路复用器的选择引脚不受约束,则两个时钟都通过多路复用器传播以供 STA 使用。在这种情况下,STA 可能会报告 TCLK 和 TCLKDIV5 之间的路径。请注意,这种路径是不可能的,因为选择线只能选择多路复用器输入之一。在这种情况下,可能需要设置一条错误路径或指定这两个时钟之间的独占时钟关系,以避免报告错误路径。这当然假设设计中其他地方的 TCLK 和 TCLKDIV5 之间没有路径。 

        如果多路复用器选择信号不是静态的并且可以在设备操作期间发生变化,会发生什么情况?在这种情况下,会对多路复用器输入端进行时钟门控(clock gating)检查。时钟门控检查在第 10 章中解释;这些检查确保多路复用器输入处的时钟相对于多路复用器选择信号安全切换。 

         图 7-12 显示了一个示例,其中时钟 SYS_CLK 由触发器的输出进行门控。由于触发器的输出可能不是常数,因此处理这种情况的一种方法是在和单元的输出处定义一个与输入时钟相同的生成时钟。

create_clock 0.1 [get_ports SYS_CLK]
# Create a master clock of period 100ps with 50%
# duty cycle.

create_generated_clock -name CORE_CLK -divide_by 1 \
-source SYS_CLK [get_pins UAND1/Z]
# Create a generated clock called CORE_CLK at the
# output of the and cell and the clock waveform is
# same as that of the master clock.

         下一个示例是频率高于源时钟频率的生成时钟。图 7-13 显示了波形。

create_clock -period 10 -waveform {0 5} [get_ports PCLK]
# Create a master clock with name PCLK of period 10ns
# with rise edge at 0ns and fall edge at 5ns.
create_generated_clock -name PCLKx2 \
-source [get_ports PCLK] \
-multiply_by 2 [get_pins UCLKMULTREG/Q]
# Creates a generated clock called PCLKx2 from the
# master clock PCLK and the frequency is double that of
# the master clock. The generated clock is defined at the
# output of the flip-flop UCLKMULTREG.

         请注意,-multiply_by 和 -divide_by 选项指的是时钟频率,即使在主时钟定义中指定了时钟周期。

时钟门控单元输出的主时钟示例(Example of Master Clock at Clock Gating Cell Output)

         考虑图7-14中所示的时钟门控示例,两个时钟分别输入进一个与门单元中,问题是与门单元的输出是什么呢?如果与门单元的输入均为时钟,则可以安全地在与门单元的输出端定义一个新的主时钟,因为该单元的输出与任何一个输入时钟都没有相位关系的可能性很小。

create_clock -name SYS_CLK -period 4 -waveform {0 2} \
[get_pins UFFSYS/Q]
create_clock -name CORE_CLK -period 12 -waveform {0 4} \
[get_pins UFFCORE/Q]
create_clock -name MAIN_CLK -period 12 -waveform {0 2} \
[get_pins UAND2/Z]
# Create a master clock instead of a generated clock
# at the output of the and cell.

        在内部引脚上创建时钟的一个缺点是它会影响路径延迟计算并迫使设计人员手动计算源延迟。

使用Edge和Edge_shift选项生成时钟(Generated Clock using Edge and Edge_shift Options)

        图 7-15 显示了生成时钟的示例。除了两个异相时钟之外,还会生成一个 2 分频时钟。图中还显示了时钟的波形。 

        下面给出了该示例中所有时钟的定义。衍生时钟的定义使用了-edges选项,这是定义衍生时钟的另一种方法。该选项采用源主时钟{上升,下降,上升}的边沿列表,以形成新的衍生时钟。主时钟的第一个上升沿是沿1,第一个下降沿是沿2,下一个上升沿是沿3,依此类推。 

create_clock 2 [get_ports DCLK]
# Name of clock is DCLK, has period of 2ns with a
# rise edge at 0ns and a fall edge at 1ns.
create_generated_clock -name DCLKDIV2 -edges {2 4 6} \
-source DCLK [get_pins UBUF2/Z]
# The generated clock with name DCLKDIV2 is defined at
# the output of the buffer. Its waveform is formed by
# having a rise edge at edge 2 of the source clock,
# fall edge at edge 4 of the source clock and the next
# rise edge at edge 6 of the source clock.
create_generated_clock -name PH0CLK -edges {3 4 7} \
-source DCLK [get_pins UAND0/Z]
# The generated clock PH0CLK is formed using
# the 3, 4, 7 edges of the source clock.
create_generated_clock -name PH1CLK -edges {1 2 5} \
-source DCLK [get_pins UAND1/Z]
# The generated clock with name PH1CLK is defined at
# the output of the and cell and is formed with
# edges 1, 2 and 5 of the source clock.

         如果生成时钟的第一个边沿是下降沿怎么办?考虑生成的时钟 G3CLK,如图 7-16 所示。可以通过指定边沿 5、7 和 10 来定义此类生成的时钟,如下面的时钟约束所示。自动推断 1ns 处的下降沿。

create_generated_clock -name G3CLK -edges {5 7 10} \
-source DCLK [get_pins UAND0/Z]

         -edge_shift 选项可与 -edges 选项结合使用,以指定相应边沿的任何移位以形成新生成的波形。它指定边列表中每个边的移动量(以时间为单位)。这是使用此选项的示例。

create_clock -period 10 -waveform {0 5} [get_ports MIICLK]
create_generated_clock -name MIICLKDIV2 -source MIICLK \
-edges {1 3 5} [get_pins UMIICLKREG/Q]
# Create a divide-by-2 clock.
create_generated_clock -name MIIDIV2 -source MIICLK \
-edges {1 1 5} -edge_shift {0 5 0} [get_pins UMIIDIV/Q]
# Creates a divide-by-2 clock with a duty cycle different
# from the source clock's value of 50%.

         边沿列表中的边沿列表必须按非递减顺序排列,但同一边沿可用于两个条目以指示独立于源时钟占空比的时钟脉冲。上例中的 -edge_shift 选项指定第一个边沿是通过将(源时钟的边沿 1)移动 0ns 获得的,第二个边沿是通过将(源时钟的边沿 1)移动 5ns 获得的,第三个边沿是通过以下方式获得的将(源时钟的边沿 5)移动 0ns。图 7-17 显示了波形。

使用Invert 选项生成的时钟(Generated Clock using Invert Option)

         这是生成时钟的另一个示例;这个使用 -invert 选项。

create_clock -period 10 [get_ports CLK]
create_generated_clock -name NCLKDIV2 -divide_by 2 -invert \
-source CLK [get_pins UINVQ/Z]

        -invert 选项在应用所有其他生成的时钟选项后将反转应用于生成的时钟。图 7-18 显示了生成这种反相时钟的原理图。

生成时钟的时钟延迟(Clock Latency for Generated Clocks)

         也可以为生成的时钟指定时钟延迟。在生成时钟上指定的源延迟指定了从主时钟定义到生成时钟定义的延迟。因此,到由生成时钟驱动的触发器的时钟引脚的总时钟延迟是主时钟的源延迟、生成时钟的源延迟和生成时钟的网络延迟之和。如图 7-19 所示。

         一个生成时钟可以有另一个生成时钟作为其源,即可以有生成时钟的生成时钟,以此类推。但是,生成的时钟只能有一个主时钟。生成时钟的更多示例将在后面的章节中描述。 

典型时钟生成场景(Typical Clock Generation Scenario)

         图 7-20 显示了时钟分布如何出现在典型 ASIC 中的场景。振荡器在芯片外部并产生低频(典型值 10-50 MHz)时钟,片上 PLL 将其用作参考时钟以生成高频低抖动时钟(典型值 200-800 MHz) .然后将该 PLL 时钟馈送到时钟分频器逻辑,该逻辑为 ASIC 生成所需的时钟。

         在时钟分配的一些分支上,可能有时钟门,用于在必要时关闭设计的非活动部分的时钟以节省功耗。 PLL 的输出端还可以有一个多路复用器,以便在必要时可以绕过 PLL。

         在进入设计的芯片输入引脚上为参考时钟定义了一个主时钟,在 PLL 的输出端定义了第二个主时钟。 PLL 输出时钟与参考时钟没有相位关系。因此,输出时钟不应是参考时钟的生成时钟。最有可能的是,时钟分频器逻辑生成的所有时钟都被指定为 PLL 输出的主时钟的生成时钟。

7.4 约束输入路径(Constraining Input Paths)

         本节将介绍输入路径的约束。这里需要注意的一点是,STA无法检查不受约束的路径上的任何时序,因此需要约束所有路径以进行时序分析。在后面的章节中会介绍一些示例,其中一些示例可能并不关心某些逻辑,因而这些输入路径可能可以不用约束。例如,设计人员可能并不在乎一些输入控制信号的时序,因此可能并不需要进行本节中将要介绍的时序检查。但是,本节假定我们要约束全部的输入路径。

        图 7-21 显示了被分析设计 (DUA) 的输入路径。触发器 UFF0 位于设计外部,并向设计内部的触发器 UFF1 提供数据。数据通过输入端口 INP1 连接。 

         CLKA 的时钟定义指定了时钟周期,它是两个触发器 UFF0 和 UFF1 之间可用的总时间量。外部逻辑所用的时间是 Tclk2q,即启动触发器 UFF0 的 CK 到 Q 延迟,加上 Tc1,即通过外部组合逻辑的延迟。因此,输入引脚 INP1 上的延迟规范定义了 Tclk2q 加上 Tc1 的外部延迟。在本例中,此延迟是相对于时钟 CLKA 指定的。

         这是输入延迟约束。

set Tclk2q 0.9
set Tc1  0.6
set_input_delay -clock CLKA -max [expr Tclk2q + Tc1] \
[get_ports INP1]

         该约束指定输入 INP1 上的外部延迟为 1.5ns,这与时钟 CLKA 相关。假设 CLKA 的时钟周期为 2ns,则 INP1 引脚的逻辑只有 500ps (= 2ns - 1.5ns) 可用于在设计内部传播。此输入延迟规范映射到输入约束,即 Tc2 加上 UFF1 的 Tsetup 必须小于 500ps,触发器 UFF1 才能可靠地捕获触发器 UFF0 启动的数据。请注意,上面的外部延迟被指定为最大数量。

        让我们考虑同时考虑最大和最小延迟的情况,如图 7-22 所示。以下是此示例的限制条件。

create_clock -period 15 -waveform {5 12} [get_ports CLKP]
set_input_delay -clock CLKP -max 6.7 [get_ports INPA]
set_input_delay -clock CLKP -min 3.0 [get_ports INPA]

         INPA 的最大和最小延迟源自 CLKP 到 INPA 的延迟。最大和最小延迟分别指最长和最短路径延迟。这些通常也可能对应于最坏情况下的慢速(最大时序角)和最佳情况下的快速(最小时序角)。因此,最大延迟对应于最大拐角处的最长路径延迟,最小延迟对应于最小拐角处的最短路径延迟。在我们的示例中,1.1ns 和 0.8ns 是 Tck2q 的最大和最小延迟值。组合路径延迟 Tc1 的最大延迟为 5.6ns,最小延迟为 2.2ns。 INPA 上的波形显示了数据到达设计输入的窗口以及预期稳定的时间。从 CLKP 到 INPA 的最大延迟为 6.7ns (= 1.1ns +5.6ns)。最小延迟为 3ns (= 0.8ns+ 2.2ns)。这些延迟是根据时钟的有效边沿指定的。在给定外部输入延迟的情况下,设计内部的可用建立时间是慢角(slow corner)下的8.3ns(= 15ns-6.7ns)和快角(fast corner)下的12ns(= 15ns-3.0ns)中的最小值。因此,8.3ns是用来可靠地捕获DUA内部数据的可用时间。

        以下是输入约束的更多示例。

set_input_delay -clock clk_core 0.5 [get_ports bist_mode]
set_input_delay -clock clk_core 0.5 [get_ports sad_state]

        由于未指定maxmin选项,因此500ps这个值将同时用于最大延迟和最小延迟。此外部输入延迟是相对于时钟clk_core的上升沿指定的(如果输入延迟是相对于时钟的下降沿指定的,则必须使用-clock_fall选项)。 

7.5 约束输出路径(Constraining Output Paths)

        本节将借助以下三个说明性示例描述输出路径的约束。 

示例 A 

         图 7-23 显示了通过分析设计的输出端口的路径示例。 Tc1 和 Tc2 是通过组合逻辑的延迟。

        时钟 CLKQ 的周期定义了触发器 UFF0 和 UFF1 之间的总可用时间。外部逻辑的总延迟为 Tc2 加 Tsetup。该总延迟 Tc2 Tsetup 必须指定为输出延迟规范的一部分。请注意,输出延迟是相对于捕获时钟指定的。数据必须及时到达外部触发器UFF1以满足其建立时间要求。 

set Tc2  3.9
set Tsetup 1.1
set_output_delay -clock CLKQ -max [expr Tc2 + Tsetup] \
[get_ports OUTB]

         这指定相对于时钟边沿的最大外部延迟为 Tc2 加 Tsetup;并且应该对应5ns的延迟。可以类似地指定最小延迟。

示例 B

         图 7-24 显示了具有最小和最大延迟的示例。最大路径延迟为 7.4ns(= 最大 Tc2 加上 Tsetup = 7 0.4)。最小路径延迟为 -0.2ns(= 最小 Tc2 减去 Thold = 0 - 0.2)。因此输出约束为:

create_clock -period 20 -waveform {0 15} [get_ports CLKQ]
set_output_delay -clock CLKQ -min -0.2 [get_ports OUTC]
set_output_delay -clock CLKQ -max 7.4 [get_ports OUTC]

        图 7-24 中的波形显示了何时 OUTC 必须稳定才能被外部触发器可靠地捕获。这描述了数据必须在所需的稳定区域开始之前在输出端口准备好,并且必须保持稳定直到稳定区域结束。这映射到 DUA 内部输出端口 OUTC 的逻辑时序要求。 

示例 C

        这是显示输入和输出规范的另一个示例。该模块有两个输入,DATAIN 和 MCLK,以及一个输出 DATAOUT。图 7-25 显示了预期的波形。 

create_clock -period 100 -waveform {5 55} [get_ports MCLK]
set_input_delay 25 -max -clock MCLK [get_ports DATAIN]
set_input_delay 5 -min -clock MCLK [get_ports DATAIN]

set_output_delay 20 -max -clock MCLK [get_ports DATAOUT]
set_output_delay -5 -min -clock MCLK [get_ports DATAOUT]

7.6 时序路径组(Timing Path Groups)

         设计中的时序路径可被视为路径的集合。每条路径都有一个起点和一个终点(a startpoint and an endpoint)。有关一些示例路径,请参见图 7-26。

        在STA中,时序路径是根据有效的起点和终点(valid startpoints and valid endpoints)来划分的。有效的起点包括:输入端口或者同步器件(如触发器和存储器)的时钟引脚。有效的终点包括:输出端口或者同步器件的数据输入引脚。因此,有效的时序路径包括:

  • 从输入端口到输出端口
  • 从输入端口到触发器或存储器的数据输入引脚
  • 从一个触发器或存储器的时钟引脚到另一个触发器或存储器的数据输入引脚
  • 从一个触发器或存储器的时钟引脚到输出端口

        图7-26中的有效时序路径包括:

  • 输入端口A到输出端口Z
  • 输入端口A到触发器UFFA的D引脚
  • 触发器UFFA的CK引脚到触发器UFFB的D引脚
  • 触发器UFFB的CK引脚到输出端口Z

         时序路径可以根据与路径终点相关的时钟分为不同时序路径组(path groups)。因此,每个时钟都有一组与之相关的时序路径。还有一个默认时序路径组(default path group),其中包括了所有non-clocked(异步)路径。

在图7-27的示例中,时序路径分组为:

  • CLKA组:输入端口A到触发器UFFA的D引脚
  • CLKB组:触发器UFFA的CK引脚到触发器UFFB的D引脚
  • 默认组:输入端口A到输出端口Z、触发器UFFB的CK引脚到输出端口Z

         静态时序分析和报告通常对每个路径组分别执行。

7.7 外部属性建模(Modeling of External Attributes)

         虽然 create_clock、set_input_delay 和 set_output_delay 足以约束设计中的所有路径以执行时序分析,但这些不足以为模块的 IO 引脚获得准确的时序。还需要以下属性来准确地对设计环境进行建模。对于输入,需要指定输入的转换。可以使用以下方式提供此信息:

  • set_drive(此命令已过时,不推荐使用。)
  • set_driving_cell
  • set_input_transition

        对于输出,需要指定输出引脚看到的容性负载。这是通过使用以下命令约束指定的: 

  • set_load 

7.7.1驱动强度建模(Modeling Drive Strengths)

        set_driveset_driving_cell约束用于对驱动模块输入端口的外部单元的驱动强度进行建模。在没有这些约束的默认情况下,假定所有输入都具有无限的驱动强度,即输入引脚的过渡时间为0。

        set_drive明确指定了DUA输入引脚上的驱动电阻值,该电阻值越小,驱动强度越高,电阻值为0表示无限的驱动强度。

set_drive 100 UCLK
# Specifies a drive resistance of 100 on input UCLK.

# Rise drive is different from fall drive:
set_drive -rise 3 [all_inputs]
set_drive -fall 2 [all_inputs]

         输入端口的驱动用于计算第一个单元的转换时间。指定的驱动值还用于计算存在任何 RC 互连时从输入端口到第一个单元的延迟。

Delay_to_first_gate =
(drive * load_on_net) + interconnect_delay

延迟值 = (驱动强度 * 网络负载) + 互连线延迟

         set_driving_cell 命令提供了一种更方便、更准确的方法来描述端口的驱动能力。 set_driving_cell 可用于指定驱动输入端口的单元。

set_driving_cell -lib_cell INV3 \
-library slow [get_ports INPB]
# The input INPB is driven by an INV3 cell
# from library slow.
set_driving_cell -lib_cell INV2 \
-library tech13g [all_inputs]
# Specifies that the cell INV2 from a library tech13g is
# the driving cell for all inputs.
set_driving_cell -lib_cell BUFFD4 -library tech90gwc \
[get_ports {testmode[3]}]
# The input testmode[3] is driven by a BUFFD4 cell
# from library tech90gwc.

         与驱动规范一样,输入端口的驱动单元用于计算第一个单元的转换时间,并在存在任何互连时计算从输入端口到第一个单元的延迟。

        set_driving_cell 命令的一个警告是,由于输入端口上的容性负载而导致的驱动单元的增量延迟作为输入上的附加延迟包括在内。

         作为上述方法的替代方法,set_input_transition 命令提供了一种在输入端口表达转换的便捷方式。可以选择指定参考时钟。以下是图 7-30 中所示示例的规范以及其他示例。

set_input_transition 0.85 [get_ports INPC]
# Specifies an input transition of 850ps on port INPC.
set_input_transition 0.6 [all_inputs]
# Specifies a transition of 600ps on all input ports.
set_input_transition 0.25 [get_ports SD_DIN*]
# Specifies a transition of 250ps on all ports with
# pattern SD_DIN*.
# Min and max values can optionally be specified using
# the -min and -max options.

         总之,需要输入端的转换值来确定输入路径中第一个单元的延迟。在没有此约束的情况下,假设理想的过渡值为 0,这可能不现实。

7.7.2 容性负载建模(Modeling Capacitive Load)

         set_load约束在输出端口上设置了电容性负载,以模拟由输出端口驱动的外部负载。默认情况下,端口上的电容性负载为0。可以将负载显式地指定为电容值或某个单元的输入引脚电容。

set_load 5 [get_ports OUTX]
# Places a 5pF load on output port OUTX.
set_load 25 [all_outputs]
# Sets 25pF load capacitance on all outputs.
set_load -pin_load 0.007 [get_ports {shift_write[31]}]
# Place 7fF pin load on the specified output port.
# A load on the net connected to the port can be
# specified using the -wire_load option.
# If neither -pin_load nor -wire_load option is used,
# the default is the -pin_load option.

         指定输出负载很重要,因为该值会影响驱动输出的单元的延迟。在没有这样的规范的情况下,假设负载为 0,这可能是不现实的。

        set_load 命令还可用于在设计中指定内部网络上的负载。下面是一个例子:

set_load 0.25 [get_nets UCNT5/NET6]
# Sets the net capacitance to be 0.25pF.

7.8 设计规则检查(Design Rule Checks)

        STA中两个常用的设计规则是最大过渡时间-max_transition和最大电容-max_capacitance。这些规则将会检查设计中的所有端口和引脚是否满足过渡时间和电容的规定约束。这些规则可以使用以下命令指定: 

  • set_max_transition
  • set_max_capacitance

        作为STA的一部分,任何设计规则的违例(violation)均以裕量(slack)的形式报告。以下是些例子:

set_max_transition 0.6 IOBANK
# Sets a limit of 600ps on IOBANK.
set_max_capacitance 0.5 [current_design]
# Max capacitance is set to 0.5pf on all nets in
# current design.

网络上的电容是通过将所有引脚电容加上任何IO负载再加上网络上的任何互连电容的总和计算得出的。下图7-32为一个示例:

Total cap on net N1 =
pin cap of UBUF1:pin/A +
pin cap of UOR2:pin/B +
load cap specified on output port OUTP +
wire/routing cap
= 0.05 + 0.03 + 0.07 + 0.02
= 0.17pF

Total cap on net N2 =
pin cap of UBUF2/A +
wire/routing cap from input to buffer
= 0.04 + 0.03
= 0.07pF

网络N1的总电容 = UBUF1的A引脚电容 + UOR2的B引脚电容 + OUTP的输出负载电容 + 走线互连电容

​ = 0.05 + 0.03 + 0.07 + 0.02 = 0.17 pF

网络N2的总电容 = UBUF2的A引脚电容 + 走线互连电容

​ = 0.03 + 0.04 = 0.07 pF

        过渡时间是延迟计算的一部分。对于图7-32中的示例(假设UBUF2单元使用线性延迟模型):

Transition time on pin UBUF2/A =
drive of 21* total cap on net N2
= 2 * 0.07 = 0.14ns = 140ps

Transition time on output port OUTP =
drive resistance of UBUF2/Z * total cap of net N1 =
1 * 0.17 = 0.17ns = 170ps

 UBUF2的A引脚过渡时间 = 2 * 网络N2的总电容
                     = 2 * 0.07 = 0.14ns = 140ps

输出端口OUTP过渡时间 = UBUF2的Z引脚的驱动电阻 * 网络N1的总电容

                    ​= 1 * 0.17 = 0.17ns = 170ps

        还可以为设计指定其他设计规则检查,比如:set_max_fanout(指定设计中所有引脚的扇出约束),set_max_area(用于设计)。但是,这些检查适用于综合(synthesis)而非STA。

7.9 虚拟时钟(Virtual Clocks)

         虚拟时钟是存在但不与设计的任何引脚或端口相关联的时钟。它用作 STA 分析中的参考,以指定相对于时钟的输入和输出延迟。图 7-33 显示了一个适用虚拟时钟的示例。分析中的设计从 CLK_CORE 获取时钟,但驱动输入端口 ROW_IN 的时钟是 CLK_SAD。在这种情况下,如何指定输入端口 ROW_IN 上的 IO 约束?同样的问题发生在输出端口 STATE_O 上。

        为了处理这种情况,可以定义一个不指定源端口或引脚的虚拟时钟。在图 7-33 的示例中,为 CLK_SAD 和 CLK_CFG 定义了虚拟时钟。 

create_clock -name VIRTUAL_CLK_SAD -period 10 -waveform {2 8}
create_clock -name VIRTUAL_CLK_CFG -period 8 \
-waveform {0 4}
create_clock -period 10 [get_ports CLK_CORE]

         定义了这些虚拟时钟后,可以相对于该虚拟时钟指定 IO 约束。

set_input_delay -clock VIRTUAL_CLK_SAD -max 2.7 \
[get_ports ROW_IN]
set_output_delay -clock VIRTUAL_CLK_CFG -max 4.5 \
[get_ports STATE_O]

         图 7-34 显示了输入路径上的时序关系。这将被分析设计中的输入路径限制为 5.3ns 或更小。

         图 7-35 显示了输出路径上的时序关系。这将被分析设计中的输出路径限制为 3.5ns 或更小。

         -min 选项在 set_input_delay 和 set_output_delay 约束中指定时,用于验证快速(或最小)路径。使用虚拟时钟只是限制输入和输出 (IO) 的一种方法;设计人员也可以选择其他方法来约束 IO。

7.10 完善时序分析(Refining the Timing Analysis)

用于约束分析的四个常用命令是:

  • set_case_analysis :在单元的引脚或输入端口上指定常量值。
  • set_disable_timing :中断单元的时序弧。
  • set_false_path :指定实际不存在的路径,这意味着在STA中不需要检查这些路径。
  • set_multicycle_path :指定可能花费超过一个时钟周期的路径。

第8章将详细讨论set_false_pathset_multicycle_path约束。

7.10.1 指定非活动信号(Specifying Inactive Signals)

         在设计中,某些信号在芯片的特定模式下会具有恒定值。例如,如果芯片中具有DFT(可测性设计)逻辑,则在正常功能模式下,芯片的TEST引脚将一直为0。为STA指定这样的常量值通常很有用,除了不必报告任何不相关的路径之外,这还有助于减少分析空间。例如,如果未将TEST引脚设置为常数,则可能会存在一些奇怪的长路径,而这些长路径在功能模式下永远不会存在。通过使用set_case_analysis约束来指定此类常数信号。

set_case_analysis 0 TEST

set_case_analysis 0 [get_ports {testmode[3]}]
set_case_analysis 0 [get_ports {testmode[2]}]
set_case_analysis 0 [get_ports {testmode[1]}]
set_case_analysis 0 [get_ports {testmode[0]}]

        如果设计具有多种功能模式,而只需要分析其中一种功能模式,则可以使用set_case_analysis来指定要分析的模式。

set_case_analysis 1 func_mode[0]
set_case_analysis 0 func_mode[1]
set_case_analysis 1 func_mode[2]

         请注意,可以在设计中的任何引脚上指定案例分析。案例分析的另一个常见应用是设计可以在多个时钟上运行,并且适当时钟的选择由多路复用器控制。为了使 STA 分析更容易并减少 CPU 运行时间,对每个时钟选择分别进行 STA 是有益的。图 7-36 显示了多路复用器选择具有不同设置的不同时钟的示例。

set_case_analysis 1 UCORE/UMUX0/CLK_SEL[0]
set_case_analysis 1 UCORE/UMUX1/CLK_SEL[1]
set_case_analysis 0 UCORE/UMUX2/CLK_SEL[2]

         第一个 set_case_analysis 导致为 MIICLK 选择 PLLdiv16。 PLLdiv8 的时钟路径被阻塞,不会通过多路复用器传播。因此,没有使用时钟 PLLdiv8 分析时序路径(假设时钟在多路复用器之前没有进行任何翻转)。类似地,最后一个 set_case_analysis 导致为 ADCCLK 选择 SCANCLK,并阻塞 CLK200 的时钟路径。

7.10.2 打破单元格中的时序弧(Breaking Timing Arcs in Cells)

         每个单元都有从其输入到输出的时序弧,并且时序路径可能会通过这些时序弧中的其中一个。在某些情况下,单元中的一条路径可能无法发生。例如可能有这样一种情况,其中时钟连接到多路复用器的选择端,而多路复用器的输出是数据路径的一部分。在这种情况下,中断多路复用器选择引脚和输出引脚之间的时序弧可能很有用。图7-37为一个示例,通过多路复用器选择端的路径不是有效的数据路径。可以使用set_disable_timing命令来中断这种时序弧。

set_disable_timing -from S -to Z [get_cells UMUX0]

        由于时序弧不再存在,因此需要分析的时序路径更少。另一个类似用法的例子是禁用触发器的最小时钟脉冲宽度检查。 

         使用set_disable_timing命令需要格外小心,因为它会删除通过指定引脚的所有时序路径。在可能的情况下,最好使用set_false_pathset_case_analysis命令。

7.11 点对点规范(Point-to-Point Specification)

         可以通过使用set_min_delayset_max_delay命令来约束点对点路径,这将引脚到引脚之间的路径延迟限制在了命令指定值内。该约束将覆盖所有默认的单周期时序路径以及此类路径的任何多周期路径约束。set_max_delay约束了指定路径的最大延迟,而set_min_delay约束了指定路径的最小延迟。

set_max_delay 5.0 -to UFF0/D
# All paths to D-pin of flip-flop should take 5ns max.
set_max_delay 0.6 -from UFF2/Q -to UFF3/D
# All paths between the two flip-flops should take a
# max of 600ps.
set_max_delay 0.45 -from UMUX0/Z -through UAND1/A -to UOR0/Z
# Sets max delay for the specified paths.
set_min_delay 0.15 -from {UAND0/A UXOR1/B} -to {UMUX2/SEL}

        在上述示例中,需要注意的是,使用非标准的内部引脚将迫使它们成为起点和终点,并在这些点处分割路径。

        还可以类似地指定从一个时钟到另一个时钟的点对点约束。

set_max_delay 1.2 -from [get_clocks SYS_CLK] \
-to [get_clocks CFG_CLK]
# All paths between these two clock domains are restricted
# to a max of 1200ps.
set_min_delay 0.4 -from [get_clocks SYS_CLK] \
-to [get_clocks CFG_CLK]
# The min delay between any path between the two
# clock domains is specified as 400ps.

         如果路径上有多个时序约束,例如时钟频率约束、set_max_delayset_min_delay,则最严格的那个约束是始终用于检查的约束。多个时序约束可能是先应用某些全局(global)约束,然后再应用某些局部(local)约束。

7.12 路径分割(Path Segmentation) 

        路径分段(path segmentation)是指将时序路径分解为可以进行时序分析的较小路径。

        时序路径具有起点和终点,可以使用set_input_delayset_output_delay命令在时序路径上创建其它起点和终点。通常在单元的输出引脚上指定set_input_delay来定义新起点,而通常在单元的输入引脚上指定set_output_delay来定义新终点。这些约束定义了新的时序路径,它是原始时序路径的子集。

        考虑图7-38中所示的路径。为SYSCLK定义时钟后,待分析的时序路径即为从UFF0 / CK到UFF1 / D。如果仅对报告从UAND2 / Z到UAND6 / A的路径延迟感兴趣,则可以使用以下两个命令:

set STARTPOINT [get_pins UAND2/Z]
set ENDPOINT [get_pins UAND6/A]
set_input_delay 0 $STARTPOINT
set_output_delay 0 $ENDPOINT

        定义这些约束会导致从UFF0 / CK到UFF1 / D的原始时序路径被分段,并分别在UAND2 / Z和UAND6 / A处创建内部起点和内部终点。现在,时序报告将明确显示此新路径。请注意,还会自动创建另外两条时序路径,一条从UFF0 / CK到UAND2 / Z,另一条从UAND6 / A到UFF1 / D。因此,原始的时序路径已被分为了三个部分,每个部分分别进行时序分析。 

        set_disable_timing、set_max_delay 和 set_min_delay 命令也会导致时序路径被分段。

  • 3
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA静态时序分析和动态时序分析是两种不同的时序分析方法,用于评估设计的时序性能和稳定性。 静态时序分析是一种在设计编译阶段进行的分析方法。它基于设计元数据和时序约束,通过计算信号路径的传播延迟和时序约束之间的差异来评估设计的时序性能。静态时序分析可以提前检测到潜在的时序问题,如setup和hold错误,并提供相关的报告和警告信息。它通常用于优化设计,通过调整布局布线、逻辑重划等方式来改善时序性能。 动态时序分析是一种在设计完成后、在实际运行或仿真过程进行的分析方法。它通过模拟或测试电路的实际运行情况,考虑信号传播延迟、时钟抖动、噪声等因素,评估设计在实际环境时序性能。动态时序分析可以更准确地模拟设计的实际行为,并检测到一些静态时序分析无法捕捉到的问题。 区别总结如下: 1. 时间点:静态时序分析在设计编译阶段进行,动态时序分析在设计完成后进行。 2. 分析对象:静态时序分析基于设计元数据和时序约束,动态时序分析基于实际运行或仿真过程的电路行为。 3. 检测能力:静态时序分析可以提前检测到潜在的时序问题,如setup和hold错误,动态时序分析可以检测到静态分析无法捕捉到的问题。 4. 优化方法静态时序分析通过调整布局布线、逻辑重划等方式来改善时序性能,动态时序分析可以帮助验证设计在实际环境的可靠性和稳定性。 综上所述,静态时序分析和动态时序分析是两种不同的时序分析方法,用于评估设计的时序性能和稳定性,各有其优缺点和应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值