FPGA静态时序分析与约束(一)、理解亚稳态
FPGA静态时序分析与约束(二)、时序分析
FPGA静态时序分析与约束(三)、读懂vivado时序报告
前三章我们已经掌握了时序分析基本原理。但是,综合工具不知道我们的设计时钟频率是多大,我们想要的设计需求延时是多少,外部进来的时钟和数据之间的走线延时是多少,就没办法给出正确的时序报告以及违规路径。因此时序约束是必不可少的,只有正确的时序设计加上合理的时序约束,整个设计系统才能高效的运转。
简单理解为:
vivado的约束文件后缀为.XDC。文件里的语法为XDC语言,和TCL语言类似,都属于顺序语言。
因此在进行时序约束时需要考虑一下约束的顺序。以下是xilinx官方推荐的约束顺序:
从时序约束本身来说,如上图所示,通常可以分为以下 4 个主要步骤进行,即时钟约束(Create Clock)、输入/输出接口约束(Input/Output Delays,I/O 约束)、时钟分组和跨时钟约束(Clock Groups and CDC)、时序例外约束(Timing Exceptions)。
一个工程里可以拥有多个约束文件,根据设计需求可以有以下建议:
当使用多个 XDC 文件时,必须特别留意时钟定义,并确认从属关系排序是否正确,物理约束可能位于任意约束文件中的任意位置。
时钟必须首先完成定义,方可供其他约束使用。时序约束创建流程的第一步是明确必须定义哪些时钟,以及这些时钟必
须定义为“primary clock”(基准时钟)还是“generated clock”(生成时钟)。
在 Vivado 工具中,设计中未约束的时钟可以通过时钟网络报告(Clock NetworksReport)和时序确认报告(Check Timing Report)进行查看。
create_clock -name<clock_name>-period <period> -waveform {<rise_time> <fall_time>} [get_ports <input_port>]
create_clock -name sysclk -period 20 -waveform {5 10} [get_ports clk_in]
create_clock -name txclk -period 6.667 [get_pins gt0/TXOUTCLK]
(ps:没有定义上升沿和下降沿时,默认占空比为50%)
create_clock -name sys_clk -period 6.667 [get_ports sys_clk_p]
管脚上除了时钟,还有一些数据信号,其同步时钟只存在于外部芯片,并不存在于 FPGA 器件内。这种情况下,为了时序分析的需要也必须定义一个时钟用于描述时序数据引脚的外部时钟信号,这个时钟就称为虚拟时钟。顾名思义,这个时钟并不是实际存在于FPGA 器件中的,因此它在定义时无须依附于任何设计中的实际物理节点(不像主时钟约束时必须有实际的端口或网络相映射)。虚拟时钟同样是以createclock 命令进行约束定义的,但无须指定目标端口或网络。约束语法如下:
create_clock -name <> -period <period>
create_clock-period 10.000 -name vclk - waveform {0.000 5.000}
create_clock-period 10.000 -name scLK - waveform {0.000 5.000} [get ports clk]
若源寄存器和目的寄存器的时钟存在相差,则两个时钟的约束参数就会发生改变,应根据实际情况进行约束:
create_clock -period 10.000 -name vclk - waveform {2.000 7.000}
create_clock -period 10.000 -name sclk - waveform {0.000 5.000} [get ports clk]
衍生时钟主要是指由已有的主时钟进行分频、倍频或相移而产生出来的时钟信号,如由时钟管理单元(MMCM等)或一些设计逻辑所驱动产生的时钟信号。衍生时钟的定义取决于主时钟的特性,衍生时钟约束必须指定时钟源,这个时钟源可以是一个已经约束好的主时钟或另一个衍生时钟。衍生时钟并不直接定义频率、占空比等参数,而是定义其与时钟源的相对关系,如分频系数、倍频系数、相移差值、占空比差值等。因此,在做衍生时钟约束前,要求先做好其时钟源的约束定义。
大部分生成时钟都是由 Vivado 自动衍生的,因此也是自动添加好约束的。如果生成时钟由用户自己生成(例如,自分频),时序工具不能自动生成的衍生时钟,需要使用 create_generated_clock 命令对其进行手动约束。语法如下:
create_generated_clock -name <generated_clock_name> \
-source <master_clock_source_pin_or_port> \
-multiply_by <mult_factor> \
-divide_by <div_factor> \
<pin_or_port>
create_clock -name clkin-period 5 [get ports clkin]
create_generated_clock -name clkdiv2 -source [get_ports clkin]- divide_by 2 [get_pinsREGA/Q]
定义时钟及其波形后,下一步是输入与噪声或不确定性建模相关的所有信息。
set _input_jitter
命令进行更改指定峰值间抖动值(ns为单位)。set_input_jitter
命令只能约束主时钟的抖动值,不能用于约束衍生时钟的抖动值。除了MMCM或PLL外,主时钟所设定的时钟抖动值将会传递给它的衍生时钟。每条 set_input_jitter 命令只能约束一个主时钟,若需要约束多个主时钟的抖动值,则需要多条命令分别进行约束。set_system_jitter
调整全局抖动。vivado不建议增大默认系统抖动值。set_input_jitter
约束语法如下:set_input_jitter [get_clocks <clock_name>] <jitter_in_ns>
约束例子1:以下两条命令分别约束主时钟 clk1 和 clk2的输人抖动值为0.3ns 和 0.3ns。虽然它们的时钟抖动值一样,但仍然需要使用 set input iitter 命令为两个时钟分别设定抖动值。
set_input_jitter clk1 0.3
set_input_jitter clk2 0.3
set_system jitter
约束语法如下:set_system_jitter <jitter_in_ns>
约束例子:例如,对时钟引脚 clk 做主时钟约束,命名为sysclk,使用 set_system_jitter 约束该主时钟的输入抖动值为 0.1ns,命令如下:
create_clock-period 10-name sysclk [get ports clk]
set_system_jitter sysclk 0.1
set_clock_uncertainty
的基本语法结构如下:set_clock_uncertainty -setup \
-from [get_clocks <clock0_name>] \
-to [get_clocks <clock1_name>] \
<uncertainty_value>
当设计者希望为某个时钟或某两个时钟之间的时序路径增加时序余量时,也可以使用 set_clock_uncertainty 命令进行约束定义
例子1:若要给主时钟 clk 增加 500ps(0.5ns)的余量,那么可以使用以下命令为时钟 clk 设定额外的 0.5ns的时钟不确定性时间
set_clock_uncertainty-from clk-to clk 0.500
除了指定设计的每个端口的位置和 I/O 标准外,还必须指定输入和输出延迟约束以描述进出器件接口的外部路径的时序。这些延迟是根据通常同样在开发板上生成并进入器件的时钟来定义的。在某些情况下,如果与 I/O 路径相关的时钟所含波形不同于开发板时钟的波形,那么必须根据虚拟时钟来定义延迟
set_input_delay 命令用于指定输入数据引脚相对于其时钟沿的路径延时。通常输入延时值包括了数据信号从外部芯片到FPGA引脚的板级延时以及与其板级的参考时钟之间的相对延时值。因此,输人延时值可以是正值,也可以是负值,取决于时钟相对数据信号在FPGA引脚上的相位关系。
set_input_delay 命令可以应用于 FPGA 器件的输入数据引脚或双向数据引脚,但不适用于 FPGA 内部信号或时钟输入引脚。若使用 set _input_delay 约束时钟输人引脚,将会被时序工具忽略。set_input_delay 以max 和min 参数分别表示约束的最大值和最小值,最大值用于建立时间检查,最小值用于保持时间检查。
set_input_delay <max delay> -max -clock [get_clocks <clock>] [get_ports <ports>]
set_input_delay <min delay> -min -clock [get_clocks <clock>] [get_ports <ports>]
约束例子1:输人引脚为 CLK0 的主时钟 sysclk,同时约束了max 和min 值分别为4ns 和 1ns 的输入延时约束:
create_clock -name sysclk -period 10 [get ports CLK0]
set_input_delay -clock sysclk -max 4 [get ports DIN]
set_input_delay -clock sysclk -min 1 [get ports DIN]
输出延迟与输入延迟类似,区别在于输出延迟表示为了确保在所有情况下均可正常工作,输出路径在器件外部的最短和
最长时间。
set_output_delay <delay> -clock [get_clocks <clock>] [get_ports <ports>]
约束例子1:该实例对一个输出引脚DOUT进行输出延时约束,参考时钟是事先定义好的主时钟sysclk。该约束未指定max 和min,表示约束的延时值同时应用于max 和min 两种情况:
create_clock -name sysclk-period 10 [get ports CLK0]set output delay-clock sysClk 6 [get ports DOUT]
所谓虚假路径并非此路径不存在,而是意指该路径是设计中的非功能路径或没有任何时序要求的路径。显然,这样的路径需要通过虚假路径约束,让时序工具放弃对它们的任何时序努力和时序分析。为何要做虚假路径约束?因为移除了这些非功能路径的时序要求后,可以减少花在这些非功能路径上的时序努力,减少编译时间,同时腾出有限的布局布线资源,用于提升整体的时序性能。
工程中施加了虚假路径约束,设计工具在编译时将会完全移除这些路径,不做任何的时序努力和分析。可以预见,在减少了具有时序要求的时序路径后,设计编译的时间可以在一定程度上得以提升。反之,若很多虚假路径没有被移除,时序工具需要为这些虚假路径做出额外的编译努力,势必会导致编译时间的增加,甚至可能由于有限的布局布线资源无法得到最合理的分配,导致时序无法收敛。
因此,设计中的虚假路径都应该有效识别并进行约束。常见的虚假路径包括如下几种:
默认情况下,Vivado对设计中所有时钟之间的路径进行时序约束。设计者可使用以下约束来修改此默认行为:
虚假路径约束的基本语法结构如下:
set_false_path -from <startpoints> -to <endpoints>
约束例子1:如下虚假(False)路径约束,将覆盖到所有以 reset 信号起始的寄存器路径:
set_false_path -from [get port reset]-to [all registers]
约束例子2:如下路径约束,将覆盖从 CLKA 时钟到 CLKB时钟的所有时序路径。注意这个约束中,仅覆盖从 CLKA 时钟到 CLKB时钟的所有时序路径,但不包括从 CLKB时钟到CLKA 时钟的时序路径:
set_false_path-from [get clocks CLKA]-to [get clocks CLKB]
若希望 False 约束既能覆盖从 CLKA 时钟到 CLKB时钟的所有时序路径,也能覆盖从CLKB 时钟到 CLKA 时钟的所有时序路径,那么必须两个时钟方向都做约束:
set_false_path -from [get clocks CLKA]-to [get clocks CLKB]
set_false_path -from [get clocks CLKB]-to [get clocks CLKA]
异步时钟组约束的基本语法结构如下:
set_clock_groups -asynchronous -group <clock_name_1> -group <clock_name_2>
该时钟组约束下,clock_name_1到clock_name_2、clock_name_1到clock_name_2都将不被分析。
当 2 个主时钟及其相应的生成时钟构成 2 个异步域,并且这 2 个异步域之间的所有路径均已正确完成同步时,即可立
即对多个时钟应用时钟组约束:
set_clock_groups -asynchronous -group {clkA clkA_gen0 clkA_gen1 } \
-group {clkB clkB_gen0 clkB_gen1 }
时钟约束、I/0约束以及时序例外约束,是时序约束的最基本、最重要的约束方法。对于这三大类约束以及它们所涵盖的具体的约束语法,在进行时序约束时,通常也需要遵循定的顺序进行约束输入,以满足时序约束语法的基本要求。
按照推荐的约束顺序,从上到下罗列了具体的约束语法:
多周期约束用于调整建立时间和保持时间检查的起始时钟沿到目标时钟沿所需的时钟周期数。因为默认情况下,Vivado 时序工具都是以单周期为单位进行时序路径分析。但在实际设计中,单周期路径对于某些逻辑可能并不准确,导致对它们的时序要求过高(即过约束)。
其基本语法结构如下:
set_multicycle_path <num cycles> -from <startpoints> -to <endpoints>
set_multicycle_path -hold <num cycles> -from <startpoints> -to <endpoints>
约束例子1:放宽建立时间要求,同时保持时间要求保留不变,当源时序单元和目标时序单元受时钟使能信号控制并且此信号每 N个周期就会激活时钟时,此状况就会发生。以下示例中,时钟使能每3个周期就会激活一次,并且起点和端点时钟相同
约束:
set_multicycle_path -from [get_pins REGA/C] -to [get_pins REGB/D] -setup 3
set_multicycle_path -from [get_pins REGA/C] -to [get_pins REGB/D] -hold 2
最大延时约束(set_max_delay)将覆盖默认的建立时间分析的最大路径延时值。最小延时约束(set_min_delay)将覆盖默认的保持时间分析的最小路径延时值,set_max_delay 和 set_min_delay 通常不建议用于约束输入或输出引脚与内部寄存器对于一些异步信号之间的路径,通常建议使用之间(pin2reg 以及 reg2pin)的路径延时。而set max delay 和 set min delay 进行约束例如,对于设计中的某两个异步时钟域之间的数据通信已经使用双寄存器锁存等方式进行同步了,就可以施加 set false_path 或 setclock_groups 约束关闭某两个异步时钟域之司的数据路径检查。然而,设计者仍然期望查看并确认这两个时钟域之间的时序路径延时就可以使用 set max delay 和 set min delay进行约束(而不是使用 set_false_path 或 set_clock_groups 进行约束)
最大路径延时(maximum delay)约束命令格式如下:
set_max_delay <delay> -from <startpoints> -to <endpoints>
最小路径延时(minimum delay)约束命令格式如下:
set_min_delay <delay> -from <startpoints> -to <endpoints>
《UG949》
《FPGA时序约束与分析——吴厚航》