概述
本文转载IC_learner - 博客园http://www.cnblogs.com/IClearner/
数字IC之路-SDC篇(一):基本的时序路径约束_u012675910的博客-CSDN博客_sdc约束本文转载自IC_learner的博客,转载请标明出处 http://www.cnblogs.com/IClearner/时序约束可以很复杂,这里我们先介绍基本的时序路径约束,复杂的时序约束我们将在后面进行介绍。在本节的主要内容如下所示:·时序路径和关键路径的介绍 ·建立时间、保持时间简述 ·时钟的约束(寄存器-寄存器之间的路径约束) ·输入延时的约束 ·输出延...https://blog.csdn.net/u012675910/article/details/89917167
RTL代码描述了电路的时序逻辑和组合逻辑,即RTL代码体现了电路的寄存器结构和数目、电路的拓扑结构、寄存器之间的组合逻辑功能以及寄存器与I/O端口之间的组合逻辑功能。但代码中并不包括电路的时间(路径的延时)和电路面积(门数)。综合工具现在不能很好地支持异步电路,甚至不支持异步电路,因此时序路径的约束主要是针对同步电路的,关于异步的电路的约束,后面也会进行相关的说明。
1. 时序路径与关键路径
时序路径是一个点到点的数据通路, 数据沿着时序路径进行传递。每条时序路径有一个起点(Startpoint)和一个终点(Endpoint)。
起点定义为:
· 输入端口;
· 触发器或寄存器的时钟引脚。
终点定义为:
· 输出端口;
· 时序器件的除时钟引脚外的所有输人引脚。
这样, 时序路径可以是输入端口到寄存器、 寄存器到寄存器、 寄存器到输出端口、 输入端口到输出端口。如下面这个电路中:
4条路径:
1:从输入端口A到FF1的D端;
2:从FF1的CLK端到FF2的D端;
3:从FF2的CLK端到输出端口out1;
4:从输入端口A到输出端口out1。
路径1、2、3、4都存在有延时,延时最长的一条路径称为关键路径。一般情况下,路径1、2、3是最常见的,路径4比较少见。
2. 路径2(寄存器到寄存器之间的路径)的约束:
我们先从寄存器到寄存器之间的路径2开始;前面说到了,为什么要约束时序路径,是为了满足寄存器的建立时间和保持时间。对于路径2,数据从FF1的D端口传输到FF2的D端口,主要需要经历触发器的翻转时间/转换延时、寄存器与寄存器之间的组合逻辑延时、连线延时这些种延时。因为数据是随着时钟的节拍一拍一拍往后传的,因此这里的寄存器与寄存器之间的路径约束,就是对时钟的建模,或者是说对时钟的约束。下面进行说明:
为了满足FF2建立时间的要求,也就是数据经过上面的延时(触发器的翻转时间/转换延时、寄存器与寄存器之间的组合逻辑延时、连线延时)之后到达FF2的D端的时间再加上FF2的建立时间,需要要小于时钟周期;也就是说,你的那些延时不能过大,延时一旦过大,数据可能就不满足建立时间的关系,甚至还更新不了。举个例子说:
现在的节拍(0ns这一时刻)到来后,数据(比如说是一个高电平)从FF1的D端传来,经过组合逻辑,在下一个节拍(20ns这一时刻)的时候传到FF2的D端,更新FF2的数据(0ns时,FF2保存的是低电平),如红色箭头所示;但是由于延时太大,下一个节拍到来了(20ns到了),这个高电平还在还在组合逻辑那里,如绿色箭头所示,就导致了FF2的D端数据不能得到更新,或者不满足建立时间,由此可能引起锁存错误。当对时钟进行建模之后,拍长也就决定了,也就是那些延时(触发器的翻转时间/转换延时、寄存器与寄存器之间的组合逻辑延时、连线延时)最大是多少也就知道了,通过对时钟进行建模,也就是通过对寄存器与寄存之间的路径进行约束,DC就知道了这条路径运行的最大延时,就会选择合适的单元来满足这些延时的约束,如果DC选来选去,发现最牛逼的单元得到的电路延时还是很大,无法满足FF2的建立时间要求,DC就会报错。这个时候,你就要进行修改设计了(比如修改约束或者修改代码)。
为了满足FF2的保持时间,也就是数据经过上面的延时(触发器的翻转时间/转换延时、寄存器与寄存器之间的组合逻辑延时、连线延时)之后到达FF2的D端的时间,不能小于某个值。也就是说,这些延时也不能太小。举个极端的例子说,在0ns的时候,触发器有效沿到来,FF1和FF2都要更新下数据,FF1准备锁存高电平,FF2准备锁存低电平;由于FF1反应很快,电路延时很小,FF1寄存住的高电平很快就会传到FF2的D端口,高电平就会冲掉FF2要锁存的低电平(也就是FF2的D端口低电平还没有稳定,违反了保持时间),也就是说会导致低电平对FF2的保持时间不能得到满足,导致FF2更新数据失败,要锁存住的低电平可能就产生亚稳态。因此就有传输延时需要大于FF2的保持时间。此外,我们由此也可以知道,保持时间的分析比建立时间的分析提前一个时钟周期沿,也就是说在0ns时候传输数据,建立时间是在下一个时钟上升沿(20ns时刻)进行检查FF2的D端口数据是否稳定(若不稳定,就违反了建立时间),而保持时间是在发送数据的同一时刻(也就是0ns时刻)检查FF2的D端口数据是否稳定(如果不稳定,就违反了保持时间);关于保持时间的分析比建立时间的分析提前一个时钟周期沿这一点需要注意。
然而,保持时间一般是能够满足的,也就是传输延时一般是大于触发器的保持时间的,即使满足不了,在后端版图设计的时候,也可以有修改措施(比如路径加缓冲器增加延时)。因此我们在约束的时候,我们一般不关注保持时间,而是注重建立时间。
经过上面一大堆的废话,相信大家已经对这个约束过程有一定的了解了,下面进行概括一下,并进行时钟建模。
通过上面的讲解,我们知道,一般情况下,如果寄存器和寄存器之间组合电路的延迟大于Clock_cycle-Tsu(Clock_cycle是时钟周期,Tsu是触发器的建立时间),电路的功能会不正确,将不能正常工作。如果已知电路的时钟工作频率,就知道了寄存器和寄存器之间组合电路的最大时延,如下图所示
Tclk-Q是FF2的从引脚CLK到引脚Q的延时,Tsetup是FF3的建立时间,这两个参数都由工艺库提供。总结完成之后,下面对时钟进行建模,也就是寄存器到寄存器之间的路径进行约束,时钟的建模是比较复杂的,因此先一步一步地讲解,最后给出约束脚本。
定义时钟的命令为:create_clock。假设时钟周期为10ns,定义时钟的命令就是:
create_clock -period 10 [get_ports clk]
对于的时钟波形为:
定义时钟时(虚拟时钟除外,虚拟时钟在后面说),我们必须定义时钟周期(也就是-period这个选项)和时钟源(端口或引脚)(也就是设计中的clk),也可以加上一些可选项(option)来定义时钟的占空因数(duty cycle),偏移(offset/skew)和时钟名( clock name),我们可以通过man create_clock 来查看命令的相关选项。
一旦定义了时钟,对于寄存器之间的路径,我们已经做了约束。我们可以用report_clock命令来查看所定义的时钟以及其属性。如果我们需要使用时钟的两个沿(上升沿和下降沿),时钟的占空因数将影响时序的约束。
然而单单定义一个时钟周期进行约束寄存器与寄存器之间的路径很显然是过于理想的,需要再添加其他的时钟属性,在添加之前,需要知道时钟的偏移(skew)、抖动(jitter)、转换时间(transition)、延时(latency)这几个概念或者这几个时钟的属性:
①时钟的偏移(skew):时钟分支信号在到达寄存器的时钟端口过程中,都存在有线网等延时,由于延时,到达寄存器时钟端口的时钟信号存在有相位差,也就是不能保证每一个沿都对齐,这种差异称为时钟偏移(clock skew),也叫时钟偏斜。时钟的偏移如下图所示:
此外,时钟skew与时钟频率并没有直接关系,skew与时钟线的长度及被时钟线驱动的时序单元的负载电容、个数有关。
②时钟抖动(jitter):相对于理想时钟沿实际时钟存在不随时间积累的、时而超前、时而滞后的偏移称为时钟抖动,简称抖动,如下图所示:
时钟的抖动可以分为随机抖动(Random Jitter,简称Rj)和固有抖动(Deterministic jitter):
·随机抖动的来源为热噪声、Shot Noise和Flick Noise,与电子器件和半导体器件的电子和空穴特性有关,比如ECL工艺的PLL比TTL和CMOS工艺的PLL有更小的随机抖动;
固定抖动的来源为:开关电源噪声、串扰、电磁干扰等等,与电路的设计有关,可以通过优化设计来改善,比如选择合适的电源滤波方案、合理的PCB布局和布线。也就是说:jitter与时钟频率无直接关系。
时钟的偏移和时钟的抖动都影响着时钟网络分枝的延迟差异(相位差异),在Design Compiler里面,我们用时钟的不确定性(uncertainty)来表示这两种情况的影响(skew和jitter)。
③时钟的转换时间(transition) :时钟的上升沿跳变到下降沿或者时钟下降沿跳变到上升沿的时间,这个时间并不是如左下图所示那样完全没有跳变时钟的,而是像右下图那样,时钟沿的跳变时间就是时钟的转换时间(后面约束的时候会有相关的解释)
时钟的转换时间与与单元的延时时间(也就是器件特性)还有电容负载有关
④时钟的延时(latency) :时钟从时钟源(比如说晶振)出发到达触发器时钟端口的延时,称为时钟的延时,包含时钟源延迟(source latency)和时钟网络的延迟(network latency),如下图所示:
时钟源延迟(clock source latency),也称为插入延迟(insertion delay),是时钟信号从其实际时钟原点到设计中时钟定义点(时钟的输入引脚)的传输时间,上图是3ns。时钟网络的延迟( clock network latency)是时钟信号从其定义的点(端口或引脚)到寄存器时钟引脚的传输,经过缓冲器和连线产生的延迟(latency),上图是1ns。OK,时钟的附加的buff属性差不多就是这样了。
2.1 Design Compiler中的时钟约束
在默认的情况下,逻辑综合时,即使一个时钟要驱动很多寄存器,DC也不会在时钟的连线上加时钟缓冲器(clock buffer)以加强驱动能力,时钟输输入端直接连接到所有寄存器的时钟引脚,也就是说,对于高扇出(high fanout)的时钟连线,DC不会对它做设计规则的检查和优化,如下左图所示。在时钟连线上加上时钟缓冲器或作时钟树的综合(clock tree synthesis)一般由后端(back end)工具完成,后端工具根据整个设计的物理布局(placement)数据,进行时钟树的综合。加入时钟缓冲器后,使整个时钟树满足skew, latency和transition的目标。时钟树综合后的电路如下图所示:
在DC中利用create_cloclk、set_clock_uncertainty、set_clock_latency、set_clock_transition分别进行时钟的周期、偏移、延时、转换约束。
时钟偏差的建模
set_clock_uncertainty:对时钟的偏移和抖动进行建模,也就是对时钟的偏差进行建模,具体使用为:
假设时钟周期为10ns,时钟的建立偏差为0. 5ns,用下面命令来定义进行约束:
create_clock -period 10 [get_ports CLK]
set_ clock_ uncertainty -setup 0.5 [get_clocks CLK]
在默认的情况下,"set-clock_uncertainty”命令如果不加开关选项“-setup”或“-hold",那么该命令给时钟赋予相同的建立和保持偏差值。 这是一种对偏差建模的方式,也就是对建立时间和保持时间进行建模的方式;除此之外,还可以对时钟的上升沿和下降沿进行偏差建模,比如上升沿的偏差是0.2ns,下降沿的偏差是0.5ns,则有:
set_ clock_ uncertainty -rise 0.2 -fall 0.5 [get_clocks CLK]
一般情况下,我们只约束建立时间,也就是只用第一种方式进行时钟偏差建模。当对建立时间偏差建模之后,这时,时钟周期、时钟偏差和建立时间的关系如下图所示:
假设时钟周期是10ns,建立时间偏差是0.5ns,触发器的建立时间是0.2ns,这时候从图中就可以看到,留给寄存器间的路径的裕量就减少了,也就是说,对寄存器间的约束就变得更加严格了,寄存器的翻转延时、组合逻辑延时与线网延时等这些延时的和必须小于9.3ns,否则就违反了FF2的建立时间。这一点是要注意的。
对于保持时间,在未考虑时钟偏移之前,前面说了,组合逻辑的延时要大于触发器的保持时间(具体原因参考前面的描述),当对时钟偏差建模之后,这时,时钟周期、时钟偏差和保持时间的时序关系如下所示:
时钟转换时间的建模:
由于时钟并不是理想的方波,用set_ clock_ transition来模拟时钟的转换(transition)时间。默认的上升转换时间为从电压的20%上升至80%的时间,下降的转换时间为从电压的80%下降至20%的时间。如果set_clock_transition命令中不加开关选项“-setup”或“-hold" ,那么该命令给时钟赋予相同的上升和下降转换时间。一般情况下,我们只约束最大的转换时间,如最大转换时间是0.2ns,那么就加上-max选项:
set_clock_transition -max 0.2 [get_clocks CLK]
时钟延迟的建模
时钟从时钟源(比如说晶振)出发到达触发器时钟端口的延时,称为时钟的延时,包含时钟源延迟(source latency)和时钟网络的延迟(network latency)。我们使用set_clock_latency进行时钟延时的建模。一般情况下,我们把时钟源延迟(source latency)和时钟网络的延迟(network latency)分开来,因为时钟源延时需要建模,是因为DC是真的不知道这延时是多大,但是对于时钟网络的延迟,DC在布局布线前不知道,但是在布局布线后就可以计算出来时钟网络的延时了,因此在布局布线之后进行综合时,就没有必要对时钟网络进行延时,因此就要把这两个延时分开来进行约束。先说布局布线之前:时钟周期为10ns,时钟源到芯片的时钟端口时间是3ns,时钟端口都内部触发器的时间是1ns,如下图所示:
那么就用下面的命令进行建模:
create_clock -period 10 [get-ports CLK]
set_clock_latency -source 3 [get_clocks CLK]
set_clock_latency 1 [get_clocks CLK]
通常情况下,我们约束最大的延时,也就是加上-max的选项,表示最大延时是多少(如set_clock_latency -source -max 3 [get_clocks CLK] 就是时钟源到芯片时钟端口最大的时间是3ns)。布局布线之后:就可以计算实际的线网延时,就要使用
set_propagated_clock [ get_clocks CLK] 这个命令代替上面的
set_clock_latency 1 [get_clocks CLK]这个命令。
基本的时钟建模就OK了,下面进行总结并给出我们这个例子中使用的约束脚本,理想时钟和实际时钟的对比,如下图所示:
3. 路径1(输入端口到寄存器D端)的约束:
这里讨论的是模块前后使用的是同一个时钟CLK,如下图所示,至于使用不同的时钟(比如前面的模块是ClkA而不是Clk,那么约束就不一样了)放在后面说。
在上图中,在Clk时钟上升沿,通过外部电路的寄存器FF1发送数据经过输人端口A传输到要综合的电路,在下一个时钟的上升沿被内部寄存器FF2接收。它们之间的时序关系如下图所示:
对于我们要综合的模块,DC综合输入的组合逻辑,也就是上面的电路N,得到它的延时是Tn,但是这个Tn是否满足的要求(比如说满足触发器的建立时间)呢?在进行约束之前,DC是不知道的,因此我们通过约束这条路径,也就是告诉DC外部的延时(包括寄存器翻转延时和组合逻辑、线网的传输延时)是多少,比如说是Tclk-q+Tm,在约束了时钟之后,DC就会计算这条路径留给电路N的延时是多少,也就是Tclk-q+Tm。然后DC就拿Tclk -(Tclk-q+Tm)和Tn+Tsetup相比较,看Tclk -(Tclk-q+Tm)是否比Tn+Tsetup大,也就是看综合得到的电路N的延时Tn是不是过大,如果Tn太大,大于Tclk -(Tclk-q+Tm),那么DC就会进行优化,以减少延时。如果延时还是太大,DC就会报错。因此我们要进行输入端口的约束,告诉外部电路的延时是多少,以便DC约束输入的组合逻辑。
如果我们已知输入端口的外部电路的延迟(假设为4 ns,包括翻转延时和外部的逻辑延时),就可以很容易地计算出留给综合电路输入端到寄存器N的最大允许延迟:
DC中,用get_input_delay命令约束输人路径的延迟:
set_input_delay -max 4 -clock CLK [get_ports A]
我们指定外部逻辑用了多少时间,DC计算还有多少时间留给内部逻辑。在这条命令中,外部逻辑用了4 ns,对于时钟周期为10 ns的电路,内部逻辑的最大延迟为10 - 4 - Tsetup = 6 。也就是说DC根据最大6ns的时间余量进行布局布线,时序路径长度尽量保持在6ns一下。
输入延迟还可以分为系统同步和时钟同步:
CSDNhttps://mp.csdn.net/mp_blog/creation/editor/117925884
路径3(寄存器到输出端口)的约束:
clk时钟上升沿通过内部电路的寄存器FF2发送数据经要综合的电路S,到达输出端口B,在下一个时钟的上升沿被到达外部寄存器的FF2接收。他们之间的时序关系如下图所示,我们要要约束的的组合路径电路S的延时,要DC计算它的延时是否能够满足时序关系,就要告诉DC外部输出的延时大概是多少:
当我们已知外部电路的延迟(假设为5.4 ns),就可以很容易地计算出留给要综合电路输出端口的最大延迟,如下图所示:
我们指定外部逻辑用了多少时间,DC将会计算还有多少时间留给内部逻辑。举个例子说,对于下面的这个电路模型:
寄存器到输出端口的时序路径约束为:
create_clock -period 20 [get_ports Clk]
set_output_delay -max 7.0 -clock Clk [get_ports B]
DC要求我们对所有的时间路径作约束,而不应该在综合时还留有未加约束的路径。我们可以假设输人和输出的内部电路仅仅用了时钟周期的40%。如果设计中所有的模块都按这种假定设置对输人/输出进行约束,将还有20%时钟周期的时间作为富余量( Margin),富余量中包括寄存器FF1的延迟和FF2的建立时间,即:富余量=20%时钟周期 - Tclk-q - Tsetup,如下图所示:
对于前面的电路,就要按照这么一个比例进行设置:
对应的约束为:
create_clock -period 10 [get-ports CLK]
set_input_delay -max 6 -clock CLK [all_inputs]
remove_input_delay [get ports CLK] ;#时钟不需要输入延迟的约束
set_output_delay -max 6 -clock CLK [all-outputs]
如果设计中的模块以寄存器的输出进行划分,时间预算将变得较简单,如下图所示:
时间预算的约束为:
create_clock -period 10 [get-ports CLK]
set_input_delay -max $Tclk-q -clock CLK [all_inputs]
remove_input_delay [get ports CLK] ;#时钟不需要输入延迟的约束
set_output_delay -max [expr 10-$Tclk-q] -clock CLK [all-outputs]
最后
以上就是清脆翅膀为你收集整理的学习数字电路-时序约束的全部内容,希望文章能够帮你解决学习数字电路-时序约束所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复