当前位置:   article > 正文

FPGA设计时序约束用法详细说明大全终章

时序约束

目录

一、序言

二、时序约束概览

2.1 时序约束分类

2.2 图解clock latency

2.3 时钟类型(主时钟,虚拟时钟,生成时钟)

三、如何设计合理的约束?

3.1 时序约束规范

3.2 约束的优先级

3.3 易混约束区别

3.3.1 Set False Path与Set Clock Group

3.3.2 Set False Path与Set Disable Timing

四、工程示例

4.1 工程代码

4.2 时序约束

4.3 综合网表连接

4.4 时序报告解析时序约束

4.4.1 create_clock

4.4.2 create_generated_clock

4.4.3 Rename Auto-Derived Clock

4.4.4 set_input_jitter  

4.4.5 set_system_jitter 

4.4.6 set_clock uncertainty

4.4.7 set_clock_latency

4.4.8 set_bus_skew

4.4.9 set_clock_groups

4.4.10 set_input_delay/set_output_delay

4.4.11 set_max_delay/set_min_delay

4.4.12  set_group_path

4.4.13 set_false_path

4.4.14 set_case_analysis 

4.4.15 set_data_check

4.4.16 set_clock_sense

五、参考资料


一、序言

    在之前的文章中,以命令为章节进行了相关的使用说明,命令间彼此间是相互独立的。在本章中,将从时序约束整体的角度对这些约束进行一个使用说明概述,结合时序报告,这样有助于深入理解命令的使用。

二、时序约束概览

    ​时序约束根据约束特性可分为5类:时钟特性,端口路径延时,时序例外约束,断言约束,其他类,每一类的功能作用如下图

2.1 时序约束分类

2.2 图解clock latency

    ​clock latency的理解可分为PLL和非PLL来进行,时钟源来自芯片内部的PLL,图中的Clock definition point即是指用create_clock约束的位置,pll的输出位置即为时钟源位置

时钟源来自芯片外部时,create_clock的位置即为图中clock definition point位置,到触发器的CK端口时延为Network latency,时钟源到定义点的时延为source latency

2.3 时钟类型(主时钟,虚拟时钟,生成时钟)

主时钟:

生成时钟Generated clock:来源于主时钟,如主时钟的分频时钟或倍频时钟。因此,生成时钟的时钟源为对应的主时钟,时序路径分析时,生成时钟路径中时钟的起点是主时钟的定义位置。

虚拟时钟Virtual clock:主要用于辅助内部设计与外部设计进行时序分析

 

问题:是否可以将生成时钟替换成另一个主时钟?

    该操作是可以的,也存在相关场景,但是会存在一些缺点,通过使用create_clock创建主时钟代替create_generated_clock创建的生成时钟将会产生一个新的时钟域,会引入一些跨时钟域问题,而使用生成时钟不会产生新的时钟域。

    另外,主时钟的时钟源在时钟的定义位置点,生成时钟的时钟源是对应的主时钟,因此用生成时钟时源时钟source latency会自动的被包含。

三、如何设计合理的约束?

3.1 时序约束规范

在设置时序约束时,按照一定的逻辑顺序进行约束有助于他人对约束的理解以及修改,建议按照以下顺序设置时序约束

## 第一部分:时钟申明

# 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设置断开时序

## 第四部分:设置物理约束

3.2 约束的优先级

优先级如下图

在时序约束中,不同约束之间存在优先级,这个需要特别注意,否则将达不到预期的约束效果

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]

3.3 易混约束区别

3.3.1 Set False Path与Set Clock Group

两者都可以针对时钟对象设置不分析,但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

3.3.2 Set False Path与Set Disable Timing

    除去设置格式的差异,从表面看两者都可以针对设置的对象不进行分析,set_disable_timing是屏蔽时序弧,等价于移除,与该时序弧相关的所有路径都会被移除,当需要对经过某个pin/cell/port上的所有路径都不进行分析时,则建议使用set_disable_timing

    set_false_path是不对路径进行时序处理,时序弧仍有效,如果该时序弧相关的时序路径有多条,伪路径只作用于部分路径,时序工具会计算所有时序路径,但只对存在时序约束的时序路径进行分析。

四、工程示例

4.1 工程代码

    下面以一个设置了所有时序约束的工程对时序约束进行示例

  1. 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);
  2. input CLKIN1,CLKIN2,CLKINSEL,CLKFBIN,clk1,clk2,rst,d1,d2,S;
  3. input [4:0] i_bus;
  4. output reg [4:0] o_bus,bus_clk2;
  5. output out_syn,out_asyn,and_out,CLKFBOUT;
  6. reg ff1,ff2,ff_asyn,ff_syn,ff_and;
  7. reg ff_case;
  8. output reg o_case;
  9. reg [4:0] bus;
  10. wire sum12,and_c,CLKOUT0,CLKOUT1;
  11. wire [4:0] bus_c;
  12. wire o_bufgmux,ffcase_n;
  13. PLLE2_ADV #(
  14.      .BANDWIDTH("OPTIMIZED"),  // OPTIMIZED, HIGH, LOW
  15.      .CLKFBOUT_MULT(8),        // Multiply value for all CLKOUT, (2-64)
  16.      .CLKFBOUT_PHASE(0.0),     // Phase offset in degrees of CLKFB, (-360.000-360.000).
  17.      // CLKIN_PERIOD: Input clock period in nS to ps resolution (i.e. 33.333 is 30 MHz).
  18.      .CLKIN1_PERIOD(0.0),
  19.      .CLKIN2_PERIOD(0.0),
  20.      // CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for CLKOUT (1-128)
  21.      .CLKOUT0_DIVIDE(1),
  22.      .CLKOUT1_DIVIDE(2),
  23.      .CLKOUT2_DIVIDE(4),
  24.      .CLKOUT3_DIVIDE(5),
  25.      .CLKOUT4_DIVIDE(1),
  26.      .CLKOUT5_DIVIDE(1),
  27.      // CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for CLKOUT outputs (0.001-0.999).
  28.      .CLKOUT0_DUTY_CYCLE(0.4),
  29.      .CLKOUT1_DUTY_CYCLE(0.5),
  30.      .CLKOUT2_DUTY_CYCLE(0.5),
  31.      .CLKOUT3_DUTY_CYCLE(0.5),
  32.      .CLKOUT4_DUTY_CYCLE(0.5),
  33.      .CLKOUT5_DUTY_CYCLE(0.5),
  34.      // CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for CLKOUT outputs (-360.000-360.000).
  35.      .CLKOUT0_PHASE(0.0),
  36.      .CLKOUT1_PHASE(0.0),
  37.      .CLKOUT2_PHASE(0.0),
  38.      .CLKOUT3_PHASE(0.0),
  39.      .CLKOUT4_PHASE(0.0),
  40.      .CLKOUT5_PHASE(0.0),
  41.      .COMPENSATION("EXTERNAL"),   // ZHOLD, BUF_IN, EXTERNAL, INTERNAL
  42.      .DIVCLK_DIVIDE(1),        // Master division value (1-56)
  43.      // REF_JITTER: Reference input jitter in UI (0.000-0.999).
  44.      .REF_JITTER1(0.0),
  45.      .REF_JITTER2(0.0),
  46.      .STARTUP_WAIT("FALSE")    // Delay DONE until PLL Locks, ("TRUE"/"FALSE")
  47.   )
  48.   PLLE2_ADV_inst (
  49.      // Clock Outputs: 1-bit (each) output: User configurable clock outputs
  50.      .CLKOUT0(CLKOUT0),   // 1-bit output: CLKOUT0
  51.      .CLKOUT1(CLKOUT1),   // 1-bit output: CLKOUT1
  52.      .CLKOUT2(CLKOUT2),   // 1-bit output: CLKOUT2
  53.      // Feedback Clocks: 1-bit (each) output: Clock feedback ports
  54.      .CLKFBOUT(CLKFBOUT), // 1-bit output: Feedback clock
  55.      // Clock Inputs: 1-bit (each) input: Clock inputs
  56.      .CLKIN1(CLKIN1),     // 1-bit input: Primary clock
  57.      .CLKIN2(CLKIN2),     // 1-bit input: Secondary clock
  58.      // Control Ports: 1-bit (each) input: PLL control ports
  59.      .CLKINSEL(CLKINSEL), // 1-bit input: Clock select, High=CLKIN1 Low=CLKIN2
  60.      .RST(rst),           // 1-bit input: Reset
  61.      // Feedback Clocks: 1-bit (each) input: Clock feedback ports
  62.      .CLKFBIN(CLKFBIN)    // 1-bit input: Feedback clock
  63.   );
  64.   // End of PLLE2_ADV_inst instantiation
  65. always@(posedge CLKOUT0,negedge rst)
  66.    if(!rst)
  67.    begin
  68.        ff1<=1'b0;
  69.        ff2<=1'b0;
  70.    end
  71.    else begin
  72.        ff1<=d1;
  73.        ff2<=d2;
  74.    end
  75. assign sum12=ff1+ff2;
  76. always@(posedge CLKOUT1,negedge rst)
  77.    if(!rst)
  78.        ff_syn<=1'b0;
  79.    else begin
  80.        ff_syn<=sum12;
  81.    end
  82. assign out_syn=ff_syn;
  83. always@(posedge clk1,negedge rst)
  84.    if(!rst)
  85.        ff_asyn<=1'b0;
  86.    else begin
  87.        ff_asyn<=sum12;
  88.    end
  89. assign out_asyn=ff_asyn;
  90. assign and_c=ff_asyn&d1;
  91. always@(posedge clk1,negedge rst)
  92.    if(!rst)
  93.        ff_and<=1'b0;
  94.    else begin
  95.        ff_and<=and_c;
  96.    end
  97. assign and_out=ff_and;
  98. always@(posedge clk1,negedge rst)
  99.    if(!rst)
  100.        bus<=5'b0;
  101.    else begin
  102.        bus<=i_bus+1'b1;
  103.    end
  104. assign bus_c=bus+d2;
  105. always@(*)
  106.    begin
  107.        o_bus=bus;
  108.    end
  109. always@(posedge clk2,negedge rst)
  110.    if(!rst)
  111.        bus_clk2<=5'b0;
  112.    else begin
  113.        bus_clk2<=bus_c+d1;
  114.    end
  115. //set_case_analysis
  116.   BUFGMUX #(
  117.   )
  118.   BUFGMUX_inst (
  119.      .O(o_bufgmux),   // 1-bit output: Clock output
  120.      .I0(CLKIN1), // 1-bit input: Clock input (S=0)
  121.      .I1(CLKIN2), // 1-bit input: Clock input (S=1)
  122.      .S(S)    // 1-bit input: Clock select
  123.   );
  124. always@(posedge o_bufgmux,negedge rst)
  125.    if(!rst)
  126.        ff_case<=1'b0;
  127.    else begin
  128.        ff_case<=d1;
  129.    end
  130. assign ffcase_n=!ff_case;
  131. always@(posedge o_bufgmux,negedge rst)
  132.    if(!rst)
  133.        o_case<=1'b0;
  134.    else begin
  135.        o_case<=ffcase_n;
  136.    end
  137. endmodule

4.2 时序约束

设计中的约束如下

  1. //创建主时钟和生成时钟
  2. create_clock -period 10.000 -name clkin1 -waveform {0.000 5.000} -add [get_ports CLKIN1]
  3. create_clock -period 5.000 -name clkin2 -waveform {0.000 2.500} -add [get_nets CLKIN2]
  4. create_clock -period 4.000 -name clk2 -waveform {0.000 2.000} -add [get_ports clk2]
  5. create_clock -period 4.000 -name clk1 -waveform {0.000 2.000} -add [get_ports clk1]
  6. 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]
  7. set_input_jitter [get_clocks clk2] 0.500
  8. set_clock_latency -clock [get_clocks clk2] 0.333 [get_pins {bus_reg[1]/D}]
  9. set_system_jitter 0.009
  10. set_clock_uncertainty 0.500 [get_clocks clk1]
  11. //设置时钟组和总线偏斜
  12. set_clock_groups -name clkin1_group -asynchronous -group [get_clocks clkin1]
  13. 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
  14. 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}]
  15. 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}]
  16. //设置时序例外分析
  17. set_false_path -setup -from [get_pins {bus_reg[2]/C}] -to [get_pins {bus_clk2_reg[4]/D}]
  18. set_max_delay -from [get_pins {bus_reg[1]/C}] 2.000
  19. set_min_delay -from [get_pins {bus_reg[0]/C}] 0.500
  20. set_external_delay -from [get_ports CLKFBOUT] -to [get_ports CLKFBIN] 0.444
  21. set_multicycle_path -from [get_pins {bus_reg[0]/C}] -to [get_pins {bus_clk2_reg[2]/D}] 2
  22. set_disable_timing [get_cells {bus_reg[3]}]
  23. //设置时序断言
  24. set_case_analysis 1 [get_ports S]
  25. set_data_check -from [get_pins {bus_reg[2]/C}] -to [get_pins {bus_reg[2]/Q}] 0.333 -clock [get_clocks clk2]
  26. set_clock_sense -positive -clocks [get_clocks clk1] [get_pins ff_asyn_reg/C]
  27. group_path -name {group_path} -weight 1.000 -from [get_ports {d1 d2}]

4.3 综合网表连接

4.4 时序报告解析时序约束

下面将结合时序报告结果对约束命令进行解释,将更加深刻的理解各条命令的作用

4.4.1 create_clock

在clock Networks中可看到4个约束的主时钟及频率

4.4.2 create_generated_clock

在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]

4.4.3 Rename Auto-Derived Clock

对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]

约束前

约束后

4.4.4 set_input_jitter  

设置时序路径的输入抖动,最终体现在clock uncertainty上,只对主时钟间的路径有效,对于涉及PLL时钟或生成时钟间的路径无效。

set_input_jitter [get_clocks clk1] 0.555

4.4.5 set_system_jitter 

系统抖动的约束在Unconstrained path中查看,与Clock uncertainty的关系可但击时序路径中clock uncertainty查看clock uncertainty equation

set_system_jitter 0.789

4.4.6 set_clock uncertainty

        选择查看包含clk1的时序路径,点击clock Uncertainty,弹出图中弹框,User Uncertainty即为约束的值

set_clock_uncertainty 0.500 [get_clocks clk1]

4.4.7 set_clock_latency

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}]

4.4.8 set_bus_skew

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即为约束值

4.4.9 set_clock_groups

    ​在上述设计中只设定了一个时钟组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]

4.4.10 set_input_delay/set_output_delay

约束命令如下,输入端口时延为参考时钟为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}]

4.4.11 set_max_delay/set_min_delay

需注意,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

4.4.12  set_group_path

将起点为d1,d2的时序路径单独筛选出来,在other path groups中的group_path栏显示

group_path -name {group_path} -weight 1.000 -from [get_ports {d1 d2}]

4.4.13 set_false_path

将从起点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中可以查看

4.4.14 set_case_analysis 

设计中触发器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]

4.4.15 set_data_check

    ​对设计中的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结果

4.4.16 set_clock_sense

    ​触发器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   

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/502484
推荐阅读
相关标签
  

闽ICP备14008679号