SDC Constraints:时钟约束文件笔记
1. 本节核心
这份 SDC 脚本主要用于描述综合阶段的时钟约束,包括:
- 基本单位设置
- 主时钟
create_clock
- 生成时钟
create_generated_clock
- 时钟不确定性
set_clock_uncertainty
- 时钟边沿转换时间
set_clock_transition
- 时钟延迟
set_clock_latency
- 多时钟异步关系
set_clock_groups
2. 简洁注释版脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
set sdc_version 2.1
set_units -time ns -resistance kOhm -capacitance pF -voltage V -current mA
set IS_SYN 1
set IS_PR 0
create_clock -name clk -period 1.0 -waveform {0.0 0.5} [get_ports clk]
create_clock -name clk1 -period 1.2 -waveform {0.0 0.6} [get_ports clk1] create_clock -name clk2 -period 1.2 -waveform {0.0 0.6} [get_ports clk2] create_clock -name clk3 -period 1.2 -waveform {0.0 0.6} [get_ports clk3] create_clock -name clk4 -period 1.2 -waveform {0.0 0.6} [get_ports clk4]
if {${IS_SYN} == 1} {
create_generated_clock -name clk_div2 \ -master_clock clk \ -divide_by 2 \ -source [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV2_reg/clocked_on] \ [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV2_reg/Q]
create_generated_clock -name clk_div4 \ -master_clock clk_div2 \ -divide_by 2 \ -source [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV4_reg/clocked_on] \ [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV4_reg/Q] }
if {${IS_SYN} == 1} {
set_clock_uncertainty -setup 0.3 [get_clocks clk] set_clock_uncertainty -setup 0.6 [get_clocks clk_div2] set_clock_uncertainty -setup 1.2 [get_clocks clk_div4] set_clock_uncertainty -setup 0.36 [get_clocks clk1] set_clock_uncertainty -setup 0.36 [get_clocks clk2] set_clock_uncertainty -setup 0.36 [get_clocks clk3] set_clock_uncertainty -setup 0.36 [get_clocks clk4]
set_clock_transition 0.1 -rise [all_clocks] set_clock_transition 0.1 -fall [all_clocks]
set_clock_latency -source 0.08 [all_clocks] -rise -late set_clock_latency -source 0.02 [all_clocks] -rise -early
set_clock_latency 0.05 [get_clocks clk] set_clock_latency 0.05 [get_clocks clk_div2] set_clock_latency 0.05 [get_clocks clk_div4] set_clock_latency 0.01 [get_clocks clk1] set_clock_latency 0.01 [get_clocks clk2] set_clock_latency 0.01 [get_clocks clk3] set_clock_latency 0.01 [get_clocks clk4] }
set_clock_groups -asynchronous \ -group {clk clk_div2 clk_div4} \ -group {clk1} \ -group {clk2} \ -group {clk3} \ -group {clk4}
|
3. 关键命令总结
| 命令 |
作用 |
create_clock |
创建顶层输入时钟 |
create_generated_clock |
创建由已有时钟生成的分频 / 倍频 / 门控时钟 |
set_clock_uncertainty |
设置时钟不确定性,预留 setup margin |
set_clock_transition |
设置时钟边沿转换时间,即 clock slew |
set_clock_latency -source |
设置理想时钟源到 create_clock 定义点的延迟 |
set_clock_latency |
设置 create_clock 定义点到寄存器 clock pin 的时钟网络延迟 |
set_clock_groups -asynchronous |
声明异步时钟组,切断跨组时序分析 |
4. set_clock_latency -source 和普通 set_clock_latency
4.1 带 -source
1 2
| set_clock_latency -source 0.08 [all_clocks] -rise -late set_clock_latency -source 0.02 [all_clocks] -rise -early
|
表示:
1
| 理想时钟源 → create_clock 定义点
|
这段路径的延迟。
例如:
1
| Ideal Clock Source → [get_ports clk]
|
它描述的是时钟到达设计定义点之前的延迟。
4.2 不带 -source
1
| set_clock_latency 0.05 [get_clocks clk]
|
表示:
1
| create_clock 定义点 → 寄存器 clock pin
|
这段芯片内部时钟网络的延迟,也就是综合阶段对未来 clock tree delay 的估计。
例如:
1
| [get_ports clk] → clock tree → FF/CK
|
4.3 简单示意图
1 2 3 4 5 6 7 8 9 10 11 12 13
| 理想时钟源 │ │ set_clock_latency -source │ source latency ▼ create_clock 定义点 例如 [get_ports clk] │ │ set_clock_latency │ clock network latency ▼ 寄存器 clock pin 例如 FF/CK
|
5. set_clock_latency 和时钟树的关系
在综合阶段还没有真正做 CTS,所以工具不知道时钟从端口到各个寄存器 CK pin 的真实延迟。
因此:
1
| set_clock_latency 0.05 [get_clocks clk]
|
可以理解为:
1
| 假设 clk 从定义点到寄存器 CK pin,大约有 0.05ns 的时钟树插入延迟。
|
综合阶段使用的是估计值;后端 CTS 之后,STA 会使用真实时钟树和寄生参数计算得到的延迟。
| 阶段 |
时钟树状态 |
latency 来源 |
| 综合前 / 综合中 |
没有真实 CTS |
人为设置 set_clock_latency |
| 后端 CTS 后 |
已有真实时钟树 |
工具根据时钟树计算 |
| Signoff STA |
真实布线和寄生参数 |
SPEF + 实际时钟树延迟 |
6. create_generated_clock 生成时钟约束
6.1 生成时钟何时创建
在 DC 中:
1 2 3 4
| analyze elaborate current_design link
|
之后,RTL 已经被展开成内部设计结构,可以使用:
查找分频寄存器和关键 pin。
因此 generated clock 约束通常放在:
1 2
| elaborate + link 之后 compile_ultra 之前
|
6.2 二分频时钟
RTL 中如果有:
1 2 3
| always_ff @(posedge CLK or negedge rst_n) begin CLK_DIV2 <= ~CLK_DIV2; end
|
说明 CLK_DIV2 每个 CLK 上升沿翻转一次,因此:
对应约束:
1 2 3 4 5
| create_generated_clock -name clk_div2 \ -master_clock clk \ -divide_by 2 \ -source [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV2_reg/clocked_on] \ [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV2_reg/Q]
|
6.3 四分频时钟
RTL 中如果有:
1 2 3
| always_ff @(posedge CLK_DIV2 or negedge rst_n) begin CLK_DIV4 <= ~CLK_DIV4; end
|
说明:
1
| CLK_DIV4 = CLK_DIV2 / 2 = CLK / 4
|
对应约束:
1 2 3 4 5
| create_generated_clock -name clk_div4 \ -master_clock clk_div2 \ -divide_by 2 \ -source [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV4_reg/clocked_on] \ [get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV4_reg/Q]
|
6.4 常用检查命令
1 2 3 4
| get_cells -hier *CLK_DIV* get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV2_reg/* get_pins u_MANUAL_CLOCK_DIVIDER/CLK_DIV4_reg/* report_clock -attributes -nosplit
|
7. 易混点总结
| 概念 |
含义 |
clocked_on |
分频寄存器的时钟输入端 |
Q |
分频寄存器输出端,也是 generated clock 产生点 |
-master_clock |
generated clock 的源时钟 |
-divide_by 2 |
二分频 |
latency |
时钟路径延迟,类似“时钟树有多长” |
uncertainty |
时钟不确定性,类似“时钟有多不准” |
transition |
时钟边沿转换时间,类似“时钟边沿陡不陡” |
8. 一句话总结
这份 SDC 时钟约束文件主要完成:
1 2 3 4
| 创建主时钟和分频时钟 设置时钟不确定性、transition 和 latency 声明多时钟之间的异步关系 让 DC 在综合前就能正确理解各个时钟域的时序关系
|
其中最关键的是:clk_div2 和 clk_div4 不能当成普通数据信号,需要在 elaborate + link 之后、compile_ultra 之前用 create_generated_clock 显式声明。