一个设计中的时序路径可视为一组路径。每个路径有一个起点(startpoint)和终点(endpoint)。图7-26展示了一些示例路径。
在STA中,时序路径是根据有效起点和终点来划分的。有效的起点包括:输入端口或者同步器件(如触发器(flip-flops)和存储器(memories))的时钟引脚。有效的终点包括:输出端口或者同步器件的数据输入引脚。因此,有效的时序路径可以是:
图7-26中的的有效时序路径有:
时序路径根据路径终点所相关的时钟被分为不同时序路径组(path groups)。因此,每个时钟都有一组与之相关的时序路径。这里还有一个默认时序路径组(default path group),包含了所有非时钟/异步(non-clock/asynchronous)路径。
在图例7-27中,时序路径组有:
静态时序分析和报告通常按照时序路径组来分别执行。
尽管create_clock、set_input_delay和set_output_delay足以约束设计中用于执行时序分析的所有路径,但这些并不足以获取该模块
I
O
IO
IO引脚上的准确时序。为了准确地对设计环境进行建模,还需要以下属性。对于输入,需要在输入端口处指定压摆(slew)。可以使用以下方式提供此信息:
对于输出,我们需要指明输出引脚的电容负载。可由如下命令进行指定:
set_drive和set_driving_ cell约束用于对驱动模块输入端口的外部单元的驱动强度进行建模。在没有这些约束的默认情况下,假定所有输入都具有无限的驱动强度,即输入引脚的过渡时间为
0
0
0。
set_drive明确指定了
D
U
A
DUA
DUA输入引脚上的驱动电阻值,该电阻值越小,驱动强度越高,电阻值为
0
0
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]
输入端口的驱动强度用来计算第一个单元的过渡时间。所指定的驱动数值还可用来计算从输入端口到第一个单元的延迟值,在存在 R C RC RC互连的情况下。
D e l a y _ t o _ f i r s t _ g a t e = ( d r i v e ∗ l o a d _ o n _ n e t ) + i n t e r c o n n e c t _ d e l a y Delay\_to\_first\_gate=(drive*load\_on\_net)+interconnect\_delay 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_drive约束一样,set_driving_cell也可用于计算第一个单元的过渡时间,并在任何互连情况下计算从输入端口到第一个单元的延迟值。
使用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 0 0。
set_load指令在输出端口放置一个电容负载以对输出端口所驱动的外部负载进行建模。默认情况下,输出端口的电容负载是
0
0
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 0 0的假定是与现实不符的。
set_load同样可以用来指定一个设计中内部网络的负载。例子如下:
set_load 0.25 [get_nets UCNT5/NET6]
# Sets the net capacitance to be 0.25pF.
STA中两个常用的设计规则是最大过渡时间-max_transition和最大电容-max_capacitance。这些规则将会检查设计中的所有端口和引脚是否满足过渡时间和电容的规定约束。这些规则可以使用以下命令指定:
作为STA的一部分,任何对这些设计规则的违例将会用裕量(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.
一个网络的电容是通过所有引脚电容加上所有 I O IO IO负载再加上网络上的任何互连电容的总和计算得出的。图7-32便是一个例子。
T
o
t
a
l
c
a
p
o
n
n
e
t
N
1
=
p
i
n
c
a
p
o
f
U
B
U
F
1
:
p
i
n
/
A
+
p
i
n
c
a
p
o
f
U
O
R
2
:
p
i
n
/
B
+
l
o
a
d
c
a
p
s
p
e
c
i
f
i
e
d
o
n
o
u
t
p
u
t
p
o
r
t
O
U
T
P
+
w
i
r
e
r
o
u
t
i
n
g
c
a
p
=
0.05
+
0.03
+
0.07
+
0.02
=
0.17
p
F
T
o
t
a
l
c
a
p
o
n
n
e
t
N
2
=
p
i
n
c
a
p
o
f
U
B
U
F
2
/
A
+
w
i
r
e
r
o
u
t
i
n
g
c
a
p
f
r
o
m
i
n
p
u
t
t
o
b
u
f
f
e
r
=
0.04
+
0.03
=
0.07
p
F
过渡时间计算作为时延计算的一部分。以图7-32为例(假定 U B U F 2 UBUF2 UBUF2单元是线性时延模型),
T
r
a
n
s
i
t
i
o
n
t
i
m
e
o
n
p
i
n
U
B
U
F
2
/
A
=
d
r
i
v
e
o
f
2
∗
t
o
t
a
l
c
a
p
o
n
n
e
t
N
2
=
2
∗
0.07
=
0.14
n
s
=
140
p
s
T
r
a
n
s
i
t
i
o
n
t
i
m
e
o
n
o
u
t
p
u
t
p
o
r
t
O
U
T
P
=
d
r
i
v
e
r
e
s
i
s
t
a
n
c
e
o
f
U
B
U
F
2
/
Z
∗
t
o
t
a
l
c
a
p
o
n
n
e
t
N
1
=
1
∗
0.17
=
0.17
n
s
=
170
p
s
还可以为设计指定其他设计规则检查,比如:set_max_fanout(指定设计中所有引脚的扇出约束),set_max_area(用于设计)。但是,这些检查适用于综合(synthesis)而非STA。
虚拟时钟(virtual clock)是存在的时钟,但与设计中的任何引脚或端口均不相关。在STA中仅用作参考,以指定相对于时钟的输入延迟和输出延迟。虚拟时钟的示例如图7-33所示。 待分析设计的时钟端为CLK_CORE,但输入端口ROW_IN的驱动时钟为CLK_SAD。在这种情况下,如何指定输入端口ROW_IN的
I
O
IO
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]
有了这些虚拟时钟定义, I O IO 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.3 n s 5.3ns 5.3ns或更短。
图7-35展示了输出路径中的时序关系。这将待分析设计中的输出路径限制为了 3.5 n s 3.5ns 3.5ns或更短。
-min选项在set_input_delay和set_output_delay约束中指定时,可用于检查最小时序路径。使用虚拟时钟只是约束输入和输出(
I
O
IO
IO)的一种方法,设计人员还可以选择其它方法来约束
I
O
IO
IO。
常用来限制分析空间的四种常见命令如下:
在第八章中讲详细讨论set_false_path和set_multicycle_path约束。
在一个设计中,实际信号在芯片的特定模式下是一个常量值。例如,如果一个芯片中具有
D
F
T
DFT
DFT逻辑(Design For Test, 可测性设计),那么芯片的
T
E
S
T
TEST
TEST引脚在普通(normal)模式下的值应该一直为
0
0
0。对于STA来说指定这样的常量值是很有用的。这可以缩小分析空间同时不再报告不相干的路径。例如,如果
T
E
S
T
TEST
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]
注意可以在设计中的任一引脚上指定set_case_analysis,这个命令的另一常见应用是可以在多个时钟上运行的设计,并且时钟的适当选择由多路复用器控制。为了使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选择了
P
L
L
d
i
v
16
PLLdiv16
PLLdiv16被用于
M
I
I
C
L
K
MIICLK
MIICLK,
P
L
L
d
i
v
8
PLLdiv8
PLLdiv8的时钟路径被阻塞并且不会通过多路复用器传播。因此,使用
P
L
L
d
i
v
8
PLLdiv8
PLLdiv8的时序路径不会被分析(假定时钟不会到多路复用器前的任何触发器,在多路复用器前不驱动任何触发器)。类似的,最后一个set_case_analysis选择了
S
C
A
N
C
L
K
SCANCLK
SCANCLK被用于
A
D
C
C
L
K
ADCCLK
ADCCLK,且
C
L
K
200
CLK200
CLK200的时钟路径被阻塞。
每个单元都有从其输入到输出的时序弧,并且时序路径可能会通过这些时序弧中的其中一个。在某些情况下,穿过单元的一条路径可能无法发生。例如可能有这样一种情况,其中时钟连接到多路复用器的选择端,而多路复用器的输出是数据路径的一部分。在这种情况下,中断多路复用器选择引脚和输出引脚之间的时序弧可能很有用。图7-37的示例,通过多路复用器选择端的路径不是有效的数据路径。可以使用set_disable_timing命令来中断这种时序弧。
set_disable_timing -from S -to Z [get_cells UMUX0]
由于时序弧不再存在,因此需要分析的时序路径更少。类似用法的另一个示例是取消触发器的最小时钟脉冲宽度检查。
使用set_disable_timing命令需要格外小心,因为它会删除通过指定引脚的所有时序路径。在可能的情况下,最好使用set_false_path和set_case_analysis命令。
可以通过使用set_min_delay和set_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_delay和set_min_delay,则最严格的那个约束是始终用于检查的约束。多个时序约束可能是先应用某些全局(global)约束,然后再应用某些局部(local)约束。
断开一个时序路径为多个可以进行时序分析的较短路径视为是路径分割。
一个时序路径具有起始点(startpoint)和终止点(endpoint)。此外时序路径上的起始点和终止点可以使用set_input_delay和set_output_delay来指定。通常在单元的输出引脚上使用set_input_delay定义一个起始点;在单元的输入引脚上使用set_output_delay定义一个终止点。这些约束定义了新的时序路径,它是原始时序路径的子集。
图7-38中给出了一些路径。为 S Y S C L K SYSCLK SYSCLK定义时钟后,待分析的时序路径即为从 U F F 0 / C K UFF0/CK UFF0/CK到 U F F 1 / D UFF1/D UFF1/D。如果只对从 U A N D 2 / Z UAND2/Z UAND2/Z到 U A N D 6 / Z UAND6/Z UAND6/Z的路径的时序报告感兴趣,则以下两个命令可应用:
set STARTPOINT [get_pins UAND2/Z]
set ENDPOINT [get_pins UAND6/A]
set_input_delay 0 $STARTPOINT
set_output_delay 0 $ENDPOINT
定义这些约束会导致从 U F F 0 / C K UFF0 / CK UFF0/CK到 U F F 1 / D UFF1 / D UFF1/D的原始时序路径被分段,并分别在 U A N D 2 / Z UAND2 / Z UAND2/Z和 U A N D 6 / A UAND6 / A UAND6/A处创建内部起点和内部终点。现在,时序报告将明确显示此新路径。请注意,还会自动创建另外两条时序路径,一条从 U F F 0 / C K UFF0 / CK UFF0/CK到 U A N D 2 / Z UAND2 / Z UAND2/Z,另一条从 U A N D 6 / A UAND6 / A UAND6/A到 U F F 1 / D UFF1 / D UFF1/D。因此,原始的时序路径已被分为了三个部分,每个部分分别进行时序分析。
set_disable_timing、set_max_delay和set_min_delay命令也会对时序路径进行分段。