一、为什么一定要搞定 为什么一定要搞定 时序分析在ASIC设计中的重要性毋须多说(我也不甚了解)。在FPGA设计中,很少进行细致全面的时序约束和分析,Fmax是最常见也往往是一个设计唯一的约束。这一方面是由FPGA的特殊结构决定的,另一方面也是由于缺乏好用的工具造成的。好的时序约束可以指导布局布线工具进行权衡,获得最优的器件性能,使设计代码最大可能的反映设计者的设计意图。 花些功夫在静态时序分析上既可以保证设计质量,也可以促使设计者再认识自己的代码。这后一点,对于我们这些逻辑设计初学者来说,尤为重要。从门级(在Altera的FPGA器件中是LE级)再认识自己的代码,可以更深入地体会语言的特点,也可以更深入地理解综合工具对语言的处理,对于设计能力的提高帮助很大。 TimeQuest是Altera在6.0版的软件中加入的具备ASIC设计风格的静态时序分析(STA)工具。通过初步试用和观看网络教程,我感觉TimeQuest确实比Timng Analyzer功能强大一些,而且使用界面比较友好,易于进行深入的时序约束和结果分析。 TimeQuest采用Synopsys Design Constraints(SDC)文件格式作为时序约束输入,不同于Timing Analyzer采用的Quartus Settings File(QSF)约束文件。这正是TimeQuest的优点:采用行业通用的约束语言而不是专有语言,有利于设计约束从FPGA向ASIC设计流程迁移;有利于创建更细致深入的约束条件。 二、时序分析基本概念 时序分析基本概念 以下内容译自Quartus II Version 10.0 Handbook, Volume 3:Verification的SectionII 7.3:Timing Analysis Overview部分。 TimeQuest需要读入布局布线后的网表才能进行时序分析。读入的网表是由以下一系列的基本单元构成的: 1. Cells:Altera器件中的基本结构单元(例如,查找表、寄存器、IO单元、PLL、存储器块等)。LE可以看作是Cell。 2. Pins:Cell的输入输出端口。可以认为是LE的输入输出端口。注意:这里的Pins不包括器件的输入输出引脚,代之以输入引脚对应LE的输出端口和输出引脚对应LE的输入端口。 3. Nets:同一个Cell中,从输入Pin到输出Pin经过的逻辑。特别注意:网表中连接两个相邻Cell的连线不被看作Net,被看作同一个点,等价于Cell的Pin。还要注意:虽然连接两个相邻Cell的连线不被看作Net,但是这个连线还是有其物理意义的,等价于Altera器件中一段布线逻辑,会引入一定的延迟(IC,Inter-Cell)。 4. Ports:顶层逻辑的输入输出端口。对应已经分配的器件引脚。 5. Clocks:约束文件中指定的时钟类型的Pin。不仅指时钟输入引脚。 6. Keepers:泛指Port和寄存器类型的Cell。 7. Nodes:范围更大的一个概念,可能是上述几种类型的组合,还可能不能穷尽上述几种类型。 下面这幅图给出了一个时序网表的示例,展示了基本单元中的一部分。 有了网表的 基本单元,我们就可以描述TimeQuest进行时序分析的对象:Edges。 Edges:Port-Pin,Pin-Pin,Pin-Port的连接关系都是Edges。注意,这里的Pin-Pin连接关系既包括Cell内部的连接(Net),也包括相邻Cell外部的Pin-Pin连接。 Edges根据起止路径分为三类。 1. Clock paths:从Clock Port或内部生成的clock Pin到寄存器Cell的时钟输入Pin。 2. Data paths:从输入Port到寄存器Cell的数据输入Pin,或从寄存器Cell的数据输出Pin到另一个寄存器Cell的数据输入Pin。 3. Asynchronous paths:从输入Port到寄存器Cell的异步输入Pin,或从寄存器Cell的数据输出Pin到另一个寄存器Cell的异步输入Pin。 下面这幅图给出了三种不同的Edges。 还要注意这样一组概念,这里的edge指的是时钟沿: 1. Launch Edge:前级寄存器发送数据对应的时钟沿,是时序分析的起点。 2. Latch Edge:后级寄存器捕获数据对应的时钟沿,是时序分析的终点。 下面这幅图给出了发送、捕获时钟沿的示意图。本例在launch edge(0 ns)时寄存器reg1发送数据,在latch(5 ns)时寄存器reg2捕获数据。 时序分析公式的基本公式: 数据到达时间内部寄存器到寄存器的路径(内部寄存器到寄存器的路径(internal registerinternal register-to-to-register paths)register paths) (1)Data Arrival Time:Launch Edge + 前级寄存器Clock path的延时 + 前级寄存器Cell从时钟Pin到数据输出Pin的Net延时(uTco) + Data path的延时。 数据需要时间乮建立or保持乯(2)Data Required Time:Latch Edge + 后级寄存器Clock path的延时 (+ uTh)或(- 时钟到达时间uTsu)。 (3)Clock Arrival Time:Latch Edge + 后级寄存器Clock path的延时。 建立时间SLACK(4)Clock Setup Slack = Data Required Time – Data Arrival Time 从外部输入引脚到内部寄存器(从外部输入引脚到内部寄存器(path from an input port to a internal register)path from an input port to a internal register) (1)Clock Setup Slack = Data Required Time – Data Arrival Time 外部器件到FPGA的时钟网络延时就是数据应该在什么时候到达(2)Data Arrival Time = Launch Edge + Clock Network Delay +Input Maximum Delay + Pin-to-Register Delay FPGA内部从输入引脚到目的寄存器的延时FPGA输入引脚的最大延时(3)Data Required Time = Latch Edge + Clock Network Delay to Destination Register – μtSU. 从内部寄存器到输出从内部寄存器到输出引脚输出引脚(引脚(path frompath from an internal register to an output portfrom an internal register to an output port) an internal register to an output port) FPGA---->外部器件(1)Clock Setup Slack = Data Required Time – Data Arrival Time 数据在存储器内部传输的时间寄存器到输出引脚的延时时钟到源寄存器的延时乮数据是在时钟下传输的丆所以要加上时钟延时乯(2)Data Arrival Time = Launch Edge + Clock Network Delay to Source Register +μtCO + Register-to-Pin Delay (3)Data Required Time = Latch Edge + Clock Network Delay – Output Maximum Delay of Pin 应该是可对于外部器件来说的到达外部器件的时钟延时 在下一篇分析建立时间和保持时间时,就必须用到上述三个概念。 不是很明白丆现阶段理解为FPGA的输出引脚最大延时 三、时序分析基本公式 时序分析基本公式 以下内容译自Quartus II Version 7.0 Handbook, Volume 3:Verification的6-28:Clock Analysis部分。 TimeQuest静态时序分析的对象包括:寄存器和寄存器之间的路径、I/O之间、I/O和寄存器之间的路径、异步复位和寄存器之间的路径。TimeQuest根据Data Arrival Time和Data Required Time计算出时序余量(Slack)。当时序余量为负值时,就发生了时序违规(Timing Violation)。 需要特别指出的一点是:由于时序分析是针对时钟驱动的电路进行的,所以分析的对象一定是“寄存器-寄存器”对。在分析涉及到I/O的时序关系对时,看似缺少一个寄存器分析对象,构不成“寄存器-寄存器” 对,其实是穿过FPGA的I/O引脚,在FPGA外部虚拟了一个寄存器作为分析对象。 一、 建立时间(Setup Time)检查: 遵循的原则是信号从Launch edge开始计时,经过一系列的时序路径,到达后级寄存器的数据输入Pin的速度不能太慢,时间不能太长,否则会侵占后级寄存器数据输入Pin相对于Latch edge的建立时间。刚好满足后级寄存器建立时间的数据到达时间是Data Required Time(相对于Latch edge计算),实际的数据到达时间是Data Arrival Time(相对于Launch edge计算)。显然,在建立时间检查中,Data Arrival Time要小于Data Required Time,否则就会造成建立时间违规。也就是说,Data Required Time是Data Arrival Time的最大值。二者之差就是建立时间的时序余量。 1)寄存器-寄存器(Register-to-Register)路径检查: Clock Setup Slack = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay Source Register +μtco + Register-to-Register Delay Data Required Time = Clock Arrival Time – μtsu – Setup Uncertainty Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 2)输入引脚-寄存器(Pin-to-Register)路径检查:外部器件 --->FPGAClock Setup Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + Input Maximum Delay of Pin + Pin-to-Register Delay Data Required Time = Clock Arrival Time – μtsu Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 3) 寄存器-输出引脚(Register-to-Pin)路径检查: Clock Setup Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + μtco + Register-to-Pin Delay Data Required Time = Clock Arrival Time – Output Maximum Delay of Pin Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 从上面三组公式可以看出:Data Arrival Time的前两项是相同的;Data Required Time的第一项是相同的;Clock Arrival Time的公式是相同的。 所以,第一组公式可以归纳如下: Clock Setup Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = 时钟到达前级寄存器的时刻 + 前级寄存器时钟到后级寄存器数据输入的延迟 Data Required Time = 时钟到达后级寄存器的时刻 – 后级寄存器的建立时间 其中,后两个公式的第二项在其他情况下适当修改即可。 这就和一些书中讲到时序分析时采用的公式一致了。 report_timing -from [get_registers reg1] -to [get_registers reg2] -setup -npaths 1 -panel_name \"Report Timing\" 二、 保持时间(Hold Time)检查: 遵循的原则是信号从Launch edge开始计时,经过一系列的时序路径,到达后级寄存器的数据输入Pin的速度不能太快,时间不能太短,否则会侵占后级寄存器数据输入Pin相对于上一个Latch edge的保持时间。刚好满足后级寄存器保持时间的数据到达时间是Data Required Time(相对于Latch edge计算),实际的数据到达时间是Data Arrival Time(相对于Launch edge计算)。显然,在保持时间检查中,Data Arrival Time要大于Data Required Time,否则就会造成保持时间违规。也就是说,Data Required Time是Data Arrival Time的最小值。二者之差就是保持时间的时序余量。 相对于建立时间检查,保持时间检查稍微难懂一些。二者都是同步逻辑设计中对同一个规则的不同解释:当前时钟沿发出的数据要在下一个时钟沿被正确捕获,不能晚,也不能早。晚了,会造成下一个时钟沿的建立时间违规,当前时钟沿发送的数据不能被下一个时钟沿捕获;早了,会造成上一个时钟沿发送的数据保持时间违规,上一个时钟沿发送的数据不能被当前时钟沿正确捕获。 二者在计算公式上的区别在于Slack计算公式中减数与被减数关系。 1)寄存器-寄存器(Register-to-Register)路径检查: Clock Hold Slack = Data Arrival Time – Data Required Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register +μtCO + Register to Register Delay Data Required Time = Clock Arrival Time + μtH + Hold Uncertainty Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 2)输入引脚-寄存器(Pin-to-Register)路径检查: Clock Setup Slack Time = Data Arrival Time – Data Required Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + Input Minimum Delay of Pin + Pin to Register Delay Data Required Time = Clock Arrival Time + μtH Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 3) 寄存器-输出引脚(Register-to-Pin)路径检查: Clock Setup Slack Time = Data Arrival Time – Data Required Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + μtCO + Register to Pin Delay Data Required Time = Clock Arrival Time – Output Minimum Delay of Pin Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 需要注意的是,上面公式中的Latch Edge实际对应的是上一个Launch Edge。所以,当Launch Clock和Latch Clock是同一个时钟时,上述公式中的Latch Edge等于0;当前级和后级时钟不同时,还需要具体计算Latch Edge的取值。 report_timing -from [get_registers reg1] -to [get_registers reg2] -hold -npaths 1 -panel_name \"Report Timing\" 三、 恢复时间(Recovery Time)检查: 遵循的原则是异步控制信号变化的时刻不能介于寄存器的Latch edge和相应的建立时间之间,否则会导致寄存器的建立时间违规,数据输出进入亚稳态。即从前级寄存器的Launch edge开始计时,经过一系列的时序路径,前级寄存器数据输出到达后级寄存器异步控制Pin的速度不能太慢,时间不能太长,否则会破坏后级寄存器在Latch edge的数据建立时间。该检查主要应用于异步控制信号由有效电平向无效电平转换的时刻,在该时刻破坏数据建立时间会导致亚稳态;在异步控制信号由无效电平向有效电平转换的时刻破坏数据的建立时间不会造成亚稳态。 从上述定义,可以得到和建立时间检查类似的公式。 1)寄存器-寄存器(Register-to-Register)路径检查: Recovery Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + μtCO + Register to Register Delay Data Required Time = Clock Arrival Time – μtSU Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 2)输入引脚-寄存器(Pin-to-Register)路径检查: Recovery Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Maximum Input Delay + Port to Register Delay Data Required Time = Clock Arrival Time – μtSU Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register report_timing -from [get_ports async_rst] -to [get_registers reg2] -recovery -npaths 1 -panel_name \"Report Timing\" 四、 移除时间(Removal Time)检查: 遵循的原则是异步控制信号变化的时刻不能介于寄存器的Latch edge和相应的保持时间之间,否则会导致寄存器的保持时间违规,数据输出进入亚稳态。即从前级寄存器的Launch edge开始计时,经过一系列的时序路径,前级寄存器数据输出到达后级寄存器异步控制Pin的速度不能太快,时间不能太短,否则会破坏后级寄存器在上一个Latch edge的数据保持时间。该检查主要应用于异步控制信号由有效电平向无效电平转换的时刻,在该时刻破坏数据保持时间会导致亚稳态;在异步控制信号由无效电平向有效电平转换的时刻破坏数据的保持时间不会造成亚稳态。 从上述定义,可以得到和保持时间检查类似的公式。 1)寄存器-寄存器(Register-to-Register)路径检查: Removal Slack Time = Data Arrival Time – Data Required Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + μtCO of Source Register + Register to Register Delay Data Required Time = Clock Arrival Time + μtH Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 2)输入引脚-寄存器(Pin-to-Register)路径检查: Removal Slack Time = Data Arrival Time – Data Required Time Data Arrival Time = Launch Edge + Input Minimum Delay of Pin + Minimum Pin to Register Delay Data Required Time = Clock Arrival Time + μtH Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register report_timing -from [get_ports async_rst] -to [get_registers reg2] -removal -npaths 1 -panel_name \"Report Timing\" 五、多周期路径(Multicycle Paths)检查: 在上述的建立、保持时间检查中,都假设数据从Launch edge开始发送,在Latch edge被捕获;Launch edge和Latch edge是相邻最近的一对时钟沿。在多周期路径检查中,仍然采用Launch edge和Latch edge的概念;但是Launch edge和Latch edge不再是相邻的一对时钟沿,而是间隔一定时钟周期的一对时钟沿,间隔的时钟周期个数由用户指定。 在同步逻辑设计中,通常都是按照单周期关系考虑数据路径的。但是往往存在这样的情况:一些数据不需要在下一个时钟周期就稳定下来,可能在数据发送后几个时钟周期之后才起作用;一些数据经过的路径太复杂,延时太大,不可能在下一个时钟周期稳定下来,必须要在数据发送后数个时钟周期之后才能被采用。针对这两种情况针对这两种情况,针对这两种情况,设计者的设计意图都是:数据的有效期在以Lauch edge为起始的数个时钟周期之后的Latch edge。edge。这一设计意图不能够被时序分析工具猜度出来,图不能够被时序分析工具猜度出来,必须由设计者在时序约束中指定;必须由设计者在时序约束中指定;否则,否则,时序约束工具会按照单周期路径检查的方式执行,具会按照单周期路径检查的方式执行,往往会误报出时序违规。往往会误报出时序违规。 不设置多周期路径约束的后果有两种:一是按照单周期路径检查的结果,虚报时序违规;二是导致布局布线工具按照单周期路径的方式执行,虽然满足了时序规范,但是过分优化了本应该多个周期完成的操作,造成过约束(Over-Constrain)。过约束会侵占本应该让位于其他逻辑的布局布线资源,有可能造成其他关键路径的时序违规或时序余量变小。 在多周期路径的建立时间(Setup Time)检查中,TimeQuest会按照用户指定的周期数延长Data Required Time,放松对相应数据路径的时序约束,从而得到正确的时序余量计算结果;在保持时间(Hold Time)检查中,TimeQuest也会相应地延长Data Required Time,不再按照单周期路径的分析方式执行(不再采用Launch edge最近的时钟沿,而是采用Latch edge最近的时钟沿),这就需要用户指定保持时间对应的多周期个数。TimeQuest计算Hold Time的缺省公式等同于PrimeTime。PrimeTime会采用建立时间检查对应时钟沿的前一个时钟沿进行保持时间检查,并多会造成保持时间检查违规,需要用户指定保持时间检查对应的时钟沿为Launch edge最近的时钟沿。(西电出版社《数字IC系统设计》p189) TimeQuest缺省的Hold Time检查公式是需要用户修改的——针对Setup Time多周期路径的设置也会影响到Hold Time的检查。究其原因,多周期路径是为了解决信号传播太慢的问题,慢到一个周期都不够,所以要把Setup Time的检查往后推几个周期——扩大Setup Time检查的时间窗口。而Hold Time检查信号是否传播得太快,如果把检查时刻往后推,就缩小了Hold Time检查的时间窗口。 “信号跳变抵达窗口”:对Latch寄存器来说,从previous时钟对应的Hold Time开始,到current时钟对应的Setup Time结束。 “信号电平采样窗口”:对Latch寄存器来说,从current时钟对应的 Setup Time 开始,到current时钟对应的Hold Time结束。 Launch寄存器必须保证驱动的信号跳变到达Latch寄存器的时刻恰好处于“信号跳变抵达窗口”内,才能保证不破坏Latch寄存器的“信号电平采样窗口”。 时序检查的目的就是确认信号跳变发生在“信号跳变抵达窗口”内,而不会发生在“信号电平采样窗口”内。 多周期路径的设置是通过延后 Setup Time检查的时刻,扩大了“信号跳变抵达窗口”,放松了时序约束。通过窗口的概念,也很容易理解延后Hold Time,就会缩小“信号跳变抵达窗口”。 背景资料: Specify multicycle set-up paths constraints Specifying multicycle hold requirements constraints 随文附上一个rar,可以采用上面的命令执行并观察结果。该实例改编自Altera的multicycle_exception。 该实例由两个级联寄存器构成。 学习时序分析一定要学会察看Technology Map Viewer。 在前面的一篇文章中,给出了建立时间检查的基本公式: 1)寄存器-寄存器(Register-to-Register)路径检查: Clock Setup Slack = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay Source Register +μtco + Register-to-Register Delay Data Required Time = Clock Arrival Time – μtsu – Setup Uncertainty Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 2)输入引脚-寄存器(Pin-to-Register)路径检查: Clock Setup Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + Input Maximum Delay of Pin + Pin-to-Register Delay Data Required Time = Clock Arrival Time – μtsu Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 3) 寄存器-输出引脚(Register-to-Pin)路径检查: Clock Setup Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + μtco + Register-to-Pin Delay Data Required Time = Clock Arrival Time – Output Maximum Delay of Pin Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register 在前两组公式中,Data Required Time计算公式的第二项都是 -uTsu。 但是在TimeQuest中对两级级联寄存器的时序分析中,执行report_timing -from [get_ports data_in] -to [get_registers reg1] -setup -npaths 1 -panel_name \"Report Timing\"却得到了如下图所示的结果,请注意图中Data Required Time的第三行中reg1的uTsu取值: 在Incr一列中,reg1的uTsu取值为0.036ns,在计算公式中作为正数值计入了Data Required Time的结果中。 发现这一现象以后,经过分析,我认为有两种可能: 1. 计算公式正确,但是TimeQuest计算错误。 2. 计算公式正确,uTsu的真实取值是负数,在上图中负负为正,TimeQuest计算正确。 我一直倾向于后一种可能,毕竟TimeQuest是Altera的一个招牌工具,这样明显的错误早就该解决了。但是从Setup时间的定义上看,uTsu又不可能是负值。 后一种可能虽然更合理,但是又没有充足的证据证明这一点,这一数据是Altera给定的,原值是正是负无从知晓,在help里查也没查到,所以我一直对于TimeQuest存有怀疑。 直到今天,我偶然想起前些天计算一个输出引脚的建立时间余量时,在同样的位置看到过一个取值为负的数据。这样看来,Incr一列中,不是只能有正数值,也可以有负数值。 如果这个负值是我指定的,在Incr一列中出现负值就不奇怪了;但是我很清楚地记得,没有什么特殊条件导致我会在时序约束中采用负值。那么,这个负号应该是TimeQuest在计算中刻意加入的。负号可以加入,自然也可以去除,上图中uTsu的负号就可能是TimeQuest去除的。 下面,让我们通过输出引脚的建立时间检查(公式3)来证明一下: 仍然以两级级联寄存器为例,计算公式重写如下: 3) 寄存器-输出引脚(Register-to-Pin)路径检查: Clock Setup Slack Time = Data Required Time – Data Arrival Time Data Arrival Time = Launch Edge + Clock Network Delay to Source Register + μtco + Register-to-Pin Delay Data Required Time = Clock Arrival Time – Output Maximum Delay of Pin Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register Data Required Time中第二项是可以人为指定的。我们通过set_output_delay -add_delay -max -clock clk_in 2.000 [get_ports data_out]来指定Output Maximum Delay of Pin的取值为2ns。 执行TimeQuest建立时间检查命令report_timing -from [get_registers reg2] -to [get_ports data_out] -setup -npaths 1 -panel_name \"Report Timing\"。得到如下图所示的结果: 可以看到,我们在时序约束中指定的输出引脚延时2ns被作为负数加入了Data Required Time的计算公式中。这样一来,TimeQuest的计算和上面的计算公式就一致了。 同理,在reg1的建立时间余量计算中,uTsu原本是负值,经过计算公式中的一次负号变换,就作为正数加入了Data Required Time的计算公式中。 这样看来,在Altera的器件中,uTsu是作为负值提供给TimeQuest进行计算的。这一负值是器件本身的特性,还是为了补偿计算误差的需要有意加入的,还需要进一步的考证。 相关链接: 请问负的hold 时间和建立时间一般由什么引起的? 优化逻辑分析仪对高速系统的建立/保持时间的调节 google上搜索negative setup time could anybody give me a clear picture of negative setup and negative hold ? Negative setup and Negative hold Negative setup time and postive hold time? Method of HDL simulation considering hard macro core with negative setup/hold time 上午给Altera发了一个Service Request,下午就得到了回复: 但是这个回复没有解决我的疑惑,还要继续问: 隔了一个周末,正当我为自己是否说错了话而忐忑时,回复出来了。 感谢Roger,TimeQuest在这一点上是没错的。负的建立时间是特定时序模型的特点,模型在器件上不同的位置具有不同的特征参数。负的建立时间和寄存器靠近引脚有关。我们不必关心,交给工具去处理好了。 TimeQuest就一定要搞定——就一定要搞定——时序约束和分析流程——时序约束和分析流程 时序约束和分析流程 TimeQuest的约束和分析流程是与Quartus II的编译流程紧密结合的。 TimeQuest进行约束和分析的对象都来自Quartus II编译流程各阶段的编译结果。二者对应关系如下: 1. 分析与解析 Start Analysis & Elaboration -> RTL Viewer Quartus II编译的第一步是纯粹的“逻辑综合”,虽然经过了逻辑优化,但是生成的数据库并不对应FPGA器件的物理结构,生成的网表中节点的名称也不与FPGA器 件的Cell名称对应。由于TimeQuest进行约束和分析的对象是FPGA器件的底层物理单元,所以这一步编译过程完成后不能进行TimeQuest 时序约束和分析。 这一步在TimeQuest操作流程中没有实际意义。 这一步在TimeQuest操作流程中没有实际意义。 2. 分析与综合(与映射) Start Analysis & Synthesis -> Technology Map Viewer(Post-Mapping) -> Create Timing Netlist(Post-Map), Specify Timing Constraints, Early Timing Estimate 这一编译步骤的名称虽然是“分析与综合”,但是在“综合”后还进行了一步“映射”(Mapping)。Start Analysis & Synthesis = Start Analysis & Elaboration + Mapping。这一步完成后生成的数据库已经对应了FPGA器件的物理结构,可以供TimeQuest进行时序约束之用。由于“映射”过程实际是预先布局过程,“映射”后的数据库包含了FPGA底层Cell的位置信息和Cell本身的时序信息,TimeQuest根据这一数据库生成的时序网表中的节点与FPGA底层Cell是对应的。由于预先布局尚未执行时序驱动的布局和布线工作,也没有读入引脚位置等约束信息,这时的网表不包含布线信息,而且布局结果也会在P&R后发生变化,所以不能获得准确的时序分析结果。在这一步进行的时序分析是Early Timing Estimate,只是根据Cell本身的时序信息和由预布局结果得来的Cell之间的位置关系进行的“估计”。 这一步在TimeQuest操作流程中的意义在于可以进行时序约束和时序预估。 3. 适配(P&R) Start Fitter -> Technology Map Viewer, Chip Planner -> Generate Timing Reports Create Timing Netlist(Post-Fit), 这一步骤的名称“适配”对应的操作是“布局和布线”(P&R)。这一步骤是在上一个步骤获得时序约束信息后进行的,Fitter会努力按照时序约束的要求进行布局和布线优化。这一步骤获得的数据库包含了Cell的位置、Cell本身的时序信息和Cell之间连线资源的分布和时序信息,TimeQuest根据这一数据库生成的网表就是FPGA最终实现结果的时序网表,可以反映最终实现结果的时序特性。此时进行的时序分析才是最准确的。 这一步在TimeQuest操作流程中的意义在于可以进行最终的时序分析,并检查适配结果是否满足了时序约束的要求。(如文章开头引用的Quartus II Help文档给出的流程图所示,在这一步才执行时序约束也是可以的,但是如果不指出在第2步就可以进行时序约束,会产生“先有鸡还是先有蛋”的矛盾,这一点就是Altera文档误导读者之处。此外,在这一步才执行时序约束会重复执行P&R操作,浪费编译时间。) 在上述流程的每一步中,都有Netlist Viewer与编译和时序分析的对应关系。根据这一对应关系,设计者可以借助Netlist Viewer工具观察编译生成的网表,间接观察和分析TimeQuest生成的对应的时序网表。Netlist Viewer实现了TimeQuest时序约束对象的可视化。 在上述操作流程的最后一步,还可以通过Chip Planner直观察看设计在FPGA中的实现情况,并且与TimeQuest的时序分析报告一一对应。Chip Planner实现了TimeQuest时序分析结果的可视化。 相关链接:在线观看Chinese Version: Validating Performance with the TimeQuest Static Timing Analyzer,离线观看Chinese Version: Validating Performance with the TimeQuest Static Timing Analyzer 关键路径中的时序分析工具对设计成败至关重要 附图:TimeQuest操作流程。 TimeQuest就一定要搞定——就一定要搞定——图解——图解Setup Time时序余量计算 时序余量计算 一图胜千言。Quartus II 7.2版的TimeQuest Timing Analysis工具中新添加了“波形察看”功能,可以帮助设计者更直观地理解特定路径上寄存器之间的时序关系。 对于时序分析初学者来说,理解时序分析的公式与实际器件的物理特性之间的对应关系是一大难点,这一难点也是掌握时序分析方法的关键点。借助 TimeQuest的Waveform视图,再结合Quartus的其他视图工具,理解这一难点就容易多了。 下面就是一个简单的Setup Time时序分析的图解: 图一:查看RTL Viewer。 图中start_sync引脚是本设计的输入引脚。之所以命名为_sync,是因为在这个简化了的局部的设计中,start_sync虽然是FPGA的输入引脚,但是可以认为在FPGA外部驱动这一引脚的电路是与本设计同步的。对于 start_sync信号,只要设置适当的input_delay约束,就可以进行时序分析。另外,在图中还有一个引脚是ack_async,之所以命名为_async,是因为该引脚是一个异步输入引脚,在FPGA外部驱动这一引脚的电路与本设计的时钟关系不确定。对于ack_async信号,没有必要进行时序分析(没有必要进行时序分析(需要设置false_path约束)约束),而且还需要进行跨时钟域信号传播的两级同步处理。start_sync是本示例时序分析的起点。 图二:查看Technology Map Viewer。 图中具有双层结构的模块是FPGA器件一个Logic Cell的示意图,这个Logic Cell对应了设计中的sreg.01寄存器和其次态逻辑。从该图中可以看出,典型的LC由实现组合逻辑的LUT(内层框内图形)和实现时序逻辑的 REG(外层D触发器)构成。本文举例进行时序分析的对象是从“FPGA输入引脚start_sync”到“sreg.01的REG寄存器D输入端”之间的路径。 图三:查看Chip Planner视图。 图中所示是start_sync所在的I/O Cell与sreg.01所在的Logic Cell之间的Inter-Cell延时,该延时值为3.940ns,在图六的时序分析计算公式中会引用。在图四和图五中分别给出了I/O Cell和Logic Cell的内部视图。 图四:查看start_sync输入引脚的I/O Cell。 图中所示是start_sync所在的I/O Cell的Resource Property Editor视图。从图中可以看出,由于FPGA的I/O是可编程的,所以该Cell由输出电路和输入电路两部分组成。图中蓝色部分的起点是引脚的Pad 所在之处,Pad的左边是输出电路,右边是输入电路。蓝色部分是实际使用到的电路——start_sync引脚的输入电路逻辑。这部分电路会引入一定的延时,在图六的时序分析计算公式中会引用。 图五:查看sreg.01寄存器的Logic Cell。 图中所示是sreg.01所在的Logic Cell的Resource Property Editor视图。与图二相对应,该图中蓝色部分是实际使用到的电路——LUT + REG。其中四输入LUT部分和REG之前的选择电路会引入延时,在图六的时序分析计算公式中会引用。 图六:查看start_sync输入引脚与sreg.01寄存器的Report Setup Timing结果。 该图是 在TimeQuest中执行report_timing -from_clock {CLK} -to_clock {CLK} -from {start_sync} -to {try1:inst|sreg.01} -setup -npaths 10 -detail path_only -panel_name {Report Timing}命令得到的。从右上角开始,按照顺时针顺序分为四个部分。第一象限列出了时序分析所需要的各项参数取值;第二象限是时序分析结果的统计数 据;第三象限是根据第一象限参数计算得到的时序分析结果;第四象限是波形图,详见图七。在该图中,我们主要关心第一和第三象限的内容。 第一象限上半部分是Data Arrival Path各组成部分延时的详细列表。行3对应手工设置的Input_delay,2ns;行4对应I/O Cell内部电路的门延时,1.135ns;行5对应图三中示出的I/O Cell与Logic Cell之间的Inter-Cell线延时,3.940ns;6对应Logic Cell内部电路的门延时,0.238ns。(行4、行5、行6之和组成了图七中的Data Delay时间) 第一象限下半部分是Data Required Path各组成部分延时的详细列表。行1对应CLK的周期,10ns;行2对应时钟网络延时,2.389ns;行4对应REG的Setup Time,0.029ns。该Logic Cell的建立时间是一个正数值。 第三象限给出了该路径的Setup Time Slack的计算结果。由Setup Time余量的计算公式(Data Required Time - Data Arrival Time)可以得出行6(12.360ns)与行5(7.313ns)之差为Slack计算结果:5.047ns。 图七:查看start_sync输入引脚与sreg.01寄存器的Setup Time Slack计算图解。 该图示出 了start_sync到sreg.01寄存器D输入端之间的时序关系。其中豆绿色部分是Setup Time Slack,Data Required Time由Input Delay和Data Delay组成,Data Arrival Time由Setup Relationship、Clock Delay和uTsu组成。这幅图清晰地示出了Launch Edge和Latch Edge的概念和相互关系,Data Required Time和Data Arrival Time的计算和相互关系,还有Clock Skew对时序的影响,以及“正”的Setup Time的特性。这幅图是对图六中的Timeing Report的直观解释。 PS:在前面几篇关于Timing Analysis的文章中,我使用的TimeQuest工具还是7.2以前的版本, 那时还没有察看waveform的功能。那时虽然把时序分析结果的统计数据采用扇形图表示,但是对于理解时序分析的原理没有什么太大的帮助。7.2版的这一改进还是非常有用的。 相关链接:提高FPGA设计生产力的工具、技巧和方法指南(本文揭示了可视化技术在时序分析中的重要作用) TimeQuest就一定要搞定——时序分析基本公式 TimeQuest就一定要搞定——取值为负数的建立时间 Quartus II 中Tsu/Tco 的约束方法 Synplify综合获得的网表可否用于TimeQuest进行约束 进行约束 下面这幅图应该很能说明问题。 再结合这篇文章TimeQuest 就一定要搞定——时序约束和分析流程和下面这幅图分析一下。 由这些信息看来,Synplify的综合流程与TimeQuest的时序约束和分析流程没有交叉点,无需任何处理就可以集成到一个开发流程中。 有些项目不采用Synplify的原因推测如下: 1. Quartus II的综合能力已经足够了,无需第三方工具,这一点与Xilinx和Lattice的工具是有区别的。甚至存在Synplify综合能力弱于 Quartus II的情况。 2. Synplify虽然可以进行时序约束,但是存在约束不到位,分析不准确的问题。这一点是Synplify作为一个综合工具存在的本质问题,这也是 Synplify引入“物理综合”等技术的原因。但是“物理综合”也不能彻底解决“综合不同于物理实现”这一本质问题。归根结底,只有器件厂商能够解决物理问题。这样一来,在采用Synplify的流程中,需要设计者熟悉两种工具的工作原理,编写两套时序约束文件。在Quartus II使用者看来,与其这样,还不如撇开Synplify,直接采用Quartus II和TimeQuest来的方便准确。 相关链接: Timing Constraints Generation Technology Preserving The Intent Of Timing Constraints Meeting Timing and Reducing Area with the Synplify Pro Tool Preserve Timing Gains in Incremental Design The Impact of Timing Exceptions on FPGA Performance TimeQuest就一定要搞定——就一定要搞定——由——由QSF生成SDC SDC QSF是Quartus Settings File的缩写,包含了一个Quartus工程的所有约束,包括工程信息、器件信息、引脚约束、编译约束和用于Classic Timing Analyzer的时序约束。 SDC是Synopsys Design Constraints的缩写,该文件用于TimeQuest Timing Analyzer的时序约束和定制报告。 在TimeQuest中把Classic Timing Analyzer的约束语句转换为SDC是很容易的。在Constraints菜单下,执行Generate SDC File from QSF即可。 以Quartus II安装路径下的\\qdesigns\\fir_filter项目为例,QSF文件中关于时序约束的语句如下: # 约束clk为100MHz的时钟。 set_global_assignment -name FMAX_REQUIREMENT \"100 MHz\" -section_id clocka set_instance_assignment -name CLOCK_SETTINGS clocka -to clk # 约束clkx2为clk的二倍频时钟,相位偏移0.5ns set_global_assignment -name BASED_ON_CLOCK_SETTINGS clocka -section_id clockb set_global_assignment -name DIVIDE_BASE_CLOCK_PERIOD_BY 2 -section_id clockb set_global_assignment -name OFFSET_FROM_BASE_CLOCK \"500 ps\" -section_id clockb set_instance_assignment -name CLOCK_SETTINGS clockb -to clkx2 # 约束所有从clk到clkx2的时序路径为Multicycle,取值2 set_instance_assignment -name MULTICYCLE 2 -from clk -to clkx2 由该组QSF约束转换得到的SDC约束如下: # Original Clock Setting Name: clocka create_clock -period \"10.000 ns\" \\ -name {clk} {clk} # Original Clock Setting Name: clockb create_generated_clock -multiply_by 2 -offset \"0.500 ns\" \\ -source clk \\ -name {clkx2} \\ {clkx2} # ** Multicycles # QSF: -name MULTICYCLE 2 -from clk -to clkx2 set_multicycle_path -end -setup -from [get_clocks {clk}] -to [get_clocks {clkx2}] 2 set_multicycle_path -end -hold -from [get_clocks {clk}] -to [get_clocks {clkx2}] 1 从上面的例子可以看出,SDC比QSF简洁了些,在Multicycle的约束上也清晰明确了些。 TimeQuest就一定要搞定——Path时序余量计就一定要搞定——图解——图解Multicycle 算(未完待续)未完待续) 在上一篇关于TimeQuest的文章中,我引用了Quartus II自带的一个示例。这个示例很有代表性——两个相位关系固定的时钟域、标准同步设计、复杂组合逻辑路径、调用了DSP资源。这个例子用来学习 TimeQuest的用法和时序分析的基本原理是再好不过了。 除了上面提到的几个特点,这个例子中还包含了极为特殊的一种时序情况:跨时钟域的多周期时序分析。该示例中关于多周期的约束条件如下: set_multicycle_path -end -setup -from [get_clocks {clk}] -to [get_clocks {clkx2}] 2 set_multicycle_path -end -hold -from [get_clocks {clk}] -to [get_clocks {clkx2}] 1 上面的约束中,clk是100MHz的时钟;clkx2是由clk二倍频得到的,频率是200MHz,与clk有0.5ns的相位差。根据上面的约束,从clk到clkx2的建立时间路径是2个clkx2周期,从clk到clkx2的保持时间路径是1个clkx2周期。 在跨时钟域时序分析中,只有当两个时钟之间有确定的时序关系时时序约束才有意义,这是本文要着重分析的内容;当两个时钟之间没有确定的相位关系时,约束二者之间的时序关系是没有意义的,针对这种情况,只能采用标准的跨时钟域数据传递处理,还要记得设置二者之间的时序路径为false_path。 图一、查看Multicycle约束为0的Hold Time时序余量计算 图二、查看Multicycle约束为1的Hold Time时序余量计算 图三、查看Multicycle约束为2的Hold Time时序余量计算 参考:图解Multicycle Path时序余量计算---AN 481 Applying Multicycle Exceptions in the TimeQuest Timing Analyzer 图解Multicycle Path时序余量计算--Multicycles Exception Between Two Synchronous Clock Domains TimeQuest就一定要搞定——就一定要搞定——看懂时序波形图——看懂时序波形图 看懂时序波形图 时序分析和时序约束在很多朋友看来是FPGA设计中的“高级”技术,是可以“明天再学”的功课。想一想,我们设计的每一个正确运行的数字电路在每一个ps内都正在我们有意或者无意设定的时序约束范围内运行着——时序分析这门所谓“高级”的技术,体现的正是数字电路运行的基本原理。我们今天放弃学习的科目,正是我们最需要学习的“基本”技术。 我学习时序分析和约束只是刚刚入门。从我学习时序分析的经历看来,学习使用时序分析工具并不难,有文档可以参考,有例子可以实践,EDA工具本来就是方便设计者使用的,好学好用是理所应当的;理解时序分析的概念和原理确实有一定难度,强记几个公式不难,依样画葫芦把数值代入公式得到与时序分析结果相符的数值也是小学水平,可是在实践中,却总是难以理清这些数值之间的关系,“打哪儿指哪儿”容易,“指哪儿打哪儿”太难。知其然而不知其所以然,这是我最初面对那些时序分析计算结果时的感受。带着这样的感受,我一直徘徊在时序分析技术的门外。 直到最近一段时间以来,riple 才逐渐摆脱了这种不踏实、不自信的感受。这是得益于反复观察和分析TimeQuest中的Waveform视图。从这一自学过程中,riple总结出学习时序分析原理的一个关键点:在脑海中建立时序分析公式与实际电路物理属性之间的映射关系。建立了这种映射关系,才能理解时序分析公式的意义和来历,才能做到知其所以然,才能做到定性和定量地分析电路的时序性能。 时序波形图是建立这一映射关系的好帮手。波形图对于理解电路运行时序的重要性,恐怕所有做过仿真的朋友都深有体会。为什么波形图如此重要,因为硬件电路是并行运行的。即使一个最简单的同步电路中也会有两个以上的信号在同时变化和相互作用。人脑并不擅长处理并行过程,这需要太多的内存来记忆中间变量, 需要太多的循环来更新这些变量。人的注意力很难保持太长时间,稍不留神,头脑中的并行仿真过程就失败了。这也是为什么我们需要仿真工具的原因,保留我们的精力去做更重要和更具创意的事,让电脑代替人脑做我们不擅长的工作。 在网上常见的讲解时序分析概念的文章中, riple 最常见到的是电路的时序路径图,即一条时序路径是由哪些基本传播路径组成的。这样的时序路径图只能定性地示意时序分析公式的原理,难以定量地辅助设计者完成时序分析公式的计算。在这样的学习过程中,我的思维直接从电路图跳跃到了公式,缺少了一个中间环节——波形图。这是造成我知其然不知其 所以然的原因。我上面分析了波形图对于定量理解电路行为的重要性,那么为什么这些文章中不包含一幅波形图呢?原因很简单,不容易画。正如电路仿真需要EDA一样,把一幅波形图画得清晰准确也需要电脑的辅助。 TimeQuest中自动生成的时序波形图很好地解决了“缺少波形图”这一自学时序分析原理过程中的问题。在TimeQuest中,时序波形图与时序分析公式是一一对应的,看着波形图去逐项理解时序分析公式中的各个元素是再容易不过了。 在下面这幅时序波形图中,我们可以看到10个波形,相应地表示了10组电路物理属性之间的关系。对于缺少训练的头脑(我的头脑就是其中之一)来说, 包含这么多信息的波形是很难在思维中模拟出来的。这些波形准确地表示了实际电路的物理特性,至于是否能够清晰地反映电路的时序关系,还需要读者逐君自己花些力气。 人脑不擅长模拟复杂的并行时序关系,这是事实。不过话又说回来,上面这幅波形图也没有太复杂到哪里去。看懂它不是难事,只要加以练习,掌握它甚至在设计和分析电路的思维活动中灵活使用它也不会太难。我们这些逻辑设计工程师已经花费了很多时间在“基本功”的学习和熟练上,在这门既“基本”又“高级”的 功夫上也不应该太惜力啊! 注:上面这幅波形图的详细分析可以参考TimeQuest 就一定要搞定——图解Setup Time时序余量计算。 FPGA时序约束的几种方法 时序约束的几种方法 对自己的设计的实现方式越了解,对自己的设计的时序要求越了解,对目标器件的资源分布和结构越了解,对EDA工具执行约束的效果越了解,那么对设计的时序约束目标就会越清晰,相应地,设计的时序收敛过程就会更可控。 从最近一段时间工作和学习的成果中,我总结了如下几种进行时序约束的方法。按照从易到难的顺序排列如下: 0. 核心频率约束 这是最基本的,所以标号为0。 1. 核心频率约束+时序例外约束 时序例外约束包括FalsePath、MulticyclePath、MaxDelay、MinDelay。但这还不是最完整的时序约束。如果仅有这些约束的话,说明设计者的思路还局限在FPGA芯片内部。 2. 核心频率约束+时序例外约束+I/O约束 I/O约束包括引脚分配位置、空闲引脚驱动方式、外部走线延时(InputDelay、OutputDelay)、上下拉电阻、驱动电流强度等。加入I/O约束后的时序约束,才是完整的时序约束。FPGA作为PCB上的一个器件,是整个PCB系统时序收敛的一部分。FPGA作为PCB设计的一部分,是需要PCB设计工程师像对待所有COTS器件一样,阅读并分析其I/O Timing Diagram的。FPGA不同于COTS器件之处在于,其I/O Timing是可以在设计后期在一定范围内调整的;虽然如此,最好还是在PCB设计前期给与充分的考虑并归入设计文档。 正因为FPGA的I/O Timing会在设计期间发生变化,所以准确地对其进行约束是保证设计稳定可控的重要因素。许多在FPGA重新编译后,FPGA对外部器件的操作出现不稳 定的问题都有可能是由此引起的。 3. 核心频率约束+时序例外约束+I/O约束+Post-fit Netlist 引入Post-fit Netlist的过程是从一次成功的时序收敛结果开始,把特定的一组逻辑(Design Partition)在FPGA上实现的布局位置和布线结果(Netlist)固定下来,保证这一布局布线结果可以在新的编译中重现,相应地,这一组逻辑的时序收敛结果也就得到了保证。这个部分保留上一次编译结果的过程就是Incremental Compilation,保留的网表类型和保留的程度都可以设置,而不仅仅局限于Post-fit Netlist,从而获得相应的保留力度和优化效果。由于有了EDA工具的有力支持,虽然是精确到门级的细粒度约束,设计者只须进行一系列设置操作即可,不需要关心布局和布线的具体信息。由于精确到门级的约束内容过于繁多,在qsf文件中保存不下,得到保留的网表可以以Partial Netlist的形式输出到一个单独的文件qxp中,配和qsf文件中的粗略配置信息一起完成增量编译。 4. 核心频率约束+时序例外约束+I/O约束+LogicLock LogicLock是在FPGA器件底层进行的布局约束。LogicLock的约束是粗粒度的,只规定设计顶层模块或子模块可以调整的布局位置和大小(LogicLock Regions)。成功的LogicLock需要设计者对可能的时序收敛目标作出预计,考虑特定逻辑资源(引脚、存储器、DSP)与LogicLock Region的位置关系对时序的影响,并可以参考上一次时序成功收敛的结果。这一权衡和规划FPGA底层物理布局的过程就是FloorPlanning。 LogicLock给了设计者对布局位置和范围更多的控制权,可以有效地向EDA工具传递设计者的设计意图,避免EDA工具由于缺乏布局优先级信息而盲目优化非关键路径。由于模块在每一次编译中的布局位置变化被限定在了最优的固定范围内,时序收敛结果的可重现性也就更高。由于其粗粒度特性,LogicLock的约束信息并不很多,可以在qsf文件中得到保留。 需要注意的是,方法3和4经常可以混合使用,即针对FloorPlanning指定的LogicLock Region,把它作为一个Design Partition进行Incremental Compilation。这是造成上述两种方法容易混淆的原因。 5. 核心频率约束+时序例外约束+I/O约束+寄存器布局约束 寄存器布局约束是精确到寄存器或LE一级的细粒度布局约束。设计者通过对设计施加精准的控制来获得可靠的时序收敛结果。对设计中的每一个寄存器手工进行布 局位置约束并保证时序收敛是一项浩大的工程,这标志着设计者能够完全控制设计的物理实现。这是一个理想目标,是不可能在有限的时间内完成的。通常的做法是设计者对设计的局部进行寄存器布局约束并通过实际运行布局布线工具来获得时序收敛的信息,通过数次迭代逼近预期的时序目标。 不久前我看到过一个这样的设计:一个子模块的每一个寄存器都得到了具体的布局位置约束。该模块的时序收敛也就相应地在每一次重新编译的过程中得到了保证。 经过分析,这一子模块的设计和约束最初是在原理图中进行的,在达到时序收敛目标后该设计被转换为HDL语言描述,相应的约束也保存到了配置文件中。 6. 核心频率约束+时序例外约束+I/O约束+特定路径延时约束 好的时序约束应该是“引导型”的,而不应该是“强制型”的。通过给出设计中关键路径的时序延迟范围,把具体而微的工作留给EDA工具在该约束的限定范围内 自由实现。这也是一个理想目标,需要设计者对每一条时序路径都做到心中有数,需要设计者分清哪些路径是可以通过核心频率和简单的时序例外约束就可以收敛 的,哪些路径是必须制定MaxDelay和MinDelay的,一条也不能遗漏,并且还需要EDA工具“善解人意”的有力支持。设定路径延时约束就是间接地设定布局布线约束,但是比上述3、4、5的方法更灵活,而且不失其准确性。通过时序约束而不是显式的布局和网表约束来达到时序收敛才是时序约束的真谛。 记得有网友说过“好的时序是设计出来的,不是约束出来的”,我一直把这句话作为自己进行逻辑设计和时序约束的指导。好的约束必须以好的设计为前提。没有好的设计,在约束上下再大的功夫也是没有意义的。不过,通过正确的约束也可以检查设计的优劣,通过时序分析报告可以检查出设计上时序考虑不周的地方,从而加以修改。通过几次“分析—修改—分析”的迭代也可以达到完善设计的目标。应该说,设计是约束的根本,约束是设计的保证,二者是相辅相成的关系。