相关阅读
静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html
当设计中存在多个时钟(同步或异步)时,该如何使用SDC命令约束设计呢?本文就将对此进行讨论。
逻辑独立
例1 多个时钟完全逻辑独立
图1 逻辑独立的时钟
以图1所示的待综合设计为例, 其中CLK1和CLK2是来自同一个晶振的分频时钟,频率分别是500MHz和750MHz,由于有确定的相位关系,它们是同步的。
可以注意到,在待综合设计中两个时钟域不会出现交互情况,但来自两个时钟域的信号通过多路复用器驱动输出端口OUT,而输出端口OUT在外部解复用并分别驱动各自时钟域的寄存器。
由于两个多路复用/解复用器的选择端是连接在一起的,因此当选择输出CLK1时钟域的信号时,输出端口OUT驱动外部的CLK1时钟域的寄存器;当选择输出CLK2时钟域的信号时,输出端口OUT驱动外部的CLK2时钟域的寄存器;
假设使用以下的SDC命令约束待综合设计,会发生什么?
create_clock -period 2.0 [get_ports CLK1]
create_clock -period [expr {1000/750.0}] [get_ports CLK2]
set_output_delay -max 0.15 -clock [get_clocks CLK1] [get_ports OUT1]
set_output_delay -max 0.52 -clock [get_clocks CLK2] -add_delay [get_ports OUT1] # 值得注意的是,为了在同一个端口定义两个输出延迟,需要在第二个set_output_delay命令时使用-add_delay选项,否则将会覆盖第一个输出延迟
在这种情况下,Design Compiler将会认为来自CLK1时钟域的信号可以被CLK2时钟域的寄存器捕获,而来自CLK2时钟域的信号可以被CLK1时钟域的寄存器捕获,从而在这几种情况中找出最严格的发射/捕获沿进行分析,这是过分约束的。实际上,我们希望Design Compiler忽略从CLK1时钟域到CLK2时钟域和CLK2时钟域到CLK1时钟域的时序分析。有两种方法可以完成该要求,使用set_false_path命令或set_clock_groups命令。
使用两条set_false_path命令,指定起点为时钟CLK1,终点为时钟CLK2的时序路径和起点为时钟CLK2,终点为时钟CLK1的时序路径为虚假路径;使用set_clock_groups命令创建两个逻辑独立的时钟组,分别包含CLK1和CLK2时钟。
create_clock -period 2.0 [get_ports CLK1]
create_clock -period [expr {1000/750.0}] [get_ports CLK2]
set_output_delay -max 0.15 -clock [get_clocks CLK1] [get_ports OUT1]
set_output_delay -max 0.52 -clock [get_clocks CLK2] -add_delay [get_ports OUT1]set_false_path -from [get_clocks CLK1] -to [get_clocks CLK2]
set_false_path -from [get_clocks CLK2] -to [get_clocks CLK1]
# 两种方式均可
set_clock_groups -logically_exclusive -group [get_clocks CLK1] -group [get_clocks CLK2]
例2 多个时钟部分逻辑独立
图2 部分逻辑独立的时钟
图2所示的例2与例1相似,唯一的区别在于,在待综合设计中时钟域CLK1与时钟域CLK2之间存在时序路径(如图中的红线所示),如果还使用如下所示的SDC命令,会发生什么?
create_clock -period 2.0 [get_ports CLK1]
create_clock -period [expr {1000/750.0}] [get_ports CLK2]
set_output_delay -max 0.15 -clock [get_clocks CLK1] [get_ports OUT1]
set_output_delay -max 0.52 -clock [get_clocks CLK2] -add_delay [get_ports OUT1]set_false_path -from [get_clocks CLK1] -to [get_clocks CLK2]
set_false_path -from [get_clocks CLK2] -to [get_clocks CLK1]
# 两种方式均可
set_clock_groups -logically_exclusive -group [get_clocks CLK1] -group [get_clocks CLK2]
这会导致待综合设计中时钟域CLK1与时钟域CLK2之间存在的时序路径也被忽略,这不是我们希望发生的,我们只希望忽略经过输出端口的不同时钟域间的时序路径。在这种情况下,只能使用set_false_path命令完成该要求,可以通过使用-through选项获得更加细粒度的控制,而不能使用set_clock_groups命令。
create_clock -period 2.0 [get_ports CLK1]
create_clock -period [expr {1000/750.0}] [get_ports CLK2]
set_output_delay -max 0.15 -clock [get_clocks CLK1] [get_ports OUT1]
set_output_delay -max 0.52 -clock [get_clocks CLK2] -add_delay [get_ports OUT1]set_false_path -from [get_clocks CLK1] \-through [get_ports OUT1] -to [get_clocks CLK2]
set_false_path -from [get_clocks CLK2] \-through [get_ports OUT1] -to [get_clocks CLK1]
例3 多个时钟驱动同一个寄存器1
图3 多个时钟驱动同一个寄存器1
在图3所示的例3中,时钟CLK1和时钟CLK2首先经过输入端口SEL1控制的多路复用器,随后再连接到寄存器的时钟端,也就是说待综合设计中的寄存器要么被时钟CLK1驱动,要么被时钟CLK2驱动。但是默认情况下,Design Compiler不会考虑多路复用器的选择性并认为多个时钟能驱动一个寄存器(该行为可以通过timing_enable_multiple_clocks_per_reg变量改变),因此来自CLK1时钟域的信号可以被CLK2时钟域的寄存器捕获,而来自CLK2时钟域的信号可以被CLK1时钟域的寄存器捕获,Design Compiler将在这几种情况中找出最严格的发射/捕获沿进行分析,这是过分约束的。实际上,我们希望Design Compiler忽略从CLK1时钟域到CLK2时钟域和CLK2时钟域到CLK1时钟域的时序分析。有四种方法可以完成该要求,使用set_disable_timing命令、set_case_analysis命令、set_false_path命令或set_clock_groups命令。
使用set_disable_timing可以将某个时钟从多路复用器输入端到输出端的时序弧中断,从而忽略有关该时钟的分析;使用set_case_analysis命令可以指定输入端口SEL1的值,从而只允许某个时钟经过多路复用器,从而忽略其他时钟的分析。
create_clock -period ... [get_ports CLK1]
create_clock -period ... [get_ports CLK2]
set_disable_timing [get_cell MUX] -from A -to Y
# 两种方式均可
set_case_analysis 0 [get_port SEL1]
上面这两种该方法的缺点也很明显,即只能选择某一个时钟进行约束,综合时并不会考虑到其他时钟的影响,这依赖用户选择最严格的时钟进行约束,对于例3这种简单情况下尚可接受,但在例4所示的复杂情况下就会变得困难。
使用两条set_false_path命令,指定起点为时钟CLK1,终点为时钟CLK2的时序路径和起点为时钟CLK2,终点为时钟CLK1的时序路径为虚假路径;使用set_clock_groups命令创建两个逻辑独立的时钟组,分别包含CLK1和CLK2时钟。
create_clock -period ... [get_ports CLK1]
create_clock -period ... [get_ports CLK2]set_false_path -from [get_clocks CLK1] -to [get_clocks CLK2]
set_false_path -from [get_clocks CLK2] -to [get_clocks CLK1]
# 两种方式均可
set_clock_groups -logically_exclusive -group [get_clocks CLK1] -group [get_clocks CLK2]
例4 多个时钟驱动同一个寄存器2
图4 多个时钟驱动同一个寄存器2
在图4所示的例4中,时钟CLK1和时钟CLK2首先经过输入端口SEL1控制的多路复用器,随后再连接到部分寄存器的时钟端;时钟CLK3和时钟CLK4首先经过输入端口SEL2控制的多路复用器,随后再连接到部分寄存器的时钟端。在这种情况下,我们希望Design Compiler忽略CLK1时钟域与CLK2时钟域和CLK3时钟域与CLK4时钟域之间的时序分析。与例3类似,有四种方法可以完成该要求,使用set_disable_timing命令、set_case_analysis命令、set_false_path命令或set_clock_groups命令。
使用set_disable_timing命令或使用set_case_analysis命令的缺点已经在例3中进行了说明,时序分析只能在时钟CLK1或时钟CLK2与时钟CLK3或时钟CLK4之间进行,这依赖用户选择最严格的时钟对进行约束。
使用四条set_false_path命令,指定起点为时钟CLK1,终点为时钟CLK2的时序路径、起点为时钟CLK2,终点为时钟CLK1、起点为时钟CLK3,终点为时钟CLK4的时序路径和起点为时钟CLK4,终点为时钟CLK3的时序路径的时序路径为虚假路径;使用两条set_clock_groups命令创建逻辑独立的时钟组,其中一对时钟组包含CLK1和CLK2时钟,另一对时钟组包含CLK3和CLK4时钟。
create_clock -period ... [get_ports CLK1]
create_clock -period ... [get_ports CLK2]
create_clock -period ... [get_ports CLK3]
create_clock -period ... [get_ports CLK4]set_false_path -from [get_clocks CLK1] -to [get_clocks CLK2]
set_false_path -from [get_clocks CLK2] -to [get_clocks CLK1]
set_false_path -from [get_clocks CLK3] -to [get_clocks CLK4]
set_false_path -from [get_clocks CLK4] -to [get_clocks CLK3]
# 两种方式均可
set_clock_groups -logically_exclusive -group [get_clocks CLK1] -group [get_clocks CLK2]
set_clock_groups -logically_exclusive -group [get_clocks CLK3] -group [get_clocks CLK4]
例5 多个时钟驱动同一个寄存器3
图5 多个时钟驱动同一个寄存器3
图5所示的例5与例4相似,唯一的区别在于,两个多路复用器的选择端是连接在一起的,只能固定选择时钟CLK1与时钟CLK3或时钟CLK2与时钟CLK4。在这种情况下,我们希望Design Compiler忽略CLK1时钟域与CLK2时钟域、CLK3时钟域与CLK4时钟域、CLK1时钟域与CLK4时钟域和CLK2时钟域与CLK3时钟域之间的时序分析。
使用set_disable_timing命令或使用set_case_analysis命令的缺点已经在例3中进行了说明,时序分析只能在时钟CLK1与时钟CLK3之间或时钟CLK1与时钟CLK3之间进行,这依赖用户选择最严格的时钟对进行约束。
如果使用set_false_path命令,则需使用八条时序路径为虚假路径;而只需使用一条set_clock_groups命令创建两个逻辑独立的时钟组,分别包含CLK1、CLK3和CLK2、CLK4时钟。
create_clock -period ... [get_ports CLK1]
create_clock -period ... [get_ports CLK2]
create_clock -period ... [get_ports CLK3]
create_clock -period ... [get_ports CLK4]set_false_path -from [get_clocks CLK1] -to [get_clocks CLK2]
set_false_path -from [get_clocks CLK2] -to [get_clocks CLK1]
set_false_path -from [get_clocks CLK3] -to [get_clocks CLK4]
set_false_path -from [get_clocks CLK4] -to [get_clocks CLK3]
set_false_path -from [get_clocks CLK1] -to [get_clocks CLK4]
set_false_path -from [get_clocks CLK4] -to [get_clocks CLK1]
set_false_path -from [get_clocks CLK2] -to [get_clocks CLK3]
set_false_path -from [get_clocks CLK3] -to [get_clocks CLK2]
# 两种方式均可
set_clock_groups -logically_exclusive -group "CLK1 CLK3" -group "CLK2 CLK4"
物理独立
例6 多个时钟物理独立
图6 物理独立的时钟
在例2、例3和例4中,在使用set_clock_groups命令时添加了-logically_exclusive选项,那么什么是逻辑独立呢?对于Design Compiler而言,逻辑独立的时钟组可以被简单理解为,不在这些时钟组之间进行时序分析,但对于IC Compiler或PrimeTime-SI而言,逻辑独立的时钟组之间会进行串扰分析,这是基于侵害者和受害者之间的时序重叠窗口进行的。
例6其实和例3几乎完全一样,唯一的区别在于,时钟CLK1和时钟CLK2是在待综合设计外部经过多路复用器然后从同一个输入端口Clk输入,在这种情况下会在输入端口Clk上定义两个时钟,但在使用set_clock_groups命令时还应该使用-logically_exclusive选项吗?
create_clock -period ... -name CLK1 [get_ports Clk]
create_clock -period ... -name CLK2 -add [get_ports Clk] # 值得注意的是,为了在同一个端口定义两个时钟,需要在第二个create_clock命令时使用-add选项,否则将会覆盖第一个时钟set_clock_groups -logically_exclusive -group [get_clocks CLK1] -group [get_clocks CLK2]
答案是否定的。由于逻辑独立的时钟组之间会进行串扰分析,IC Compiler或PrimeTime-SI在分析时会考虑到两个时钟之间的时序重叠窗口,这很显然是不合理(悲观)的,因为在物理上这两个时钟并不会同时进入设计,因此这是过分约束的。
使用-physically_exclusive选项而不是-logically_exclusive选项,能够获得更加准确的串扰分析,尽管对于Design Compiler而言,这两个选项没有任何区别。
create_clock -period ... -name CLK1 [get_ports Clk]
create_clock -period ... -name CLK2 -add [get_ports Clk]set_clock_groups -physically_exclusive -group [get_clocks CLK1] -group [get_clocks CLK2]
也许有人会问,既然-physically_exclusive选项比-logically_exclusive选项能够获得更加准确的串扰分析,那为什么不干脆全用-physically_exclusive选项?例1就应该使用-logically_exclusive选项而不是-physically_exclusive选项,因为两个时钟可以同时存在设计内并且相互之间出现串扰。
异步
例7 多个时钟异步
图7 异步时钟
例1到例6所展示的都是同步时钟,它们来自于同一个晶振,而例7中的两个来自不同晶振输出的异步时钟,它们之间的相位关系是不可预测的,因为每个晶振稳定之后的相位都是不确定。可以从图7中看出,为了避免在跨时钟域时出现亚稳态,在CLKB时钟域中有两级触发器用于同步。
我们希望Design Compiler忽略CLKA时钟域与CLKB时钟域之间的时序分析,但此时需要使用-asynchronous选项,该选项在Design Compiler中与-physically_exclusive选项、logically_exclusive选项没有任何区别,但是IC Compiler或PrimeTime-SI在分析时会认为两个时钟之间拥有无限宽的时序重叠窗口。
create_clock -period ... [get_ports CLKA]
create_clock -period ... [get_ports CLKB]set_clock_groups -asynchronous -group [get_clocks CLKA] -group [get_clocks CLKB]
时钟分组的建议
1、如果设计中能共存多个时钟,但通过多路复用器只能选择其中一个,则使用-logically_exclusive选项。
2、如果设计中不能共存多个时钟(这一般出现在一个时钟源对象上定义了多个时钟),则使用-physically_exclusive选项。
3、如果设计中能共存多个时钟,但它们没有固定的相位关系,则使用-asynchronous选项。