赞
踩
目录
3.3.1 Set False Path与Set Clock Group
3.3.2 Set False Path与Set Disable Timing
4.4.3 Rename Auto-Derived Clock
4.4.10 set_input_delay/set_output_delay
4.4.11 set_max_delay/set_min_delay
在之前的文章中,以命令为章节进行了相关的使用说明,命令间彼此间是相互独立的。在本章中,将从时序约束整体的角度对这些约束进行一个使用说明概述,结合时序报告,这样有助于深入理解命令的使用。
时序约束根据约束特性可分为5类:时钟特性,端口路径延时,时序例外约束,断言约束,其他类,每一类的功能作用如下图
clock latency的理解可分为PLL和非PLL来进行,时钟源来自芯片内部的PLL,图中的Clock definition point即是指用create_clock约束的位置,pll的输出位置即为时钟源位置
时钟源来自芯片外部时,create_clock的位置即为图中clock definition point位置,到触发器的CK端口时延为Network latency,时钟源到定义点的时延为source latency
主时钟:
生成时钟Generated clock:来源于主时钟,如主时钟的分频时钟或倍频时钟。因此,生成时钟的时钟源为对应的主时钟,时序路径分析时,生成时钟路径中时钟的起点是主时钟的定义位置。
虚拟时钟Virtual clock:主要用于辅助内部设计与外部设计进行时序分析
问题:是否可以将生成时钟替换成另一个主时钟?
该操作是可以的,也存在相关场景,但是会存在一些缺点,通过使用create_clock创建主时钟代替create_generated_clock创建的生成时钟将会产生一个新的时钟域,会引入一些跨时钟域问题,而使用生成时钟不会产生新的时钟域。
另外,主时钟的时钟源在时钟的定义位置点,生成时钟的时钟源是对应的主时钟,因此用生成时钟时源时钟source latency会自动的被包含。
在设置时序约束时,按照一定的逻辑顺序进行约束有助于他人对约束的理解以及修改,建议按照以下顺序设置时序约束
## 第一部分:时钟申明
# Primary clocks 使用create_clock创建主时钟
# Virtual clocks 使用create_clock创建虚拟时钟
# Generated clocks 使用create_generated_clock创建生成时钟
## 第二部分:时钟断言
# Clock Groups 使用set_clock_groups设置时钟组
# Bus Skew constraints 使用set_bus_skew时钟总线偏斜约束
# Input and output delay constraints 使用set_input_delay/set_output_delay设置输入输出端口时延
## 第三部分:设置时序例外
# False Paths 使用set_false_path设置虚假路径
# Max Delay / Min Delay 使用set_max_delay/set_max_delay设置最大、最小时延约束
# Multicycle Paths 使用set_multicycle_path设置多周期约束
# Case Analysis 使用set_case_analysis设置案例分析约束
# Disable Timing 使用set_disable_timing设置断开时序
## 第四部分:设置物理约束
优先级如下图
在时序约束中,不同约束之间存在优先级,这个需要特别注意,否则将达不到预期的约束效果
1)相同类型的约束,后者会覆盖前者,以creat_clock约束为例,实际生效的是第二条约束
create_clock -name clk1 -period 10 [get_ports clk_in1]
create_clock -name clk2 -period 11 [get_ports clk_in1]
但如果是后一条添加了-add,则两条都会生效
create_clock -name clk1 -period 10 [get_ports clk_in1]
create_clock -name clk2 -period 11 [get_ports clk_in1] -add
2)时序例外的约束优先级示例
a.下面的set_max_delay中,第一条约束的比第二条更详细,因此第一条约束生效
set_max_delay 12 -from [get_clocks clk1] -to [get_clocks clk2]
set_max_delay 15 -from [get_clocks clk1]
b. 下面的约束中,第一条约束对象为cell,并且约束更紧,第二条约束对象中from为时钟,并且里面的through不会影响优先级。因此,第一条约束覆盖第二条约束。
set_max_delay 12 -from [get_cells inst0] -to [get_cells inst1]
set_max_delay 15 -from [get_clocks clk1] -through [get_pins hier0/p0] -to [get_cells inst1]
两者都可以针对时钟对象设置不分析,但set false path存在方向性,set clock group不考虑方向。
示例:set_false_path from clk1 -to clk2;set_false_path from clk2 -to clk1 等效于 set_clock_group -asynchronous -group clk1 -group clk2
除去设置格式的差异,从表面看两者都可以针对设置的对象不进行分析,set_disable_timing是屏蔽时序弧,等价于移除,与该时序弧相关的所有路径都会被移除,当需要对经过某个pin/cell/port上的所有路径都不进行分析时,则建议使用set_disable_timing
set_false_path是不对路径进行时序处理,时序弧仍有效,如果该时序弧相关的时序路径有多条,伪路径只作用于部分路径,时序工具会计算所有时序路径,但只对存在时序约束的时序路径进行分析。
下面以一个设置了所有时序约束的工程对时序约束进行示例
- module all_timing(CLKIN1,CLKIN2,CLKINSEL,CLKFBIN,CLKFBOUT,clk1,clk2,rst,d1,d2,S,i_bus,o_bus,bus_clk2,out_syn,out_asyn,and_out,o_case);
- input CLKIN1,CLKIN2,CLKINSEL,CLKFBIN,clk1,clk2,rst,d1,d2,S;
- input [4:0] i_bus;
- output reg [4:0] o_bus,bus_clk2;
- output out_syn,out_asyn,and_out,CLKFBOUT;
- reg ff1,ff2,ff_asyn,ff_syn,ff_and;
- reg ff_case;
- output reg o_case;
- reg [4:0] bus;
- wire sum12,and_c,CLKOUT0,CLKOUT1;
- wire [4:0] bus_c;
- wire o_bufgmux,ffcase_n;
-
- PLLE2_ADV #(
- .BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW
- .CLKFBOUT_MULT(8), // Multiply value for all CLKOUT, (2-64)
- .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360.000-360.000).
- // CLKIN_PERIOD: Input clock period in nS to ps resolution (i.e. 33.333 is 30 MHz).
- .CLKIN1_PERIOD(0.0),
- .CLKIN2_PERIOD(0.0),
- // CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for CLKOUT (1-128)
- .CLKOUT0_DIVIDE(1),
- .CLKOUT1_DIVIDE(2),
- .CLKOUT2_DIVIDE(4),
- .CLKOUT3_DIVIDE(5),
- .CLKOUT4_DIVIDE(1),
- .CLKOUT5_DIVIDE(1),
- // CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for CLKOUT outputs (0.001-0.999).
- .CLKOUT0_DUTY_CYCLE(0.4),
- .CLKOUT1_DUTY_CYCLE(0.5),
- .CLKOUT2_DUTY_CYCLE(0.5),
- .CLKOUT3_DUTY_CYCLE(0.5),
- .CLKOUT4_DUTY_CYCLE(0.5),
- .CLKOUT5_DUTY_CYCLE(0.5),
- // CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for CLKOUT outputs (-360.000-360.000).
- .CLKOUT0_PHASE(0.0),
- .CLKOUT1_PHASE(0.0),
- .CLKOUT2_PHASE(0.0),
- .CLKOUT3_PHASE(0.0),
- .CLKOUT4_PHASE(0.0),
- .CLKOUT5_PHASE(0.0),
- .COMPENSATION("EXTERNAL"), // ZHOLD, BUF_IN, EXTERNAL, INTERNAL
- .DIVCLK_DIVIDE(1), // Master division value (1-56)
- // REF_JITTER: Reference input jitter in UI (0.000-0.999).
- .REF_JITTER1(0.0),
- .REF_JITTER2(0.0),
- .STARTUP_WAIT("FALSE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE")
- )
- PLLE2_ADV_inst (
- // Clock Outputs: 1-bit (each) output: User configurable clock outputs
- .CLKOUT0(CLKOUT0), // 1-bit output: CLKOUT0
- .CLKOUT1(CLKOUT1), // 1-bit output: CLKOUT1
- .CLKOUT2(CLKOUT2), // 1-bit output: CLKOUT2
- // Feedback Clocks: 1-bit (each) output: Clock feedback ports
- .CLKFBOUT(CLKFBOUT), // 1-bit output: Feedback clock
-
- // Clock Inputs: 1-bit (each) input: Clock inputs
- .CLKIN1(CLKIN1), // 1-bit input: Primary clock
- .CLKIN2(CLKIN2), // 1-bit input: Secondary clock
- // Control Ports: 1-bit (each) input: PLL control ports
- .CLKINSEL(CLKINSEL), // 1-bit input: Clock select, High=CLKIN1 Low=CLKIN2
- .RST(rst), // 1-bit input: Reset
- // Feedback Clocks: 1-bit (each) input: Clock feedback ports
- .CLKFBIN(CLKFBIN) // 1-bit input: Feedback clock
- );
- // End of PLLE2_ADV_inst instantiation
-
-
- always@(posedge CLKOUT0,negedge rst)
- if(!rst)
- begin
- ff1<=1'b0;
- ff2<=1'b0;
- end
- else begin
- ff1<=d1;
- ff2<=d2;
- end
-
- assign sum12=ff1+ff2;
- always@(posedge CLKOUT1,negedge rst)
- if(!rst)
- ff_syn<=1'b0;
- else begin
- ff_syn<=sum12;
- end
- assign out_syn=ff_syn;
- always@(posedge clk1,negedge rst)
- if(!rst)
- ff_asyn<=1'b0;
- else begin
- ff_asyn<=sum12;
- end
- assign out_asyn=ff_asyn;
- assign and_c=ff_asyn&d1;
-
- always@(posedge clk1,negedge rst)
- if(!rst)
- ff_and<=1'b0;
- else begin
- ff_and<=and_c;
- end
- assign and_out=ff_and;
- always@(posedge clk1,negedge rst)
- if(!rst)
- bus<=5'b0;
- else begin
- bus<=i_bus+1'b1;
- end
- assign bus_c=bus+d2;
- always@(*)
- begin
- o_bus=bus;
- end
- always@(posedge clk2,negedge rst)
- if(!rst)
- bus_clk2<=5'b0;
- else begin
- bus_clk2<=bus_c+d1;
- end
-
-
- //set_case_analysis
- BUFGMUX #(
- )
- BUFGMUX_inst (
- .O(o_bufgmux), // 1-bit output: Clock output
- .I0(CLKIN1), // 1-bit input: Clock input (S=0)
- .I1(CLKIN2), // 1-bit input: Clock input (S=1)
- .S(S) // 1-bit input: Clock select
- );
-
- always@(posedge o_bufgmux,negedge rst)
- if(!rst)
- ff_case<=1'b0;
- else begin
- ff_case<=d1;
- end
- assign ffcase_n=!ff_case;
- always@(posedge o_bufgmux,negedge rst)
- if(!rst)
- o_case<=1'b0;
- else begin
- o_case<=ffcase_n;
- end
-
- endmodule
设计中的约束如下
- //创建主时钟和生成时钟
- create_clock -period 10.000 -name clkin1 -waveform {0.000 5.000} -add [get_ports CLKIN1]
- create_clock -period 5.000 -name clkin2 -waveform {0.000 2.500} -add [get_nets CLKIN2]
- create_clock -period 4.000 -name clk2 -waveform {0.000 2.000} -add [get_ports clk2]
- create_clock -period 4.000 -name clk1 -waveform {0.000 2.000} -add [get_ports clk1]
- create_generated_clock -name gen_clk -source [get_pins PLLE2_ADV_inst/CLKOUT1] -multiply_by 2 -add -master_clock clkin2 [get_pins PLLE2_ADV_inst/CLKOUT0]
- set_input_jitter [get_clocks clk2] 0.500
- set_clock_latency -clock [get_clocks clk2] 0.333 [get_pins {bus_reg[1]/D}]
- set_system_jitter 0.009
- set_clock_uncertainty 0.500 [get_clocks clk1]
-
-
- //设置时钟组和总线偏斜
- set_clock_groups -name clkin1_group -asynchronous -group [get_clocks clkin1]
- set_bus_skew -from [get_cells {{bus_reg[0]} {bus_reg[1]} {bus_reg[2]} {bus_reg[3]} {bus_reg[4]}}] -to [get_cells {{bus_clk2_reg[0]} {bus_clk2_reg[1]} {bus_clk2_reg[2]} {bus_clk2_reg[3]} {bus_clk2_reg[4]}}] 0.550
- set_input_delay -clock [get_clocks clk1] 1.111 [get_ports {d1 d2 {i_bus[0]} {i_bus[1]} {i_bus[2]} {i_bus[3]} {i_bus[4]} rst}]
- set_output_delay -clock [get_clocks clk2] 0.222 [get_ports {and_out {o_bus[0]} {o_bus[1]} {o_bus[2]} {o_bus[3]} {o_bus[4]} out_asyn out_syn}]
-
-
- //设置时序例外分析
- set_false_path -setup -from [get_pins {bus_reg[2]/C}] -to [get_pins {bus_clk2_reg[4]/D}]
- set_max_delay -from [get_pins {bus_reg[1]/C}] 2.000
- set_min_delay -from [get_pins {bus_reg[0]/C}] 0.500
- set_external_delay -from [get_ports CLKFBOUT] -to [get_ports CLKFBIN] 0.444
- set_multicycle_path -from [get_pins {bus_reg[0]/C}] -to [get_pins {bus_clk2_reg[2]/D}] 2
- set_disable_timing [get_cells {bus_reg[3]}]
-
- //设置时序断言
- set_case_analysis 1 [get_ports S]
- set_data_check -from [get_pins {bus_reg[2]/C}] -to [get_pins {bus_reg[2]/Q}] 0.333 -clock [get_clocks clk2]
- set_clock_sense -positive -clocks [get_clocks clk1] [get_pins ff_asyn_reg/C]
- group_path -name {group_path} -weight 1.000 -from [get_ports {d1 d2}]
下面将结合时序报告结果对约束命令进行解释,将更加深刻的理解各条命令的作用
在clock Networks中可看到4个约束的主时钟及频率
在clock summary中可以看到各时钟关系,gen_clk与主时钟clkin2的关系符合约束
create_generated_clock -name gen_clk -source [get_pins PLLE2_ADV_inst/CLKOUT1] -multiply_by 2 -add -master_clock clkin2 [get_pins PLLE2_ADV_inst/CLKOUT0]
对PLL/MMCM/GT等自动生成的时钟进行重命名,命令和生成时钟一致,通过参数-rename来实现重命名
create_generated_clock -name rename_clkfbout -source [get_pins PLLE2_ADV_inst/CLKIN1] -master_clock [get_clocks clkin1] [get_pins PLLE2_ADV_inst/CLKFBOUT]
约束前
约束后
设置时序路径的输入抖动,最终体现在clock uncertainty上,只对主时钟间的路径有效,对于涉及PLL时钟或生成时钟间的路径无效。
set_input_jitter [get_clocks clk1] 0.555
系统抖动的约束在Unconstrained path中查看,与Clock uncertainty的关系可但击时序路径中clock uncertainty查看clock uncertainty equation
set_system_jitter 0.789
选择查看包含clk1的时序路径,点击clock Uncertainty,弹出图中弹框,User Uncertainty即为约束的值
set_clock_uncertainty 0.500 [get_clocks clk1]
set_clock_latency中对bus_reg[1]/C上的clk1约束时钟延时为0.345ns,找到包含clk1驱动bus_reg[1]/C的时序路径
set_clock_latency -clock [get_clocks clk1] 0.345 [get_pins {bus_reg[1]/C}]
set_bus_skew -from [get_cells {{bus_reg[0]} {bus_reg[1]} {bus_reg[2]} {bus_reg[3]} {bus_reg[4]}}] -to [get_cells {{bus_clk2_reg[0]} {bus_clk2_reg[1]} {bus_clk2_reg[2]} {bus_clk2_reg[3]} {bus_clk2_reg[4]}}] 0.550
注意:bus_skew的约束不在Report Timing Summary中查看,在菜单栏“Reports->Timing->Report Bus Skew"中进入bus skew窗口
执行“OK”后即得到bus skew的报告,下图的报告中,起点和终点就是进行了bus skew的约束,requirement即为约束值
在上述设计中只设定了一个时钟组clkin1,即对于设计clkin1只分析同步时钟路径,以需要将clk1设置时钟组为例
修改前:set_clock_groups -name clkin1_group -asynchronous -group [get_clocks clkin1]
修改后:
set_clock_groups -name clk1_group -asynchronous -group [get_clocks clkin1] -group [get_clocks clk1]
约束命令如下,输入端口时延为参考时钟为clk1
set_input_delay -clock [get_clocks clk1] 1.111 [get_ports {d1 d2 {i_bus[0]} {i_bus[1]} {i_bus[2]} {i_bus[3]} {i_bus[4]} rst}]
输出端口的时延参考时钟为0.222,约束到了输出端口o_bus上
set_output_delay -clock [get_clocks clk2] 0.222 [get_ports {and_out {o_bus[0]} {o_bus[1]} {o_bus[2]} {o_bus[3]} {o_bus[4]} out_asyn out_syn}]
需注意,set_max_delay需要在setup类型中查找,set_min_delay在hold类型中查找
set_max_delay -from [get_pins {bus_reg[1]/C}] -to [get_pins {bus_clk2_reg[1]/D}] 2.000
set_min_delay -from [get_pins {bus_reg[1]/C}] -to [get_pins {bus_clk2_reg[2]/D}] 0.500
将起点为d1,d2的时序路径单独筛选出来,在other path groups中的group_path栏显示
group_path -name {group_path} -weight 1.000 -from [get_ports {d1 d2}]
将从起点bus_reg[2]/C到终点bus_clk2_reg[4]/D的路径不进行分析
set_false_path -setup -from [get_pins {bus_reg[2]/C}] -to [get_pins {bus_clk2_reg[4]/D}]
在User Ignored Paths中可以查看
设计中触发器ff_case到o_case的时钟为o_bufgmux,但o_bufgmux有一个二输入(CLKIN1,CLKIN2)的BUFGMUX来选择o_bufgmux,通过端口S来选择,约束中指定S为常量1,即bufgmux只输出CLKIN2,即不存在clkin1驱动的ff_case到o_case的路径;如果约束S为0,不存在clkin2驱动的ff_case到o_case的路径;
set_case_analysis 1 [get_ports S]
对设计中的bus_reg[2]/C和bus_reg[2]/Q进行时序比较,setup和hold检查值都为0.333ns。对于setup,bus_reg[2]/C比bus_reg[2]/Q延时值小于0.333ns,即-0.333ns,对于hold,bus_reg[2]/C比bus_reg[2]/Q延时值大于0.333ns。需注意,约束的起点和终点必须符合时序路径的顺序,如本约束中起点和终点位置互换,则约束无效
set_data_check -from [get_pins {bus_reg[2]/C}] -to [get_pins {bus_reg[2]/Q}] 0.333 -clock [get_clocks clk1]
hold结果
触发器ff_asyn_reg为上升沿触发器,约束ff_asyn_reg/C极性为positive时,时序路径正常,约束为negative则时钟无法传输,无相关时序路径
set_clock_sense -positive -clocks [get_clocks clk1] [get_pins ff_asyn_reg/C]
set_clock_sense -negative -clocks [get_clocks clk1] [get_pins ff_asyn_reg/C]
极性约束为negative时,已无ff_asyn_reg相关的路径
用户手册:ug903-vivado-using-constraints-en-us-2022.2.pdf
链接:https://pan.baidu.com/s/17AK_-J4wRXiFLtLTorlrwg?pwd=mylt
提取码:mylt
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。