TimeQuest User Guide 翻译.docx
《TimeQuest User Guide 翻译.docx》由会员分享,可在线阅读,更多相关《TimeQuest User Guide 翻译.docx(28页珍藏版)》请在冰点文库上搜索。
TimeQuestUserGuide翻译
Section1:
GettingStarted
CoreTiming
在编译工程以后,调用Timequest。
如果SDC文件没有创建,那么可以到File->New选项创建一个新的SDC文件。
ConstrainingtheCorewithFourCommands
每个.sdc文件都应当以下面四个命令作为开头:
∙- create_clock
∙- derive_pll_clocks
∙- derive_clock_uncertainty
∙- set_clock_group
前三个命令是重要的。
命令的细节描述可以通过-long_help帮助显示出来:
∙create_clock-long_help
∙derive_pll_clocks-long_help
∙derive_clock_uncertainty-long_help
∙set_clock_groups-long_help
create_clock
当我们创建一个新的SDC文件,首先要做的就是约束输入FPGA端口的时钟信号,通过使用create_clock命令。
基本的格式如下:
create_clock-namesys_clk-period8.0[get_portsfpga_clk]
注意:
1.上面的命令创建了一个周期为8ns的系统时钟sys_clk,并将该时钟连接到我们FPGA的时钟输入端口fpga_clk;
2.Tcl和SDC是case-sensitive的,所以请确认fpga_clk和我们设计的时钟参数相符合;
3.该时钟在0ns时刻产生一个上升沿,具有50%的占空比,因而其下降沿在4ns处。
如果我们想产生不同占空比,或者添加一个时钟偏移offset,可以使用-waveform选项。
但很少需要这么做。
4.我们经常会去创建一个与端口port同名的时钟信号,这种做法是不合法的。
下面的例子:
create_clock-name fpga_clk -period8.0[get_ports fpga_clk]
现在有两个单元都有name叫做fpga_clk,一个是端口,一个我们定义的时钟。
5.在Tcl语法中,方括号[]将会执行在其内部的命令,所以[get_portsfpga_clk] 会执行搜索命令,找到一个名交fpga_clk的端口,并return其值。
这部分在章节Tclsyntaxsection部分有详细的讨论。
虽然该命令经常被使用,但仍有一部分设计人员只是简单的把端口名字写在命令后面:
create_clock-namesys_clk-period8.0 fpga_clk(Wrong)
6.重复上面的步骤,添加设计中所有的时钟信号。
(如果你不确定有哪些时钟,那么就把所有你知道的时钟输入进来,之后我们将会展示ReportUnconstrainedPaths 是怎样指定一个没有约束的时钟的。
)
建议:
除了可以输入约束命令,我们还可以通过GUI的方式输入约束。
在打开Timequest之后,再打开,sdc文件,将光标定位在需要加入约束命令的地方,然后使用Edit->InsertConstraint,选择相对应的约束。
需要注意的是,不要通过TimeQuestGUI的Constraint下拉菜单添加约束。
虽然二者看起来是一样的,但是上面方式添加的约束,将会直接作用到timingdatabase中,而不会写入到.sdc文件中,有经验的users可能会用上面的方式,但是初学者不推荐。
还是安心的使用Edit->InsertConstraint命令。
derive_pll_clocks
接下来,在我们的.sdc文件中添加如下命令:
derive_pll_clocks
就这样,加上这句话就好了!
注意:
1.每一个PLL输出信号都需要被 create_generated_clock 约束。
2.当PLL信号被创建的时候,设计者会指定每个PLL输出是怎样配置的。
所以,TImequest能够自动的去对它们创建约束,这就是derive_pll_clocks 命令做的事情。
3.这个命令同时还做了其他的工作:
它会约束transceiverclocks(这个是什么时钟),同时会在LVDSSERDES和userlogic之间添加多周期。
4.想要查看 derive_pll_clocks 命令在底层的具体实现,可以看TimeQuest的messages窗口,它会单独的列出derive_pll_clocks 实现的每一条命令
5.新手经常不会去添加derive_pll_clocks 命令,而是一条条的将create_generated_clock命令输入.sdc文件中。
理论上来说,这并没有错,但问题是,一旦我们PLL设计修改了,那么相应的.sdc文件和PLL相关的命令就需要重新编辑。
所以还是建议使用derive_pll_clocks命令去自动创建pll约束。
derive_clock_uncertainty
在.sdc文件中添加如下命令:
derive_clock_uncertainty
先不用管为什么,加上去就好了。
注意:
1.这个命令应当在所有的SDC文件中都存在。
2.它的存在不会影响早期的设计,顶多不起作用。
3.这个命令会计算FPGA里面时钟之间的uncertainties,根据各种参数(诸如PLL波动,时钟树抖动.etc)
4.如果用户不添加该命令,则会有一个报警。
以上就是时序约束要先完成的三个步骤。
对于一个有两个时钟输入的简单设计,它的SDC文件如下:
set_clock_groups
在上面的约束基础上,设计中大部分的时钟已经被约束了。
在TimeQuest中,所有的时钟默认都是相关联的,由设计者决定哪些时钟不相关。
所以举例来说,如果在一个周期8ns和10ns的时钟之间有路径,即使这两个时钟是不相关的,TimeQuest仍然会获得时钟之间2ns的setuprelationship,并试图满足它。
这是TimeQuest中的保守做法,而不像其他工具那样,默认时钟不关联。
由设计者决定哪些时钟不相关。
SDC语言有一个强大的命令 se_clock_groups,来完成这个工作。
它的语法如下:
set_clock_groups-asynchronous-group{}-group{}-group{}
注意:
1.每个group都是互相关联时钟的列表。
2. group对时钟的个数没有限制,即使需要50个group也是可以的。
但是如果通过Edit->InsetConstraint 命令添加,那么仅仅支持两个group。
但是这仅仅是GUI工具的限制,手动输入SDC命令不受这个约束。
3. TimeQuest默认所有的时钟都在一个大group中。
4.任何没有在上面命令中出现的时钟,会保持其默认属性——和所有时钟相关。
所以如果你忘记了对某个时钟进行指定,那么它将会在所有涉及到它的时域中被分析。
5. Aclockcannotbewithinmultiple-groupsinasingleassignment。
6.可以有多个set_clock_groups 命令在一个SDC文件中
7.这个命令通常会很长,所以很难在一行写完,所以记得使用“\”连接符。
8.针对有着复杂时钟的设计,写这个约束通常会比较复杂。
比如说:
有两个DDR3核和一个高速收发器可能包含有30或者更多个的时钟。
这些例子当中,我们添加上所有我们创建的时钟。
既然有前面提到的条件——所有没提到的时钟仍然和所有时钟相关,我们只需要谨慎的将我们了解的时钟合成一组就行。
如果载我们未关联的时钟域之间仍然存在failingpath,我们就根据报警提示,添加相应的时钟。
而在上面的例子当中,一大堆的时钟并不真正的被放入set_clock_groups命令当中,因为他们要么封装在IP核的 .sdc文件中,要么仅仅和相关的时钟域相连。
(Inthiscase,alargenumberoftheclockswon'tactuallybeintheset_clock_groupscommand,sincetheyareeithercutintheIP's.sdcfile(liketheonesgeneratedbytheDDR3cores),ortheyonlyconnecttoclockdomainstheyarerelatedto.)
9. 这里我特意的将 virtualclockscreatedforI/Oanalysis排除在约束外。
因为他们连接的时钟,仅仅是realpaths,所以这里没有必要排除对他们的分析(Igenerallyleave virtualclockscreatedforI/Oanalysis outofthisconstraint.Theonlyclockstheyconnecttoaregenerallyrealpaths,sothereisnoneedtocuttheiranalysistootherclocks.)。
10.对于set_clock_groups 命令的选项,要么是 –asynchronous(异步)要么是 –exclusive(独立的)。
-asynchronous 标志意味着各组时钟在组内是触发的,但相互之间是却不能异步传输数据(Theasynchronousflagmeanstheclocksarebothtoggling,butnotinawaythatcansynchronouslypassdata.)。
-exclusive标志意味着时钟不在同一时刻触发,因此是互相独立的。
解释这项的一个很好的例子是:
一个时钟选择器,有两个时钟连接到输出端。
介于一个时间段,只能有一个时钟被触发,因此这两个时钟是-exlucsive的。
TimeQuest会无差别的去分析你的设计foreitherflag。
这个选项对于ASIC设计来说是十分有用的,因为它会分析SIissue,诸如 asynchronous时钟之间的cross-talk,却不分析exclusive时钟的之间的cross-talk。
IfgoingtoHardcopy,whichusesASICanalysistoolsontheback-end,itisrecommendedtogetthisright。
对于FPGA来说,这些真的不重要。
Themoreconservativevalueis -asynchronous,sincethisstatestheclockscaninterferewitheachother,andwhatIusebydefault。
11.另一个消除时钟之间timing的方式是:
使用set_false_path.命令。
如果不想分析sys_clk和dsp_clk之间的时序,可以输入以下命令:
set_false_path-from[get_clockssys_clk]-to[get_clocksdsp_clk]
set_false_path-from[get_clocksdsp_clk]-to[sys_clk]
当只有少量的时钟信号,这样做是可以的,但是时钟多了以后,约束可读性就会很差。
在一个具有多种始终输出的PLL例子中,set_clock_groups命令可以在10行代码内,清晰的显示出时钟相关性,而时钟set_false_path则可能超过50行。
Quicktipforwritingset_clock_groupsconstraint
1.介于dderive_pll_clock 创建的所有的时钟名字并不被我们全部认知,所以一个快捷创建.sdc文件方式如下:
∙ 为每个输入时钟使用creaete_clock命令
∙ 添加derive_pll_clocks命令
∙ 添加derive_clock_uncertainty命令
2.双击左侧Task窗口的 ReportClocks 命令。
这个操作会读取我们的.sdc文件,并报告这些时钟的约束信息。
从那个report中,我们可以选中所有我们所知道名字的项目,并点击鼠标右键:
这时候我们已经以Timequest能识别的方式复制了所有的时钟信息,之后,黏贴这些信息到我们的.sdc文件中。
3.现在我们有了一个所有时钟列表,接下来将他们格式化到set_clock_groups命令中。
比如,我可以从下面的空列表开始:
set_clock_groups-asyncrhonous-group{\
}\
-group{\
}\
-group{\
}\
13
-group{\
}
然后黏贴时钟信息到这些组中,适当添减group。
4.最后,格式化这些命令,增加可读性:
我们注意到,最后一组中,有一个PLL输出信号,而其他的PLL输出则在第二组中。
这是因为这里,我设置了该时钟的频率不能和其他时钟相关。
必须将它看成一个异步时钟。
但是通常情况下,所有PLL的输出都是相关的,因此会在同一group中。
这都由设计者决定。
就这样了,对许多设计来说,约束这些核心很重要,但是在这个快速约束指导中,有一些方面并不能被覆盖到:
1.添加多周期(Multicycle),降低系统运行频率(见i.e. openingthewindow.)。
比如,一个10ns的时钟会有一个10ns的setuprelationship。
但是如果数据传输很慢,亦或者寄存器以一个更慢的速度触发,那么设计者就必须设定Multicycle来openwindow,以满足数据传输的要求。
这一操作将会使得setuprelationship变成20ns或40ns……同时保持holdrelationship为0ns。
2. Multicycle的另一个形式是,设计者希望shiftthewindow。
这通常发生在设计者想要时钟产生一个微小的相移。
比如,设计者想要从pll中生成一个10ns时钟,第二个时钟也是10ns,但是有着0.5ns的相移,默认情况下setuprelationship只有0.5ns 而holdrelationship则有-9.5ns。
对于满足0.5ns的setuprelationship几乎是不可能的。
所以大部分设计者希望数据在下一个周期window之前到达就行了。
这里可以通过在mainclock 和phase-shift-clock之间添加一个Multicycle解决。
这样setuprelationship就变成了10.5ns,而hold relationship变成了0.5ns。
当设计者生成了有相移的时钟,就应当第一时间想到使用Multicycle。
而Multicycle被称作 shiftingthewindow
如果对setup 和holdrelationship有困惑的,请查阅章节ebasicsofsetupandhold,同时也可以参阅下面的章节determiningdefaultsetupandholdrelationships。
3.添加create_generated_clock命令来rippleclock。
Rippleclock的定义是,由寄存器的输出端输出clk信号,以驱动其他寄存器的时钟输入端,该clk就被称作rippleclock。
该时钟并不会穿过寄存器,所以所有的rippleclock都必须有一个 create_generated_clock约束命令。
没有被约束的rippleclock会在timequest的”ReportUnconstrainedPaths“中被显示出来,所以很容易识别。
总的来说,rippleclock需要被避免,如果可能,使用clockenable来替代。
4.对频率选择器的输出端使用create_generated_clock命令。
如果没有该约束,所有经过选择器传播的时钟将会被视为相关联的。
届时TimeQuest将会分析所有从选择器来的路径(whereoneclockinputfeedsthesourceregisterandtheotherclockinputfeedsthedestination,andvice-versa)。
尽管有时可以满足时序要求,但这不是设计者想要的。
通过添加create_generated_clock命令来约束选择器输出端口,能够将输出端和输入时钟关联起来,以方便设计者正确的对这些时钟进行分组。
I/OTiming
(Note:
这部分不会明确的包含source-synchronousinterface的内容,虽然他们都使用相同的规则)
IO约束仅仅有两个.sdc命令,分别是 set_input_delay 和 set_output_delay ,但是这两个命令开始还是比较难理解的。
其实这两个命令最重要的内容,就是描述在FPGA的外面发生了什么,通过得到外部的描述,TimeQuest能够得到FPGA内部需要满足的要求是什么。
这里我将其分成五个步骤:
1.添加 create_clock 命令,为IO接口创建一个virtualclock。
2.为IO口添加 set_input_delay 或者 set_output_delay 。
分别用-min和-max选项各添加两个描述,并将0.0作为它们的value(这部分将在第5步重新修改);
3.设定FPGAclock和virtualclock之间的setup、holdrelationship。
、
4.添加Multicycle如果必要的话;
5.修改-max和-mindelayvalue来保证外部延时(修改第2步的0.0值)。
需要指出的是, set_output_delay 和 set_output_delay 的值是在最后一步确认的。
这对很多新人来说是完全相反的步骤。
在浏览后续步骤之后,大家就能了解这是为什么了。
同时可能注意到了,双向IO口,同时最为输入输出口,会同时用到前面两个约束。
Step1)Usecreate_clocktoaddavirtualclockfortheI/Ointerface
这总是第一步。
如果FPGA设备和一个66MHz的PCI设备、200MHz的DAC设备通信,那么设计者会添加如下命令:
create_clock-period15.151-namepci_clk_ext
create_clock-period5.0-namedac_clk_ext
注意到,这里并没有将时钟连接到FPGA的某个端口,这样它们就变成了virtualclock;他们在FPGA外部存在。
接下来就要介绍怎么使用这两个vritualclock。
Step2)Addset_input_delayorset_output_delayontheI/Oport/sAddittwice,onceusing-minandonceusing-max.Usethevalue0.0forbothdelays,andthevirtualclockfortheclock
这部分命令虽然会有点长,但是却很简单。
如果约束一个叫做DAC_DATA[5]的端口,我会添加一下命令到.sdc文件中:
set_output_delay-clockdac_clk_ext-max0.0[get_portsDAC_DATA[5]]
set_output_delay-clockdac_clk_ext-min 0.0[get_portsDAC_DATA[5]]
如上所示,- clock 选项用来描述第一步生成的virtualclock。
同时-max和-min值是0.0。
(我们会修改0.0的值在第5步)。
对于一个输入总线,我想对每根信号线使用相同的约束,那么我会这样写:
set_input_delay-clockadc_clk_ext-max0.0[get_portsADC_DATA[*]]
set_input_delay-clockadc_clk_ext-min 0.0[get_portsADC_DATA[*]]
这步是相当直接明了的,因为我只是按照步骤操作,并没有进行任何消耗脑细胞的分析过程。
虽然简单,但我们不能忽略这几句话产生的作用,虽然本质上讲,除了描述FPGA外部在发生什么,它们并没有约束任何东西。
让我们看看我们的输出约束:
1.set_output_delay\ #有一个寄存器被FPGA的输出端口所驱动
2.-clockdac_clk_ext\ #该寄存器的时钟是所谓的virtualclockdac_clk_ext
3.-max/-min0.0\ #外部延时有0.0的最大值和最小值
4.[get_portsDAC_DATA[5]\ #该寄存器被FPGA的端口DAC_DATA[[5]驱动
下面换成结构图来分析一下这个命令:
如上图所示,我们仅仅描述的是FPGA外部的电路。
这样就构成了一个完整的寄存器到寄存器之间的分析模型(对应于FPGA内部的两寄存器间时序分析模型)。
Step3)DeterminethedefaultsetupandholdrelationshipbetweentheFPGAclockandvirtualclock
这一步要求设计者决定FPGA内部的时钟和外部的virtualclock之间的setup、holdrelationship。
这一步通常是很直截了当的,因为大多数情况下,发射沿时钟和锁存沿时钟是同周期并且没有时钟偏移的,它们的关系如下图左上角所示:
对IO口来说,virtualclock将会成为外部输入的发射时钟(launchclock)或者外部输出寄存器的锁存时钟(latchclock)。
在TimingAnalysisBasics章节里面有关于setupholdrelationship的详细介绍。
相比于挖掘这些relationship,这里我将要说明TimeQuest的relationship是怎样被展示的,因此设计者不