TimeQuest之multicycle paths
王敏志
(现在发现字数会莫名其妙超出)
实际应用实例
图6是本人实际工作中设计的一个工程部分示意框图,在全编译之后主要是图中的三个PLL的输出时钟有报告时序问题,在不进行时序约束的时候上板调试是没有遇到什么问题的,只是这么多时序违约报告不知道长时间运行是否稳定,所以有必要仔细分析每一个违约时序报告。
图6
这个工程只是对于CLKIN(外部100MHz时钟)和PLL的输出进行约束,如下所示
create_clock -period 10.000 -name refclk -waveform {0 5} [get_ports {refclk}]
create_clock -period 10.000 -name clkin -waveform {0 5} [get_ports {clkin}]
derive_pll_clocks
全编译之后查看TimeQuest的报告图7所示,*pll*clk[0]、*pll*clk[2]和*pll*clk[3]分
图7
别是图6中的100MHz、250MHz和62.5MHz三个时钟我们发现这三个时钟都有报告时序违约,而且250MHz的Fmax报告才不到94MHz。打开TimeQuest分别对这三个时钟的红色报告执行report timing命令并进行分析,图8显示了对于100MHz时钟执行Report Timing后的结果,产生违约的路径的Launch clock是62.5MHz,Latch clock是100MHz,也就是说这些违约路径都是跨时钟域的路径,再分析源代码发现这些路径都是跨时钟传递数据,逻辑设计保证在传递数据的时候能安全传递,即通过握手控制信号保证数据稳定传输,所以这些路径可以认为是false paths。针对这些路径加入false paths约束如下
set_false_path -from [get_clocks {inst|altpll_component|pll|clk[3]}]\ -to [get_clocks {inst|altpll_component|pll|clk[0]}]
再重新编译工程,发现100MHz的时序违约没有了,如图9所示。
图8、对100MHz时序违约路径执行Report Timing命令结果
图9、解决*pll|clk[0]即100MHz时序违约
重新打开TimeQuest,依照从易到难原则,这次解决*pll|clk[3]即62.5MHz时钟时序违约问题。同样执行Report Timing命令我们得到类似图8的报告界面,如图10所示。
图10、对62.5MHz时序违约路径执行Report Timing命令结果
产生违约的路径的Launch clock是100MHz,Latch clock是62.5MHz,也就是说这些违约路径同样都是跨时钟域的路径,再分析源代码发现这些路径都是跨时钟传递的控制信号(图6框图所示),这些100MHz时钟域的控制信号和62.5MHz时钟域被控制的模块是完全异步的关系,所以这些路径可以认为是false paths。针对这些路径加入false paths约束如下
set_false_path -from [get_clocks {inst|altpll_component|pll|clk[0]}]\ -to [get_clocks {inst|altpll_component|pll|clk[3]}]
上述false paths命令其实就是前面false paths命令的反向操作,即这两条false paths命令分别“cut”了100MHz和62.5MHz这两个时钟域之间路径的时序分析。再重新编译工程,发现62.5MHz的时序违约没有了,如图11所示。
图9、解决*pll|clk[3]即62.5MHz时序违约
还剩最后一个,总的slack到-10.586ns,打开TimeQuest并对此违约路径执行Report Timing命令,报告结果如图12所示。
图12、对250MHz时序违约路径执行Report Timing命令结果
由于负slack量很大,所以时序违约也许不止一种情况(实际情况也确实如此),图12所示的报告默认只报告最差的10条。仔细分析图12已经报告出来的这些违约路径,发现跟图8和图10报告的违约路径类似,也都是一些跨时钟域的路径,这里的Launch clock是100MHz,Latch clock是250MHz。也就是说可以把这些路径当作false paths处理,由于本文是论述多周期,所以我想是不是可以通过加入多周期约束来解决这个问题呢?尽管100MHz与250MHz不是整数倍的关系,但是图12时序图看出可以加入一个4周期的end建立多周期约束,同时加入一个3周期的保持多周期来解决这个问题。命令如下所示:
set_multicycle_path -from [get_clocks {inst|altpll_component|pll|clk[0]}] -to [get_clocks {inst|altpll_component|pll|clk[2]}] -end -setup 4
set_multicycle_path -from [get_clocks {inst|altpll_component|pll|clk[0]}] -to [get_clocks {inst|altpll_component|pll|clk[2]}] -end -hold 3
(注:本人不确定多周期是否必须两个时钟必须要是整数倍关系,但根据这个例子似乎不是也可行啊!)
重新编译工程,发现250MHz还是有时序违约,但是负的slack减少了,如图13所示
图13
打开TimeQuest针对违约路径执行Report Timing命令,得到的报告结果如图14所示
图14
仔细分析图14报告的违约路径,以及时序图,这些违约路径的Launch clock和Latch clock为同一时钟,即250MHz时钟。研究这些违约路径的原始代码发现from node其实是一个计数器的输出,而此计数器的计数频率虽然是250MHz,但是有条件的计数,所以这些路径更适合加多周期约束,这里先使用false paths约束,最后再把图12和图14所示的违约路径分别改成false paths和多周期路径约束。这里先加入的false paths如下所示
set_false_path -from [get_registers {SEP_TDC_7ch:inst13|tdc1ch_won:inst?|TDC1ch2a:TCH0|lpm_counter30:RGZ1|lpm_counter:lpm_counter_component|cntr_rsh:auto_generated|safe_q
重新编译工程,发现250MHz的时序违约没有了,而它的Fmax也提高到250MHz以上了,如图15所示(注意和图7比较)。
图15
附1
前面有提到图12所示的违约路径应该false paths约束,而图14所示的违约路径应该加多周期路径约束。那么首先将图12所示的违约路径修改成false paths约束,约束命令如下,也即Launch clock是100MHz,而Latch clock是250MHz时钟。
set_false_path -from [get_clocks {inst|altpll_component|pll|clk[0]}] -to [get_clocks {inst|altpll_component|pll|clk[2]}]
重新编译后的结果如图16所示。
图16
上图显示修改成false paths约束后似乎也能解决时序违约问题,对比图15,Fmax似乎跑的更高一些。而图14所示的时序违约路径的约束修改为多周期路径约束并没有成功,不管我如何加多周期约束在FIT的时候都是通不过,提示“Critical Warning (332008): Read_sdc failed due to errors in the SDC file”,也许是多周期语法有错?下面列出我尝试过的命令格式:
第一条:
set_multicycle_path -end -setup –to [get_pins {SEP_TDC_7ch:inst*|tdc1ch_won:inst1|TDC1ch2a:TCH0|lpm_add_sub21:RGT1|lpm_add_sub:lpm_add_sub_component|add_sub_30k:auto_generated|pipeline_dffe
第二条:
set_multicycle_path -end -setup –to [get_pins {SEP_TDC_7ch:inst13|tdc1ch_won:inst?|TDC1ch2a:TCH0|lpm_counter30:RGZ1|lpm_counter:lpm_counter_component|cntr_rsh:auto_generated|safe_q
第三条:加上 –from即从时钟到上述PINs也不行。
第四条:将“get_pins”改成“get_cells”以及“get_registers”也不行。
所以对于图14显示的违约路径还是加false paths来处理。最终工程的时序报告如图16所示。
文章评论(0条评论)
登录后参与讨论