目录

一、时序约束基础

二、时序路径

三、多周期路径约束

1、使能信号导致多周期路径

2、同频时钟相位偏移的跨时钟域路径

3、同步时钟之慢时钟到快时钟的跨时钟域路径

4、同步时钟之快时钟到慢时钟的跨时钟域路径

四、伪路径约束

1、电路功能不会发生

2、异步时钟跨时钟域

3、异步复位路径

五、最大/最小延迟约束

1、对某些路径实施过约束

2、代替多周期路径约束

3、对异步跨时钟域路径采用set_max_delay进行约束

六、设置时钟组约束

1、约束异步时钟

2、对同一时钟源创建多个时钟周期约束

七、约束优先级

1、等效约束,后者覆盖前者

2、不同类型的时序例外路径约束

3、同类型的时序例外路径约束


一、时序约束基础

时序分析是建立在时序约束的基础上的,如果没有时序约束,EDA工具在进行时序分析的时候会默认所有时钟都是有关联的,从而进行布局布线,而这样的布局布线的结果很容易造成时序违例,并且布局布线的结果也不是我们想要的,所以要进行时序约束,而时序约束就是告诉vivado我们的时钟周期是多少,各时钟之间的关系等。

进行时序约束其实就是为了满足建立时间和保持时间的要求,那什么是建立时间,什么是保持时间呢?

建立时间:建立时间就是指在时钟有效沿到来之前,数据必须保持稳定的最小时间;

保持时间:保持时间就是指在时钟有效沿到来之后,数据必须保持稳定的最小时间;

建立时间和保持时间均是由硬件特性所决定的,当选定使用的fpga后,就意味着建立时间和保持时间确定了。

为什么数据要满足建立时间和保持时间的要求呢?

为了避免采到亚稳态,因为数据的信号变化在实际上板过程中并不是瞬时变化的,它有一个从低到高,从高到低的过程,因此为了保证输出数据的准确性必须采到一个稳定的信号状态。

亚稳态:指触发器无法在某个规定的时间段内达到一个确定的状态。

采集到亚稳态的危害:当一个触发器进入亚稳态时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。在这个稳定期间,触发器输出一些中间级电平,或者可能处于振荡状态,并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。可能引起电路的振荡,系统崩溃。

竞争和冒险:门电路两个输入信号同时向相反的逻辑电平跳变(一个从1变为0,一个从0变为1)的现象称为竞争。由于竞争而在电路输出端可能产生尖峰脉冲的现象就称为竞争-冒险。

二、时序路径

时序约束是针对时序路径设置的,因此在创建时序约束之前要先明确设计中可能存在的时序路径。如图所示显示了4中时序路径,每种时序路径都有起点、终点、约束命令。

 

这4类路径中,最为核心的是标记2的同步时序路径,这类路径的起点模块和终点模块均为同一时钟驱动的时序逻辑,事实上,如果把PCB看作是一个大的系统,标记1、2、3所示的路径可以归结为一个统一的模型:触发器+组合逻辑+触发器,如下图所示:

 

一个完整的时序路径由源时钟路径、数据路径和目的时钟路径3部分构成,约束的目的就是使下式成立:

Tclk≧Tco+Tlogic+Trouting+Tsu-Tskew

Tco+Tlogic+Trouting≧Th+Tskew

Tclk:一个时钟周期。

Tco:时钟到输出时间(clock to output),是时钟到达后有效数据出现在发起寄存器Q端口所需时间。

Tlogic:组合逻辑传输延时。

Trouting:两级寄存器之间的布线延时。

Tsu:接收端寄存器的建立时间setup time。

Tskew:时钟偏斜的时间,指一个同源时钟到达两个不同的寄存器时钟端口的时间差别。造成时钟偏斜的原因主要是两条时钟路径到达寄存器的长度不同。如今的FPGA中一般都有全铜层的全局时钟驱动网络,全局时钟资源的时钟偏斜非常小,一般可以忽略不记

Th:接收端寄存器的保持时间hold time。

上述的公式是怎么得来的呢?这就要说到信号的发射沿与捕获沿:

发射沿:源端寄存器发送数据的时钟边沿;

捕获沿:目的端寄存器捕获数据的时钟边沿;

在vivado进行时序分析时,会默认采用最严格的方式进行时序分析,在检查建立时间时会寻找发射沿之后的距离最近的捕获沿进行分析;在检查保持时间时以建立时间的检查为前提,即总是在建立时间的前一个时钟周期边沿检查保持时间,其实就是数据在时刻0的边沿被发起,建立时间的检查是在时刻1进行,而保持时间的检查是在时刻0进行,因此保持时间的检查是在建立时间检查的前一个时钟沿。

因此由上图,我们的数据不能过晚到达捕获沿,否则就会不满足建立时间的要求,同时下一个数据也不能过早的到达捕获沿,否则就会造成当前数据丢失或采集到亚稳态。

因此可以得出这样的时序要求:

Tclk≧Tco+Tlogic+Trouting+Tsu-Tskew

Tco+Tlogic+Trouting≧Th+Tskew

三、多周期路径约束

Vivado默认按照单周期关系分析数据路径,但在工程实践中往往会出现这样的情形:数据路径逻辑较为复杂,使得数据无法在一个时钟周期内稳定下来;或者数据可以在一个时钟周期内稳定下来,但在数据发送之后的几个时钟周期,后续逻辑才使用。在这些情形下,设计者的设计意图都是使数据的有效期从发起沿为起始直至数个时钟周期之后的捕获沿。这一设计意图无法被时序分析工具猜测出来,必须由设计者在时序约束中指明。否则,时序分析工具会按照单周期路径检查的方式执行,往往会爆出时序违规。 

这时可以使用set_multicycle_path约束来指定多周期路径。

1、使能信号导致多周期路径

如下图,使能信号ce的周期是时钟周期的整数倍,且有效期(高有效)为一个时钟周期。

 

为便于分析,这里假定ce的周期为时钟周期的3倍,相应的时序如上图所示。

默认情况下,建立时间检查为1时刻的目的时钟边沿,而我们需要的建立时间检查应为3时刻,因为使能信号的周期为时钟周期的3倍,我们不需要严格要求在1时刻必须满足建立时间,在3时刻满足建立时间即可,也就是图中的标记④,基于此获得的保持时间检查为图中的标记⑤。

但是把标记⑤作为保持时间检查是不合理的,真正的保持时间检查应为标记⑦和标记⑧(下一个使能信号的保持时间检查)。基于上述分析,可确定建立时间需求应为3个时钟周期,保持时间需求应为0个时钟周期,因此,相应的多周期路径约束如下Tcl脚本所示。

set_multicycle_path -from [get_pins data0_reg/C] -to [get_pins data1_reg/D] -setup -end 3
set_multicycle_path -from [get_pins data0_reg/C] -to [get_pins data1_reg/D] -hold -start 2

-setup:表示建立时间所需要的时钟周期个数。(也就是捕获沿相对于发射沿向右移动3个周期)

-hold:表示分析保持时间时,相对于默认的捕获沿实际的捕获沿应回调的时钟周期个数。(还可以这样理解:源端时钟发射沿向后移动2个周期,与当前的保持时间检查位置一致,也就是符合我们需要的发射沿与保持时间检查沿的相对位置)

-end:表示以目的端时钟作为时钟周期计数基准。

-start:表示以源端时钟作为时钟周期计数基准。

-from:路径的源头。

-to:路径的终点。

数字:需要的周期个数。

默认情况下:

对建立时间的分析是设置目的时钟为多周期。

对保持时间的分析是设置源时钟为多周期。

因此,-end和-start可以省略,不过建议在使用时明确指明是-end还是-start。

2、同频时钟相位偏移的跨时钟域路径

这里的同步时钟是指由同一个MMCM/PLL生成的时钟,时钟之间的相位是明确的。具体时序如图所示。在只有时钟周期约束的情况下,时序分析工具会认为建立时间检查和保持时间检查为图中的虚线所示,但实际上应该是图中的实线所示。此时应通过多周期路径约束调整,如Tc1脚本所示。这里只需对建立时间调整即可,因为建立时间检查调整之后,基于此的保持时间检查正好就是真实的保持时间检查。

Tcl脚本:

set_multicycle_path -from [get_clocks clk1] -to [get_clocks clk2] -setup -end 2

该情形为同步同频时钟相位正向偏移,对于同步同频时钟负向偏移的两个时钟之间的跨时钟域路径约束与之同理。

3、同步时钟之慢时钟到快时钟的跨时钟域路径

同步时钟之慢时钟到快时钟的跨时钟域路径如下图所示。真实的建立时间检查和保持时间检查应为图中的实线所示。但在只有时钟周期约束时,建立时间需求为单个时钟周期,也就是1时刻,这就要通过多周期路径约束调整为图中的SC,基于SC所获得的HC为图中的虚线所示,显然这与实际情况不符,应将其回调两个时钟周期。故此情形下的多周期路径约束如Tcl脚本所示:

Tcl脚本:

set_multicycle_path -from [get_clocks clk1] -to [get_clocks clk2] -setup -end 3

set_multicycle_path -from [get_clocks clk1] -to [get_clocks clk2] -hold -end 2

4、同步时钟之快时钟到慢时钟的跨时钟域路径

同步时钟之快时钟到慢时钟的跨时钟域路径如下图所示。真实的建立时间检查和保持时间检查应为图中的实线所示。但在只有时钟周期约束时,源时钟3、2、1时刻的建立时间检查均为目的时钟的0时刻,因此需要将建立时间检查设置为3个周期,将保持时间检查回调2个周期。

注意:此时需要相对于源时钟进行设置,使用的是-start而不是-end。故此情形下的多周期路径约束如Tcl脚本所示:

Tcl脚本:

set_multicycle_path -from [get_clocks clk1] -to [get_clocks clk2] -setup -start 3

set_multicycle_path -from [get_clocks clk1] -to [get_clocks clk2] -hold -start 2

如果不设置多周期路径约束会有怎样的后果呢?

  1. 时序分析工具依然会按照单周期路径处理多周期路径,因此有可能虚报时序违例。
  2. 布局布线工具依然按照单周期路径的方式执行,有可能满足时序规范,但过分优化了本应该多个周期完成的操作,实际上造成了对多周期路径的过约束,从而侵占了本应该让位于其他逻辑的布局布线资源,有可能造成其他关键路径的时序违例或时序裕量变小,这在资源利用率很高时尤其突出。

总的来说,多周期路径约束的好处在于使布局布线工具优先考虑其他关键路径。

四、伪路径约束

伪路径并不表示该路径不存在,而是指基于该路径的电路功能不会发生或该路径无须时序约束。比如一些信号传输我们已经使用打拍或者异步FIFO进行了跨时钟域处理,因此这部分不会发生时序违例的情况,那这部分就可以设置伪路径。

典型的伪路径包括:

  1. 通过双触发器同步的跨时钟域路径。
  2. 只在上电时工作的寄存器对应的路径。
  3. 异步复位路径。
  4. 测试逻辑对应的路径(只在测试时使用,此时需要正常约束;在正常工作时,该部分的逻辑电路不被使用,故可作为伪路径处理)。

设置伪路径约束有两个好处:

  1. 缩短编译时间:这是因为工具不用再考虑对这些路径如何优化以实现时序收敛。
  2. 提高编译质量:这是因为工具可以将重点放在关键路径上,给予其较高的优先级如优先布局、布线,从而达到时序收敛的目的。

1、电路功能不会发生

如下图所示是一个因某路径的电路功能不会发生而被当作伪路径处理的案例。

图中,当sel为0时,电路为标记①的路径;当sel为1时,电路为标记②的路径。这两条路径是存在且功能会发生的。而标记③的路径尽管存在但永远不会发生,故被判为伪路径,相应的约束如Tcl 脚本所示:

Tcl脚本:

set_false_path -from [get_cells {opb_r_reg}] -to [get_cells {dout_reg}]

2、异步时钟跨时钟域

对于异步时钟的跨时钟域路径,要从设计上保证跨时钟域路径的安全性,比如我们在设计中已经使用打拍或者异步FIFO处理跨时钟域信号,那么从约束角度而言可以将其设置为伪路径,如图所示为跨时钟域路径。通过Tc1脚本可将其设置为伪路径。

Tcl脚本:

set_false_path -from [get_cells rega] -to [get_cells regb]

尽管有时也可以使用下面的这种约束,但与上面的约束相比,该约束过于粗糙且会增加编译时间,因为该工具要遍历clka和clkb下的所有Cell。

set_false_path -from [get_clocks clka] -to [get_clocks clkb]

如果同时存在两个时钟域间相互的数据传输,即有数据从clka时钟域到clkb时钟域,也有数据从clkb时钟域到clka时钟域,此时应将这两个方向均设置为伪路径。

3、异步复位路径

对于全局异步复位路径,也可以设置为伪路径,即set_false_path,但前提是设计本身是安全的。由于异步复位本身存在弊端(释放时间会因为延迟而不同,可能会对控制路径有潜在风险),因此建议在设计中使用同步复位。对异步复位路径,若可判为伪路径,则约束如下所示:

set_false_path -from [get_ports rst]

五、最大/最小延迟约束

最大延迟约束:将覆盖默认的建立时间检查的最大路径延时值。

最小延迟约束:将覆盖默认的保持时间检查的最小路径延时值。

使用 set_max_delay和set_min_delay 的三种场合如下所示。

1、对某些路径实施过约束

对实施过约束的某些路径进行最大/最小延迟约束可以使工具对这些路径进行深入优化、布局,从而增强布线器为达到时序收敛的灵活性,比如输入管脚的信号经过组合逻辑后直接输出到管脚可以进行最大/最小延迟约束。

2、代替多周期路径约束

代替多周期路径的目的仍然是对这些路径采取过约束。例如,时钟周期4ns,相应的多周期路径约束如下:

set_multicycle_path -from [get_cells rega] -to [get_cells regb] 3

对多周期路径采用set_max_delay进行约束,如下:

set_max_delay -from [get_cells rega] -to [get_cells regb] 12

3、对异步跨时钟域路径采用set_max_delay进行约束

如果设计中的某两个异步时钟域之间的数据通信已经使用打拍等方式进行同步了,就可以施set_false_path或set_clock_groups约束关闭某两个异步时钟域之间的数据路径检查,但是如果设计者仍期望查看并确认这两个时钟域之间的时序路径延时,或者要放宽约束,保证两个时钟间的路径延时符合实际情况,那么可以用set_max_delay和set_min_delay。

对于异步跨时钟域路径,有如下场景:从clka到clkb的路径均为伪路径;从clkb到 clka 的路径,除了图中的regb 到rega要求最大延迟为 5ns 外,其余路径也是伪路径,如下图所示:

此时,对于从clka到clkb的路径,可直接采用set_false_path进行约束。对于从clkb到clka的路径,分为两部分处理:从regb到rega的路径和其余路径。从regb到rega的路径采用set_max_delay进行约束,那么其余路径如何约束呢?如果直接采用set_false_path进行约束,则由于其优先级高于set_max_delay,将会造成前述的set_max_delay失效,故这里采用一种可替代set_false_path的方案,即仍然采用set_max_delay,只是将其值设置为时钟周期的10倍(这里的数值只要较大即可,满足建立时间检查)。

Tcl脚本:

set_false_path -from [get_clocks clka] -to [get_clocks clkb]

set_max_delay -datapath_only 5 -from [get_cells regb] -to [get_cells rega]

set_max_delay -datapath_only 50 -from [get_clocks clkb] -to [get_clocks clka]

-datapath_only 当异步跨时钟域路径可以忽略时钟偏斜(ClockSkew)时添加此选项。

六、设置时钟组约束

在默认情形下,Vivado 会认为所有的时钟都是同步的。因此,如果出现异步时钟,则需要明确地告知工具,这就会用到set_clock_groups。使用set_clock_groups的常用场景如下所示。

1、约束异步时钟

对于全局时钟clkA 和clkB,如果两者是异步时钟,则可通过set_clock_groups 进行约束如下:

set_clock_groups -async -group clkA -group clkB

该约束与如下所示的约束等效。

set_false_path -from clkA -to clkB

set_false_path -from clkB -to clkA

这表明从clkA到clkB和从clkB到clkA的路径均为伪路径,但要注意,set_clock_groups的优先级高于set_false_path。

如果clkA/clkB作为主时钟,且生成了一些时钟,则上面的约束可变为如下所示的写法:

set_clock_groups -async -group {clkA clkA_gen0 clkA_gen1 ...} -group {clkB clkB_gen0 clkB_gen1 ...}

更简洁的写法,使用-include_generated_clock,如下:

set_clock_groups -async -group [get_clocks -include_generated_clock clkA] -group [get_clocks -include_generated_clock clkB]

2、对同一时钟源创建多个时钟周期约束

需要对同一时钟源创建多个时钟周期约束主要有以下两种情形:

1、对同一个工程,需要测试在不同时钟频率下,能否实现时序收敛,从而获得该设计所能运行的最高时钟频率。

2、对同一个工程,不同的板卡需要不同的时钟频率。

以上两种情形如果分别创建工程或者分别创建不同的约束文件都需要执行多次的综合、布局布线,而对同一时钟源创建多个时钟周期约束最为经济。

假设有如下工程,需要满足以下两种配置:

1、wbClk的工作频率为100MHz;bftClk的工作频率为200MHz;所有跨时钟域路径均按异步跨时钟域路径处理。

2、wbClk的工作频率为150MHz;bftClk的工作频率为200MHz;所有跨时钟域路径均按异步跨时钟域路径处理。

相应的约束如下:

create_clock -name wbClkA -period 10 [get_ports wbClk]

create_clock -name wbClkB -period 6.667 [get_ports wbClk] -add

create_clock -period 5 -name bftClk [get_ports bftClk]

set_clock_groups -physically_exclusive -name two_clk_grps -group wbClkA -group wbClkB

set_clock_groups -async -name my_async_clks -group [get_clocks "wbClkA wbClkB"] -group bftclk

注意:在约束工作频率为150MHz的时钟(对应时钟周期为6.667ns)时,需要添加-add选项,否则,第一条约束将会被覆盖。同时,需要指明两个时钟 wbClkA和wbClkB不可能同时存在,这就需要用到set_clock_groups及其选项-physically_exclusive。在声明跨时钟域路径为异步时,需要用到set_clock_groups及其选项-asynchronous(可简写为-async)。

如果wbClk和bftClk均有生成时钟,则在声明异步跨时钟域路径时,应包含生成时钟。因此,可采用如下方法,即使用-include_generated_clocks选项。

set_clock_groups -async -name my_async_clks -group [get_clocks -include_generated_clocks "wbClkA wbClkB"] -group [get_clocks -include_generated_clocks bftclk]

七、约束优先级

1、等效约束,后者覆盖前者

例如,对输入时钟clk in设置时钟周期约束:先后设置时钟周期为10ns 和 8ns,如下所示,则最终的时钟周期以8ns为准。这是因为XDC本身是按顺序执行的解释性命令,第2条命令与第1条命令完全等效,故第2条命令覆盖了第1条命令。如果在第2条命令中添加了-add 选项,那么此时这两条命令均有效。

create_clock -name clk1 -period 10 [get_ports clk_in]

create_clock -name clk2 -period 8 [get_ports clk_in]

2、不同类型的时序例外路径约束

遵循如下所示优先级:

对于如下所示的约束,如果regtx1由clktx驱动、regrx1由clkrx驱动,则可根据上图中的优先级原则执行,此时set_max_delay无效。

set_false_path -from [get_clocks clktx] -to [get_clocks clkrx]

set_max_delay -datapath_only 5 -from [get_cells regtx1] -to [get_cells regrx1]

3、同类型的时序例外路径约束

同类型的时序例外路径约束遵循的原则是“越具体,优先级越高”。

例如,对于如下所示的约束,第1条命令包含-from和-to选项,而第2条命令只包含-from选项,因此,对于从clk1到clk2的路径,第1条命令将覆盖第2条命令,时序引擎最终按12ns处理。但如果还有从clk1到其他时钟域,如clk3的路径,那么第2条路径依然有效。

set_max_delay 12 -from [get_clocks clk1] -to [get_clocks clk2]

set_max_delay 15 -from [get_clocks clk1]

对于如下所示的约束,第2条命令既有-from和-to选项,又有-through选项,似乎比第1条更具体。但在第1条中,即便inst0由clk1驱动,但-from和-to的对象是比clock更具体的Cell。因此,对于从inst0到inst1的路径,时序引擎按照第1条路径约束。

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]

时序例外路径约束的优先级相对于普通的时钟周期约束更为复杂,因此,一个基本设计原则是避免对同一条路径施加不同的时序例外路径约束。此外,还可借助report_exceptions查看时序例外路径约束报告,从而发现潜在问题。

参考文献:

《Vivado 从此开始》高亚军

FPGA的时序约束(理论篇) - 知乎

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐