dc综合的sdc约束
单周期时序约束
- 时序约束的内容
- 所有输入逻辑路径(从输入端口开始)
- 内部(寄存器到寄存器)路径
- 所有输出路径(结束于输出端口)

- DC将设计分成时序路径,每个路径都有一个:
-
起始
- Input port
- 触发器或寄存器的时钟引脚
-
终点
+ output port
+ 顺序设备的任何输入引脚,时钟引脚除外
-

对时钟进行约束
- 创建时钟
1 | # 设置时钟的周期约束 |

- 模仿时钟到寄存器的时钟延时,clk到两个触发器的时间是不一样的


表示组合路径的最大延迟只能是1.78,必须将clock的uncertainty考虑进来
1 | set_clock_uncertainty -setup 0.14 [get_clocks clk] |
- 设置时钟到达的latency,-source表示外部源时钟的延迟
1 | set_clock_latency -source -max 3 [get_clocks clk] # source latency 约束 |

- 设置时钟引脚的transaction time
Transition 模拟寄存器时钟引脚上时钟波形的上升和下降时间:
1 | set_clock_transition Tt [get_clocks clk] |
- cts(时钟树综合)完成前后的约束对比:
在完成时钟树综合之后,可以适当降低uncertainty的值,因为时钟树综合后,实际的时钟偏斜(skew)和抖动(jitter)更明确,不需要预留太多余量;并且不用设置clock的net latency,直接使用
set_propagated_clock命令计算传播时钟延迟没,之前用 set_clock_latency 预估的 network latency 被实际布局布线后的时钟树延迟取代,工具会实际计算从时钟端口到每个寄存器时钟引脚的延迟,不再用预估值;不再需要 set_clock_transition(因为实际时钟树会给出更精确的转换时间)

对输入/输出进行约束

- set_input_delay
set_input_delay约束的是图中箭头部分的延时,用一个周期减去这段就可以得到N部分组合逻辑所需的约束值
1 | set_input_delay -max 0.8 -clock clk [get_ports A] |
- 多输入/输出的约束,做相同的约束

对于输入延迟约束,需要排除输入的时钟
1 | set_input_delay -max 0.5 -clock CLK [remove_from_collection [all_inputs] [get_ports CLK]] |
- set_output_delay
1 | set_output_delay -max 1.1 -clock CLK [all_outputs] |
- 不同ports的约束
实际的约束结果,A、B为0.5,C为0.8,CLK没有约束
后面的约束会覆盖前面的约束
1 | set_input_delay -max 0.5 -clock CLK [all_inputs] |
- 约束组合路径

通过下面这些约束,首先时钟周期为2ns,setup要求为0.1ns,input_delay为0.4ns,output_delay为0.2ns,那么组合路径所允许的最大时间延迟为:2-0.1-0.4-0.2=1.3ns
1 | create_clock -period 2 [get_ports CLK] |
- 约束纯组合设计(创建虚拟时钟)

1 | create_clock -name VCLK -period 2 |
- Time Budgeting 1/2


保守预算:?和N大约为40%

1 | # 对上面进行约束的例子 |
- 寄存器输出

对于input_delay,最大延迟就是从clk到q的最大延迟,即
$clk_to_q_max,对于output_delay,最大的延迟就是时钟周期减去clk到q的最小延迟,即10-$clk_to_q_min
1 | set clk_to_q_max 1.5 |
单周期约束扩展
- 创建时钟,定义占空比

1 | create_clock -period 2 -wave_form {0,0.6} [get_ports CLK] |
- 创建时钟,初始的相位偏移(会带来额外的影响,不建议使用)
大多数综合、STA 工具默认期望时钟的第一个上升沿在时间0,使用
-wave_form {0.4 1.4}后
- 时钟源点(source latency)会引入一个隐含的偏移
- 与其他同步时钟的相位关系变得不直观
使用
set_clock_latency更好

1 | create_clock -period 2 -wave_form {0.4,1.4} [get_ports CLK] |
- 创建更复杂的时钟

对应的时钟波形:

上面触发器的时序约束,默认从clk到d选择时间短的,即0.6ns
- 下降沿时钟的input_delay约束

1 | create_clokc -period 2 [get_ports CLK] |
对应M逻辑可用的时间:

- 多输入路径的input_delay约束

1 | create_clock -period 2 [get_ports CLK] |
告诉dc有两条约束,选择约束更紧的作为具体的input_delay约束条件,如果没有-add_delay选项,默认选择下面这条约束指令
- 设置驱动单元

1 | set_input_delay -max 0.6 -clock CLK [get_ports A] |
在input_delay的基础上会再额外增加一个延时,从下面这张图中可以看出,额外增加了0.12ns的延迟

- 在具体的设置中是要基于零负载来进行的
- set_driving_cell_gate匹配对应的驱动器
例如:有下面三个条件:
- 当50pf负载时,0.6ns
- 当0负载时,0.48ns
- Driving cell on input port A: Qin pin of FD1 flip-flop
对应的约束如下
1 | create_clock -period 4 [get_ports CLK] |
- 复杂输出路径的约束

最大延迟需要加上setup time,因此时钟上升沿的delay是2.4+0.1=2.5ns
对于时钟下降沿的部分,max ouput_delay为0.6+0.1=0.7ns
1 | create_clock -period 4 [get_ports CLK] |
- 默认外部时钟延迟

复杂时序约束和异常
同步多时钟
- 同步时钟和异步时钟的概念
当两个时钟间的相位是固定关系的,则可以称这两个时钟为同步时钟(synchronous clock)。一般同源,如由同一个MMCM or PLL产生的两个时钟可以称为同步时钟。因此可以将主时钟和与之对应的衍生时钟约束成同一个时钟组。
无法判定两个时钟间相位时,则可以称这两个时钟为异步时钟(asynchronous clocks)。两个来自不同晶振的时钟,一定是异步时钟。通常情况下设计中不同的主时钟肯定是异步时钟,因此可以将这两个主时钟及其衍生时钟约束成不同的时钟组
- 多时钟input_delay

1 | create_clock -period 3.0 -name CLKA # 虚拟时钟 |
上面约束的两个时钟,dc默认是同步时钟

查找两个时钟的上升沿,选择两个上升沿更短的来进行计算
查看波形图,两个上升沿差距更短的是1ns
那么TN应该满足什么条件呢?应该满足的关系如下所示
- 多时钟的output_delay

1 | create_clock -period [expr 1000/750] -name CLKD |

同样需要查找两个上升沿约束更短的部分,分别查找时钟C和时钟D和E短的时间间隔
分别是0.67ns和1ns,Ts对于两条约束等效要求的延迟如下,应该选择约束更紧的作为具体的sdc
- 时钟间的不确定度

1 | create_clock -period 3 [get_ports CLK1] |
上述的最后一条约束反映了两个时钟之间的偏移

- Generated clocks

对于二分频电路:
1 | create_generated_clock -divide_by 2 -name CK -source [get_ports CLK] [get_pins FFT1/Q] |
- 逻辑上互斥的时钟约束

在选择器的作用下,只会选择一条路径,紫色或者蓝色的路径
1 | create_clock -period 2 [get_ports CLK1] |
- 部分逻辑上互斥的时钟约束
和上面不同的是CLK1和CLK2的逻辑在前面部分存在交互

1 | create_clock -period 2 [get_ports CLK1] |
- 工作时钟选择约束

如果不进行约束,DC优化的路径包括,CLK1 -> CLK1 , CLK1 -> CLK2 , CLK2 -> CLK1 , CLK2 -> CLK2
但是实际上的只有相同的时钟之间的路径,设置的约束如下
1 | set_app_var timing_enable_multiple_clocks_per_reg true # 允许寄存器有多个clk |
异步时钟
- 异步时钟组约束

CLK1和CLK2是异步时钟,设置的约束如下所示:
1 | create_clock -period 3 [get_ports CLK1] |
多周期路径

例如最上面的加法器需要6个时钟周期,需要补充的是不仅仅是DC的约束,在实际的RTL代码中也要保证在6个周期后再进行采样,一般需要一个单独的控制电路
1 | create_clock -period [get_ports CLK] |
上述的约束并不完整,也要保证hold time满足,在最开始和计算完成之后周期的hold time满足就可以
1 | set_multicycle_path -hold 5 -from {A_reg[*] B_reg[*]} -to C_reg[*] |
