tag 标签: timequest,时序约束,时序分析

相关博文
  • 热度 16
    2012-5-24 21:09
    3134 次阅读|
    3 个评论
    最近在altera FPGA里设计一个外设的驱动模块,模块本身逻辑很简单如下图所示,但是模块和外设之间的时序约束问题搞的很头疼,今天先讲讲总结的一些Timequest下外设约束方法,特别是那毫无用户体验而言的 Create  Generated Clocks用法。 要让外设正确接收FPGA发出的数据,需要dout和clkout满足外设的建立保持时间,如下图所示。   时序分析是基于源reg的Tco、目的reg的Tsu,源reg到目的reg的Tdelay路径延迟以及到两个reg的clk skew计算出来的,现在Timequest不知道外设接收reg和时钟输入端的延迟参数,无法分析,还需分若干步配置:   1.使用Create Clocks建立系统时钟sysclk   create_clock -name {sysclk} -period 20.000 -waveform { 0.000 10.000 } Timequset里的所有时钟都需要手动设置,首先设置系统时钟,后面的时钟都要基于这个时钟才能生成 。   2.使用Create  Generated Clocks建立输出时钟clkout   外设的时钟源于FPGA的输出port clkout,如果不建立时钟,timequest只会把clkout当作一个普通的输出引脚,时序分析器认为目的reg缺少驱动时钟,无法分析。Timequest中将通过倍频、分频或者移相等生成的时钟都归为Generated Clocks,你可以使用Create Clocks创建试一下,不会提示创建失败,但是在最后的时序分析里不会加入clkout的clock network delay,Timequest没有你想象的那么智能,知道clkout是从一个分频模块输出,自动加入模块延迟分析,它不知道这些。所以还是使用Create Generated Clocks来创建吧,先填写源时钟sysclk,再填写生成时钟和源时钟的关系,2分频,最后指定target 生成时钟到clkout引脚,这三个步骤看似没问题,结果却是创建失败,提示找不到sysclk到clkout之间的路径,如下所示。 Warning: No paths exist between clock target "clk_out" of clock "clkout" and its clock source. Assuming zero source clock latency.   但是sysclk到clkout明明是有路径的啊,之间的逻辑也很简单,就是一个二分频关系,bdf图如下所示。 clk_div模块的代码如下:   reg clk_div; always @(posedge clk or negedge rset_n) begin     if(!rset_n)         clk_div = 0;     else         clk_div = ~clk_div; end   尝试了很多方法都无效,最终实验成功了一种自认为很别扭的方法,“曲线救国”分两步走: 首先 Create  Generated Clocks 从引脚sysclk 到 寄存器clk_div create_generated_clock -name {clk_div_r} -source -divide_by 2 -master_clock {sysclk} 再 Create  Generated Clocks 从寄存器clk_div到输出引脚clk_out  create_generated_clock -name {clkout} -source -master_clock {clk_div_r} 这才把clk_out设置为和sysclk关联的输出时钟。   3. 用set output delay 设置基于clkout时钟的输出dout延迟 。   set_output_delay -add_delay  -clock   5.000 , 这句话在源reg和目的reg之间搭建起一座桥梁,实现两个作用: 1.告诉分析工具,clkout是目的reg的驱动时钟(但是前提是clkout需要被Timequest认为是个时钟),dout是目的reg的数据源,分析工具才能计算出路径的clk skew(clkout的 clock network delay  - sysclk的 clock network delay ); 2.告诉了分析工具 外设reg的建立时间Tsu和路径延迟Tdelay,这两个参数之和其实就是输出延迟,分别源于外设数据手册和PCB板的走线延迟。   4.设置set max delay和set min delay   如果不需要更严苛的约束,不设置这两个参数也可以。经过前三步,时序分析器已经知道了源reg和目的reg的时钟频率,系统会默认使用时钟频率分析,既最大延迟为时钟周期Tclk,最小延迟为0。这里的set max delay约束Tco和clk skew为了满足外设的建立时间,使(Tclk + clk skew)-(Tco+Tdelay) Tsu,set min delay 约束Tco和clk skew满足外设的保持时间,(Tco+Tdelay) - clk skew Th。   5.设置多周期约束   由于本例的特殊性,源时钟是目的时钟的两倍,需要多时钟约束设置,由篇幅所限,下次再细讲。   最后可以在Report Timing的Registers to Outputs的setup和hold里看到时序余量分析了。     回顾约束的整个过程,最闹心的就是第二步 Create  Generated Clocks了,可能一直受altera里的pll设置影响,只要设置源时钟,填好输出输入时钟关系,pll就可以用了,到了Timequest里的生成时钟设置,我也想当然的认为,clkout是由sysclk生成变化而来,源里面只要填sysclk,关系填好就肯定没问题了,但是结果并非这么简单。   再回到第二步,再尝试从sysclk直接 Create  Generated Clocks指定到输出时钟clkout,发现除了找不到sysclk和clkout之间的路径之外还有一个警告 Warning: Node: clk_div:inst|clk_div was determined to be a clock but was found without an associated clock assignment。 警告clk_div被设置为了时钟,但是没有指定关联的源时钟即没指定clk_div是由哪个时钟生成的,从这个警告推理:我设置的 Generated  时钟是clkout,而clkout是由clk_div驱动的,所以Timequest也将clk_div认为是一个时钟路径node,但是我只告诉了Timequest clkout的源时钟是sysclk,而没有告诉它clk_div的源时钟是哪个,所以创建失败,虽然从程序显而易见源也是sysclk,看来我高估了TimeQuest的智商,按照上述的“两步走”方案,第一步就是告知clk_div的源时钟是sysclk,第二步再生成基于clk_div的clkout就ok了   推测Timequest中对Creat  Generated Clocks分析过程是这样的:从最终的target Clock端口往回分析,寻找这个时钟路径上的net寄存器,看其是否有关联时钟,如果有,看是否已经指定了,如果指定了则继续反向分析直到源时钟,如果没有则提示创建失败。 为了验证这个推测,再级联一个分频模块clk_div如下图所示。 此时该如何建立基于sysclk的输出时钟clk_out呢,从clk_out管脚返回分析,clk_out由ints5|clk_div驱动,ints5|clk_div的关联时钟是inst4|clk_div,inst4|clk_div的关联时钟是sysclk,所以要分三步创建:   首先创建基于sysclk的inst4|clk_div。 create_generated_clock -name {clk_div_r} -source -divide_by 2 -master_clock {sysclk}     再创建基于 inst4|clk_div的 inst5|clk_div。 create_generated_clock -name {clk_div_rr} -source -divide_by 2 -master_clock {clk_div_r}     最后创建基于 inst5|clk_div的clk_out。 create_generated_clock -name {clkout} -source -master_clock {clk_div_rr}     验证结果,少了上述任何一步都无法得到正确的输出时钟,比如用Create clk 创建inst4|clk_div 取代第一步,虽然也可以生成clk_out,但最终的输出延迟会减小。   多数工程中,使用分频模块输出时钟的做法并不多,更多的是使用pll,我又尝试了下使用PLL产生一个外部时钟,PLL的源为sysclk,仍然无法直接 Create  Generated Clocks从sysclk到clk_out,而是首先derive_pll_clocks将所有的PLL输出都设为时钟,再 Create  Generated Clocks从PLL的时钟输出寄存器到clk_out才可以。   最后感叹下:9.1版本的TimeQuest能再智能点吗?  
  • 热度 13
    2012-5-18 20:45
    2703 次阅读|
    0 个评论
      这篇我想分享一个之前在用TimeQuest约束双边沿模块的input delay时犯得一个错误,有人看了可能会觉得傻傻的,什么眼神,delay_fall和clk_fall怎么会分不清呢,字面意思好区分,可要深究在约束里的具体含义,还得花点功夫,下面以ddio接收模块为例说明它们的含义以及碰到的一些问题。   ddio接收模块为双边沿工作模式,如图一所示,ddio_in接入DFFH和DFFL,时钟下降沿 DFFL锁存DL,但不立刻输出,直到时钟上升沿高电平使能latch时输出,同时DFFH在上升沿锁存输出DH,和DL拼接成输出数据,这样就实现了对双边沿输入数据的采样输出。 图一   其时序特性是,上升沿发送的数据下降沿采样,下降沿发送的上升沿采样, 工作波形如图二所示,需要施加约束才能正确的双边沿采样。 图二   首先用create_clock创建输入时钟频率为100MHz的ddio_clk_s,然后用set input delay关联输入数据ddio_in和输入时钟ddio_clk_s,设置延迟为2ns,查看IO Timing,发现TimeQuest分析了两条路径如图三所示,一条是上升沿到下降沿,这是我们想要的,另一条是上升沿到上升沿,这不是我们需要的,而且还没有下降沿到上升沿的路径,看来这种简单的约束方式明显存在问题。 图三   set input delay默认是基于时钟上升沿设置,TimeQuest不清楚用户的真实使用情况:上升沿发出的ddio_in数据到底是被DFFH采样还是被DFFL采样呢,所以默认源端上升沿发出的数据会同时被这两个D触发器采样,这就出现了上述rise to fall和 rise to rise两条路径,第二条无关路径设置为伪路径后可以被去除。   下降沿到上升沿的路径如何设置呢? 打开set input delay看看能否找到一些新的线索。 图四   如图四,首先映入我眼帘就是醒目的rise和fall的选项,既然set input delay默认是基于rise上升沿的,那勾选fall,应该就是基于下降沿了吧,这是我当时的第一反应。可是分析结果里还是没有下降沿到上升沿的路径,又注意到这个fall选项是被划在input delay options里,按理fall应该是用来修辞input delay的,但是怎么个修辞法,当时并没有细究,出于对曾今过了英语六级的那份自信,我仍然认为,fall表示数据是基于时钟下降沿输入的。当时也查了些前辈的博客,其中特权同学很早之前的一篇 深入剖析I/O 里也有对fall和rise的翻译如图五: 图五   特权同学认为fall是时钟的下降沿延时,但是fall是用来修辞input delay的而不是clock,所以我并不认可这种翻译,此时注意到表格里还有一个参数是 -clock_fall,这个好像和我想找的意思相符,为了验证参数的具体含义,又继续搜索找到了altera关于set input delay的中参数的官方解释如下: -clock_fall     Specifies that input delay is relative to the falling edge of the clock -fall               Specifies the falling input delay at the port   此时我才大悟, -clock_fall才是我一直寻找的,它才是基于时钟下降沿的意思。勾选using falling clock edge后,下降沿到上升沿的路径终于千呼万唤始出来,不过同前述,也会多一条下降沿到下降沿到的路径,用伪路径可以轻松去之。   双边沿约束的问题解决了,可是官方对fall的解释  the falling input delay 是神马意思呢?都是四级的词汇,凑在一起,就不是很明了了,数据下降延迟?听起来总感觉怪别扭的,跑去和同事一起讨论这个问题。一组输入数据变化时,哪有上升和下降之说?(数据从0010变为1001,你说是上升还是下降呢? ), 上升下降应该是针对某一根数据线的变化而言的(数据 从0010变为1001,你可以说第0位上升了,第1位下降了),但是TimeQuest真的想知道你每根数据线的上升下降延迟吗?no no no,回想下set input delay的本质是告诉Timequest最大输入延迟让其约束建立时间,和最小延迟约束保持时间,TimeQuest只想知道输入的最大最小延迟就可以了。源端发送数据的每一位的上升延迟和下降延迟可能会不一样,也有一个大小之分,比如第0位上升延迟为0.4ns,下降延迟为0.8ns,第1位的上升延迟为0.5ns,下降延迟为0.9ns,TimeQuest会用其中相对较大的0.9ns去分析建立时间,相对小的0.4ns去分析保持时间,而不会去关心数据具体某位是如何变化的。既然TimeQuest只关心延迟的大小,那只要在set input delay里设置max min delay不就可以了吗,何必设置rise和fall呢?   测试后发现,如果不设置rise和fall,会导致约束不精准。举个例子:源端发出数据的输入上升延迟Tdelay_rise为0.5ns,下降延迟为Tdelay_fall为0.8ns,路径最大延迟为2ns,最小延迟为1ns,只设置set input delay的 max delay为2.8ns,min delay 为1.5ns,其中ddio_in 的路径延迟报告如图六所示。 图六   注意红色线标记,data path为2.129ns。   如果加上rise 和fall选项,设置 max  fall 为2.8ns,max rise 为2.5ns,min fall 为1.8ns,min rise 为1.5ns,ddio_in 的延迟报告如图七所示。 图七   看红色线标记处,data path为1.998ns,比前者少了0.131ns,这两种约束的最大和最小延迟相同,但结果却不同, 原因在于FPGA的内部逻辑针对输入数据的上升Trise和下降Tfall的延迟也是不一样的,假设Trise Tfall,第一种约束方式的最大路径延迟是Trise + 2.8+ Tother,第二种方式指定了fall和rise后,TimeQuset知道了指定的最大输入延迟发生在数据下降时刻,所以分析的整体最大路径延迟会变为Tfall + 2.8 + Tother,这种约束方式更符合实际的应用,也更加精确。虽然两种约束方式的结果相差甚微,不会对普通应用造成影响,但对一些高速苛刻的应用,可就不能小视了。   set output delay一样也有rise  和 fall的选项,和set input delay作用类似,这里就不再敷述了。
  • 热度 10
    2012-4-27 21:10
    2979 次阅读|
    0 个评论
    -------------------------------------------------------------------------------------------------------------------- 由于博客字数所限,全文上半内容“ 换位思考多周期约束多周期约束(上) ”请点击这里 http://bbs.ednchina.com/BLOG_ARTICLE_3003477.HTM --------------------------------------------------------------------------------------------------------------------   整合TimeQuest和用户的需求   多周期约束的作用是让TimeQuest明晰发送接收波形的真实状态,放宽或缩紧建立和保持时间约束,其中TimeQuest期望从用户那得到 current launch、current latch、 next launch 和previous latch这些量,而用户希望告诉TimeQuest真实的建立保持关系。要将用户的诉求准确的转化为TimeQuest的需求,设计者需在两者中做出权衡,所以在多周期语法规则的设定上,不能完全偏袒某一方,双方都要有些取舍。   在语法的选词上,设计者倾向于用户,使用了通俗易懂的setup和hold,表示建立时间和保持时间对应的宽松周期个数,比如下面的语句表示建立时间宽松2个周期,保持时间宽松1个周期。 set_multicycle_path   -setup   -end  from    to     2 set_multicycle_path   -hold    -end  from    to    1   宽松的周期个数是要相对默认路径而言的,为了准确的将setup和hold宽松个数准确的转化为 current launch、current latch、next launch和previous latch这些量 ,设计者制定了倾向于TimeQuest的语法规则,用于默认情况下的current launch,current latch,next launch和next latch的定位。   分析默认的建立时间路径规则。TimeQuest先以一个launch边沿为基准定为current launch,再向后寻找距此边沿最近的一个latch边沿定为current latch,并将两者的setup个数定为1个周期。   图四红色线条为发送和接收波形无相移时默认的建立时间路径。 图四   图五红色线条为发送和接收波形存在相移时默认的建立时间路径,虽然A和B间距不满一个周期,但TimeQuest为了方便处理,仍将此时的setup定为1个周期。 图五   由于默认的建立时间路径setup已被设为1一个周期了,如要宽松1个周期,须在默认的基础上再叠加1个周期,置setup = 2,current latch才会往后移动一个周期,如上图蓝色线所示,结合默认分析规则和setup的个数,TimeQuest就可以定位current launch和current latch。   分析默认的保持时间路径规则。保持时间的检查路径会有两条,一条是current launch到previous latch,另一条是next launch到current latch,当current launch和current latch确定后,TimeQuest会基于单周期分析,默认current launch的后一个时钟为next launch,current latch的前一个时钟为previous latch,并将两条保持时间路径的默认hold个数都设为0,如图六所示。 图六   如保持时间宽松1个周期,如图七所示,previous latch会向前移动一个周期,由于波形的周期性,next launch也会向后移动一个周期。 图七   结合setup和hold个数以及单周期分析准则,TimeQuest可以知晓 previous latch和 next launch。由上分析可得,保持时间默认 路径是相对current launch和current latch而定的,和建立时间路径存在着间隔单周期的依赖关系,会随着建立时间路径变化而改变。回到开篇的一个疑问:为什么有时只要基于建立时间设置多周期个数就可以了,因为setup设定后,保持路径也会相应改变,如果此时刚好满足用户需求,就不用再设置hold了。   至此,依据设计者制定的规则,已经可以将用户提供的setup和hold周期个数转换为TimeQuest想要的launch和latch信息了,虽然规则不算最直观,但考虑到要满足所有用户的需求,通用性已然成为设计的首要目标( 规则越简单,通用性越强,在分析setup,hold时默认基于单周期的分析法则真的不能再简单了 ),而用户体验在FPGA这个垄断性的行业,苦逼的工程师们真的不要奢望太多。   消除不确定性   上述所举例子的发送接收波形的频率都是相同的,如果频率不同,现有的语法规则就可能出现不确定问题了,如图八所示。 图八   仍按照默认的setup路径分析方法,先找一个launch边沿为基准,再去确定之后最近的latch边沿,但会发现存在两个基准,launch边沿A和B对应的最近的latch边沿都是C,launch A到latch C以及launch B到latch C的setup值都为1个周期,此时,TimeQuest无法确定用户波形到底是哪一种。   为了消除歧义,换另一种分析方法,先找一个latch边沿为基准,再确定之前最近的launch边沿,这样current launch和current latch的关系就一一对应了,如图九所示。 图九   两种方法的区别在于基准的选择。根据基准的不同,设计者创造了两种模式start和end,start模式参考的基准是latch边沿,end模式参考的是launch边沿,对于同频波形,不存在不确定性,无所谓使用哪种模式,当发送频率比接收频率快一倍以上时需用start模式,同理,当接收频率比发送波形快一倍以上时使用end模式。   综上,经过一个产品设计的大致思考流程(明确产品目标--- 整合用户需求 ----- 准确表达需求)后,我对TimeQuest多周期约束有了更深的认识,不仅知其然,而且知其所以然。其中基于单周期的分析规则对我也有些启发,规则如此简单,但的确能满足要求,当时在分析默认的保持时间路径时,我自己也尝试着想了些规则,但都是从方便用户的角度出发,忽视了TimeQuest的需求,不仅复杂,通用性还不好,可见 对需求挖掘的深浅直接影响着产品的复杂度。 从用户角度出发,追求用户体验,这些道理经常被耳提面令,但工欲善其事,必先利其器,在开发过程遇到的一些开发工具的问题,我们可以尝试下换位思考,从设计者的角度出发,往往除了能解决开发工具的疑惑,还能收获一些其他设计者好的思路并应用到自己的设计中。 最后再无力的吐槽一句:一边使用着用户体验极差的开发工具,一边却想着开发用户体验极佳的产品,真的有点为难工程师们了。(TimeQuest,我不是在说你,你已经很不错了) ---------------------------------------------------------- 由于博客字数限制,全文上半内容“ 换位思考多周期约束多周期约束(上) ”请点击 http://bbs.ednchina.com/BLOG_ARTICLE_3003477.HTM ----------------------------------------------------------    
  • 热度 15
    2012-4-27 09:46
    2620 次阅读|
    2 个评论
      在开篇前先推荐两篇文档,一篇是altera的官方文档 Appling Multicycle Execptions in the TimeQuest Timing Analyzer ,另一篇是riple兄很早之前推荐过的Multicycles Exception Between Two  Synchronous Clock,这两篇都是关于多周期约束很好的上手文档,虽然可以快速上手解决当务之急,但事后不免还会有些疑惑。TimeQuest中的多周期约束语法的设置选项有:基于setup(建立时间)的个数,基于hold(保持时间)的个数,start模式和end模式,如下所示。   set_multicycle_path   -setup   -start   from   to   2 set_multicycle_path  -hold   -end   from   to   2   但在使用过程中,为什么有时只设置基于建立时间的多周期个数就可以了?而为什么有时建立时间和保持时间的多周期个数都要设置?保持时间设置和建立时间设置存在什么依赖关系?为什么会有start和end两种模式,分别在什么情况下使用?我们是TimeQuest的用户,用户使用产品时只会去关心自己的需求,而用户成千上万,需求也千奇百怪,产品设计者为了满足所有用户,必须提高产品的通用性,最简单的方法就是增加选项模式,当一个需求简单的用户使用这个通用产品时,面对多重的选择和模式,往往会无从下手,因为根本就不知道这些选项设置的作用,自然就会产生上述的那些为什么。 要解答这些为什么,我们可以试着换位思考,从TimeQuest设计者的角度出发,如何设计多周期约束的语法规则?   明确设计目的   先来看看一个最常见的发送接收波形如图一所示, A时刻发送的数据B时刻锁存,launch(发送)边沿和latch(锁存)边沿间隔为一个时钟周期。 图一   这种情况下,建立时间和保持时间裕量为 setup slack = (current latch edge - current launch edge ) + Tskew - (Tdelay + Tco + Tsu)                   = T + Tskew - (Tdelay + Tco + Tsu)   hold  slack  = Tdelay + Tco - (Th + previous latch edge - current launch edge)                     = Tdelay + Tco - Th 其中Tskew是时钟偏斜,Tdelay为传输延迟,Tco为源寄存器的输出延迟,Tsu和Th为寄存器需要的建立保持时间。   如果接收波形整体延迟一个时钟周期,如图二所示,latch边沿改变了,A时刻发送的数据C时刻锁存,B时刻发送的数据D时刻锁存。 图二   此时,我们期望的建立时间和保持时间裕量为 setup slack   = (current latch edge - current launch edge ) + Tskew - (Tdelay + Tco + Tsu)                     = 2*T + Tskew - (Tdelay + Tco + Tsu) hold  slack   = Tdelay + Tco - (Th + previout latch edge - current launch edge)                  = Tdelay+Tco - (T+Th)   和前一种情况比较,建立时间裕量宽裕了一个周期,保持时间裕量缩紧了一个周期,但TimeQuest并不知道latch边沿变了,如果不进行多周期约束,仍按照前一种情况的裕量去约束,结果就会使得建立时间多了没必要的裕量,而保持时间的裕量可能不足。所谓的多周期是相对单周期而言的,launch和latch默认间隔为单周期,当launch和latch间隔为多个周期时,就需要用到多周期约束了,一个完整的时序分析路径是由Tskew、Tco、Tdelay、Tsu、Th以及launch时刻和latch时刻等共同决定的,后两项会随着用户不同的需求而改变,TimeQuest无法自动获得,所以多周期约束语法规则设计的目的就是准确的告诉TimeQuest波形何时launch何时latch,进行适当的建立保持约束。   明确TimeQuest的需求   我们已经知道了TimeQuest无法自己获取launch时刻和latch时刻 ,必须由用户提供,那么 TimeQuest 具体需要哪些信息才能 完全了解发送接收波形呢?   举一个典型的多周期波形,如图三所示,A时刻发送的数据B时刻锁存,B时刻发送的数据C时刻锁存,A为current launch,B即为current latch又是next launch,C是next latch。 图三   图三的发送接收关系,我们可以表示为下面几个式子: current latch   - current launch = 2个时钟周期 current latch   - next launch     = 0个时钟周期 previous latch - current launch     = 0个时钟周期   由于波形的周期性,后两个表达式是完全等效的,图二的发送接收关系同样可以表示为: current latch   - current launch = 2个时钟周期 current latch   - next launch     = 1个时钟周期 previous latch - current launch     = 1个时钟周期   将这几个表达式推广到更多不同的例子,会发现只要知道了current launch、current latch、next launch和previous latch就能确定任何形式的发送接收波形,因此TimeQuest只需获得这四个量,也就清楚波形的真实情况了。   明确用户的需求   假设用户的波形如图二所示,相比常见的图一单周期波形,建立时间宽裕了一个周期,而保持时间紧缩了一个周期,作为 用户,其实并不关心 current launch、current latch、next launch和previous latch这些量,只会关注如何把变化了的建立保持关系告知TimeQuest,让其在该放松的地方放宽约束,该紧缩的地方加强约束。 ------------------------------------------------------------------------------------------------------------- 由于博客字数限制,还有 整合TimeQuest和用户的需求, 消除不确定性,等更多精彩内容 放到“ 换位思考多 周期约束(下) ”中, 点击这里 http://bbs.ednchina.com/BLOG_ARTICLE_3003478.HTM 。
  • 热度 12
    2012-3-8 20:47
    3609 次阅读|
    3 个评论
      最近调试了下altera里的ddio模块,在Timequest约束ddio_out输出时,遇到了一个其实不算是问题的问题。 ddio_out模块如图1所示。 图1 DH和DL在clk上升沿采样,时钟的高电平随即使能DH通道输出高位数据,下降沿到来时使能DL通道输出低位数据,这样就实现了数据的双边沿输出。   为了实现ddio_out的数据和时钟的源同步,必须要对输出ddr_out进行约束,简化后工程如图2所示。 图2 整个约束过程和其他外设类似,详情可以查看 http://bbs.ednchina.com/BLOG_ARTICLE_3002035.HTM 。首先创建衍生时钟,然后set output delay from衍生时钟 to ddr_out,最后查看输出的建立保持余量。   奇怪的事情发生了, Timing报告里只有从sysclk  (pll_inst|altpll_component|auto_generated|pll1|inclk 其实就是sysclk,下文都用sysclk代替)  到ddr_out的路径,如图3所示。按经验,约束一个系统的输出延迟,Timequest会自动列出输出寄存器的路径,ddio_out模块的输出寄存器有DH和DL,但是 DH 和 DL 到ddr_out的时序路径报告哪去了呢? 图3 查看set false path,是否有将data_l和data_h到输出设为伪路径,结果sdc文件里没有关于ddio的伪路径。 查看Technology map viewer, DH 和 DL 寄存器是否被优化了,结果两个寄存器都还健在。 更改时序报告生成方式,试了Report Setup Summary、Report ALL I/O Timings...结果都一样。 最后换工程、换quartus 11(当前是9.1)、换电脑...就差没换人品了,Timing报告就是不显示 DH 和 DL 的输出路径。   对我非常确定及其肯定的经验,最终,还是妥协了,现在从头开始分析ddio_out的工作本质。 用 Technology map viewer sysclk分析唯一的线索从sysclk到ddr_out的路径,如图4所示。源寄存器不在ddio里,而在pll模块里,Timequest将这条看似毫无关联的路径认为是影响ddr_out输出延迟的关键路径,嗯,这个问题开始有点意思。 图4 绘制出ddio_out的时序图如图5所示,sysclk和sysclk(sel)为同一个时钟,都由pll驱动,前者为DH和DL的采样时钟,后者控制选择器的选择端,由于路径不同,存在一定的sysclk_skew,Tco为约束对象ddr_out的输出延迟。 图5   假设改变DL、DH的输出 dataout_l 和 dataout_h 的路径延迟,保持sysclk(sel)的延迟不变,ddr_out延迟会怎么变化呢?结果如图6所示,ddr_out的输出延迟没有变化。   图6 假设保持图6中的 dataout_l 和 dataout_h 的路径延迟,增大sysclk和 sysclk(sel)的延迟sysclk_skew,ddr_out还会不变吗?结果如图7所示,ddr_out的输出延迟变大了。 图7 从上述3个图的假设和结果可以证明,sysclk(sel)才是真正的关键路径,决定了ddr_out的输出延迟,而 dataout_l 和 dataout_h 的路径应该就是伪路径了, 所以Timequest只显示出这条路径信息,但是伪路径为什么没有出现在sdc文件的set false path呢? 我的回答是:它们不能算是伪路径。   dataout_l 和 dataout_h 的路径延迟 虽然不会影响输出延迟,但会改变输出数据,如图8所示,同时增大 dataout_l 和 dataout_h 的路径延迟,输出数据变混乱了,由于dataout_h延迟过大,在sysclk(sel)的高电平的前半阶段,仍然会输出上一个高位数据,dataout_l延迟过大也导致低电平阶段前期会输出了上一个低位数据。 图8 数据混乱,当然不是我们所期望的,所以 dataout_l 和 dataout_h 的路径肯定还是要被约束的,既然在Timequest里都没有显示,我们肯定是没法操作了,那最大的可能就是被潜规则了,Timequest自己完成了这两条路径的约束,可以从图8推测出这条潜规则: 0 Tco_datah sysclk_skew,sysclk_skew Tco_datal T/2。   综上所述,推测Timequest约束ddio_out输出延迟的过程: 1.根据约束要求,改变 sysclk到ddr_out的路径延迟,满足约束要求。 2.潜规则,sysclk到ddr_out的路径延迟确定后,sysclk_skew也就定了,约束ddio_out的Dl,DH寄存器满足0 Tco_datah sysclk_skew,sysclk_skew Tco_datal T/2,保证输出数据正确。   为了简化用户的操作,Timequest内部还会有很多类似的潜规则约束。虽然无法得知DH、DL被潜规则后的心情是否和XXX一样无奈,只希望大家在遇到此类问题,不用再纠结了。