TimeQuest用户手册.docx
- 文档编号:29577038
- 上传时间:2023-07-24
- 格式:DOCX
- 页数:37
- 大小:1.01MB
TimeQuest用户手册.docx
《TimeQuest用户手册.docx》由会员分享,可在线阅读,更多相关《TimeQuest用户手册.docx(37页珍藏版)》请在冰豆网上搜索。
TimeQuest用户手册
JAQLEUNG
TimeQuest用户手册
原文:
TimeQuestUserGuide(By:
RyanScoville)
秋哥小刀
2017/5/11
本译文包括原文的大部分内容,由于翻译水平有限,建议在阅读本译文后能够研读原文。
第一章译文说明
在翻译过程中,很多专业术语使用直译的方式往往不易理解,但选择的中文词汇又怕引起歧异,所以在这里罗列了这些词汇的准确英文拼写。
在阅读过程中,若是出现难以理解的语句,请首先对照相关词汇的英文词组以读者的思维重新理解,或是直接阅读英文原文的相关章节。
第二章入门
本章的编写目的是为了让用户可以更快速地上手操作时序约束。
以下内容将涉及到多个主题,以帮助用户快速理解和应用时序约束技术,关于这些主题的详细内容将在后续章节中讲解。
建议所有用户通读本章并确认已完全理解本章内容。
本章的最后一节为时序分析结果,理解时序分析结果是进行时序约束不可或缺的一部分。
如果不能读懂时序分析报告,将不具备对片上时序和I/O时序约束的能力。
所以,推荐在本章学习过程中能够始终结合时序分析结果进行阅读。
1.片内时序
编译项目成功并启动TimeQuest,然后就可以输入时序约束命令了。
如果项目中尚未添加SDC文件,可通过菜单File->New来新建一个.sdc文件。
SDC文件推荐使用项目名称进行存储,且通常存储在项目文件夹中。
几乎每个.sdc文件都是以下面4条命令开始:
1)create_clock
2)derive_pll_clocks
3)derive_clock_uncertainty
4)set_clock_groups
其中,前3条命令可以让用户在几分钟内分析完设计中的大部分时序问题。
当我们学习这些命令的过程中,一定要搭配阅读迭代方法。
迭代方法章节会讲述如何快速修改一个.sdc文件、如何重新运行分析、如何进行迭代分析。
关于这4条命令的详细信息,可以在TimeQuest中输入-long_help进行查看:
create_clock–long_help
derive_pll_clocks–long_help
derive_clock_uncertainty–long_help
set_clock_groups–long_help
1)create_clock
新建一个.sdc文件后,首先要做的就是使用create_clock命令对输入FPGA的时钟进行约束。
该命令的基本语法为:
create_clock–namesys_clk–period8.0[get_portsfpga_clk]
注:
⏹上述命令创建了一个名为sys_clk的时钟,这个时钟具有8ns的时钟周期,且这个时钟被应用到了设计端口fpga_clk上。
⏹TCL和SDC语法是大小写敏感的,所以要保证fpga_clk与设计中时序端口的名称大小写一致。
⏹如果未作说明,sys_clk时钟默认在0ns时具有上升沿,4ns时具有下降沿,即默认为50%占空比。
如果用户需要一个不同的占空比或者需要一个移相,请使用-waveform选项。
但是实际设计中很少会有这种必要。
⏹用户通常会创建一个与所应用端口名称一致的时钟,这是完全合法的。
上述例句可改写为:
create_clock–namefpga_clk–period8.0[get_portsfpga_clk]
现在将有两个独立的个体被叫做fpga_clk:
一个是用户设计的端口,一个是源自该端口的时钟。
⏹在TCL语法中,方括号会执行其内部的语句(关于语法,会在TCL语法章节有更多的讨论)。
所以[get_portsfpga_clk]会在设计的所有端口中查找匹配fpga_clk的端口并返回。
更多的设计者习惯像下面这样以更简洁的方式编写上述语句:
create_clock–namesys_clk–period8.0fpga_clk
⏹用这条命令为每一个已知的输入时钟端口创建时钟约束。
(如果用户不确信是否已为所有输入时钟创建了约束,只需先约束暂时已知的,剩下的可以在ReportUncontrainedPaths中查看到。
)
提示:
用户可以直接在SDC文件中直接输入约束命令,也可以使用可视化图形界面来添加约束。
启动TimeQuest后,用TimeQuest或QuartusII打开.sdc文件,从菜单Edit->InsertConstraint添加约束:
千万不要像下图这样从TimeQuest窗口的Constraints下拉菜单来添加约束:
虽然两种操作很像,但是后者是直接将约束应用到时序数据库,而不是添加到.sdc文件。
高级设计人员可能有时需要使用后者,但对初学者来说,请务必使用前者:
通过操作.sdc文件来控制时序约束。
2)derive_pll_clocks
添加下面的命令到你的.sdc文件:
derive_pll_clocks
注:
⏹PLL的所有输出都需要使用create_generated_clock进行约束。
⏹用户创建PLL的过程中要配置其输出,所以PLL创建完毕后TimeQuest有足够的信息来自动约束其输出时钟。
而这就是derive_pll_clocks所要做的。
⏹这条命令还会执行其他一些操作,如:
约束收发器时钟,在LVDSSERDES(并行转换器)和用户逻辑之间添加倍数周期。
⏹如果想知道derive_pll_clocks到底做了些什么,可以在TimeQuest的消息窗口中DerivePLLClocks下查看:
⏹初学者一般不喜欢使用derive_pll_clocks,更倾向于create_generated_clock(看起来更底层些,可以让理解更扎实)。
从技术上这没有问题,因为二者的最终效果是一致的。
但是如果用户在设计过程中修改了PLL,他们必须要记得修改.sdc文件中相应的约束条件。
因此存在太多忘记修改.sdc文件,又花费大量时间去调试的例子,所以还是使用derive_pll_clocks比较靠谱。
直接把PLL的约束丢给TimeQuest吧。
3)derive_clock_uncertainty
添加下面的命令到你的.sdc文件:
derive_clock_uncertainty
注:
⏹在65nm以下工艺水平的设计中,需要在.sdc文件中使用该命令。
⏹在早期工艺水平的设计中,这条语句没有任何影响,也不会做任何事。
⏹这条命令会计算FPGA内部时钟之间的不确定因素,像PLL抖动、时钟树抖动等。
⏹如果用户的.sdc文件中不包含该命令,会出现警告提示。
到此,前3条命令就介绍结束了。
对于一个设计文件,如果包含2路输入时钟,它的.sdc文件将如下所示:
4)set_clock_groups
通过上面的操作,设计中大部分或者全部的时钟都得到了约束。
在TimeQuest中,除非用户特别说明,默认所有的时钟都是相关的。
例如,在一个8ns时钟和10ns时钟之间有若干条路径,即使这两个时钟是完全异步的,但是对TimeQuest来说,这些路径存在2ns的建立时间关系,而且TimeQuest会以此尝试对这些路径进行约束。
相比其他工具那样假设所有时钟都是不相关的,TimeQuest选择了一种更保守的分析方式:
存在的就是要分析的。
所以,需要用户主动告诉TimeQuest哪些时钟是不相关的,这样TimeQuest就不会去分析不相关时钟之间的路径。
set_clock_groups命令的语法如下:
set_clock_groups–asynchronous–group{}–group{}–group{}
注:
⏹每个-group选项是一组相关时钟的列表
⏹对-group选项的数目没有限制。
如果是通过菜单Edit->Insert输入约束,最多只支持2个分组,这是操作界面的输入限制,可通过.sdc文本编辑来扩展分组数目。
⏹这条命令看起来像是在给时钟分组。
其实TimeQuest假定所有时钟都是相关的,默认将它们分在了一个更大的分组中。
所以,这条命令其实是在切断不相关时钟间的关联。
⏹任何未被分组的时钟会保持与所有时钟相关。
所以如果你忘记将一个时钟分组,那么它会被保守分析:
TimeQuest尝试约束该时钟与其他时钟之间的异步路径。
⏹一个时钟不能同时存在多个分组中。
⏹用户可以使用多条set_clock_groups语句。
⏹这条命令通常会分行编写,以提高其可读性。
通常“空格\”意味着一行结束,继续下一行。
稍后会展示该语法结构。
(注意:
\后不能跟任何其他符号,包括空格)
⏹对于包括复杂时钟的设计,编写这条约束命令可能会是一个迭代的过程。
比如,一个包含两个DDR3核心和高速收发器的设计至少含有30多个时钟。
这种情况下,首先仅对创建的时钟进行分组,未被分组的时钟仍然与所有时钟相关。
如果通过约束,不相关的时钟之间仍然有失败的路径,那么就继续向命令中添加新的时钟。
仍然有很大一部分时钟不会出现在set_clock_groups命令中,因为它们已经在IP核的.sdc文件中切断关联了,或者它们只和相关的时钟之间有路径连接。
⏹我通常不会将用于I/O时序分析的虚拟时钟添加到此约束中。
因为它们不会和片上时钟之间有路径连接,所以无须考虑它们。
⏹set_clock_groups后面的选项可以是-asynchronous或-exclusive。
-asynchronous表示时钟是都会触发,但是不能同步传递数据。
-exclusive表示时钟不会同时触发,因此相互独立。
一个很贴切的例子就是时钟复用器,其输出会连接到两个时钟。
因为同一时刻只会有一个时钟可以触发,所以它们是相互独立的。
不过,TimeQuest不会关心这两种标志,它会做同样的分析。
这个选项其实是用作ASIC的时序分析中。
⏹切断时钟之间关联的另一种方法是使用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]
当时钟数目有限时,set_false_path用起来很方便。
但是当时钟数目大量增加时,其可读性就大打折扣。
在一个拥有3个多路输出PLL的简单的设计中,set_clock_groups命令可以在10行内清楚地显示哪些时钟是相关的。
而set_false_path命令可能要超过50行,而且很难看出哪些时钟之间的关联是被切断的。
编写set_clock_groups约束的快捷提示
1)因为derive_pll_clocks会根据设计自动创建很多时钟,而设计人员可能并不是很清楚这些时钟的确切名称。
一种快速添加set_clock_groups约束的方式就是先完成上面的3条约束:
为外部输入时钟添加create_clock约束;添加derive_pll_clocks约束;添加derive_clock_uncertainty约束。
2)双击TimeQuest界面左侧Task面板中的ReportClocks。
软件会自动读取你的.sdc文件然后应用到设计中,进而为所有时钟出具分析报告。
从报告上,选中第一列的时钟名称并拷贝,像下图所示:
然后粘贴到你的.sdc文件中。
3)现在你的.sdc文件中就有了一列时钟(设计中的所有时钟),将这些时钟名称按照格式填入到set_clock_groups命令就行了。
比如,我会先写出一个空的命令:
Set_clock_groups–asynchronous–group{\
}\
-group{\
}\
-group{\
}\
然后根据时钟之间的关系,将它们填入到上面的空命令中。
当然,可根据实际需要增加或者删除分组。
4)最后,重新编辑一下命令的格式来增强其可读性。
下图是一个.sdc文件的快照:
你可能注意到了,我将sys_clk和the_system_pll的c0、c1输出时钟放在了一个分组,而将the_system_pll的c2输出时钟单独放在了另一个分组。
这是因为c2的频率不能和其他时钟进行关联,必须被看成和其他时钟是异步的。
通常情况下PLL的大多数输出都是相互关联的,所以会在同一个分组中,但这不是绝对的,取决于用户本身的设计。
好了,对于很多设计来说,上面就是要对片上时序进行约束所要做的全部内容。
还有一些常用的片上时序约束命令在上面没有涉及:
⏹在寄存器间添加倍数周期可以让时序分析以一个更低的速率进行,即:
开窗。
比如,一个10ns的时钟会有一个10ns的建立时间关系。
如果数据以一个更低的速率在变化,或是由于时钟使能的控制导致寄存器以一个更低的速率触发,用户就想要在数据的传输路径间开辟一个窗口,一个数据传递的窗口。
这个窗口会使建立时间变成时钟周期的倍数,比如20ns,40ns等等,而保持时间仍为0ns。
⏹倍数周期的第二种使用形式是移窗。
比如,用户设计的PLL输出了一个10ns的时钟,同时还输出一个10ns并移相0.5ns的时钟。
所以常规时钟到移相时钟的默认建立时间关系就是0.5ns,而保持时间关系是-9.5ns。
0.5ns的建立时间,噢天哪,这几乎是不可能的。
所以用户此时希望数据可以传递到下一个窗口(下一个时钟周期)。
通过在常规时钟和移相时钟之间添加一个倍数周期,建立时间关系就变成了10.5ns,保持时间关系变成了0.5ns。
每当用户要约束一个常规时钟和一个移相时钟之间的路径时,就要考虑到应用这种移窗操作。
⏹如果对关于默认建立时间和保持时间关系的讨论感到困惑,请阅读建立与保持时间基础和确定默认建立和保持时间关系。
⏹为脉动时钟添加create_generated_clock命令。
一个寄存器的输出驱动了下一个寄存器的clk引脚,这就是一个脉动时钟。
时钟一般不会通过寄存器传播,所以所有的脉动时钟都需要应用create_generated_clock来纠正对它们的时序分析。
未约束的脉动时钟将在TimeQuest的ReportUnconstrainedPaths中罗列出来,所以很容易被分辨出来。
推荐使用控制时钟使能的方式,而不是脉动时钟。
⏹为时钟复用器输出添加create_generated_clock命令。
如果没有添加,所有经过时钟复用器的时钟都将被关联。
TimeQuest会做这样一种分析:
复用器前端一个时钟驱动了源寄存器,而复用器后端另一个时钟驱动了目标寄存器,反之亦然。
但这往往不是设计者想要的。
所以为时钟复用器输出时钟添加create_generated_clock约束,可以使它们和复用器的输入关联以纠正时钟的分组,让TimeQuest在做时序分析时,时钟复用器两端的时钟一致。
2.I/O时序
(注:
本章内容不涵盖源同步接口,尽管分析原则是一致的。
)
关于I/O时序的约束,SDC命令中只有set_input_delay和set_output_delay。
刚开始可能很难理解它们执行约束的原理。
这时要树立一个观念:
这2条约束是为了描述FPGA外部的时序要求,然后TimeQuest为了达到这种要求而算出FPGA内部的一些约束条件。
我把I/O时序约束的过程分为5个步骤,这有利于建立时序约束的直觉:
1)使用create_clock命令为I/O接口创建虚拟时钟。
2)使用set_input_delay或set_output_delay为I/O端口添加约束。
分为两次进行:
一次使用-min选项,一次使用-max选项。
延时值都使用0ns(步骤5中会修改该值)。
3)确定FPGA时钟和虚拟时钟之间的建立时间关系和保持时间关系。
4)如果默认时序关系不正确,使用倍数周期进行约束。
5)根据外部延时来修改-max和-min参数。
这里需要指出的是,set_input_delay和set_output_delay的延时参数是最后指定的,而新手往往都是最先确定的。
看完下面步骤1就会明白为什么要这样做了。
同时注意,双向I/O端口会既被当做输入端口又被当做输出端口进行分析,所以需要同时用set_input_delay和set_output_delay进行约束。
步骤1)使用create_clock为I/O接口添加虚拟时钟
如果FPGA与一个工作在66MHz的PCI设备和一个工作在200MHz的DAC通讯,需要添加下面的命令道.sdc文件中:
create_clock–period12.151–namepci_clk_ext
create_clock–period5.0–namedac_clk_ext
这里并没有将两个时钟应用到任何FPGA元素,所以称之为虚拟时钟,它们是存在于FPGA之外的时钟。
虚拟时钟具体怎么使用会在下面几步进行讲述。
步骤2)使用set_input_delay或set_output_delay为I/O端口添加约束
如果是约束一个称为DAC_DATA[5]的输出端口,可以向.sdc文件添加命令:
set_output_delay–clockdac_clk_ext–max0.0[get_portsDAC_DATA[5]]
set_output_delay–clockdac_clk_ext–min0.0[get_portsDAC_DATA[5]]
-clock选项后跟步骤1创建的虚拟时钟,-max和-min选项的参数值为0.0。
这里0.0只是起到占位符的作用,会在步骤5中被修改。
对于一条输入总线,希望其所有端口都作同样的约束,可以在.sdc文件中添加:
set_input_delay–clockadc_clk_ext–max0.0[get_portsADC_DATA[*]]
set_input_delay–clockadc_clk_ext–min0.0[get_portsADC_DATA[*]]
该步骤比较浅显易懂,但是要理解这2条命令具体干了什么。
这2条命令其实并没有作任何约束,而是在描述FPGA外部的路径。
比如对于输出端口的约束语句,我们把它拆分开来:
a)Set_output_delayFPGA的输出端口连接到一个外部目标寄存器
b)-clockdac_clk_ext这个外部目标寄存器是有虚拟时钟dac_clk_ext驱动的
c)-max/min0.0FPGA外部的数据延时最大和最小都是0.0
d)[get_portsDAC_DATA[5]]FPGA内部的源寄存器从DAC_DATA[5]端口连接到外部
下面我们看看这条命令的图解:
从图中可以看出,该步骤只是描述了一个FPGA外部的回路。
现在出现在我们面前的就像分析片上时序时一样,只是纯粹的寄存器之间的数据传输。
步骤3)确定FPGA时钟和虚拟时钟之间的建立时间关系和保持时间关系
大多数情况下,发起时钟和锁存时钟频率相同且边沿对齐,因此建立时间关系为一个时钟周期,保持时间关系为0ns,如下图左上角所示:
对于I/O来说,在输入约束时,虚拟时钟是发起时钟;而在输出约束时,虚拟时钟是锁存时钟。
如果需要更深入地学习如何确定建立时间和保持时间关系,请阅读时序分析基础。
下面将讲解利用TimeQuest查看时序关系,而不是如何计算时序关系。
例:
一个100MHz的时钟深入FPGA,通过PLL仍以100MHz驱动数据传输。
通过前面的约束步骤,创建一个10ns的外部虚拟时钟并应用到输出端口:
create_clock–period10.0–nametx_clk_ext
set_output_delay–clocktx_clk_ext–max0.0[get_ports{TX_DATA[*]TX_PAR}]
set_output_delay–clocktx_clk_ext–min0.0[get_ports{TX_DATA[*]TX_PAR}]
在上面的例子中,创建了一个虚拟时钟tx_clk_ext,同时输出端口TX_DATA[*]和TX_PAR向由tx_clk_ext驱动的外部寄存器传输数据,并设置外部数据延时为0.0ns。
因为片上时钟周期也是10.0ns,而且两个时钟没有相位差,所以默认建立时间关系为10.0ns,默认保持时间关系为0.0ns。
如果你并对此有所怀疑,可以读取迭代方法中使用的.sdc文件并对这些端口执行报告时序。
点击TimeQuest的下拉菜单Reports->CustomReports->ReportTiming,在ToClock中选择tx_clk_ext,执行两次report_timing,分别报告建立时间关系和保持时间关系。
在这个例子中,可以获得两份报告:
左侧面板中显示的是SetupRelationship,如红框中所示,在Relationship列中的数值是10.0ns,和期望值一致。
在Summary下是路径的详细描述,其中发送时间是0ns,锁存时间是10ns。
HoldRelationship的查看和上面类似。
说了这么多,到底是要表达什么呢?
当发起时钟进入FPGA,传输到源寄存器,数据通过输出端口传递到外部寄存器,数据到达目标寄存器的时间必须大于0ns(保持时间关系)且小于10ns(建立时间关系)。
因为我们设置的外部延时最大和最小都是0ns,即外部无延时,所以在FPGA内部,数据延时必须要大于0ns小于10ns。
步骤4)使用倍数周期进行约束
这一步并不是必要的。
如果使用步骤3中的默认时序关系进行路径分析不能完全正确,就要考虑使用倍数周期来确定建立和保持时序关系。
倍数周期的使用通常发生在需要进行开窗操作或移窗操作时。
要注意的是,在这一步中我们不会去考虑外部延时,像外部器件的Tsu或Tco、电路板布线延时等,这些是步骤5的考虑范畴,这里我们只需确定时序关系即可。
如果一个接口连接到FLASH设备,而FLASH设备的每一次操作可能需要花费多个FPGA时钟周期,这时就需要进行开窗操作:
set_multicycle_path–setup–to[get_ports{FLASH_DATA[*]}]4
set_multicycle_path–hold–to[get_ports{FLASH_DATA[*]}]3
这两条语句会告诉TimeQuest,FLASH_DATA信号从FPGA输出需要花费4个时钟周期。
如果原始的建立和保持时序关系是10ns和0ns,那么现在就是40ns和0ns(假定时钟周期是10ns)。
如果FPGA内部的时钟有相位偏移(通常是通过PLL实现),而外部时钟无相位偏移,那么通常需要移窗操作。
例如,FPGA内部的触发时钟移相了-500ns,那么默认建立时间关系将是500ps。
要进行移窗操作,可以添加以下命令:
set_multicycle_path–setup–to[get_ports{FLASH_DATA[*]}]2or
set_multicycle_path–setup–from[get_clocks{pll\clk[0]}–to[get_clocksclk_ext]2
第1条语句会修改相应输出路径的时序关系,第2条会修改两个时钟之间的所有路径的时序关系。
只要可以覆盖所有期望的路径,可以选用二者中的任何一个。
如果时钟周期为10ns,上面的命令会修改建立时间关系为9.5ns,而不是默认的0.5ns。
而保持时间关系会从-9.5ns修改为0.5ns。
如果FPGA内部时钟是向前移相了一点,可能就不需要使用倍数周期。
比如,默认建立时间
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TimeQuest 用户手册