zoukankan      html  css  js  c++  java
  • 【黑金原创教程】【TimeQuest】【第六章】物理时钟与外部模型

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢!


    黑金动力社区2013年原创教程连载计划:

    http://www.cnblogs.com/alinx/p/3362790.html


    《FPGA那些事儿--TimeQuest 静态时序分析》REV6.0 PDF下载地址:

    http://www.heijin.org/forum.php?mod=viewthread&tid=24978&page=1&extra=#pid172055


    第六章:物理时钟与外部模型

    6.1 物理时钟①

    6.2 物理时钟②

    6.3 物理时钟③

    6.4 物理时钟④

    6.5 无奈的set_max_delay与set_min_delay

    总结:


    第六章:物理时钟与外部模型

    6.1 物理时钟①

    clip_image002

    图6.1.1(左)fpga2ic外部模型,(右)理想时钟。

    在理想时序中出现的时钟称为理想时钟,换之在物理时序中出现的时钟称为物理时钟。笔者知道自己在说废话 ... 不过理想时钟的特性如图6.1.1右图所示,fpga_clk 与 ext_clk没有任何延迟。假设fpga发送数据,ic读取数据的话,那么fpga_clk 的启动沿必定在0ns触发,而ext_clk的锁存沿必定在10ns读取。

    clip_image004

    图6.1.2 clock skew(时间差)。

    相比之下,物理时钟就没有那么单纯了 ... 物理时钟有许多特性如:clock skew(时间差),jitter(抖动),或者latency(潜伏)等,这些物理时钟的特性又称为uncertainly —非定性,或者非理想。clock skew 我们已经在前面学习过,亦即 fpga_clk 与 ext_clk 的抵达时间不一致所导致的时间差,如 fpga_clk 有2ns的延迟,而ext_clk 有 3ns的延迟,那么时钟差就是 1ns,如图6.1.2所示。公式是:

    clock skew = < destination reg clock delay > - < source reg clock delay >

    clip_image006

    图6.1.3 时钟抖动.。

    那么什么是抖动与潜伏呢?当时钟源产生时钟信号的时候,除了时钟路径的延迟以外,时钟产生源本来也有延迟,不过该死不死的是,这个产生源的延迟是非常暧昧的,它有时大有时小 ... 如图6.1.3所示,假设倒霉的fpga连接到劣质的时钟源,该时钟源的最小延迟是 1ns,最大延迟是2ns(这时候还不包括 fpga_clk 路径本身的延迟)。

    结果,右图的时序被产生,亦即 fpga_clk 有时受1ns的min延迟影响,称为 early;fpga_clk 有时也受2ns的max延迟影响,称为 late。话中的 early/min 或者 late/max 也称为 clock latency(潜伏时钟)。clock latency 可说是非常恶趣味的玩笑,这种不确定的因数最要人摸不着,也让人最抓狂。

    虽说 fpga 内部额也有时钟抖动 ... 不过fpga内部有专门的硬件过滤时钟的抖动,以至于内部的时钟潜伏小到可以忽略它。所以说,时钟抖动就成为了外部模型的烦恼,不过也不是那么严重,以目前的科技而言,要把抖动控制在皮秒级别是绝对没问题的。此外,如果设计对时序不严谨的话,基本上也可以忽略时钟潜伏的问题。

    话是这么说 ... 不过同学们也休想偷懒,因为TimeQuest部分约束命令是与物理时钟有关,所以不得不学习,哎 ...

    ===================================================================

    时钟信号的抖动问题日最让人头疼的地方是 ... 它不像数据那样有多位宽,delay max 往往是针对有最大延迟的某位数据,反之 delay min 是针对某位有最小延迟的数据。至于时钟抖动都是朝向同一个时钟信号砸去,亦即 delay min 也是该时钟信号,delay max 也是该时钟信号。所以说,我们必须换个思路再思考。

    clip_image008

    图6.1.4 delay min 影响 fpga_clk 和 建立关系与保持关系的等价图。

    如图6.1.4的左图所示,由于fpga_clk被1ns延迟的delay min 影响,导致建立时间为9ns,而保持时间为1ns;换之,右图的启动沿与下一个启动沿也被1ns延迟的delay min影响,最后建立关系取得9ns,保持关系取得 -1ns。

    clip_image010

    图6.1.5 delay max 影响 fpga_clk 和建立关系与保持关系的等价图。

    图6.1.5的左图中,fpga_clk受2ns延迟的delay max影响,导致建立时间取得8ns,而保持时间取得2ns;换之,右图中的启动沿与下一个启动沿皆被2ns延迟的delay max 影响,结果取得8ns的建立关系,还有-2ns的保持关系。

    根据图6.1.4与图6.1.5的各种信息,我们总结出 ... 在物理时序的角度上建立时间越短越危险,同样保持时间越短越危险,因此我们可以这样说:delay max(late)影响启动沿,delay min(early)影响下一个启动沿。因为delay max(late)会造就最小的建立时间,换之 delay min(early)会造就最小的保持时间。

    clip_image012

    图6.1.6 有抖动但是没有min/max(early/late)之分,称为 both。

    有时候时钟信号的产生源会有延迟但是没有抖动,又或者说产生源有抖动但是没有 min/max(early/late)之分,这种情况下我们称为both,具体内容和 input/output delay both

    差不多。如图6.1.6所示,假设产生源有 1ns 的延迟,但是没有抖动,换句话说,右图中的启动沿和下一个启动沿,皆被1ns的延迟影响向右移至1ns。

    clip_image014

    图6.1.7 fpga_clk时钟信号路径延迟1ns。

    这种情况与 fpga_clk 路径延迟为1ns等价,如图6.1.7所示。如果反过来思考话,在第五章出现的 input min/max 与 output min/max公式,我们可以除掉 clock ckew,如下所示:

    input max = <ext2fpga delay max> - < destination reg clk delay - source reg clk delay > + ext_Tco

    = <ext2fpga delay max> - < clock skew > + ext_Tco

    input min = < fpga2ext delay min > - < destination reg clk delay - source reg clk delay > + ext_Tco

    = <fpga2ext delay min> - < clock skew > + ext_Tco(或者 ext_minTco)

    output max = <fpga2ext delay max> - < destination reg clk delay - source reg clk delay > + ext_Tsu

    = <fpga2ext delay max> - < clock skew > + ext_Tsu

    output min = < fpga2ext delay min > - < destination reg clk delay - source reg clk delay > - ext_Th

    = <fpga2ext delay min> - < clock skew > - ext_Th

    为(除掉clock skew 部分):

    input max = <ext2fpga delay max> + ext_Tco

    input min = <ext2fpga delay min> + ext_Tco(或者 ext_minTco)

    output max = <fpga2ext delay max> + ext_Tsu

    output min = < fpga2ext delay min > - ext_Th

    同学们可能会觉得非常疑惑,然后问:“如果将外包资料的 clock skew 除掉的话,TimeQuest 又该如何知道外边有关 fpga_clk 延迟与 ext_clk延迟的信息呢?”好问题,这就是接下来我们要学习的约束命令,亦即 set_clock_latency。

    实验七:set_clock_latency告诉TimeQuest外部时钟延迟信息

    clip_image016

    图6.1.8 假想实验的外部模型。

    图6.1.8是沿用实验六的假想外部模型,亦即ic1输出fpga读取,fpga输出ic2读取。

    其中ic1致fpga的D[0..3]最小延迟是2ns,最大延迟是4ns;换之fpga 致 ic2的D[0..3]最小延迟是2ns,最大延迟是4ns。此外也有100Mhz 的 ext1_clk,fpga_clk与ext_clk给相应的硬件提供时钟,其中ext1_clk有1ns延迟,fpga_clk有2ns延迟,至于ext2_clk有3ns延迟。(注意,目前任何时钟信号的产生源还没有发生抖动)

    接下来计算 input delay min/max 与 output delay min/max:

    input max = <ext2fpga delay max> + ext_Tco

    = 4ns + 0.5

    = 4.5ns

    input min = <fpga2ext delay min> + ext_Tco(或者 ext_minTco)

    = 2ns + 0.5ns

    = 2.5ns

    output max = <fpga2ext delay max> + ext_Tsu

    = 4ns + 0.5ns

    = 4.5ns

    output min = < fpga2ext delay min > - ext_Th

    = 2ns - 0.5ns

    = 1.5ns

    接下来,让我们来认识一下 set_clock_latency 约束命令:

    set_clock_latency的约束行为不是为某个时钟设置延迟,而是告诉TimeQuest有关外边时钟信号的延迟信息。虽然说 set_clock_latency 约束命令,内外模型的时钟潜伏它都可以设置,不过TimeQuest会无视set_clock_latency 对内部模型的一切影响,所以说它是半残废的约束命令,具体实例往后再谈。

    不管怎么说,先打开实验七,然后建立和实验七同名的 .sdc文件,然后将下列信息贴上:

    #**************************************************************

    # Create Clock

    #**************************************************************

    create_clock -name {fpga_clk} -period 10.000 -waveform { 0.000 5.000 } [get_ports {CLK}]

    create_clock -name {ext1_clk} -period 10.000 -waveform { 0.000 5.000 }

    create_clock -name {ext2_clk} -period 10.000 -waveform { 0.000 5.000 }

    #**************************************************************

    # Set Input Delay

    #**************************************************************

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[3]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[3]}]

    #**************************************************************

    # Set Output Delay

    #**************************************************************

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[3]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[3]}]

    首先声明3个 create clock,亦即告诉TimeQuest有:100Mhz 的 fpga_clk 对应 CLK 口,还有100Mhz虚拟时钟的ext1_clk与ext2_clk。至于set input delay 与 set input delay 是针对Din与Dout的延迟声明。内容的大体上与实验六差不多一样,不过区别的只是 input/output delay 不考虑各个时钟信号的时间差(clock skew)。

    clip_image018

    图6.1.9 手动建立 Best Case 网表。

    需要编译的同学先编译一下实验,然后打开TimeQuest 手动声明 Best Case 网表,如图6.1.9所示。接着连打 Read SDC File 与 Update Timing Netlist.

    clip_image020

    clip_image022

    clip_image024

     

    图6.1.10 Set_Clock_Latency 的界面。

    从 Constraint 的菜单下打开 set clock latency 的界面,如图6.1.10所示。Latency type 下的 Early,Late还有Both,就如上述解释的那样,early对应 min,late对应 max,而 both对应 min/max 或者 early/late。至于左边的 Rise/Fall与Both不用鸟它,我们现在用不到,总之默认下 Both就是了。

    Targets 是指对应的时钟信号,然而delay value是指该对应时钟信号的延迟值。同学只要根据图6.1.8假想实验的信息输入即可,亦即 ext1_clk 延迟1ns,fpga_clk延迟2ns,ext2_clk延迟3ns ... 结果如图6.1.10所示。完后,下面的代码就会自动添加在 sdc 文件中:

    #**************************************************************

    # Set Clock Latency

    #**************************************************************

    set_clock_latency -source 2.000 [get_clocks {fpga_clk}]

    set_clock_latency -source 1.000 [get_clocks {ext1_clk}]

    set_clock_latency -source 3.000 [get_clocks {ext2_clk}]

    接下来是习惯性的双击 Report Timing Netlist 更新网表,然后又习惯性的双击 Report Timing 调出全部8对节点的 Setup 时序报告,与Hold时序报告,接着再比较一下实验六的8对节点 Setup 时序报告与Hold时序报告。

    clip_image026

    clip_image028

    图6.1.11 实验七(左)与实验六(右)8对节点的setup时序报告。

    除了节点rData~Dout有相同的setup余量之外,似乎Din~rData的setup余量报告是不同。除此之外实验六与实验七的 clock skew 也有明显的差别,大约是2ns,不过先抛开clock skew不讲 ... 为什么Din~rData会的建立余量会有所不同呢,差别大约是0.5~0.8ns,其中关键就是Data Delay。笔者尝试展开节点 Din[0]~rData[0]的详细来看看:

    clip_image030

    clip_image032

    图6.1.12 实验七(左)与实验六(右)节点Din[0]~rData[0] 详细的setup时序报告。

    6.1.12左图中的 clock network delay 有1ns的延迟,这就是我们为 ext1_clk1设置1ns delay both的结果,换之右图中的 clock network delay 则为0ns。再接者左图Din[0]的输入延迟是4.5ns,而右图的Din[0]是3.5ns ... 这个信息告诉我们,实验七(左)不将 clock skew 计算在 input delay 中,而另用 set_clock_latency 命令告诉 TimeQuest ext1_clk有1ns的延迟,换之实验六则不同。

    继续看左图关键的 Dout[0]|datain 延迟是1.222ns,右图则是1.971,相差大约是0.7ns,也就是这个原因,导致实验七(节点rDin~rData)的setup余量比实验六的setup余量还要小的原因,亦即造就 Data Delay 的不同,至于为什么会多出0.7ns呢?笔者猜想应该是使用 set_clock_latency 的代价,又或者什么的 ... 真正的答案也只有 TimeQuest 自己知道吧!?

    接着把焦点转向 Data Required Path中,稍微注意左图的 clock path 延迟是3.473ns,而右图的clock path 是1.473ns,两者相差了2ns ... 这个信息告诉我们1.473ns是 fpga_clk内部的路径延迟,换之相差的2ns是实验七用 set_clock_latency 告诉 TimeQuest 有关 fpga_clk 外部有2ns延迟的原因。

    经过上述分析以后,我们可以得知实验七与实验六除了Dout[0]|datain 有0.7ns的差别以外,其他结果经过计算以后都相互符合。说着说着我们将实验七与实验六的 hold 时序报告也来比较一下看看:

    clip_image034

    clip_image036

    图6.1.13 实验七(左)与实验六(右)8对节点点的hold时序报告。

    从图6.1.13将实验七与实验六的 hold 余量比较一下,还是节点 Din~rData在搞怪,用狗眼一照又是 Data Delay 有问题,我们尝试展开节点Din[0]~rData[0]的详细信息看看:

    clip_image038

    clip_image040

    图6.1.14 实验七(左)与实验六(右)节点Din[0]~rData[0] 详细的hold时序报告。

    图6.1.14左图中的 clock network delay 有1ns,换之右图的 clock network delay是零值,这事情告诉我们,实验七用 set_clock_latency 告诉TimeQuest ext1_clk有1ns的延迟。接着注意左图的 Din[0] 输入延迟有2.5ns,而右图的 Din[0] 输入延迟是 1.5ns,这种现象原来是实验七没有将 clock skew 加入 set input delay 公式里,而实验六则相反。

    再者就是最可疑的 Dout[0]datain 延迟,左图是 1.222ns 而右图是1.971ns,之间的相差有0.7ns左右,笔者猜这是有使用 set_clock_latency 与没有使用的差别吧?也就是这个0.7ns的差别,导致建立余量(节点Din~rData)不相等。

    接着请注意 Data Required Path 中的clock path延迟,左图是3.473ns,右图是1.473ns,很明显左图大右图2ns,造就这个差别的原因绝对是实验七用 set_clock_latency 告诉 TimeQuest 那 fpga_clk 有2ns的延迟。至于导致两个实验的节点(Din~rData)的保持余量不同的凶手,估计就是那个充满阴谋的 Dout[0]datain ... 为什么它要犯罪呢?应该是吃 set_clock_latency 太多了吧?/

    clip_image042

    clip_image044

    图6.1.15 实验七(左)与实验六(右)节点rData[0]~Dout[0] 详细的setup时序报告。

    我们也顺便分析一下有关节点 rData[0]~Dout[0]的setup时序报告。首先注目一下Data Arrival Path 中的 clock network delay,左图是3.473ns,而右图是1.473ns,相差是2ns,其中的原因是实验七用 set_clock_latency 告诉 TimeQuest,fpga_clk 有2ns的缘故,换之实验六则没有。

    再者是 Data Required Path 中的 clock network delay,左图是3ns,右图则是0ns,有3ns

    的区别,这是因为实验七用 set_clock_latency告诉 TimeQuest,ext2_clk有3ns的延迟,反之实验六则没有。接下来就是 Dout[0]的输出延迟,左图是4.5ns,右图是3.5ns,其中的1ns相差是因为实验六有将 clock skew 计算在 set output delay 公式中,换之实验七则没有。

    clip_image046

    clip_image048

    图6.1.16 实验七(左)与实验六(右)节点rData[0]~Dout[0] 详细的hold时序报告。

    图6.1.16是节点 rData[0]~Dout[0]的详细hold时序报告,首先把注意力焦距在 Data Arrival Path 的 clock network delay,左图是3.473ns,右图是1.473ns,它们有2ns的相差,这是因为实验七用 set_clock_latency告诉TimeQuest该fpga_clk有2ns的延迟,换之实验六则没有。

    接着从Data Required Path 中可以得知,左图的 clock network delay 有 3ns的延迟,而右图是零值,这是因为实验七用 set_clock_latency 告诉 TimeQuest 该 ext2_clk 有 3ns的延迟。至于Dout[0]的输出延迟,左图是1.5ns,而右图是0.5ns,其中的1ns差别是实验六将 clock skew 计算在 set output delay 公式中,换之实验七则没有。

    从这个实验中我们可以这样结论:

    在计算 set_input_delay 与 set_output_delay 的时候,我们可以除掉 clock skew,取而代之用 set_clock_latency 约束命令告诉 TimeQuest关于外部模型中到底什么时钟信号,然而又有多少的延迟。其中时钟信号的产生源没有抖动,又或者说抖动的 early 与 late 值(both)作为前提。此外,透过 set_clock_latency 约束命令,在 Data Arrival Path 与 Data Required Path的信息中 clock network delay 也会显示对应的延迟。

    6.2 物理时钟②

    让我们继续时间抖动的问题吧 ... 在上一个章节里我们使用了 set_clock_latency约束命令告诉TimeQuest 有关外部时钟的各种延迟信息,然而这些时钟虽然有延迟但是没有发生抖动,结果造就 delay both。

    笔者在前面讲过,时间抖动最让人头疼的问题既是时钟信号不像数据信号有多位宽,delay min 或者 delay max 都有对应的数据位。而抖动是造就单个时钟信号同时拥有delay min 与 delay max,单是源寄存器的时钟信号抖来抖去已经够烦了,同学们请想象一下 ... 如果源时钟寄存器与目的寄存器的时钟信号同时抖来抖去,会是什么样的情形呢?

    不过幸运的是,set_clock_latency 约束命令可以简化这个难题 ...

    实验八 时钟抖动与 set_clock_latency

    clip_image050

    图6.2.1 fpga_clk与ext_clk时钟产生源发生抖动。

    首先我们必须知道,时钟抖动的max对应 late而 min对应 early,此外 max 针对启动沿,也针对建立关系,min针对下一个启动沿,也针对保持关系。从图6.2.1中我们可以知道 ext1_clk,fpga_clk 与 ext2_clk的产生源都有 min 1ns 与 max 2ns的抖动,时钟抖动再加上原本的路径延迟:

    ext1_clk delay min : 1ns + 1ns = 2ns

    ext1_clk delay max : 1ns + 2ns = 3ns

    fpga_clk delay min : 2ns + 1ns = 3ns

    fpga_clk delay max : 2ns + 2ns = 4ns

    ext2_clk delay min : 3ns + 1ns = 4ns

    ext2_clk delay max : 3ns + 2ns = 5ns

    接着再计算一下不包括 clock skew 的 input/output delay:

    input max = <ext2fpga delay max> + ext_Tco

    = 4ns + 0.5

    = 4.5ns

    input min = <fpga2ext delay min> + ext_Tco(或者 ext_minTco)

    = 2ns + 0.5ns

    = 2.5ns

    output max = <fpga2ext delay max> + ext_Tsu

    = 4ns + 0.5ns

    = 4.5ns

    output min = < fpga2ext delay min > - ext_Th

    = 2ns - 0.5ns

    = 1.5ns

    接着再打开实验八,建立同名的 sdc 文件,然后将下列代码添加进去,而上述代码的意义基本上与实验七一样,不要忘了网表是 create_timing_netlist -model fast。

    #**************************************************************

    # Create Clock

    #**************************************************************

    create_clock -name {fpga_clk} -period 10.000 -waveform { 0.000 5.000 } [get_ports {CLK}]

    create_clock -name {ext1_clk} -period 10.000 -waveform { 0.000 5.000 }

    create_clock -name {ext2_clk} -period 10.000 -waveform { 0.000 5.000 }

    #**************************************************************

    # Set Input Delay

    #**************************************************************

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[3]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[3]}]

    #**************************************************************

    # Set Output Delay

    #**************************************************************

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[3]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[3]}]

    clip_image052

    clip_image054

    图6.2.2 ext1_clk 输入2ns延迟的early与3ns延迟的 late。

    clip_image056

    clip_image058

    图6.2.3 fpga_clk 输入3ns延迟的early与4ns延迟的 late。

    clip_image060

    clip_image062

    图6.2.4 ext2_clk 输入4ns延迟的early与5ns延迟的 late。

    接着打开 set clock latency 界面,按图6.2.2~4的步骤输入相对应的约束。

    #**************************************************************

    # Set Clock Latency

    #**************************************************************

    set_clock_latency -source -late 4.000 [get_clocks {fpga_clk}]

    set_clock_latency -source -early 3.000 [get_clocks {fpga_clk}]

    set_clock_latency -source -late 3.000 [get_clocks {ext1_clk}]

    set_clock_latency -source -early 2.000 [get_clocks {ext1_clk}]

    set_clock_latency -source -late 5.000 [get_clocks {ext2_clk}]

    set_clock_latency -source -early 4.000 [get_clocks {ext2_clk}]

    完后该 sdc 文件会自动添加上述的代码

    事实上,透过 set_clock_latency 将各个外部时钟信号的抖动信息告诉 TimeQuest是一种吃快餐,贪便利的方法 ... 因为我们对整个时序分析的过程是100%的瞎子,完全不知道里边发生什么事。虽然这种做法没有不妥,还不如说非常好用,可是对于笔者这种喜欢吃妈妈料理的孩子而言,心里总是不舒服 ...

    笔者编辑这本笔记的初衷不是解释 TimeQuest 的用法,而是思考它,探讨它 ... 打从骨子想知道它是什么样的一个东西。为此,笔者需要更进一步思考时钟抖动如何影响 clock skew,然而这种情况下的 clock skew 又会得到怎样的等价图(建立关系与保持关系)。

    6.3 物理时钟③

    时钟抖动之所以让人觉得忧郁,因为1个时钟信号抖动就会产生2个可能性的时序,2个时钟信号同时抖动,就会产生4个可能性的时序,恰恰好TimeQuest 模型是由两个寄存器,亦即两个时钟信号组成。所以说,用一般的方法理解时钟抖动会耗死自己不偿命的,不过 TimeQuest 有用例外的“手段”去解决它 ... 至于是什么样的“手段”呢?同学们一定很好奇吧!?

    clip_image064

    图6.3.1 时钟抖动的外部模型。

    假设我们有一个 fpga2ic 的外部模型,如图6.3.1所示。同是100Mhz频率的fpga_clk与ext_clk都有 min 1ns 与 max 2ns的抖动延迟。我们先假设 fpga2ext 的D[0]有2ns的延迟,然后fpga 向 ic 发送 10ns周期的D[0]数据 ...

    clip_image066

    图6.3.2 fpga_clk min delay & ext_clk min delay(左) 与 fpga_clk min delay & ext_clk max delay(右)的第1,2种可能性。

    如图6.3.2所示,首先会产生前2种可能性,亦即 fpga_clk min & ext_clk min 与 fpga_clk min & ext_clk max,然而左图有 8ns的建立时间与2ns的保持时间,至于右图有 9ns的建立时间与1ns的保持时间。

    clip_image068

    图6.3.3 fpga_clk max delay & ext_clk min delay(左) 与 fpga_clk max delay & ext_clk max delay(右)的第3,4种可能性。

    如图6.3.3所示,接着会产生后2两种可能性,亦即 fpga_clk max & ext_clk min 与 fpga_clk max & ext_clk max,而左图有7ns的建立时间与3ns的保持时间,右图则有8ns的建立时间与2ns的保持时间。

    图6.3.1都有可能出现这4种时序,那么我们又该选择哪一种可能性呢?无论怎么选择,哪一种可能性都是真确的,同学们是不是觉得很忧郁呢?呵呵,笔者也是 ... 不过我们可以这样想:“哪一种可能性会产生最小的建立时间?又哪一种可能性会产生最小的保持时间?”

    clip_image070

    图6.3.4 fpga_clk max delay & ext_clk min delay(左) 与 fpga_clk min delay & ext_clk max delay(右)的可能性。

    不用想答案是非常明显的,亦即 fpga_clk max & ext_clk min 会产生最小的建立时间,简称 S.L.D.E可能性(source_reg_clk late,destination_reg_clk early)。换之,fpga_clk min & ext_clk max 会产生最小的保持时间,简称 S.E.D.L 可能性(source_reg_clk early,destination_reg_clk late)。然后我们可以无视余下的可能性。

    接着让我们来计算一下 slde 与 sedl 的clock skew:

    clock skew = < destination reg clk delay> - < source reg clk delay >

    SLDE clock skew = < destination reg clk early/min delay > - < source reg clk late/max delay >

    = < ext_clk min delay > - < fpga_clk max delay >

    = 1ns - 2ns

    = -1ns

    clock skew = < destination reg clk delay> - < source reg clk delay >

    SEDL clock skew = < destination reg clk late/max delay > - < source reg clk early/min delay >

    = < ext_clk max delay > - < fpga_clk min delay >

    = 2ns -1ns

    = 1ns

    clip_image072

    图6.3.5 SLDE clock skew(左)与SEDL clock skew对数据的影响。

    我们知道 clock skew的定义就是将时钟差反映在数据的身上,然而 SLDE时间差是-1ns,则 SEDL时间差是 1ns。如图6.3.5的左图所示,原本起跑线是 2ns的数据,受到 -1ns 时间差的影响,然后移动到3ns的位置,最终得到7ns的建立时间与 3ns的保持时间。

    换之,左图的数据,原本也是在2ns的起跑线,不过受1ns时间差的影响,然后移动到1ns的位置,结果造就9ns的建立时间与1ns的保持时间。同学们稍微比较一下 图6.3.4 与图6.3.5的建立时间与保持时间看看,是不是一样?

    clip_image074

    图6.3.6 SLDE clock skew与SEDL clock skew,建立关系与保持关系的等价图。

    此外我们也可以说 SLDE 时间差针对建立时间,针对建立关系,针对启动沿;换之 SEDL时间差针对保持时间,针对保持关系,针对下一个启动沿。如图6.3.6所示,数据D[0]有2ns的延迟 ... 原本位置在2ns的启动沿,不小心被-1ns的SLDE时间差推了一把,然后仆街在3ns的位置,最终导致7ns的建立关系。换之,原本位置在12ns 的下一个启动沿,不小心撞到 1ns的SEDL时间差,然后跌在11ns的位置,最终导致-1ns的保持关系。

    clip_image076

    图6.3.7 多位宽 ,fpga_clk max delay & ext_clk min delay(左) 与 fpga_clk min delay & ext_clk max delay(右)的可能性。

    图6.3.7 是多位宽数据,其中D[0]有2ns的延迟,D[1]有3ns的延迟,D[2]有4ns的延迟 ... 接着 fpga_clk 与 ext_clk 同时抖动会产生4种可能性的时序,不过根据上述的理解,fpga_clk max & ext_clk min 可能性数据D[2]会有最小的建立时间,如左图所示是 5ns;反之 fpga_clk min & ext_clk max可能性数据D[1]会有最小的保持时间,如右图所示是1ns。

    fpga_clk max & ext_clk min 可能性又叫 SLDE,其中的时间差称为 SLDE clock skew;换之,fpga_clk min & ext_clk max可能性又叫 SEDL,其中的时间差称为 SEDL clock skew。根据图6.3.7中信息,SLDE时间差是 -1ns,而SEDL时间差有 1ns。

    clip_image078

    图6.3.8 SLDE 时间差(左),SEDL时间差(右)。

    图6.3.7的数据经过各种可能性的时间差相互作用以后,结果会是如图6.3.8所示。左图中的 fpga_clk 与 ext_clk 不再跳来跳去,至于每一位数据D受 -1ns 的SLDE时间差影响以后,都向右移动 1ns;换之,右图的每一位数据D受1ns的SEDL时间差影响以后,都向左移动1ns。不过不管怎么样,图6.3.7与图6.3.8的每一位数据D都有同样的建立时间与保持时间。

    clip_image080

    图6.3.9 多位宽,SLDE clock skew与SEDL clock skew,建立关系与保持关系的等价图。

    同样我们知道 SLDE时间差 针对启动沿,针对建立时间,针对建立关系;而 SEDL时间差则针对下一个启动沿,针对保持时间,针对保持关系。此外,我们也知道数据的 delay max 也针对启动沿,数据的 delay min 也针对下一个启动沿。

    如图6.3.9所示,原本已经受数据delay max 延迟的启动沿,再加上-1ns SLDE 时间差的影响,最终落在5ns的位置,从而取得5ns的建立关系。至于下一个启动沿它先被 2ns的delay min影响,然后又受到1ns SEDL时间差的影响,下一个启动沿最终落在 11ns的位置,从而取得 -1ns的保持关系。

    我们知道数据的 delay max 影响启动沿,此外SLDE clock skew 也是影响启动沿,因此output max 可以这样更动:

    output max = < fpga2ext delay max > - [< dest. reg clock delay min > - < source reg clock delay max >]

    = < fpga2ext delay max > - [ < ext_clk delay min > - < fpga_clk delay max > ]

    = < fgap2ext delay max > - < SLDE clock skew >

    = < fpga2ext delay max > - < SLDE clock skew > + ext_Tsu

    至于数据的 delay min 影响下一个启动沿,而SEDL clock skew 同是影响下一个启动沿,因此 output min 可以这样更动:

    output min = < fpga2ext delay min > - [< dest. reg clock delay max > - < source reg clock delay min >]

    = < fpga2ext delay min > - [ < ext_clk delay max > - < fpga_clk delay min > ]

    = < fgap2ext delay min > - < SEDL clock skew >

    = < fpga2ext delay min > - < SEDL clock skew > - ext_Th

    接下来,我们让我们来理解一下,如果外部模型是 ic2fpga的情况,在两个时钟信号同时抖动的话,到底会发生什么不一样的情形呢?

    ===================================================================

    clip_image082

    图3.6.10 ic2fpga的外部模型。

    图3.6.10 是ic2fpga 的外部模型,其中 ext_clk 和 fpga_clk皆为100Mhz,两者的产生源都有 min 1ns 与 max 2ns的抖动。然后我们也假设一下 D[0]有2ns延迟,D[1]有3ns,D[2]有4ns延迟。

    clip_image084

    图6.3.11 多位宽 ,ext_clk max delay & fpga_clk min delay(左) 与 ext_clk min delay & fpga_clk max delay(右)的可能性。

    同学们有没有觉得图6.3.11很眼熟,没错它是图6.3.7的换皮,只是稍微调动一下fpga与ic之间的角色位置。根据原理,2个时钟信号的抖动会产生4个可能性的时序图,不过从图 6.3.11 的左图中可以发现 ext_clk max delay & fpga_clk min delay 可能性的数据D[2]拥有最小的建立时间;换之,ext_clk min delay & fpga_clk max delay 可能性的数据D[0]拥有最小的保持时间。

    其中 SLDE clock skew 的取值是 (ext_clk max delay & fpga_clk min delay的时间差):

    clock skew = < destination reg clk delay> - < source reg clk delay >

    SLDE clock skew = < destination reg clk early/min delay > - < source reg clk late/max delay >

    = < fpga_clk min delay > - < ext_clk max delay >

    = 1ns - 2ns

    = -1ns

    而SLDE clock skew 的取值是 (ext_clk min delay & fpga_clk max delay的时间差):

    clock skew = < destination reg clk delay> - < source reg clk delay >

    SEDL clock skew = < destination reg clk late/max delay > - < source reg clk early/min delay >

    = < fpga_clk max delay > - < ext_clk min delay >

    = 2ns -1ns

    = 1ns

    然后将 SLDE clock skew 与 SEDL clock skew 加入图 6.3.11。

    clip_image086

    图6.3.12 SLDE 时间差(左),SEDL时间差(右)。

    图6.3.12的ext_clk 与 fpga_clk 不再跳来跳去,换之左图中的数据D,皆被 -1ns 的SLDE时间差向右推一把。而右图中的数据D,皆被 1ns 的 SEDL 时间差向左拉一把。

    完后可以发现图6.3.11与图6.3.12的各个数据都有相同的建立时间与保持时间。

    clip_image088

    图6.3.14 多位宽,SLDE clock skew与SEDL clock skew,建立关系与保持关系的等价图。

    至于图6.3.14是建立关系与保持关系的等价图 ... 其中启动沿原先受4ns数据delay max的延迟影响,然后又被 -1ns 的SLDE时间差推一把,结果落在6ns的位置,最终取得5ns的建立关系。至于下一个启动沿,原先也是被2ns数据delay min的影响,接着它不小心被 1ns 的SLDE时间差绊了一跤,最终落在11ns的位置,结果也造就 -1ns的保持关系。

    我们知道数据的 delay max 影响启动沿,此外SLDE clock skew 也是影响启动沿,因此input max 可以这样更动:

    input max = < ext2fpga delay max > - [< dest. reg clock delay min > - < source reg clock delay max >]

    = < ext2fpga delay max > - [ < fpga_clk delay min > - < ext_clk delay max > ]

    = < ext2fpga delay max > - < SLDE clock skew >

    = < ext2fpga delay max > - < SLDE clock skew > + ext_Tco

    至于数据的 delay min 影响下一个启动沿,而SEDL clock skew 同是影响下一个启动沿,因此 input min 可以这样更动:

    input min = < ext2fpga delay min > - [< dest. reg clock delay max > - < source reg clock delay min >]

    = < ext2fpga delay min > - [ < fpga_clk delay max > - < ext_clk delay min > ]

    = < ext2fpga delay min > - < SEDL clock skew >

    = < ext2fpga delay min > - < SEDL clock skew > + ext_Tco

    //等价//

    = < ext2fpga delay min > - < SEDL clock skew > + ext_minTco

    ===================================================================

    当我们成功推导出加入时间抖动的 input/output min/max 公式以后,我们可以用 set_input_delay 与 set_output_ delay 约束命令,不仅将数据的延迟,还有寄存器特性,甚至是抖动的时间差,包裹成“外包资料”... 而不是用 set_clock_latency 约束命令告诉 TimeQuest 有关时间抖动的信息。

    实验九 时钟抖动与 input/output 约束命令

    clip_image050[1]

    图6.3.15 假想实验的外部模型。

    图6.3.15的假想实验基本上和实验八一样,不过这一回我们不再使用 set_clock_latency 将时钟抖动的信息告诉 TimeQuest,而是直接透过 input/output 公式将时钟抖动包裹在一次成为外部资料。首先从图6.3.15取出各种延迟信息:

    ext1_clk delay min : 1ns + 1ns = 2ns

    ext1_clk delay max : 1ns + 2ns = 3ns

    fpga_clk delay min : 2ns + 1ns = 3ns

    fpga_clk delay max : 2ns + 2ns = 4ns

    ext2_clk delay min : 3ns + 1ns = 4ns

    ext2_clk delay max : 3ns + 2ns = 5ns

    D[0..3] delay min : 2ns

    D[0..3] delay max : 4ns

    先计算 input min/max 的结果:

    input max = < ext2fpga delay max > - [< dest. reg clock delay min > - < source reg clock delay max >]

    = < ext2fpga delay max > - [ < fpga_clk delay min > - < ext1_clk delay max > ]

    = < ext2fpga delay max > - < SLDE clock skew >

    = < ext2fpga delay max > - < SLDE clock skew > + ext_Tco

    = 4ns - < 3ns - 3ns > + 0.5ns

    = 4.5ns

    input min = < ext2fpga delay min > - [< dest. reg clock delay max > - < source reg clock delay min >]

    = < ext2fpga delay min > - [ < fpga_clk delay max > - < ext1_clk delay min > ]

    = < ext2fpga delay min > - < SEDL clock skew >

    = < ext2fpga delay min > - < SEDL clock skew > + ext_Tco

    = 2ns - < 4ns - 2ns > + 0.5ns

    = 0.5ns

    接着计算 output min/max 的结果:

    output max = < fpga2ext delay max > - [< dest. reg clock delay min > - < source reg clock delay max >]

    = < fpga2ext delay max > - [ < ext2_clk delay min > - < fpga_clk delay max > ]

    = < fgap2ext delay max > - < SLDE clock skew >

    = < fpga2ext delay max > - < SLDE clock skew > + ext_Tsu

    = 4ns - < 4ns - 4ns > + 0.5ns

    = 4.5ns

    output min = < fpga2ext delay min > - [< dest. reg clock delay max > - < source reg clock delay min >]

    = < fpga2ext delay min > - [ < ext2_clk delay max > - < fpga_clk delay min > ]

    = < fgap2ext delay min > - < SEDL clock skew >

    = < fpga2ext delay min > - < SEDL clock skew > - ext_Th

    = 2ns - < 5ns - 3ns > - 0.5ns

    = -0.5ns

    然后,打开实验九然后建立同名的 sdc 文件,接着将下列的代码拷贝进去:

    #**************************************************************

    # Create Clock

    #**************************************************************

    create_clock -name {fpga_clk} -period 10.000 -waveform { 0.000 5.000 } [get_ports {CLK}]

    create_clock -name {ext1_clk} -period 10.000 -waveform { 0.000 5.000 }

    create_clock -name {ext2_clk} -period 10.000 -waveform { 0.000 5.000 }

    #**************************************************************

    # Set Input Delay

    #**************************************************************

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 0.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 0.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 0.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[3]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 0.500 [get_ports {Din[3]}]

    #**************************************************************

    # Set Output Delay

    #**************************************************************

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] -0.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] -0.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] -0.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[3]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] -0.500 [get_ports {Dout[3]}]

    代码的内容和实验八差不多,不同的只是少了 set_clock_latency 约束命令,换之就是 set_input_delay 与 set_output_delay 被更改了。如果同学不喜欢直接粘贴代码,也可以透过 TimeQuest手动输入相关的内容。

    接下来打开TimeQuest,然后手动建立网表 create_timing_netlist -model fast,再者就是管理的双击 Read SDC File,双击 Update Timing Netlist ... 完后举例所有节点的 setup 时序报告与hold时序报告。

    clip_image090

    clip_image092

    图6.3.16 实验九(左)与实验八(右)的 setup 时序报告。

    图6.3.16是实验九与实验八的setup时序报告比较,节点 rData~Dout 有相同的setup 余量,而节点 Din~rData也有相近的 setup 余量,但是左图与右图之间有 0.5~0.8ns的区别,估计是 DataIn那里出现差别。此外同学们稍微注意一下两者之间的clock skew,其中有4ns与3ns的差别,这就表示实验九有将“时钟抖动”信息打包在 input/output 公式里,而实验八则透过 set_clock_latency将“时钟抖动”信息告诉TimeQuest。

    clip_image094

    clip_image096

    图6.3.17 实验九(左)与实验八(右)的 hold 时序报告。

    图6.3.17是实验九与实验八的 hold时序报告比较,节点 rData~Dout拥有一样的 hold 余量,而节点Din~rData则又0.5~0.8ns的差别,不用差凶手也是 DataIn。同样两者之间的 clock skew 有 4ns~3ns的区别,原因与上述所述的一样。

    实验九的重点是要证明:除了用 set_latency_clock 可以将物理时钟的抖动信息告诉TimeQuest以外,我们也可以透过 input/output 公式将时钟的抖动信息包裹在同一个“外包资料”里。至于哪一个办法比较好用 ... 这就见仁见智了。

    6.4 物理时钟④

    笔者曾在前面讨论过,物理时钟既是不理想时钟,其中clock skew,clock jitter 或者 clock latency 等物理时钟的特性,称为 clock uncertainly。然而TimeQuest 也有专门的约束命令用来针对 clock uncertainly,约束命令名为 set_clock_uncertainly。该约束命令的行为仅告诉TimeQuest保险信息而已,而该约束命令有两种功能:

    (一)设置而外的 setup 或者 hold 保险余量。

    (二)设置物理时钟的不确定性。

    功能一很容易理解 ... 假设节点A有 5ns建立余量 与 2ns保持余量,不过笔者却很怕死的为节点A设置而外1ns的保险余量,结果节点A有4ns的建立余量与1ns的保险余量。从另一个角度来思考“提升保险余量有也是提升环境的极端性”,这种思路和网表的质量一样,亦即越极端的网表,保险余量与大。(功能一也可以用来约束tRise与tFall延迟)

    至于功能二中所谓的物理时钟不确定性,就是我们之前所曾学过的,时钟抖动所产生的各种可能性时序。我们知道TimeQuest 模型至少需要2个寄存器,换句话一个节点需要2个时钟信号,如果两个时钟信号同时发生抖动,根据概率论会产生4种可能性的时序。

    不过,这4种可能性的时序有何 set_clock_uncertainly 约束命令有什么关系呢?让笔者拿 input/output 公式来解释:

    input max = < ext2fpga delay max > - < SLDE clock skew > + ext_Tco

    input min = < ext2fpga delay min > - < SEDL clock skew > + ext_Tco

    output max = < fpga2ext delay max > - < SLDE clock skew > + ext_Tsu

    output min = < fpga2ext delay min > - < SEDL clock skew > - ext_Th

    input/output 公式如果有考虑时钟抖动的可能性,就会有标志性的 SLDE 时间差与 SEDL时间差,而 set_clock_uncertainly 约束命令就是针对它们。此外,我们也知道 SLDE时间差是针对建立关系,而SEDL时间差是针对保持关系。在此之前我们先将它们从 input/output 公式中除掉:

    input max = < ext2fpga delay max > + ext_Tco

    input min = < ext2fpga delay min > + ext_Tco

    output max = < fpga2ext delay max > + ext_Tsu

    output min = < fpga2ext delay min > - ext_Th

    然后再将 SLDE与SEDL的时间差透过 set_clock_uncertainly 告诉TimeQuest即可。

    实验十 时间抖动与 set_clock_uncertainly

    clip_image050[2]

    图6.4.1 假想实验的外部模型。

    实验十的内容是基于实验八 ... 不管怎么样,我们先求出各种延迟信息:

    ext1_clk delay min : 1ns + 1ns = 2ns

    ext1_clk delay max : 1ns + 2ns = 3ns

    fpga_clk delay min : 2ns + 1ns = 3ns

    fpga_clk delay max : 2ns + 2ns = 4ns

    ext2_clk delay min : 3ns + 1ns = 4ns

    ext2_clk delay max : 3ns + 2ns = 5ns

    计算不包括 SEDL 与 SLDE时间差的 input/output delay:

    input max = <ext2fpga delay max> + ext_Tco

    = 4ns + 0.5

    = 4.5ns

    input min = <fpga2ext delay min> + ext_Tco(或者 ext_minTco)

    = 2ns + 0.5ns

    = 2.5ns

    output max = <fpga2ext delay max> + ext_Tsu

    = 4ns + 0.5ns

    = 4.5ns

    output min = < fpga2ext delay min > - ext_Th

    = 2ns - 0.5ns

    = 1.5ns

    再者将 input max/min 的 SEDL 与 SLDE 时间差另外算出:

    input max SLDE = < dest. reg clock delay min > - < source reg clock delay max >

    = < fpga_clk delay min > - < ext1_clk delay max >

    = 3ns - 3ns

    = 0ns

    input min SEDL = < dest. reg clock delay max > - < source reg clock delay min >

    = < fpga_clk delay max > - < ext1_clk delay min >

    = 4ns - 2ns

    = 2ns

    接着另外算出 output max/min 的 SEDL 与 SLDE 时间差:

    output max SLDE = < dest. reg clock delay min > - < source reg clock delay max >

    = < ext2_clk delay min > - < fpga_clk delay max >

    = 4ns - 4ns

    = 0ns

    output min SEDL = < dest. reg clock delay max > - < source reg clock delay min >

    = < ext2_clk delay max > - < fpga_clk delay min >

    = 5ns - 3ns

    = 2ns

    完后打开实验十,然后建立同名 sdc 文件,随之将下面的代码拷贝进去:

    **************************************************************

    # Create Clock

    #**************************************************************

    create_clock -name {fpga_clk} -period 10.000 -waveform { 0.000 5.000 } [get_ports {CLK}]

    create_clock -name {ext1_clk} -period 10.000 -waveform { 0.000 5.000 }

    create_clock -name {ext2_clk} -period 10.000 -waveform { 0.000 5.000 }

    #**************************************************************

    # Set Input Delay

    #**************************************************************

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[0]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[1]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[2]}]

    set_input_delay -add_delay -max -clock [get_clocks {ext1_clk}] 4.500 [get_ports {Din[3]}]

    set_input_delay -add_delay -min -clock [get_clocks {ext1_clk}] 2.500 [get_ports {Din[3]}]

    #**************************************************************

    # Set Output Delay

    #**************************************************************

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[0]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[1]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[2]}]

    set_output_delay -add_delay -max -clock [get_clocks {ext2_clk}] 4.500 [get_ports {Dout[3]}]

    set_output_delay -add_delay -min -clock [get_clocks {ext2_clk}] 1.500 [get_ports {Dout[3]}]

    接着打开TimeQuest随之手动建立网表 create_timing_netlist -model fast,然后惯例的双击 Read SDC File 与 Update Timing Netlist。当网表更新结束以后,从 Constraint 菜单下打开 Set Clock Uncertainly。

    clip_image098

    clip_image100

    图6.4.2 set clock uncertainly 界面,针对 source clock ext1_clk 与 destination clock fpga_clk。

    我们知道input 公式的源寄存器的时钟信号是ext1_clk所以 From Clock 对应ext1_clk,换之我们知道目的寄存器的时钟信号是 fpga_clk所示 to clock 对应 fpga_clk。此外我们也知道 input max 中的 SLDE时间差针对建立关系,而该值是 0ns,结果如6.4.2左图所示,Uncertainly是 0ns,而 analysis type 是 setup。反之,input min中的 SEDL时间差针对保持关系,结果如右图所示,uncertainly 是 2ns,而 analysis type 是 hold。

    clip_image102

    clip_image104

    图6.4.3 set clock uncertainly 界面,针对 source clock fpga_clk 与 destination clock ext2_clk。

    我们也知道output公式的源寄存器时钟信号是ext1_clk所以 from Clock 输入ext1_clk,而我们知道目的寄存器的时钟信号是 fpga_clk所示 to clock 输入 fpga_clk。另外我们也知道 output max 中的 SLDE时间差针对建立关系,而该值是 0ns,结果如6.4.3左图所示,Uncertainly是 0ns,而 analysis type 是 setup。反之,output min中的 SEDL时间差针对保持关系,结果如右图所示,uncertainly 是 2ns,而 analysis type 是 hold。

    #**************************************************************

    # Set Clock Uncertainty

    #**************************************************************

    set_clock_uncertainty -rise_from [get_clocks {fpga_clk}] -rise_to [get_clocks {ext2_clk}] -setup 0.000

    set_clock_uncertainty -rise_from [get_clocks {fpga_clk}] -rise_to [get_clocks {ext2_clk}] -hold 2.000

    set_clock_uncertainty -rise_from [get_clocks {fpga_clk}] -fall_to [get_clocks {ext2_clk}] -setup 0.000

    set_clock_uncertainty -rise_from [get_clocks {fpga_clk}] -fall_to [get_clocks {ext2_clk}] -hold 2.000

    set_clock_uncertainty -fall_from [get_clocks {fpga_clk}] -rise_to [get_clocks {ext2_clk}] -setup 0.000

    set_clock_uncertainty -fall_from [get_clocks {fpga_clk}] -rise_to [get_clocks {ext2_clk}] -hold 2.000

    set_clock_uncertainty -fall_from [get_clocks {fpga_clk}] -fall_to [get_clocks {ext2_clk}] -setup 0.000

    set_clock_uncertainty -fall_from [get_clocks {fpga_clk}] -fall_to [get_clocks {ext2_clk}] -hold 2.000

    set_clock_uncertainty -rise_from [get_clocks {ext1_clk}] -rise_to [get_clocks {fpga_clk}] -setup 0.000

    set_clock_uncertainty -rise_from [get_clocks {ext1_clk}] -rise_to [get_clocks {fpga_clk}] -hold 2.000

    set_clock_uncertainty -rise_from [get_clocks {ext1_clk}] -fall_to [get_clocks {fpga_clk}] -setup 0.000

    set_clock_uncertainty -rise_from [get_clocks {ext1_clk}] -fall_to [get_clocks {fpga_clk}] -hold 2.000

    set_clock_uncertainty -fall_from [get_clocks {ext1_clk}] -rise_to [get_clocks {fpga_clk}] -setup 0.000

    set_clock_uncertainty -fall_from [get_clocks {ext1_clk}] -rise_to [get_clocks {fpga_clk}] -hold 2.000

    set_clock_uncertainty -fall_from [get_clocks {ext1_clk}] -fall_to [get_clocks {fpga_clk}] -setup 0.000

    set_clock_uncertainty -fall_from [get_clocks {ext1_clk}] -fall_to [get_clocks {fpga_clk}] -hold 2.000

    完后上述代码会自动添加在 sdc 文件下。接下来将所有节点的 setup 时序报告与hold 时序报告都一举列出。

    clip_image106

    clip_image108

    图6.4.4 实验十(左)与实验八(右)的setup时序报告。

    图6.4.4.是实验十与实验八的setup 时序报告比较,不过双方也有同样的setup余量结果。

    clip_image110

    clip_image112

    图6.4.5 实验十(左)与实验八(右)的hold时序报告。

    图6.4.5 是实验十与实验八的hold时序报告比较,而双方有同样的hold余量,笔者稍微手痒将节点 Din[0]~rData[0] 的详细信息展开 ...

    clip_image114

    clip_image116

    图6.4.6 实验十(作)与实验八(右)的节点Din[0]~rData[0] hold信息报告的详细信息。

    我们稍微比较一下图6.4.6的两张图,右图的 clock network delay 之所以有延迟是因为实验八用 set_clock_latency 告诉TimeQuest有关时钟的抖动信息。换之左图的 clock uncertainty 有延迟信息是因为实验九用 set_clock_uncertainly 告诉 TimeQuest 各种 SLDE 与 SEDL时间差的信息。

    至于 set_clock_uncertainly 的功能一笔者就不演示了因为太单纯了,而实验十我们可以这样结论:

    set_clock_uncertainly 所谓的 uncertainly 是指时钟信号抖动的信息,不过更正确一点说就是各种时钟抖动所产生的可能性时序里所隐藏的 SLDE时钟差与SEDL时钟差,前者是针对建立关系,后者则是针对保持关系。此外,如果使用 set_clock_uncertainly该约束命令,在详细的时序报告中clock uncertainty 列表就会留下设置的痕迹。

    6.5 无奈的set_max_delay与set_min_delay

    首先,先让我们瞧瞧官方如何解释 set_max_delay 与 set_min_delay?

    set_max_delay:Specifies a maximum delay exception for a given path.

    set_min_delay:Specifies a minimum delay exception for a given path.

    set_max_delay 大意是为某个路径(实际上是指节点)指定自定义最大延迟,换之 set_min_delay 是为某个路径(实际上是指节点)指定自定义最小延迟。这两个约束命令容易让人误会的原因是英文单词的 path,这个英文单词不禁让人联想 clock path 或者 data path。以此类推,set_max_delay 或者 set_min_delay 仿佛就有能力自定义 clock path 或者 data path,不过这是美丽的误会。

    所谓的 clock path 或者 data path 是指内部延迟,然而决定内部延迟的动作除了 HDL的书写以外,还有编译器设置,而且网表的质量也有关系。所以说该约束命令与内部延迟是完全没有关系,再次强调!没有关系!

    用TimeQuest的话来说 path 往往是指某对节点,接着有 max 与 min 这两个关键字,就一定与时钟有关,而建立关系与保持关系式绝对逃不了。不过为什么说 set_max_delay 与 set_min_delay 是无奈的东西呢?

    clip_image118

    clip_image120

    图6.5.1 set_max_delay 与 set_min_delay 的界面。

    以实验十为例,网表为 fast model,从 Constraint 菜单下打开 set maximum delay 与 set minimum delay,然后针对节点 Din[0]~rData[0],maximum delay设置为6.666ns,而minimum设置为4.444ns,如图6.5.1所示。

    clip_image122

    图6.5.2 节点 Din[0]~rData[0]的setup详细报告。

    然后打开节点 Din[0]~rData[0]的详细 setup时序报告,如图6.5.2所示。我们可以看到该节点的 setup relationship不是其它,而是我们之前用 set maximum delay 设置的 6.666ns。接着注意一下右边的 waveform,很明显锁存沿向左移动大约 3.334ns,结果造就 6.666ns的建立关系。

    clip_image124

    图6.5.3 节点 Din[0]~rData[0]的hold详细报告。

    接下来,打开节点 Din[0]~rData[0]的详细 hold 时序报告,如图6.5.3所示。同样 hold relationship 不是其它而是我们经 set minimum delay 设置的 4.444ns。从右边的 waveform 那里我们可以看到下一个启动沿与锁存沿有 4.444ns的距离(保持关系)。

    clip_image126

    图6.5.4 建立关系与保持关系的等价图。

    根据上述的内容,我们知道这样一个结果,亦即 set maximum delay 直接自定义建立关系,而 set minimum delay 直接定义保持关系。有关这一点与之前所学过的 delay max 与 delay min有不同的表现 ... 如图6.5.4 所示,以往的 delay max 与 delay min是取D数据D的最大和最小延迟,然后直接反映在启动沿与下一个启动沿的身上,从而取得等价图。然后再将这些信息告诉TimeQuest,让它去计算。

    相反的,set maximum delay 与 set minimum delay 的约束行为实际上是各种乱七八糟的约束合成体,设置时钟位移也可,设置多这种路径也可以。既然 set maximum delay 与 set minimum delay 那么糟糕,为什么还要它干嘛呢?根据官方的资料 ... 在很早以前TimeQuest还小的时候,静态时序分析的工作是由传统的工具(Classic Timing Analysis Tool)负责,其中就用 set maximum delay 和 set minimum delay 约束外部ic 各种寄存器特性,如Tsu和Th。

    不过TimeQuest出现以后,随之 set input delay 与 set output delay 也跟着出现,该约束命令用“外包资料”的方式,不仅可以将时钟抖动也包装进去,而且也能将外部ic的寄存器特性也包裹进去 ... 慢慢的 set input delay 与 set output delay 就替代了 set maximum delay 与 set minimum delay 这部分的工作。

    至于要不要使用 set maximum delay 与 set minimum delay 结果是见仁见智了。

    总结:

    第六章的重点内容基本上都是围绕着“物理时钟”展开,笔者想说物理时钟是外部模型是最关键,其中物理时钟所拥有的物理特性,亦即时钟抖动,潜伏和时间差等,被TimeQuest视为 Uncertainly。至于这些问题的重要性,单是约束命令的数量就可以看出它有多受重视。

    时钟抖动是物理时钟最常见的一个表现,虽说目前的科技可以将时钟抖动控制在一定范围,不过对那些时序非常挑剔的设计而言,一天不把时钟抖动算清楚,一天都不得安宁。

    时钟抖动最大的难题就是产生多个可能性时序,以TimeQuest的模型而言,最多会产生4种可能性的时序。时钟抖动如果按一般的手段去解决是非常烦恼的。

    时钟抖动所产生最大的延迟称为max别名late,最小延迟则是 min 别名 early,这些抖动延迟又称为时钟潜伏。如果同学是懒人的话,TimeQuest 有专门的约束命令用来取得时钟抖动的信息,亦即 set_clock_latency。

    任时钟抖动的四种可能性中,SLDE的数据拥有最小的建立时间,SEDL拥有最小的保持时间。其中取得的 SLDE 时间差与 SEDL 时间差是理解相关约束命令的关键所在。

    不仅 SLDE 时间差与 SEDL 时间差可以加入input/output 公式里,而且也有专门的约束命令用来取得它们,亦即 set_clock_uncertainly.

    笔者原本打算只讲 set_clock_latency 而已,可是犯贱的骨子就喜欢往更深处砖。不过不管怎么样,收获也挺多的,以往累积的许多问题,就这样一扫而空了。到目前位置,constrainy菜单下的约束命令,只剩下Create generate clock还未讨论,下一章我们就拿它来开刀吧。

  • 相关阅读:
    uniGUI试用笔记(九)uniGUI执行程序部署有3种形式1
    CxGrid导出Excel时清除颜色的设置
    delphi 安卓程序如何读取外部配置文件
    cxgrid动态显示行号
    为Delphi程序增加UAC功能(管理员身份运行exe)
    delphi debug release区别是什么?
    启动程序的同时传参给接收程序(XE8+WIN764)
    iOS Development和iOS Distribution有什么区别
    4张图看懂delphi 10生成ipa和在iPhone虚拟器上调试(教程)
    使用Xcode 7 beta免费真机调试iOS应用程序
  • 原文地址:https://www.cnblogs.com/alinx/p/3493058.html
Copyright © 2011-2022 走看看