(4)SDC Constraints 如何写SDC约束文件中的时钟

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
#----------------------------------
# general
#----------------------------------

# 指定 SDC 版本
set sdc_version 2.1

# 设置单位:时间 ns、电阻 kOhm、电容 pF、电压 V、电流 mA
set_units -time ns -resistance kOhm -capacitance pF -voltage V -current mA

# 当前用于综合阶段
set IS_SYN 1

# 当前不是后端 PR 阶段
set IS_PR 0


#----------------------------------
# clock definition
#----------------------------------

# 创建主时钟 clk,周期 1.0ns,占空比 50%
create_clock -name clk -period 1.0 -waveform {0.0 0.5} [get_ports clk]

# 创建 clk1~clk4,周期 1.2ns,占空比 50%
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]


#----------------------------------
# generated clock definition
#----------------------------------

if {${IS_SYN} == 1} {

# clk_div2 由 clk 二分频得到
# clocked_on 是分频寄存器时钟输入端
# Q 是分频时钟输出端
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]

# clk_div4 由 clk_div2 再二分频得到,相当于 clk 的四分频
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]
}


#----------------------------------
# clock uncertainty / transition / latency
#----------------------------------

if {${IS_SYN} == 1} {

# 设置 setup uncertainty,用于预留 jitter、skew、建模误差等余量
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]

# 设置所有时钟的上升沿 / 下降沿 transition,也就是 clock slew
set_clock_transition 0.1 -rise [all_clocks]
set_clock_transition 0.1 -fall [all_clocks]

# source latency:理想时钟源到 create_clock 定义点的延迟
# early / late 用于建立最坏情况时序分析
set_clock_latency -source 0.08 [all_clocks] -rise -late
set_clock_latency -source 0.02 [all_clocks] -rise -early

# 普通 clock latency:create_clock 定义点到寄存器 clock pin 的延迟
# 综合阶段还没有真实 CTS,这里相当于估计未来 clock tree delay
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]
}


#----------------------------------
# clock relationship
#----------------------------------

# 设置异步时钟组
# 不同 group 之间不分析跨时钟 setup / hold 路径
# clk、clk_div2、clk_div4 同源相关,放在同一组
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 已经被展开成内部设计结构,可以使用:

1
2
get_cells
get_pins

查找分频寄存器和关键 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
CLK_DIV2 = CLK / 2

对应约束:

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_div2clk_div4 不能当成普通数据信号,需要在 elaborate + link 之后、compile_ultra 之前用 create_generated_clock 显式声明。

ESC 关闭 | 导航 | Enter 打开
输入关键词开始搜索