目录
[直通路径 feedthrough](#直通路径 feedthrough)
多周期路径
默认情况下,每条时序路径是单周期。
即时钟的任一沿启动的数据,被下一个触发器在下一个上升沿捕获。
如果在数据捕获前,插入了额外的周期,那么这个路径就是多周期路径。多周期路径的SDC命令是
set_multicycle_path
-hold 保持倍数。指定保持沿向左移动的边沿数
-setup 移动捕获沿, 向右移动。
-rise -fall 以下和set_false_path 意思一样
-start 启动沿向左移动
-end 捕获沿向右移动
-from
-to
-rise/fall_from
-rise/fall_to
-rise/fall_through
这些命令指定了多周期的确定路径、多周期内部的过渡过程、建立 保持的多周期关系、额外的周期是依靠捕获时钟还是启动时钟、周期数。

一个例子:
如果数据在A沿启动,则在B沿被捕获。那么分析建立关系在A~B沿之间。如果使用 -setup 3,(3倍周期)捕获沿则被移动到D沿,此时保持分析会使用C沿。因为建立沿移动,保持沿也会自动移动。
为使得保持分析回到A沿,需要使用-hold 开关。如果不回到A沿,分析时会在路径中插入缓冲器,创造一些延迟,这将占用硅片的面积。
所以,hold 和 setup 应该成对出现。最终要将保持检查恢复到A沿,即启动沿。
源同步接口是一种高速数据传输技术,其核心特点是数据信号和时钟信号由发送端(源端)同时产生并传输,接收端使用这个伴随的时钟来采样数据。
发送端在输出数据的同时,会输出一个与数据同步的时钟信号。接收端使用这个时钟来锁存数据,而不是使用本地时钟。由于时钟和数据来自同一源端,它们之间的时序关系相对稳定,可以克服传输延迟和抖动问题。
异步时钟
set_multicycle_path -setup 2 #将异步路径上的延迟限定为一个周期,不是两个
-from [get_pins xxx]
-comment "Register fields"
set_multicycle_path -hold 1
-from [get_pins -xxx]
-comment "Register fields"
set_multicycle_path -setup 2
-from [get_pins
-of_objects [get_cells -hier * -filter "full_name =~ *u_cdm_pl_reg*pl_reg_29_reg* && is_hierarchical==false"]
-leaf -filter "is_clock_pin==true"]
-comment "Register fields : cfg_skip_interval, cfg_eidle_timer, cfg_fc_wdog_disable"

默认的启动-捕获组合电路是 A --P, 使用 set_multicycle_path -setup 2 建立一个多周期,捕获沿将移动到Q,这样子的话,数据路径从A 到Q 得到的时间差不多是一个周期(目的时钟)。
需要声明为多周期路径的情况:
- 一些数据路径有大量的加法器、乘法器 或其它数据路径元器件;
- 对捕获元器件有高的建立要求,比如 存储器;
- 启动元器件有高的clk_to out 延迟,比如 存储器;
- 或者路径在一个频率非常高的时钟上;
- 有深层次的逻辑;
以上这些使用单周期都很难满足时序要求,必须被声明为多周期。
get_pins
在SDC中,get_pins** 是一个设计对象查询命令,用于获取设计中特定引脚(pin)** 的句柄(handle)。这里的 pin 指的是电路网表中逻辑单元**(cell)的输入/输出端口**。
pin 是逻辑单元(cell)的物理接口点,包括:
-
输入/输出引脚:逻辑单元的数据输入/输出端
-
DIN→ 数据输入
-
A[*]→ OTP地址总线(所有位)
-
-
时钟引脚:触发器的时钟端
-
控制引脚:如使能、复位、置位端 READED
-
READEN→ 读使能信号
-
DLE→ 数据锁存使能
-
D[*]→ OTP数据输出总线(所有位)
-
-
总线引脚:A[*]
常见引脚类型:
- 寄存器引脚
get_pins u_ff/CLK # 触发器的时钟引脚
get_pins u_ff/D # 触发器的数据输入引脚
get_pins u_ff/Q # 触发器的数据输出引脚
- 组合逻辑引脚
get_pins u_and/A # 与门的输入引脚
get_pins u_and/B
get_pins u_and/Y # 与门的输出引脚
- 模块端口引脚
get_pins u_submodule/in_data# 模块输入端口
get_pins u_submodule/out_data# 模块输出端口
实例:时钟源的pins指 触发器的输出端作为时钟源,用于产生时钟信号。例如:
-
计数器分频后的输出作为时钟
-
状态机状态跳变产生的时钟
-
数据边沿检测产生的时钟
get_ports
get_ports是SDC(Synopsys设计约束)中的命令,用于获取设计中顶层模块的端口(Port)对象,常用于约束输入/输出端口。
主要功能:返回指定顶层端口的句柄,用于设置端口相关的时序约束。
实例:时钟信号来源的端口(Port),指芯片的外部输入引脚,时钟信号从芯片外部输入。例如:
-
晶振引脚(如OSC_IN/OSC_OUT)
-
外部时钟输入引脚(如CLK_IN)
-
高速接口的参考时钟引脚(如PCIe REFCLK)
set_max_delay
组合电路路径:在数字电路中,组合逻辑是指输出仅取决于当前输入,没有记忆功能的电路[不遇到任何寄存器]。路径的延迟由门延迟和线延迟组成,决定了信号从输入到输出的传播时间。
将组合电路的延迟限制到一个范围内,使用 set_max_delay.
-rise -fall 以下和set_false_path 意思一样
-from
-to
-through
-rise/fall_from
-rise/fall_to
-rise/fall_through
delay_value #指定延迟上限
实例:
set_max_delay 8.0 from [get_ports I1] -to [get_ports O1]
最好使用相关时钟约束
除了使用 set_max_delay 约束下面的逻辑云的延迟之外,还能使用相关时钟约束,命令使用 set_input_delay和set_output_delay。
比如下图的input_delay 指定的时钟可以是从F1启动数据的时钟,指定的输入延迟是从触发器到输入引脚I1间的延迟;
output_delay 是在F2中捕获数据的时钟,指定的输出延迟是从输出引脚O1到触发器F2间的延迟;
对于端口到端口的路径,通常认为使用input_delay 和 output_delay 比 max_delay好。
如果触发器F1、F2 的时钟本身可能或不可能反馈到组合电路中,则需要创建虚拟时钟,这个虚拟时钟可以选择任何需要的周期,只要这个周期大于组合电路的最大延迟时间。
一个例子:假设组合路径的最大延迟是8.0
creat_clock -name vCLK -period 15
set_input_delay -max 3.0 -clock vCLK[get_ports I1]
set_output_delay -max 4.0 -clock vCLK[get_ports O1]

如果修改了设计,有一条寄存器路径涉及了I1或O1, 那么就和 input_delay 和 output_delay 有关系。 所以从易维护的角度讲,也是建议使用input_delay 和 output_delay ,而不是max_delay。
直通路径 feedthrough
将几个电路单元设成硬 IP,这些IP 提供直通路径,即输入信号直接到达输出端口,不经过其他电路。直通路径内的延迟只是电路单元内部连线的延迟。
一般的,直通路径将贯穿几个连续的电路单元。
点到点的异常
set_max_delay也有最佳的用处,比如在一个设计路径上,有一段路径需要被约束为一个特殊的值。
实例:
set_max_delay "[expr 2*{pcie_ss_pclk_P}\]"
-from \[get_cells "{CUSTOMER_HIERARCHY}Switch_main/UrgReg_0_reg?*?"]
-to [get_clocks pcie_ss_pclk]
双触发器:
双触发同步是处理跨时钟域信号的标准电路结构,用于减少亚稳态传播风险。
电路结构:由两个串联的触发器(DFF)组成,使用目标时钟域时钟。第一级触发器采样异步输入信号,第二级触发器对第一级输出进行采样。输出使用第二级触发器信号。
原理:第一级触发器可能出现亚稳态,但给予其一个完整时钟周期稳定。第二级触发器采样已稳定的信号,大幅降低亚稳态传播到后续逻辑的概率。
always @(posedge clk_dst or posedge rst) begin
if (rst) begin
sync1 <= 1'b0;
sync2 <= 1'b0;
end else begin
sync1 <= async_signal; // 第一级
sync2 <= sync1; // 第二级
end
end
assign sync_out = sync2; // 输出
两级触发器必须在同一时钟域,且工具应将其视为同步器单元,通常设置set_clock_groups -asynchronous或 set_false_path 避免时序检查。
因为这两级触发器之间没有其它逻辑,布线布局工具可能将他们放置的比较远的地方。通常是希望第一级触发器到第二级触发器的延迟非常小,即远小于允许的时钟周期? 所以此时使用 set_max_delay来约束。
路径阻断
1、时序约束中的路径阻断是指通过约束命令阻止工具对特定路径进行时序分析,常用于处理异步时钟域、伪路径或不需要检查的路径。主要命令:
-
set_false_path:完全忽略路径的时序检查 -
set_clock_groups -asynchronous:声明时钟组之间异步,自动阻断跨时钟域路径
2、时序约束中,如果约束部分不是从时序起始点开始,或者不是在时序终点结束,则这些时序约束会在路径线段的两端 "阻断路径"。

如果设置了set_max_delay from I1 to O1, 那么F1开始的时序路径会停止在 I1。因为被阻断了,所以不能定义时序路径: from F1 to F2
set_case_analysis
set_case_analysis是SDC(Synopsys设计约束)中的关键命令,用于在静态时序分析(STA)中将指定信号固定为恒定逻辑值,从而控制分析工具只检查特定工作模式下的时序路径。
1. 选择工作模式
固定为功能模式(禁用测试模式)
set_case_analysis 0 test_mode
set_case_analysis 0 scan_enable固定为测试模式
set_case_analysis 1 test_mode
set_case_analysis 1 scan_enable2. 简化分析复杂度
通过固定配置信号,减少多路选择器分支,让工具只分析当前激活的路径:
// 实际电路
assign data_out = (sel) ? path_a : path_b;约束:只分析path_a
set_case_analysis 1 sel # 现在只检查 path_a → data_out 的时序
3. 隔离不相关路径
忽略低功耗模式路径
set_case_analysis 0 sleep_mode
set_case_analysis 0 power_gate_en
约束管理
自顶向下:整个芯片被看作单个设计单元。约束施加在顶层,设计按照一个独立的单元进行综合。
自底向上的设计方法中,当约束向上传播时,3种变化:
- 只有芯片级的层次结构发生变化时,才会施加模块级的约束;
- 为反应SOC上下文,模块级约束应该被修改;
- 当约束在soc 上下文中没有任何意义,应该被删除。(比如被前模块约束覆盖)
如果需要手动创建芯片级约束,应该验证芯片和模块约束之间的一致性。确保顶层约束与模块间的约束没有冲突。
目前常使用自顶向下和自底向上,两者相结合的方法。
相结合
特点:模块时序按照自顶向下流程进行设计。模块约束时,考虑了在集成时相邻模块的影响。模块的接口约束应该包含:模块信息、input_delay、output_delay、电容、负载、驱动单元等。
正确分割模块间的延迟成为时序预算,
- 分配原则可以是时钟周期的固定比例、或者 逻辑电平数的比例。
- 预算分配后,如果某些模块出现正裕度,则重新分配有正裕度的模块的延迟。(正裕度 = 要求到达时间 - 实际到达时间)
- 时序预算过程可以迭代,出现增量时,不用综合整个设计,只需要对受影响的模块综合。
多工作模式合并
一个芯片通常有多种工作模式,比如快时钟模式、慢时钟模式、省电模式、测试模式、调试模式,不同的PVT角(工艺、电压、温度)。对于多模式多角度的时序约束,需要进行多种模式合并,合并后的模式是一种假设的模式,通常以比较悲观的方式对这个合并模式进行时序建模。
合并时,需要遵守这些准则:
1、合并后的任何路径、对象的约束,不能比任何模式乐观。
2、合并后的约束要易理解;
3、合并约束不应产生过多的命令、扩展太多路径;
4、合并仅限于一个较小的集合。
合并的一些实例;
1、选择悲观时钟
create_clock -name C1 -period 10 [get_ports C1] #模式1
create_clock -name C1 -period 20 [get_ports C1] #模式2
create_clock -name C1 -period 10 [get_ports C1] #模式合并后,选择悲观的时钟
2、时钟互斥时
在电路中有多路选择器,选择C1 or C2
create_clock -name C1 -period 10 [get_ports C1] #模式1
set_case_analysis 1 mux1/S
create_clock -name C2 -period 40 [get_ports C2] #模式2
set_case_analysis 0 mux1/S
合并后:
create_clock -name C1 -period 10 [get_ports C1] #模式1
create_clock -name C2 -period 40 [get_ports C2] #模式2
set_clock_group -logically_exclusive -group C1 -group C2
#保持C1和C2 ,但是在扇出锥外他们不交互
3、合并I/O 延迟
同一个时钟
create_clock -name C1 -period 10 [get_ports C1] #模式1
set_input_delay -min 0.5 -clock C1 [get ports P1]
set_input_delay -max 1.5 -clock C1 [get ports P1]
create_clock -name C1 -period 10 [get_ports C1] #模式2
set_input_delay -min 0.7 -clock C1 [get ports P1]
set_input_delay -max 1.7 -clock C1 [get ports P1]
合并后:
create_clock -name C1 -period 10 [get_ports C1] #模式1
set_input_delay -min 0.5 -clock C1 [get ports P1]
set_input_delay -max 1.7 -clock C1 [get ports P1]
多个时钟
create_clock -name C1 -period 10 [get_ports C1] #模式1
create_clock -name C2 -period 20 [get_ports C1]
set_input_delay -min 0.5 -clock C1 [get ports P1]
set_input_delay -max 1.5 -clock C1 [get ports P1]
create_clock -name C1 -period 10 [get_ports C1] #模式2
create_clock -name C2 -period 20 [get_ports C1]
set_input_delay -min 0.7 -clock C2 [get ports P1]
set_input_delay -max 1.7 -clock C2 [get ports P1]
合并后:
create_clock -name C1 -period 10 [get_ports C1]
create_clock -name C2 -period 20 [get_ports C1]
set_input_delay -min 0.5 -clock C1 [get ports P1] #模式1
set_input_delay -max 15 -clock C1 [get ports P1]
set_input_delay -min 0.7 -clock C2 [get ports P1] -add_delay #模式2
set_input_delay -max 1.7 -clock C2 [get ports P1] -add_delay
set_clock_group -logically_exclusive -group C1 -group C2
#在同一个port 使用了-add_delay, 所以需要对这俩时钟设置时钟组.
4、合并功能和测试模式
待补充