系列文章目录
FPGA时序约束(一)基本概念入门及简单语法
FPGA时序约束(二)利用Quartus18对Altera进行时序约束
FPGA时序约束(三)时序约束基本路径的深入分析
FPGA时序约束(四)主时钟、虚拟时钟和时钟特性的约束
FPGA时序约束(五)衍生时钟约束与I/O接口约束
文章目录
- 系列文章目录
- 时序例外约束
- 多周期约束
- 同相同频时钟
- 异相同频时钟
- 慢时钟域到快时钟域
- 快时钟域到慢时钟域
- 同频同相时钟实例
- 虚假路径约束
- 应用实例
- 最大最小延迟约束
- 应用实例
时序例外约束
对一些确实可以放宽时序要求的路径添加时序例外约束,以减少它们对布局布线资源的占用,从而尽可能多地释放出宝贵的资源给那些时序要求确实很高的关键路径,合理分配资源,就能够更好地确保整个系统的时序收敛。
应用案例:
- 异步跨时钟域的路径往往是以时钟与其相位关系中周期最短,即最坏情况进行时序路径分析,这往往导致时序过约束,甚至难以收敛。通常会根据实际情况忽略这些时序路径(可以使用时钟分组约束或虚假路径约束)或施加多周期约束。
- 某些逻辑的时序单元并非每个时钟周期都进行数据采样传输,此时可以使用多周期约束,适当放宽这些路径的约束。
- 有时设计中希望对时序路径施加更紧的约束,以获取更大的时序余量,此时可以使用最大/最小延时约束。
- 某些组合路径是静态的(赋值不变)或并不需要进行时序约束,此时可以使用虚假路径约束忽略这些路径。
时序约束顺序:
- 时序约束:
- 主时钟约束
- 虚拟时钟约束
- 衍生时钟约束
- I/O约束
- 时序例外约束:
- 虚假路径约束
- 最大/最小延时约束
- 多周期约束。
多周期约束
多周期约束用于调整建立时间和保持时间的起始时钟沿到目标时钟沿所需的时钟周期数。
默认是以单周期为单位进行时序路径分析。
实例:某个数据到达目的寄存器的时钟周期数大于一个时钟周期,且该数据路径的控制电路也支持这种情况。
通过放宽某些时序约束要求,把有限的布局布线资源让给更需要的关键路径,优化系统时序。
set_multicycle_path用于更改时序分析(建立时间和保持时间)中的源时钟沿或目标时钟沿的相对位置关系。
set_multicycle_path <path_ multiplier>[ - setup | - hold] [ - start | - end] [ - from<startpoints>][- to <endpoints>][- through<pins|cells|nets>]
- < path_multiplier >参数是必须指定的,它就是多周期约束的最重要的“多”的体现,即用于设置修改约束路径分析的时钟周期数,该参数的取值必须是大于0的整数
- -setup和-hold选项用于指定约束命令所针对的是路径的建立时间分析(-setup)还是保持时间分析(-hold)
- -start和-end选项用于指定约束命令的< path_multiplier >参数是以源时钟(-start)还是以目标时钟(-end)作为参考时钟
- -from指定约束路径的起始节点< startpoints >,-to指定约束路径的终止节点< endpoints >
- -through指定约束路径所经过的节点<pins | cells | nets >
-through是可选项,-from和-to可以同时指定,也可以只指定其中一个,比如约束语法中只有-from,就意味着约束将会覆盖所有从起始节点< startpoints >开始的路径。
保持(hold)时间关系与建立( setup)时间关系是紧密相关的,大多数情况可以通过如下公式进行换算。
保持时间的时钟周期数=建立时间的< path_multiplier>参数-1-保持时间的< path_multiplier >参数
set_multicycle_path命令中使用-setup选项时,不仅会改变建立时间关系,同时也会改变保持时间关系。如果希望在更改建立时间关系时,仍然维持原有的保持时间关系,则需要使用-hold选项进行额外的设置。
同相同频时钟
如下图的例子:
默认的建立时间和保持时间:
相当于:建立时间参数=1,保持时间参数=0.
- Setup=2
set_multicycle_path 2 -setup - from[get_pins data0_reg/C] -to[get_pins data1_reg/D]
- Setup=2 Hold=1
set_multicycle_path 2 -setup - from[get_pins dataO_reg/c] - to[get_pins datal_reg/D]
set_multicycle_path 1 -hold - from[get_pins data0_reg/C] - to[ get_pins datal_reg/D]
当前的建立时间关系和保持时间关系就是预期的符合实际状况且最宽松的情况。
- Setup=5
set_multicycle_path 5 -setup - from[get_pins dataO_reg/c] - to[get_pins datal_reg/D]
这样的保持时间要求很难达到时钟收敛,通常也是处于过约束状态。
- Setup=5 Hold=4
set_multicycle_path 5 -setup - from[get_pins dataO_reg/c] - to[get_pins datal_reg/D]
set_multicycle_path 4 -hold - from[get_pins data0_reg/C] - to[ get_pins datal_reg/D]
异相同频时钟
默认的约束方法:可能过约束
Setup=1:这才是实际情况
慢时钟域到快时钟域
默认的:
我们希望的是:Setup=3 Hold=2
set_multicycle_path 3 -setup -end - from[get_clocks CLK1] - to [get_clocks CLK2]
set_multicycle_path 2 -hold -end - from[ get_clocks CLK1]- to [get_clocks CLK2]
快时钟域到慢时钟域
默认最严苛的约束情况:
我们希望的:
由于时钟周期移动所针对的是源时钟,使用-start 选项(默认选项)。
set_multicycle_path 3 -setup -start -from[get_clocks CLK1] - to[get_clocks CLK2]
set_multicycle_path 2 -hold -start -from[get_clocks CLK1 ] -to[get_clocks CLK2]
在快慢不同时钟域的多周期约束中,通常需要明确指定-start或-end选项。这样能够明确地告知时序工具,所约束的时钟周期移动单位是相对于源时钟还是相对于目的时钟。
setup:
< path_multiplier >参数值越大,建立时间关系的时钟启动沿和锁存沿的距离相隔就越远(时序要求更松)
< path_multiplier >参数值越小,建立时间关系的时钟启动沿和锁存沿的距离相隔就越近(时序要求更紧)。
hold:
< path_multiplier>参数值越大,保持时间关系的时钟启动沿和锁存沿的距离相隔就越近(时序要求更松)
< path_multiplier >参数值越小,保持时间关系的时钟启动沿和锁存沿的距离相隔就越远(时序要求更紧)。
同频同相时钟实例
在图像显示或传输控制的代码中,常常会设计两个计数器用来构建一个二维的图像结构。xcnt和 ycnt就是这样两个分别代表图像显示的坐标计数器, xcnt在每个时钟周期都会递增,递增范围是0~1647的循环;ycnt则只在 xcnt计数到最大值1647时才会递增。
如果实现下图功能,那么vga_valid就会与xcnt和ycnt出现建立和保持时间的关系:
由于xcnt每个周期都变,所以不能使用多周期约束,而ycnt不是,所以他要用。
由于vga_valid对xcnt的判断是( xcnt>=(80+216))&&.( xcnt<(80+216+1280)),所以多周期约束的参数只能选在(80+216)和1648-1-(80+216+1280)中较小的一个值,即71。(原因是ycnt变化后,必须在71个周期内稳定下来,否则xcnt满足条件时再去判断ycnt更改vga_valid的值可能会出错)(我有点不理解,因为ycnt每个周期只变化一次,所以只要在80+216进行多周期约束,那么就能在xcnt满足条件时建立好,不太懂这个作者为啥要取两者的最小值)
总计一下常建议的做法是:在常规的设计约束(主时钟约束、衍生时钟约束、I/O约束等)完成后,若设计的时序收敛,且余量充足,则无须花费时间和精力在多周期路径的约束上。倒是在时序失败或余量不充足的情况下,建议再去做多周期约束。在查找可以进行多周期约束的路径时,原则上也是从出现时序失败的路径本身或相关逻辑开始,必要时再按照逻辑相关性逐步扩大范围,直到增加的多周期约束能够保证整个设计的时序收敛。
虚假路径约束
虚假路径(False路径),是指该路径是设计中的非功能路径或没有任何时序要求的路径。需要让时序工具放弃对它们的任何时序努力和时序分析。
这样设计工具在编译时将会完全移除这些路径,不做任何的时序努力和分析,可以减少编译时间,同时腾出有限的布局布线资源,用于提升整体的时序性能。
常见的虚假路径包括如下几种。
- 已经做过同步处理的跨时钟域路径。
- 上电后只做一次初始化写人的寄存器路径。·复位或测试逻辑的路径。
- 某些实际并不存在的时序路径。
虚假路径约束的基本语法结构如下:
set_false_path [ -setup] [ -hold] [ -from <node_list>] [ -to<node_list>] [ -through<node_lit>]
- setup和-hold选项用于指定约束命令所针对的是路径的建立时间分析(-setup)还是保持时间分析(-hold)。
- from指定约束路径的起始节点< startpoints >。-to指定约束路径的终止节点< endpoints >。
- through指定约束路径所经过的节点。
-through是可选项,-from和-to可以同时指定,也可以只指定其中一个。若只指定-from,-to或-through选项中的一个,则所有经过所指定节点的路径都会被认为是虚假路径。对于这种情况的约束,需要多加小心,以免误约束。
多个-through 选项可以同时使用,但是注意它们具有先后顺序,如下两条约束语句是不一样的:
set_false_path -through cell1/pin1 -through cel12/pin2
set_false_path -through cell2/pin2 -through cel11/pin1
应用实例
- 覆盖全部寄存器
set_false_path -from [get_port reset] - to [all_registers]
- 单向覆盖
仅覆盖从CLKA时钟到CLKB时钟的所有时序路径,但不包括从CLKB时钟到CLKA时钟的时序路径。(想要双向覆盖,就约束两次)
set_false_path -from [get_clocks CLKA] -to [get_clocks CLKB]
- 分组忽略时钟之间的路线
一般推荐使用set_clock_groups约束对两个或多个相斥时钟做约束,以忽略它们相互之间的时序路径。
set_clock_groups - group CLKA - group CLKB
最大最小延迟约束
最大延时约束(set_max_delay)将覆盖默认的建立时间分析的最大路径延时值。
最小延时约束(set_min_delay)将覆盖默认的保持时间分析的最小路径延时值。
通常不建议用于约束输入或输出引脚与内部寄存器之间(pin2reg 以及 reg2pin)的路径延时。
对于一些异步信号之间的路径建议使用。
例:对于设计中的某两个异步时钟域之间的数据通信已经使用双寄存器锁存等方式进行同步了,就可以施加set_false_path或set_clock_groups约束关闭某两个异步时钟域之间的数据路径检查。然而仍然期望查看并确认这两个时钟域之间的时序路径延时,就可以使用set_max_delay 和 set_min_delay进行约束(而不是使用set_false_path 或set_clock_groups进行约束)。
约束命令:
set_max_delay <delay>[ -datapath_only][ -from<node_list>][ -to <node_list>] [ -through<node_list >]
set_min_delay<delay> [ -from <node_list>][ -to<node_list>] [ -through< node_list>]
- -from指定约束路径的起始节点< startpoints >。可以同时指定多个-from节点。
- -to指定约束路径的终止节点< endpoints >。可以同时指定多个-to节点。
- through指定约束路径所经过的节点<pins l cells | nets >。可以同时指定多个-through节点。
默认时序分析时也会将时钟偏斜(Clock Skew)计算在内。若不希望将时钟偏斜考虑在内,则可以使用-datapath_only 选项将其移除。-datapath_only选项只能用于含有-from选项的set_max_delay约束命令中,set_min_delay约束命令中不能。
-datapath_only会同时将此路径的保持时间检查设置为false路径,相当于同时对此路径自动生成了set_false_path -hold约束。也就是说同一路径进行set_min_delay约束将会被忽略。
应用实例
例如对一个跨时钟域的复位信号,我们通常会用到之前说的异步打拍寄存来处理,这样其实就不需要默认的严格的时序约束了。已经算是很好的跨时钟域保护了,所以可以放宽约束了。
书中对set_max_delay,设定延时值为50ns。
书中对set_min_delay,设定延时值为-5ns。
(不太懂为什么)
约束后:
这里是常在跨时钟域时应用,所以这里的约束改变的就是Requirement的值,和前面的set_input_delay那些不一样,那些是同频同相,所以requirement就是一个周期的值。改变的是input delay的值,而如上图,这种约束根本没有这个值。