Tcl与Design Compiler (十一)——其他的时序约束选项(二)

  • Post author:
  • Post category:其他





本文如果有错,欢迎留言更正;此外,转载请标明出处

http://www.cnblogs.com/IClearner/

,作者:IC_learner



前面介绍的设计都不算很复杂,都是使用时钟的默认行为作为电路的约束,都存在有路径给你约束,即信号的变化要

在一个时钟周期内完成,并达到稳定值,以满足寄存器的建立和保持的要求

。此外进行可测性设计(design for test)时,为了提高测试的覆盖率,我们经常使用多路(multiplex,简称mux)传输电路的控制时钟,使电路的时钟信号可以由输入端直接控制。这些电路约束属于复杂的约束,除了理论上的讲解之外,还会进行实战,实战内容主要为围绕前面的伪路径和多周期路径进行的,主要内容如下:



·异步设计路径和逻辑上不存在的路径的时序约束(时序例外)



·多时钟周期的时序约束



·分频电路和多路时钟传输的时钟约束



·实战






1、异步设计路径和逻辑上不存在的路径的时序约束(时序例外)



(1)异步设计的路径约束


前面说的都是

同步时序电路

,下面就用介绍一下

异步时序电路的约束

吧。异步时序电路的时钟来自不同的时钟,模块之间的时钟是不同频或者同频不同相的关系,一些时钟在我们的设计里没有对应的端口,如下图所示:




上图中,一共用4个时钟源,有5种不同的时钟;我们要综合电路使用的是时钟

CLKC

,时钟源是

OSC3

,前后模块的时钟各不一样,因此是异步电路。


(在传统的同步和异步设计分类上,有些由同一个晶振产生的时钟由于可能没有固定的相位关系,因此会被认为是异步设计;在那种情况下,我们也可以使用这里的异步约束进行相关的时序约束)


进行异步电路设计时,设计者要注意会产生

亚稳态

,导致某些寄存器的输出为不定态。为了避免产生亚稳态问题,可以考虑在设计中

使用双时钟、不易到亚稳态的触发器(double-clocking,metastable-hard Flip-Flops)

,或使用双端口(dual-port)的FIFO等等。


对于

穿越异步边界的任何路径

,我们必须

禁止对这些路径做时序综合

。由于不同时钟源的时钟之间相位关系是不确定的,

一直在变,对跨时钟域的路径作时间约束是毫无意义

的。因此我们不要浪费DC的时间,试图使异步路径“满足时序要求”。我们可用


set_false_path


命令为跨时钟域的路径作约束(其实是解除时序路径的约束)。这也就是异步电路里面的时序约束比较重要的。


例如对于下面的异步电路:




设计之间是异步的,

存在垮时钟域的路径

(如上图所示),我们就要用

set_false_path

命令为跨时钟域的路径作约束,上图的异步电路对应的跨时钟域约束如下所示:


#Make sure

register-register paths meet timing



create_clock  -period  20  [get_ports CLKA]



create_clock  -period  10  [get_ports CLKB]


#

Don’t optimize logic crossing clock domains



set_false_path

-from

[get_clocks  CLKA]

-to

[get_clocks  CLKB]



set_false_path

-from

[get_clocks  CLKB]

-to

[get_clocks  CLKA]



如果设计中的


所有时钟都是异步


的,可用下面命令为跨时钟域的路径做约束:






set_false_path

命令对路径作时序约束后,DC做综合时,将中止对这些路径做时间的优化。



(2)逻辑上不存在的路径的约束



set_false_ path

命令除了可以用于

约束异步电路

外,还可以用于

约束逻辑上不存在的路径(logically false paths)。

逻辑上不存在的路径是什么呢,下面通过一个例子说明,对于下面的电路:







选择信号是0

的时候,前面的MUX打开的是

A1

,后面MUX打开的是

B2

,因此数据的通路就是

A1B2(数据从A1流到B2)

;当选择信号是

1

的时候,前面的MUX打开的是

B1

,后面MUX打开的是

A2

,因此数据的通路就是

B1A2

。由此可以看到,选择信号无论是1还是0,前面的

MUX的A1引脚和后面的MUX的A2引脚之间是没有数据流通的,也就是该逻辑通路并不存在

。同样,前面的MUX的B1引脚和后面的MUX的B2引脚之间的逻辑通路也不存在。因此这两条数据通路就是逻辑上不存在的路径,比如从点A1到点A2之间有一条物理上的连接路径,但是点A1输入信号并不通过这条路径传输到A2;

这种物理上存在连接关系,但是逻辑不存在的路径称为


逻辑伪路径

,在DC中,

伪路径“false path”

称为

时序例外(timing exceptions)

。可以用下面的拓扑图理解:





我们可以用

report_timing_requirements

命令报告设计中所有的例外(包括有效的例外和无效的例外)。




report_timing_requirements

命令加选项”

-ignored

“,将把无效的例外报告出来,例如:




上面的报告中,我们可以知道,从引脚

{IO_PCI_CLK\pclk}

到引脚

{IO_SDRAM_CLK\ SDRAM_ CLK}

并不存在实际的信号流通,也就是这是一条逻辑伪路径。引脚

{IO_SDRAM_CLK\SDRAM_CLK}

不是

路径的终点

(根据定义,路径的终点必须是输出端口或寄存器的数据输入引脚);引脚

FF1/Q

不是路径的起点(根据定义,时序路径的起点必须是输入端口或寄存器的时钟引脚)。注意:

report_timing_requirements

命令无”

-valid

”,选项。该命令的所有选项如下:







去掉任何不要的例外

,可使用

reset_path

命令,例如:


dc_shell  >

reset_path   -from   FF1/Q







2、多时钟周期的时序约束



(1)关于建立时间


如下图所示加法器电路,时钟clk的周期定义为10ns,按设计规格,

加法器的延迟约为6个时钟周期






①默认的的建立时间约束


默认的时间建立时间约束将指示DC在10ns的时候对C_reg进行建立时间是否满足的分析;很显然,默认的时序约束会使寄存器的数据输入引脚

C_reg/D

信号变化,不满足

建立(setup)

的要求,将产生亚稳态,寄存器

C_reg

的输出为不定态。也就是一个时钟周期的约束不能满足约束要求。



②修改后的建立时间约束


对于多时钟周期的

建立时间约束

,可以使用下面命令进行

修改




create_clock  -period  10  [get_ports  CLK]



set_multicycle_path


6


-setup  -to  [get_pins  C_reg[*]/D]



(等价于set_multicycle_path


-setup  6  -to  [get_pins  C_reg[*]/D] )


注意这条命令是要知道

多时钟周期的终点寄存器

的(注意:这条命令设置了

所有的

前级寄存器

时钟端口

到C_reg寄存器的

D端口路径都

是多时钟周期路径,而

set_multicycle_path


6


-setup  -from  A_reg/Clk  -to  [get_pins  C_reg[*]/D],

则是仅仅现在从

A寄存器的时钟端口



C_reg寄存D端口

的这一条路径而已),通过这条命令,就告诉DC将仅仅在

第6个上升沿

,即60 ns作建立的分析(也就是间隔6个时钟周期后再做建立时间分析)。这时,加法器的

最大允许延迟

是:




对应的时序关系如下图所示:





(2)关于保持时间



①默认的保持时间约束


对于保

持时间的约束

,我们是不是默认就OK了呢?在

前面的建立时间和保持时间的概念

中,我们知道

默认的保持分析时间在建立分析的前一周期

,(此处应该有链接)也就是说,在这个多时钟周期的加法器中,DC将在

50 ns这个时刻

分析电路有无违反保持要求,要求加法器的

最小延时

是(注意这是默认的情况下的所做的时序要求):





默认的保持时间分析对应的时序关系

如下所示:




也就是说,经过修改过后的多时钟周期建立时间约束和默认的保持时间约束就会告诉DC,

要DC综合出一条路径使其建立时间满足60 ns的要求,并且同时满足保持时间50ns的要求



但是要综合出这样一条路径实际上是没有必要的,这样做只会增加电路的复杂度。为什么会这样呢?这是因为默认保持时间不满足约束,也就是说,

不应该在50ns的时候进行保存时间的检测

,需要

修改多时钟周期保持时间的约束





②修改后的保持时间约束


那在上面什么时候做保持时间分析比较合适呢?我们知道

在时间为60 ns的时刻,引起寄存器C_reg的D引脚信号变化

的是时钟

CLK在0时刻的触发沿

。此刻(

在0ns时

),时钟CLK把寄存器A_reg和B_reg的D引脚信号采样到它们的输出端。再通过加法器把信号传输到寄存器C_reg的D引脚。由此可见会

冲掉C_reg的D端数据

只是

A_reg和B_reg的D引脚的变化的时候

,也就

0ns时刻

,因此应该对保持时间做出调整,应该在0ns的时候做保持时间的检测,也就是应该提前5个时钟周期,从50ns提前到0ns。


修该后的约束如下所示:




对应的时序关系如下所示:




保持时间的分析提前了5个周期,加法器的允许延时为:





仅仅通过约束

告诉DC这是一个多时钟周期的加法器电路是不够充分的,一方面是由于后面的触发器应该经过6个时钟周期之后才能采到正确的值(但是C_reg不知道什么采到的值是正确的),另一方面是约束仅仅是告诉DC如果这块电路的延时太大或者太小的时候要报错;可以这么理解,约束单单保证了时序上这个是

一个多时钟周期的加法器电路

,但是这个加法器电路经过延时得到结果后,后面的C_reg采样的正确性,需要在RTL代码的设计上保证,需要加上相应的控制信号,保证DC能够综合出能够正确工作的多时钟周期的加法器。对于前面的加法器,可以需要加上相应的使能信号,因此电路设计如下所示:





(3)多时钟路径和普通路径同在一个设计中


前面的例子是单纯的多时钟周期设计,当电路里面

同时存在多时钟周期路径和普通路径时

,如下图所示:




该电路中,要求寄存器间的

乘法运算为两个时钟周期

,加法运算为

默认的一个时钟周期

,这时候,可以使用下面命令进行约束:



create_clock  -period  10  [get_ports  clk]

;#创建时钟



set_multicycle_path


-setup  2



-from



FFA/CP



-through



Multiply/Out


-to FFB/D  ;



set_multicycle_path


-hold   1



-from



FFA/CP



-through



Multiply/Out


-to FFB/D  ;


注意电路图中的from、through、to的对象





3、分频电路和多路时钟传输的时钟约束


下面的电路中包含了时钟分频电路和多路时钟传输电路:





(1)首先是多路时钟的传输问题



对于上图中的电路,其多路时钟传输电路的模型如下所示:




其内部电路的

时钟(Int_Clk)

连接到

多路输出电路的输出

,如果我们不告诉DC要用

Tst_Clk、Ext_Clk

中的哪一个时钟,DC会自己选择一个,这就可能出现DC选择不同的时钟做建立和保持的分析,因此我们必须

指定要用哪个时钟进行约束和分析

。例如对于下面的多路时钟传输电路:




可以使用的下面命令进行约束:



create_clock   Ext_Clk   -period   10 (=create_clock  -period   10  Ext_Clk )



create_ clock  Test_Clk  -period  100



set_dont_touch_network  [get_clocks Ext_Clk]



set_dont_touch_network  [get_clocks Test_ Clk]



#Allow DesignTime to use Ext_ Clk  for


timing analysis



set_disable_timing   CLOCK_GEN/U1


-from  a  -to  y


最后一行的命令(


set_disable_timing


)去掉了MUX从引脚a到引脚Y的时间弧((timing arc),这时DC认为它们没有时间关系,也就是,我们只指定使用

Ext_ Clk

这时钟进行分析建立时间和保持时间。

set_disable_timing

命令用起来很灵活,该命令有多个选项。我们可以用该命令

使设计中用到的库单元的时间弧(timing arc)无效



set_disable_timing

命令使当前设计中的通过指定单元,引脚或端口的时间无效(相当于断开)。

set_false_ path

在这里不起作用。我们已经定义了

Test_ Clk和Ext_ Clk为时钟

,从引脚a和b到引脚Y是一条理想的时钟路径,不受约束,因此

set_false_ path

命令不起作用。


除了使用

set_disable_timing

这条命令进行多路时钟传输的约束外,还有用

模式分析特征

(case analysis feature)进行约束,如下所示:



set_case_analysis   0  [get_pins  U1/sel]



或者



set_case_analysis   0  [get_ports  sel]


与命令

set_disable_timing

相比,命令

set_case_analysis

会增加DC的运行时间,但使用模式分析命令较简单。





2)接下来是分频电路



Design Compiler不能推导出分频时钟的波形。时钟信号可以通过任何的组合电路,但

中止于寄存器

。DC

并不知道寄存器的输出端为时钟信号或非时钟信号

。如下图所示:





Int_Clk



Ext_Clk

经过

二分频后

从寄存器

U2

的输出端口Q输出的时钟,但DC并不知道这是你的时钟信号,需要添加相应的约束,如下所示:



create_clock   -period  50  [get_ports  Ext_Clk] ;




create_generated_clock  -name  Int_Clk  -source [get_pins CLOCK_GEN/U2/CP]   -divide_by  2  [get_pins  CLOCK_GEN/U2/Q] ;




set_clock_latency  -source  1. 5   [get_clocks   Int_Clk] ;



set_clock_latency   0.5  [get_clocks  Int_Clk] ;



create_generated_clock

这条命令会将

时钟源(Ext_Clk)

的任何变化自动反映在

产生的时钟(Int_Clk)

上。


做完版图后的设计已经加入了时钟树,连线的寄生参数也被反标(back-annotated)到时钟树上。这时候,DC用

set_propagated_clock

命令和时钟树的实际寄生参数自动地计算所有时钟引脚的延迟。我们不需用

set_clock_latency

命令为时钟建模。约束改成:



create_clock   -period  50  [get_ports  Ext_Clk] ;




create_generated_clock  -name  Int_Clk  -source [get_pins CLOCK_GEN/U2/CP]   -divide_by  2  [get_pins  CLOCK_GEN/U2/Q] ;




set_propagated_clock  [list  [all_clocks]  [get_generated_clock  *]]



(3)多时钟发送/接收


前面分别讲了多路时钟传输和分频的约束,也就把

下面电路图中的阴影部分单独拿出来进行约束

;将下来,将为下面的电路进行多时钟发送/接收问题

(DES_B模块和DES_A模块之间存在数据的发送和接收

)进行约束:




假设我们使用的

Ext_Clk

的时钟,其周期是50ns。模块B与模块A的时钟是有周期关系的,单单看模块A和模块B,就是多时钟同步设计的问题了,对于整个模块也就是(TOP_LEVEL),可以使用下面的约束:



create_clock   -period    50   -waveform   {0  25}  Ext_Clk



create_clock   -period   100   -waveform   {0  50}  Int Clk



set_clock_latency  -source  1. 5   [get_clocks   Int_Clk] ;



set_clock_latency   0.5  [get_clocks  Int_Clk] ;





4、实战


这次的实战和以前的实战不一样,这次的实战不再是从RTL源文件开始,而是从一个被约束过的、综合过的文件,也就是经过映射后的.ddc文件,通过对编译后的设计进行合适的约束,使得设计满足设计要求。


我们先来看一下我们要进行约束的部分RTL原理图:




这个设计包含了纯组合逻辑、时序逻辑、多路选择器导致的伪路径。组合和逻辑和时序逻辑具有不同的约束,实验初始的约束不当,有设计违规;我们需要进行合适的约束,从而消除设计违规。





启动DC,读入.ddc设计,进行读入设计后的检查


这步骤跟前面的章节类似,不再进行叙述,需要注意的是,因为需要读入.ddc设计,因此使用的命令是read_ddc






查看综合后原始的违规情况:




可以知道有违规情况。



③进行合理地约束:


最初的约束不符合情况,因此在这里我们进行合适的约束(或者说重新进行约束)。


—>约束组合逻辑:


我们根据下面的原理图进行约束:




·对于组合逻辑,一方面,组合逻辑的具有6ns的最大延时;另一方面,由于组合逻辑没有时钟输入端口,因此需要创建虚拟时钟,因此第一步对组合逻辑的约束如下:



create_clock -name vclk -period 6



set in_ports [get_ports “coeff* adr_i*”]



set_input_delay  0 -clock vclk -add_delay $in_ports



set_output_delay 0 -clock vclk -add_delay [all_outputs]


·我们可以查看约束后的虚拟时钟的路径情况:




可以看到,设计依旧违规了,这是由于多路选择器的原因,clk和虚拟时钟vclk进行交叠了;因此我们要在逻辑路径上设置伪路径,禁止这些时钟进行时序分析:



set_clock_group -name false_grp1 -logically_exclusive


-group clk -group vclk


设置完成之后,vclk不违规了。


·组合逻辑并没有约束完成,虚拟时钟vclk虽然不违规,但是clk违规了,对于组合逻辑,clk并没有起到作用,因此还需要禁止clk对组合逻辑的输入到输出进行时序分析:



set_false_path -from [get_clocks clk]


-through $in_ports


-through [all_outputs] -to [get_clocks clk]


注意,约束使用了两个“through”选项,把clk到clk的组合路径,从clk到clk的时序路径中分离出来;约束完成之后,我们可以查看一下对于组合逻辑的输入输出路径,clk的分析情况:



report_timing -from $in_ports -to [all_outputs]


结果是通过的。



—>约束多周期路径


约束完组合路径,我们就要进行约束时序逻辑路径了。时序逻辑路径是由clk控制的,我们先来看一下clk的时序路径报告:



report_timing -group clk


得到的结果是违规的,这是因为时序逻辑路径中存在多周期路径,在原理图上,mul_result_reg是多周期路径,因此需要进行设置多周期路径约束:



·建立时间的多周期约束:



set_multicycle_path




2




-setup




-to




mul_result_reg*/D


也就是设置这条路径是2个周期的路径;约束完成之后,我们可以查看是否正确约束:



report_timing -to mul_result_reg*/D


可以看到,建立时间的约束满足了,没有违规


·保持时间的多周期约束:


我们查看保持时间是否违规:



report_timing -to mul_result_reg*/D -delay min


可以看到,保持时间是违规的,因此我们要进行保持时间的多周期路径约束:



set_multicycle_path 1 -hold -to mul_result_reg*/D


再次查看之后,我们可以看到,保持时间没有违规了。



基于上面的原理图的各个约束都进行了合适的修改,主要是单独约束组合逻辑、设置虚假路径和设置(时序逻辑的)多周期路径这三个方面。


由于这是因为约束不当而引起综合后的违规,当设置了正当的约束之后,违规就消除了,我们也不必再进行综合了,实战步骤到这里就结束了。