第二章 约束命令
Timequest共包括13条约束命令(从timequest工具constrants下拉菜单可选的约束命令,实际不止这么多),分别是:
Creat clock
Creat generated clock
Set clock lantency
Set clock uncertainty
Set clock groups
Remove clocks
Set input delay
Set output delay
Set false path
Set multicycle path
Set muximum delay
Set minimum delay
Set muximum skew
各个约束命令说明
2.1 Create_clock
两个作用:(page73)
1,约束从外部进入FPGA的时钟。
2,创建虚拟时钟,虚拟时钟是指外部IC芯片用到的时钟,它们不是FPGA内部的时钟域。Create_clock不能用于约束FPGA内部的时钟。(page74)在约束命令都是添加在SDC文件里面,所以们得先创建一个SDC文件,通过timequest的cronstraints下拉菜单的generated SDC file选项可以生成。而我添加每一条命令都是通过quartus 的Edit下拉菜单insert constraint选项添加的。
我们选择通过quartus 的Edit下拉菜单insert constraint选项添加Create_clock约束命令,弹出如图11的会话框,Clock name 指你想约束的时钟名称,任意起,不过最好根据自己设计的模块起,便于分析阅读,不然时钟多了,自己都不知道哪个时钟是哪个模块的。
Period 约束时钟的周期
Rising 指时钟上升沿的开始时间
Falling 指时钟下降沿的开始时间
图11
Targets 指你想约束的哪个FPGA 管脚。
SDC command就是要添加到SDC文件里面的约束命令。
通过图11会话框的选项添加到SDC的约束命令如图39行。
2.2 Creat generated clock
Create_generated_clock的作用:(page74)
1,约束PLL。(约束命令derive_pll_clocks)
2,同步输出时钟,约束FPGA芯片输出到外部的时钟。
3,时钟多路复用器(clock muxes)
4,ripple clocks,该时钟是FPGA内部一个寄存器的输出做为另一个寄存器的时钟,如通过计数产生的时钟,源寄存器需要一个已经产生的时钟,不然ripple clock将不会约束成功。
我们选择通过quartus 的Edit下拉菜单insert constraint选项添加Create_clock约束命令,弹出如图12的会话框
图12 Create_generated_clock
Sorce 源时钟,指输入时钟,用于给被约束时钟提供时钟源,这个时钟往往是已经存在的时钟,如由之前的Create_clock产生的时钟。
Divide by 对源时钟分频
Phase 对源时钟进行相移
Multiply by 对源时钟倍频
Offset 对源时钟进行偏移,这里是偏移多少个ns,而项移是偏移多少度
Duty cycle 占空比
图12的会话框表示对管脚ext1_clk进行了约束,它的源时钟是clk,约束后的名字是 ext1_clk。
与图12对应的约束命令:
create_generated_clock -name ext1_clk -source [get_ports {CLK}] [get_ports {ext1_clk}]
当然,设计者根据自己的需求来进行约束,是否需要分频、相移等。
2.3 set_clock_latency
该约束命令用于板级的时钟延迟,用于对FPGA输入时钟、外部虚拟时钟(如外部IC的时钟)以及反馈时钟(指某个时钟从FPGA芯片输出然后又回到FPGA芯片)的约束。(page86)
如图13所示的latency type选项,set_clock_latency分为early和late之分。
图13 set_clock_latency
Set_clock_latency约束命令有late和early之分,late指最大时钟延迟,early指最小时钟延迟。当进行setup slack分析时,由于set slack=data required time - data arrived time,所以late的延时会加到data arrived time里面,对源寄存器时钟进行延时,early的延时会加到data required time里面,对目的寄存器时钟进行延时;在进行hold slack分析时,由于hold slack = data arrived time - data required time里面,所以early的延时会加到data arrived time里面,对源寄存器时钟进行延时,late的延时会加到data required time里面,对目的寄存器时钟进行延时。
上面这样分析的目的是为了分析在最糟糕情况是否满足时序约束。 而值得注意的是late与early差值会添加到clock pessimism 里面。如下图:这里late的值我设置的是3ns,eraly的值我设置的是1ns,上图是没有添加Set_clock_latency约束命令的报告,下图是添加了Set_clock_latency约束命令的报告,然后观察source latency和clock pessimism的值。
图14 未添加Set_clock_latency
图15 添加了Set_clock_latency
2.4 Set_clock_uncertainty
约束命令set_clock_uncertainty针对时钟出现的抖动(jitter),clock skew进行的约束。(page86)
图16 Set_clock_uncertainty会话框
通过会话框可以知道,该约束命令是对一个时钟到另一个时钟uncertainty的约束。另外,通过derive_clock_uncertainty命令也可以对时钟uncertainty进行约束,实际上用这个约束命令会更好,因为用这个约束命令不需要设计者去算uncertainty是多少,而set_clock_uncertainty约束命令则需要自己去算,如下图:
图17
注意,不是所有的FPGA都支持jitter分析的,有些FPGA系列芯片不支持derive_clock_uncertainty命令。比如cyclone ii系列就不支持。如果不能使用derive_clock_uncertainty命令的话,那么我们要怎么来知道时钟抖动信息然后做出正确的约束就很重要了。
建议一般用derive_clock_uncertainty约束命令对时钟的uncertainty进行约束。
由于我们能在set input delay和set output delay计算公式中添加clk skew信息,以及通过set clock latency添加时钟延迟信息,加上Set_clock_uncertainty约束命令,这3种约束都能对clk skew进行约束,所以我们在添加约束命令时,不要重复添加clk skew约束。
2.5 set_clock_groups
对于有多个时钟的设计中,可以用这个约束把相关的时钟分成一个组,与其它不相关的时钟区分开。这样也避免timequest对相关的异步时钟进行时序分析而带来不必要的麻烦。比如我们如果用pll产生了大量的异步时钟,而且这些时钟不完全相关,那么我们就需要通过这些约束把pll产生的时钟输出分组。
图 18
如图18,这个约束命令把时钟分成了两组,ext1_clk和ext1_clk_r是一组,clk、ext_div2和ext2_clk是一组,这样约束过后,timequest只对这两个组内的时钟域进行分析,两个组间的时钟路径将不会分析。
2.6 set_input_delay
set_input_delay是对外部IC输入到FPGA管脚的约束,这个约束命令中的延迟信息需要设计者告诉timequest。
图19
如图19,外部IC时钟是ext1_clk,input delay options选项中maximum用于setup slack分析,minimum用于hold slack分析,图19下面76行和77行是通过set_input_delay会话框添加的约束命令,这两条约束命令表示从外部IC到FPGA输入管脚Din[3:0]的最大延时是4ns,最小延时是2ns,外部IC时钟是ext1_clk。
会话框中的add delay选项用于说明有另外的外部寄存器连接到端口,通常用于对双倍速率接口的约束。
对于双倍速率接口的1/O约束通常这样:
set_input_delay -clock ext_clk -max 0.5 [get_ports {ddr_data[*]}]
set_input_delay -clock ext_clk -min -0.5 [get_ports {ddr_data[*]}]
set_input_delay -clock ext_clk -max 0.5 [get_ports {ddr_data[*]}] -clock_fall -add_delay
set_input_delay -clock ext_clk -min -0.5 [get_ports {ddr_data[*]}]-clock_fall -add_delay
这个约束告诉我们每一个ddr_data端口都是被两个外部的寄存器驱动,一个是在ext_clk的上升沿锁存,另一个是在ext_clk的下降沿锁存,如果每没有在最后两行添加-add delay的话,最后两行就会把开始两行的约束覆盖掉,timequest也会报出警告。
2.7 set_output_delay
这个命令约束FPGA输出到IC的延迟,其它都与set_input_delay一样,不再多说。
图20
如图20,82到85行表示FPGA输出管脚Dout2[3:0]和Dout1[3:0]到时钟为ext2_clk的外部IC输入的最大延迟是4ns,最小延迟是2ns。
2.8 set false path
Set_false_path,该约束命令是告诉timequest不要分析某个路径或者是某组路径。
图 21
如图21,该约束告诉timequest不要分析时钟域clk到ext_div2之间的路径。设计者在用该约束命令时一定要知道自己在做什么,如果某些路径本身是不存在的,但是timequest在分析时把两个不相关的时钟域联系了在一起并且这些路径不满足时序要求,如果设计者不知道的话,有可能会一直去纠结自己逻辑的问题或者是通过其它方式让这些路径满足时序要求,但是这样做不是正确的,我们应该用set false path约束命令把这些路径给屏蔽掉,这样做就不会出现错误了。
2.9 set_multicycle_path
当两个寄存器间的数据传输在一个周期内没法完成时,我们可以通过该约束命令来改变他的建立关系值和保持关系值让其满足时序要求。
图22
首先我们看一下会话框,analysis type中setup影响setup relationship值,而hold影响hold relationship值,reference clock中的start和end选项指以哪个时钟周期来算setup relationship和hold relationship的值。
然后我们再来看看setup和hold是如何影响setup relationship值和hold relationship值的:
图23
Case1是在默认情况下的setup relationship值和hold relationship值,默认情况下 -setup的值是1和 -hold 的值是0, Case2我们把setup的值该为2,然后可以看到setup relationship值和hold relationship值都各自增加了10ns。从图中可以看到,hold relationship的值要随着setup值的改变而改变,有如下公式:
setup relationship = default_setup_relationship + (MC_setup_value – 1) * clk_period (on timequest_user_guide page 50)
Holdrelationship = default_hold_relationship + (MC_setup_value – 1) * clk_period
可是我们可以发现,如果只通过setup值来改变setup relationship的值,而hold relationship值也跟着发生了改变,这样hold 分析可能不满足时序要求,接下来就讲讲analysis type中hold选项的作用。
图24
看图24,case1 的setup值为4、hold值为0时setup relationship和hold relationship的值分别从默认的10ns和0ns变成了40ns和30ns,我们再看后面3中情况,setup值保持不变,hold值从1增加到3的时候,setup relationship值一直保持不变,而hold relationship的值从30ns变成了0ns。从结果看得出这样的结论:随着hold值的增加,setup relationship保持不变,而hold relationship的值一直减小。
通过以上分析我们可以得出以下公式:
1) analysis type是setup且reference clock是start
setup relationship = default_setup_relationship + ((MC_setup_value – 1) * launch_clk_period)
Holdrelationship = default_hold_relationship + (MC_setup_value – 1) * launch_clk_period
2) analysis type是setup且reference clock是end
setup relationship = default_setup_relationship + ((MC_setup_value – 1) * latch_clk_period)
Holdrelationship = default_hold_relationship + (MC_setup_value – 1) * latch_clk_period
3) analysis type是hold且reference clock是start
hold relationship = default_hold_relationship - (MC_hold_value * launch_clk_period)
4) analysis type是hold且reference clock是end
hold relationship = default_hold_relationship - (MC_hold_value * latch_clk_period)
特别说明:用该约束命令约束时,如某个路径在一个时钟周期内无法满足时序要求,然后通过该约束命令让这个路径在3个时钟周期内完成,比如让setup relationship和hold relationship的值从默认的10ns和0ns变成了30ns和0ns,虽然通过约束让自己的设计满足了时序要求,但是我们要明白逻辑并不会这样做,我们需要修改逻辑让以前在一个时钟周期内完成的操作现在通过3个时钟周期来完成,这样我们就完成了通过约束来知道逻辑问题出现在哪个地方,然后通过修改逻辑让其满足时序要求。
下面2张图是约束前后约束后的比较。Setup值是2。
图25 约束前
图26 约束后
从图25和图26可以setup relationship和slack的值的变化。
2.10 set muximum delay和set minimum delay
set_max_delay 影响setup relationship,set_min_delay影响hold relationship;用set_max_delay和set_min_delay存在2个危险:第一,一旦用这2个约束,下降沿采集将被忽略;第二,经过pll相移后的时钟,使用这2个约束后,相移将被忽略。
建议不要使用这2个命令对I/O进行约束。对I/O的约束,建议用set_input_delay/set_output_delay。set_max_delay和set_min_delay会直接将setup relationship和hold relationship的值限制成设定的值,而其它延时造成setup relationship和hold relationship的改变将无效
参考资料
1.FPGA那些事儿--TimeQuest静态时序分析REV7.0.pdf
2.TimeQuest_User_Guide.pdf