一、实战小技巧
1.书写规范,注意换行符与空格,换行符后面不能加空格,#不能插在换行符中间
2.将参数变量化以方便更改,注意数值是否要浮点化(加小数点)和是否除得尽,下面是例子:
set CLK_DIV4 500
set RSS_CLK_GEN_HIER u_rss_top/u_rss_clk_gen_sv
set rss_bus_clk_p [expr (1000.0/1600.0)]
set rss_PLL_clk_p [expr 1000.0/($CLK_DIV4 *1.25)]
set QSPI_INOUT [get_ports {qspi_di qspi_do qspi_hold qspi_wp}] //这就是input list
3.对所有时间路径作约束,即对所有时钟要创建或说明,不然DC会报错或者warning。如果端口处存在时钟,一定要说明,不然DC会将其作为一般io,DC会要你设output_delay
4.get_pins一般建议追到cell里面的触发器的C或D端,hierarchy从第二级开始书写,追寻路径时使用模块的例化名字
5.外部异步信号在用作本模块复位时要先对外部信号进行异步复位同步释放操作,对于在模块外部已经与本模块同步的信号,要设input_delay
6.在创建时钟时,可以将所有时钟频率抬高30%左右,为后续优化留下空间
7.在设置时钟组的时候,要将生成时钟也假加入到创建的时钟组分组下面去
二、常用语法
1.创建时钟
create_clock -period 20 -name clk_50m -waveform {8 12} [get_ports Clk] -add
wavefrom一般不要,create_generated_clock用-edge {},多个时钟用同一个端口使用add
2.衍生时钟
create_clock : 一般指定时钟源,如PAD输入,或者是内部振荡器产生的时钟,不需要时钟源作为输入
reate_generated_clock : 一般用于指定内部通过时钟源产生的(分频、倍频)时钟,需要一个或多个时钟源作为输入时钟
create_generated_clock -name clock_name \
-source [get_pins {top/second/ddddd}]\
-master [get_clocks {clk_name}] \
-edges {1 9 17} \ //当生产时钟相位与原时钟相位等差别较大,强烈推荐使用这种方式
-edge_shift {2.2 2.2 2.2} \//将每个时钟沿往后延迟2.2ns,变成{3.2 11.2 19.2}
-divide_by 4\
-multiply_by 4\
-duty_cycle percent \指定占空比
-combinational \ 指定源滞后路径
-invert] \ 与正常分频后时钟反相
-preinvert \ 采用源时钟下降沿作分频时钟的开始
-add \
[get_pins {top/second/Q}] 当有引用时换成 [get_pins "$define/second/Q"] //set define top
3. input_delay output_delay
为啥要作这个约束?
如果不设置input delay和output delay,那么工具并不知道上述信息,也就是说工具并不会分析这条path。由于大多数信号进入芯片内部都是需要和芯片内部进行数据传递的,所以必须通过设计input delay和output delay的方式告诉工具此处的timing信息,这样才能保证输入的信号能够被芯片内部正确的采样,从而保证芯片工作正常。
反之,如果某些信号是一些在芯片正常工作之前就稳定的常值信号(bist en 等),那么实际上是没有必要对这些信号进行timing 分析的,所以这些信号可以不用设计input delay来简化约束。
描述port端口上的约束,是模块间的约束(与建立时间作区分)
input delay:输入信号在时钟到达后多久到达模块输入port
set_input_delay
delay_value //延迟值
[-reference_pin pin_port_name]
[-clock clock_name] //-clock [get_clocks rss_qspi_pll_sclk]创建的虚拟时钟
[-clock_fall] //如果外部时钟下降沿发送数据,需要指定该参数
[-level_sensitive]
[-network_latency_included]
[-source_latency_included]
[-rise]
[-fall]
[-max] //一般写一个input delay都是一个外部时钟对应多个port,所以有最大值,最小值
[-min] // max分析setup,min分析holdup
[-add_delay]
port_pin_list //指定设置input delay的port是哪些
Data Types
delay_value float
clock_name collection of 1 object
port_pin_list collection
常用70%设置,
set_input_delay -max [expr 0.7 * Tapb_clk] -clock apb_clk [get_ports apb_pwdata]
set_input_delay -min 2 -clock apb_clk [get_ports apb_pwdata]
//max一般看时钟,最大70%吧,min也是,保险起见在工程中我们设置的是0
set_output_delay:该输出信号在后级模块中需要在时钟沿之前提前多长时间准备好。与input差不多,我们一般使用data path-clk path +setup time作max
4.假路径约束
set_false_path -from [get_clocks clka] -to [get_clocks clkb]
用的少,对于一般情况,我们可以通过设置异步时钟组完成,对于特殊的测试单元等不跨时钟域但也不需要分析的路径却是必不可少的。
此外,对于reset,如果在工作时,reset信号有效时,时钟信号不翻转,用set_false_path。
但是,如果reset信号有动作,时钟同时也有动作,则不能set_false_path。一般异步复位可以设置false path,但是用某个clk抓过之后的异步复位(异步复位同步撤离),再在这个clk域下使用时,不要设置false path,会提示设置input_delay
5.时钟组 set_clock_groups
set_clock_groups
-physical_exclusive //物理排斥,多时钟定义在同一源接脚(mux之后)
|-logically_exclusive //逻辑排斥(MUX多路选择之前)
|-asynchronous //时钟异步,除了创建的时钟,还要包含生成时钟
[-allow_paths]
[-name name]
-group clock_list //-groups {clk1 clk2} -groups{clka clkb}
例子:-groups [get_clocks -include_generated_clocks clk0] \
-groups [get_clocks -include_generated_clocks clk1]
6.set_clock_latency 指定时钟网络滞后
set_clock_latency
-rise
-fall
-min
-max
-source
-early
-late
-clock clock_list
delay
object
7.set_multicycle_path 多周期路径
同时钟域,不同频率
快到慢,慢到快
要好好理解一下,还有点糊涂。对象是谁,设在哪,一般要求是,设置好的前后效果,危害
(4条消息) sdc中set_multicycle_path的解释_进击的芯片的博客-CSDN博客_set_multicycle_path
关于set_multicycle_path的问题 - 哔哩哔哩 (bilibili.com)
8.设置端口驱动能力
set_drive
复杂时钟树的sdc约束方法:
1.创建外部时钟
2.使用set_generated_clock,将输入时钟进行重命名,如图x0,x1是对rco,hxt的重命名
3.使用set_generated_clock,生成从mux出来的时钟,注意几选择mux就生成几个,如z0,z0_1,z0_2;
4.设置set_clock_groups -logical_exclusive -group{xo} -group{x1} 对mux前面的时钟进行约束,使其逻辑互斥,表示理论上不同时出现
5.设置set_clock_groups -physical_exclusive -group{zo} -group{z0_1} -group(z0_2)对mux出来的时钟进行约束,使其物理互斥,表示不同时出现
( 一般对时钟加SI(质量?)检查,检查信号完整性 )
6.后面类似,凡是mux前面的都要声明logical_exclusive的分组,mux后面声明physical_exclusive的分组,所以如图到 buf 前面,一共要声明四轮,到 buf一共create_generated_clock 了5个z
7此时,在buf前z处,存在5个不同名字,共用路径的时钟,为了方便,需要将其归一化,具体的操作是:新建不同的sdc文件,先使用set_case_analysis控制mux,使z处分情况,然后
set_generated_clock -name clk(buf后面那根线) -master_clock rco/hxt/pll/sleep/lxt的衍生名(之前不是说生成了5个名字嘛,就是那个名字) -source [get_pins z] -add -divide 1 [get_pins z`](buf后面的pin)
至此,buf后面模块再使用clk时,有了统一的名字
下面对分频器进行说明:
其实差不多