本节学习DC中的时序约束
时序路径介绍
默认情况下,DC将设计假定为一个同步时钟(synchronously-clocked)环境,即Single Clock、Single Cycle or Simplified Environment。并假设外部电路为一个Launching Circuitry(外部启动电路)和一个Capturing Circuitry(外部捕获电路)。Current design 输入的数据来自一个正沿触发的时钟设备(如 FF1
),输出数据发送到一个正沿触发的时钟设备(如 FF4
)。Current design 内部包含一系列寄存器以及逻辑单元。
在设计综合期间或综合之后,DC 会对设计进行时序分析,将设计分解为多个时序路径(timing paths),DC中所有的时序计算是依赖于path(路径)来进行的,时序路径的起点(Start Point)主要是输入端口(Input Port)和寄存器或触发器的时钟引脚(Clock Pin);终点(End Point)主要是输出端口(Output Port)和时序单元(如寄存器或触发器)的任意输入引脚(不包括时钟引脚)。这些路径都需要时序约束,主要的路径类型有:
- 寄存器到寄存器路径(Register to Register Path):起点为寄存器
FF
的时钟引脚CLK
,终点为寄存器FF
的数据引脚D
(反馈路径)。例如上图中的 x - 输入逻辑路径(Input Logic Path):例如下图中 Path1,起点为输入端口
A
,终点为寄存器FF
的数据引脚D
。 - 寄存器到输出路径(Register to Output Path):例如下图中 Path 2,起点为寄存器
FF
的时钟引脚CLK
,终点为输出端口Z
。
对于下图的Path3这种纯组合逻辑电路,默认情况,DC 不对其进行时序分析。若需要分析时,可以通过虚拟时钟和延迟约束显式地定义路径。
时钟介绍
时钟设置相关命令
-
使用以下命令创建一个时钟周期为2ns的CLK,通过
[get_ports clk]
绑定时钟信号到clk
端口。create_clock -period 2 [get_ports clk]
默认时钟行为(Default Clock Behavior)
- 在单时钟设计中,时钟约束应用于寄存器之间的所有时序路径,并确保它们符合单周期(Single-Cycle)和建立时间(Setup Time)的要求。
- 默认时钟信号在
0ns
上升,且默认占空比为50%
,即时钟高电平和低电平均分时钟周期。 - DC 假定时钟网络为理想时钟网络(Ideal Clock Network),即使时钟网络连接到许多触发器或锁存器的时钟/使能引脚,也不会考虑额外的缓冲或延迟。时钟信号在切换时假设瞬间完成,即零上升/下降时间;在时钟网络的所有节点上,时钟信号到达时间完全一致,即零偏移(Skew);从时钟源到寄存器的时钟路径无延迟,即零插入延迟(Insertion Delay)
- 尽管默认假设时钟网络是理想的,但实际设计中需要考虑时钟的偏移、延迟和过渡时间。可以通过建模这些参数,使时钟行为更加接近实际硬件情况,从而提高设计的时序分析精度。
时钟树建模(Model Clock Trees)
- DC 不负责综合clock buffer trees,时钟树的综合通常由物理设计工具或布局工具完成,这些工具基于实际的单元布局信息来构建时钟树。
- 布局前(Pre-Layout)的逻辑电路只假定简单的理想时钟网络,时钟路径未经过复杂优化。在布局阶段(Post-Layout),工具会添加时钟缓冲器,以优化时钟树的性能。
时钟偏移(Clock Skew)
时钟偏移(Clock Skew)是指时钟网络分支之间的最大延迟差异。在综合阶段,可以通过设置 Uncertainty 来建模时钟偏移,同时还可以包括Clock Jitter(时钟抖动),即时钟信号由于噪声或其他因素引起的周期波动;Margin Effects(余量效应),即为设计安全性额外分配的时间裕量。
使用命令 set_clock_uncertainty
来定义时钟偏移:
set_clock_uncertainty -setup Tu [get_clocks clk]
setup Tu
:为建立时间路径设置不确定性(例如Tu为不确定性的值)。[get_clocks clk]
:应用到特定的时钟对象(这里是clk
)。
set_clock_uncertainty and setup timing举例
-
创建时钟
create_clock -period 2 [get_ports clk]
-
设置时钟不确定性
set_clock_uncertainty -setup 0.14 [get_clocks clk]
图中数据从寄存器 FF1 的输出端发起。通过逻辑路径传播到寄存器 FF2 的数据端(D),数据必须在时钟信号到达 FF2 的捕获边沿前稳定。时钟周期(2ns) 被分为三个部分,clock_uncertainty(0.14ns)、setup time(0.08ns)、剩余时间即为寄存器到寄存器路径的最大延迟。
Tmax = clk_period - clock_uncertainty - setup_time
= 2 - 0.14 - 0.08
= 1.78ns
故最大允许延迟必须小于等于 1.78ns。
时钟的延迟
时钟的延迟(Latency)一般分为Network Latency(网络延迟)和Source Latency(源延迟)。
Network Latency 是从create_clock
指定的端口或引脚到寄存器时钟引脚之间的平均内部延迟。
Source Latency是从时钟的物理来源(如时钟生成器或外部晶振)到create_clock
端口或引脚的延迟,可以应用于理想时钟(pre-layout)或传播时钟(post-layout)。
常用命令
-
创建时钟:为端口
clk
创建一个周期为 10ns 的时钟信号。create_clock -period 10 [get_ports clk]
-
设置源延迟:为时钟
clk
设置 3ns 的最大源延迟。set_clock_latency -source -max 3 [get_clocks clk]
-
设置网络延迟:为时钟
clk
设置网络延迟。set_clock_latency -max [get_clocks clk]
-
设置传播时钟(可选):用于指定
clk
为传播时钟(post-layout 时钟)。set_propagated_clock [get_clocks clk]
在Pre-layout 阶段,通常假设时钟网络理想无延迟(Ideal Clock),此时使用 set_clock_latency
命令为设计添加源延迟和网络延迟的模型值。
在Post-layout 阶段,时钟网络已完成布局,此时使用 set_propagated_clock
命令,将实际传播的延迟应用到设计。
时钟转换时间(Clock Transition Time)
时钟转换时间用于描述寄存器时钟引脚(Clock Pins)上的时钟波形的上升时间和下降时间。
set_clock_transition Tt [get_clocks clk]
Tt
:时钟转换时间的值。[get_clocks clk]
:将转换时间设置到指定的时钟clk
上。
在寄存器 FF1 和 FF2 的时钟引脚上,Tt
是指时钟信号从低电平到高电平(上升时间)或从高电平到低电平(下降时间)的持续时间。
布局前(Pre-Layout)和布局后(Post-Layout)的时钟约束
布局前(Synthesis Constraints),设置理想的时钟模型,用于综合阶段。
常用命令:
create_clock -p 5 -n MCLK clk
set_clock_uncertainty -setup 0.5 MCLK
set_clock_transition 0.08 MCLK
set_clock_latency -source -max 4 MCLK
set_clock_latency -max 2 MCLK
create_clock
:定义时钟周期为5ns。set_clock_uncertainty
:设置时钟不确定性为0.5ns。set_clock_transition
:定义时钟转换时间为0.08ns。set_clock_latency
:分别设置源延迟和网络延迟。
布局后(Post-CTS STA Constraints),即在时钟树综合(Clock Tree Synthesis, CTS)后,建模实际的时钟行为。
常用命令:
create_clock -p 5 -n MCLK clk
set_clock_uncertainty -setup 0.2 MCLK
set_clock_latency -source -max 4 MCLK
set_propagated_clock MCLK
set_clock_uncertainty
:不确定性减少到0.2ns(更精准)。set_propagated_clock
:设置时钟为传播时钟,以反映实际的布局影响。
输入输出路径的时序约束
设置输入路径的时序约束
定义时钟周期为 2 ns
create_clock -period 2 [get_ports clk]
设置时钟不确定性
set_clock_uncertainty -setup 0.3 [get_clocks clk]
设置输入端口A的最大输入延迟为 0.6ns,表示数据从时钟的触发边沿到达A 的时间
set_input_delay -max 0.6 -clock clk [get_ports A]
时序分析与计算
时钟周期为 2 ns,扣除clock_uncertainty 0.3 ns,FF2 的建立时间 Tsetup 为 0.2 ns,外部输入延迟为 0.6 ns。
输入路径的最大允许延迟 Tmax = 2 − 0.3 − 0.2 − 0.6 = 0.9 ns
设置输出路径的时序约束
定义时钟周期为 2 ns
create_clock -period 2 [get_ports clk]
设置时钟不确定性
create_clock -period 2 [get_ports clk]
设置输出端口B的最大输出延迟为 0.8ns,表示数据在时钟触发边沿到达 KING’S DESIGN 的时间。
set_output_delay -max 0.8 -clock clk [get_ports B]
时序分析与计算
时钟周期为 2 ns,扣除 clock_uncertainty 0.3 ns,KING'S DESIGN 中寄存器 FF4 的建立时间为 0.1 ns。,外部延迟为 0.8 ns。
输出路径最大允许延迟 Tmax = 2 − 0.3 − 0.1 − 0.8 = 0.9 ns
对多个输入和输出端口设置时序约束
输入端口的时序约束
对除 CLK
之外的所有输入端口设置相同的输入延迟约束。
set_input_delay -max 0.5 -clock CLK \\
[remove_from_collection [all_inputs] [get_ports CLK]]
[all_inputs]
:获取设计中所有的输入端口集合(包括 A
, B
, C
, CLK
)。
[get_ports CLK]
:获取时钟端口 CLK
。
remove_from_collection
:从所有输入端口集合中移除时钟端口 CLK
,生成仅包含 A
, B
, C
的集合。
set_input_delay -max 0.5 -clock CLK
:对集合中的所有输入端口设置输入延迟约束,延迟值为 0.5ns
,参考时钟为 CLK
。
输出端口的时序约束
set_output_delay -max 1.1 -clock CLK [all_outputs]
[all_outputs]
:获取设计中所有的输出端口集合(OUT1
, OUT2
)。
set_output_delay -max 1.1 -clock CLK
:对集合中的所有输出端口设置输出延迟约束,延迟值为 1.1ns
,参考时钟为 CLK
。
如何对不同端口设置不同的时序约束
set_input_delay -max 0.5 -clock CLK [all_inputs]
set_input_delay -max 0.8 -clock CLK [get_ports C]
remove_input_delay [get_ports CLK]
- 此处为输入端口
C
单独设置一个新的输入延迟约束,最大延迟为0.8ns
,参考时钟为CLK
。 - 第二条命令会覆盖端口
C
在第一步中的设置。 - 移除时钟端口
CLK
的输入延迟约束。
约束组合逻辑路径
create_clock -period 2 [get_ports CLK]
set_clock_uncertainty -setup 0.3 [get_clocks CLK]
设置输入延迟
set_input_delay -max 0.4 -clock CLK [get_ports A]
为输入端口B设置最大输入延迟0.4ns
,参考时钟为CLK
。0.4ns
对应KOBE'S DESIGN
的输入延迟Te
。
设置输出延迟
set_output_delay -max 0.3 -clock CLK [get_ports B]
为输出端口D设置最大输出延迟0.3ns
,参考时钟为CLK
。0.3ns
由以下计算得出:
Tg
(KING'S DESIGN
的输出延迟):0.2ns
。FF4
的Tsetup
:0.1ns
。- 输出总延迟为:
0.2 + 0.1 = 0.3ns
。
TF,max = period − clock_uncertainty − input_delay − output_delay = 1.0ns
纯组合设计的约束(虚拟时钟)
设计的特殊之处
MY_DESIGN
是一个纯组合逻辑设计,没有内部寄存器。- 输入信号由外部的触发器
FF1
(KOBE'S DESIGN
)发出。 - 输出信号被外部的触发器
FF4
(KING'S DESIGN
)捕获。 - 时序约束完全依赖于输入触发器(launch edge)和输出触发器(capture edge)的时钟行为。
对于纯组合设计,要用虚拟时钟来进行约束。虚拟时钟是一个不连接到当前设计中的任何端口或引脚的时钟,它仅作为输入或输出延迟的参考。创建虚拟时钟会在DC的内存中生成一个具有用户指定名称的时钟对象。
create_clock -name VCLK -period 2
name VCLK:
- 为虚拟时钟指定名称,必须明确命名。
- 名称有助于区分虚拟时钟与设计内的实际时钟。
纯组合逻辑路径设置时序约束举例
-
创建虚拟时钟:定义虚拟时钟VCLK,作为组合逻辑路径输入/输出延迟的参考。
create_clock -period 2 -name VCLK
-
设置时钟不确定性:包含时钟偏斜(skew)、抖动(jitter)等影响。
set_clock_uncertainty -setup 0.3 [get_clocks VCLK]
-
设置输入延迟:考虑输入信号从外部FF1到组合逻辑的延迟。
set_input_delay -max 0.4 -clock VCLK [get_ports A]
-
设置输出延迟:考虑输出信号从组合逻辑到外部FF4的延迟。
Toutput_delay = Tt + Tsetup = 0.2ns + 0.1ns = 0.3ns
set_output_delay -max 0.3 -clock VCLK [get_ports B]
时间预算(Time Budgeting)
当前设计(MY_DESIGN
)中,来自上游模块(KOBE'S DESIGN
)的输入延迟未知。发送到下游模块(KING'S DESIGN
)的输出建立时间或需求未知。需要进行时间预算,合理分配时钟周期的时间,确保时序路径满足设计规范。
-
将整个时钟周期(如 10 ns 或 100 MHz)划分给输入延迟、组合逻辑延迟和输出延迟。
-
图中展示了一个例子,输入路径(
FF1
到MY_DESIGN
的输入端口N
)分配了时钟周期的 40%。 -
剩余的时钟时间将被分配给其他路径。
-
假设约束值:
- 在输入和输出延迟未知时,假设合理的延迟值用于设计分析。
- 通过合理假设,确保设计可以实现,并在后续阶段调整假设值。
-
时间预算的分配举例:
-
脚本
time_budget.tcl
定义了一个通用的时间预算,适用于MY_DESIGN
、KOBE_DESIGN
和KING_DESIGN
。create_clock -period 10 [get_ports CLK] set_input_delay -max 6 -clock CLK [all_inputs] remove_input_delay [get_ports CLK] set_output_delay -max 6 -clock CLK [all_outputs]
这里set_input_delay为6ns,那么N就是4ns,如果每个模块都这么去约束,两个模块相连时中间将剩下20%余量留给clk_to_q和setup_time
时序约束总结
输入路径、寄存器路径、输出路径分别由以下命令约束:
- 输入路径:
set_input_delay
- 寄存器路径:
create_clock
- 输出路径:
set_output_delay
时序预算的逻辑:
- 用户需要指定外部逻辑使用的时间,例如输入延迟和输出延迟。
- 设计工具(如 DC)会基于输入和输出延迟,计算剩余时间供内部逻辑使用。