如何写好一份SDC——结构篇
⚠️本文目的为 个人学习记录 及 知识分享。因个人能力受限,存在解读不正确的可能。若您参考本文进行产品设计或进行其他事项并造成了不良后果,本人不承担相关法律责任
文章目录
前言
时序约束 (SDC) 创建必须具有三个重要方面:1)“完整”,约束集包括时钟、输入和输出延迟、时钟延迟、时钟不确定性、设置案例分析(set-case-analysis)、时钟和输入转换(clock and input transition)、输出负载(output load)、最大和最小延迟(max and min delay)、错误路径异常和多周期异常路径(false path exceptions and multi-cycle exceptions paths)。False path exceptions包括时钟域交叉、异步复位、扫描使能以及使用设计的功能分析创建的false path,缺少约束会显着影响结果的质量。;2) “正确”,正确的约束集意味着无需通过外部验证工具来验证约束。这还包括计时异常,这些异常应该通过构造在功能上正确。不正确的时序异常可能会导致芯片时序故障,因为它们可以通过实施步骤掩盖芯片时序问题;3) “有意义的”约束是指不会压垮而是帮助下游工具(如综合和物理设计)的适当集合,以在面积、时序和功耗方面产生更好的芯片 QoR。
本文就一份完整的sdc的结构有哪些来展开。
1、时钟定义包含外部时钟、内部时钟和虚拟时钟
外部时钟指的是作为输入时钟以input形式进入到顶层的时钟,对于该类时钟需要使用下面的命令进行定义:
create_clock -name CLK_NAME -period CLK_PERIOD -waveform "CLK_START CLK_RISE" [get_ports CLK]
set_clock_uncertainty -setup [expr CLK_JITTER + CLK_MARGIN] [get_clocks CLK]
set_clock_uncertainty -hold [expr CLK_MARGIN] [get_clocks CLK]
上述命令依次声明了时钟名字CLK_NAME,可以自定义并不是一定要和CLK一样,但是需要唯一且一致引用;声明了周期,一般用宏定义的形式声明,方便后续调用;声明了占空比,一般情况下CLK_START是0,CLK_RISE是周期的一半用于表示5050占空比;声明了输入进来的物理端口名字;声明了建立时间和保持时间的不稳定性,用于模拟更真实的场景,值得注意的是,在第一行命令中使用的是get_ports用于定位是从该物理端口输入的时钟,而第二/三行中使用get_clocks则是该时钟域下所有的时序路径,也正因为如此可以对路径上时钟设置建立时间/保持时间的不稳定性(个人理解)
派生时钟顾名思义指的是模块内部产生的时钟,生成时钟唯一核心目的是:「当一个内部节点的时钟信号,成为独立时钟域的驱动源(即该信号驱动了其他触发器的时钟端),且其频率 / 相位与主时钟有明确的固定关系时」,才需要定义生成时钟,比如源时钟经历分频、倍频或者mux等。
像下图,两个DFF共同组成了分频器,因此只需要在DFF2/Q上定义派生时钟,而不需要DFF1/Q上定义。
对于该类时钟需要使用下面的命令进行定义:
create_generated_clock -name GC1 -divide_by 3 -source [get_port CLK] -master_clock C1 [get_pins FF2/Q]
结合上面的例子,GC1是声明了派生时钟名字;-divide_by声明几分频;声明了源时钟来源于哪个物理引脚/端口;声明了父时钟来源于哪个输入时钟。
虚拟时钟是作为输入输出端口延时的时钟源,详情见如下链接:
数字IC设计中virtual clock
2、时钟关系声明,一般有异步关系、逻辑互斥和物理互斥
set_clock_group -asynchronous -logically_exclusive -physically_exclusive
-asyn用于声明两组时钟的异步关系,当两个时钟相位不确定的时候可以用,禁止时钟组之间的时序分析,一般而言当时钟来自于不同的PLL或者晶振时,时钟之间的相位是不固定的。如果时钟之间存在CDC路径则可以额外添加-allow_path,意味着虽然声明了两者的异步关系,但是允许使用set_max/min_delay去人为添加时钟之间的延迟以进行时序分析。
-logically_exclusive,如果两个时钟同时存在但是他们之间没有任何 path,则这两个时钟可以设置为 logically exclusive,典型的情况就是一个 MUX 选择两个或多个时钟。但是并不是所有的mux都要设置逻辑互斥,比如下面的例子:

-physical_exclusive,当两个时钟在同一时刻不可能同时存在时,则这两个时钟就可以设置为物理互斥。比如在相同的端口上创建多个时钟,但是这两个时钟工作在不同的工作模式,比如TestClk 和 Function Clock。
调试技巧:
可以使用report_clock -groups去报告实际的时钟关系和预设的时钟关系是否一样
可以使用report_timing -from [get_clocks clka] -to [get_clocks clkb]去报告设置的时钟组之间是否是异步/同步关系
3、端口约束
最先应该做的是梳理顶层设计的输入输出端口,并且根据databook等确定这些端口是同步于哪些时钟,然后使用set xxx [get_port [list xxx xxx]]形式将同步于同一时钟的端口归为一个组方便后续调用。首次通过约束创建通常是一个手动、易出错且耗时的过程。对于大型设计而言,创建时钟定义和输入/输出延迟往往是一项繁琐的任务。
如上图所示,如果在DUA设计上没有对DATAIN DATAOUT的数据进行约束,那么STA工具并不能够得到有外部寄存器经过组合逻辑到达DATAIN的时间,同时也不知道DATAIN信号和输入的MCLK是什么关系,input delay和output delay就是告诉STA工具芯片外部的信号的delay信息。
input delay最常用的设置是对一组信号设置为采样时钟的70%,继续按照上图的例子,值得一提的是这里需要用虚拟时钟。下面是具体的命令,定于端口DATAIN的输入延迟,延迟值是MCLK周期的0.7倍,同步于MCLK时钟。如果稍微改一下场景,我们并不知道DATAIN的驱动时钟或者DATAIN的驱动时钟在DUA中并没有被声明,则需要额外使用虚拟时钟。
set_input_delay -max [expr 0.7 * MCLK] -clock MCLK [get_ports DATAIN]
input_delay/output_delay和普通setup/hold分析模型本质是一样的,都是两个寄存器串联起来,使用同一个clk,但是区别在于,端口约束的两个寄存器内外之分而已。我们以这个简单模型入手进一步分析input_delay/output_delay所约束的数值具体含义。setup/hold分析就不做赘述,具体可见建立时间(setup time)和保持时间(hold time)详析
内部 Reg-to-Reg 模型的建立时间(Setup)公式
对于芯片内部的两个寄存器,STA 工具的计算公式是:
T c l k 2 q _ T X + T c o m b _ i n t e r n a l < T p e r i o d − T s e t u p _ R X + T s k e w T_{clk2q\_TX} + T_{comb\_internal} < T_{period} - T_{setup\_RX} + T_{skew} Tclk2q_TX+Tcomb_internal<Tperiod−Tsetup_RX+Tskew
I/O 模型的建立时间(Setup)公式
当 Reg_TX 位于芯片外部(另一颗芯片),而 Reg_RX 是你 DUT 内部的第一级寄存器时。工具的视角中缺失了芯片外部的延迟信息,于是 SDC 引入了 input_delay:
I n p u t _ D e l a y m a x + T c o m b _ i n t e r n a l < T p e r i o d − T s e t u p _ R X + T s k e w _ i n t e r n a l Input\_Delay_{max} + T_{comb\_internal} < T_{period} - T_{setup\_RX} + T_{skew\_internal} Input_Delaymax+Tcomb_internal<Tperiod−Tsetup_RX+Tskew_internal
可以清晰地看到,Input_Delay_max 在数学模型中,完美等价并直接替换了外部电路的延迟总和:
I n p u t _ D e l a y m a x ≡ T c l k 2 q _ e x t + T t r a c e _ e x t − T s k e w _ e x t Input\_Delay_{max} \equiv T_{clk2q\_ext} + T_{trace\_ext} - T_{skew\_ext} Input_Delaymax≡Tclk2q_ext+Ttrace_ext−Tskew_ext
对于保持时间(Hold Time)的 -min 分析,其等价映射关系也是完全一致的。这也就是所约束的数值含义,覆盖了工具所看不到的边界盲区(外部器件什么时候发数据?外部 PCB 走线有多长?),这个值当作上游的Arrival Time,接着往下算内部那段就行了。工具根本无法知道真实的外部 Skew 是多少,因此创建一个完全虚拟的时钟(Virtual Clock)来专门模拟外部那个clk的时钟相位,从而将内外时钟域在逻辑上进行解耦约束。
如何理解max/min:
set_input_delay和set_output_delay用的是-max和-min。max对应的是建立时间,担心的是太晚情况,对于输入来说担心的最晚到达输入端口,对于输出担心的是最晚到达下游器件输入。min是保持时间,担心太早情况,对于输入就是说新数据来的太早,对于输出就是给下游新的数据太早。
具体来说,建立时间是时钟有效沿来之前数据维持稳定的时间,对于输入如果max超出范围也就是太晚到达,对于要求最晚11ns到达留了足够的建立时间,但是你12ns到达就不满足建立时间出现亚稳态,对于输入如果min小于范围也就是太早,对于要求最早1ns离开(新数据到)留够了保持时间,但是你0.5ns就离开(新数据到)就不满足保持时间出现亚稳态。
对于输出来说,max超范围,给下游数据太晚,建立时间不满足,min小于范围,给下游数据太早,保持时间不满足。
4、CDC路径
如果存在跨时钟域路径,时钟之间没有确定的相位关系,数据是靠同步器(比如两级触发器)来传递的。这条路径的延迟可以很长,只要不超过同步器的“容忍”范围就行,所以常规的setup/hold检查在这里不适用。因此这种情况下我们要结合set_clock_group -asyn -allow_path去使用set_max/min_delay去约束时序路径。
在同步时钟时序分析中,由于在两个DFF之间的用的是同一个时钟,在计算建立时间和保持时间的时候对于时钟仅需要考虑是Tlaunch和Tcapture,但是在异步时钟中,两个DFF分别用的是两个周期不同相位不明确的时钟,因此需要使用max/min delay去定义两个时钟间的延迟,方便进行setup/hold_time的计算。
更多推荐

所有评论(0)