相关阅读
Tcl语言https://blog.csdn.net/weixin_45791458/category_12488978.html?spm=1001.2014.3001.5482
有时候,复杂的设计需要多个时钟来完成相应的操作,当设计中有多个时钟存在时,它们需要相互协作或各司其职。有几种时钟可能由其他时钟而派生或者说生成,在定义这些时钟时需要使用创建生成时钟命令create_generated_clock。这类时钟可能是时钟分频器,时钟倍频器和时钟门控。
时钟分频器
时钟分频器产生一个比原始时钟频率更低(周期更长)的时钟信号。典型的时钟分频器是由多个T触发器串联构成的异步计数器。异步计数器的电路如图1所示,产生的时钟波形如图2所示。对于该电路,如果输入的时钟周期是10ns,则在clk_1的时钟周期是20ns,clk_2的时钟周期是40ns。
图1 异步计数器
图2 分频器电路时钟波形
时钟倍频器
时钟倍频器是一种通过增加时钟频率来获得更快时钟速度的电路。这种技术通常用于微处理器和内部总线,并配合内部高速缓存以提高处理器的吞吐量。图3给出了一个简单的时钟倍频器电路,电路利用延迟的时钟和原时钟异或产生更高的时钟频率,延迟可以使用反相器或缓冲器得到,产生的时钟波形如图4所示。在一般情况下,通过PLL锁相环实现时钟倍频。
图3 简单的时钟倍频器
图4 倍频器电路时钟波形
时钟门控
自20世纪90年代中期以来,时钟门控成为了一种非常流行的减少功耗的技术。当触发器或寄存器因时钟触发而翻转时,会产生一定的动态功耗。然而,某些情况下,部分电路在特定时间无需工作,此时禁用这些电路的时钟可以减少不必要的功耗,这称为时钟门控。图5给出了门控时钟的一个简单实现,更复杂的实现可以参考以往的文章。
图5 门控时钟
创建生成时钟指令的BNF范式
SDC指令中用于创建生成时钟的命令是create_generated_clock。该指令的BNF为:
create_generated_clock
[-name clock_name]
[-add]
[-master_clock clock]
[-divide_by divide_factor | -multiply_by multiply_factor]
[-duty_cycle percent]
[-invert]
[-preinvert]
[-edges edge_list]
[-edge_shift edge_shift_list]
[-combinational]
[-comment comment_string]
source_objects
-source master_pin
标识生成时钟源
就像create_clock指令一样,创建一个生成时钟同样需要它的时钟源对象,简单来说就是生成时钟生成的位置,源对象可以是一个端口(port)或者是一个引脚(pin)。一个生成时钟可能有多个时钟源,当然一个时钟源上也可能有多个生成时钟。
指定生成时钟的源引脚
指定生成时钟的源引脚可以使用-source选项。这个选项指明生成时钟是由哪个引脚或端口上的时钟派生的,这个原时钟被称为master clock(注意,这里不一定要原时钟的源对象是该引脚或端口,只需要master clock时钟能传播至该引脚或端口即可)。例如,在图1中,可以定义两个生成时钟,生成时钟源对象分别为clk_1和clk_2,源引脚则定义为clk,或者也可以是clk_1_reg/CK(如果已在clk定义了时钟,则会传播至clk_1_reg/CK)。
在这里需要搞清楚,生成时钟源对象和生成时钟源引脚的区别,生成时钟源对象指的是生成时钟定义在哪个位置,而生成时钟源引脚指明了哪个是获得生成时钟的原时钟。
如果一个引脚或端口上有多个时钟传播至此,则无法推断出生成时钟属于哪个master clock,需要显式指明。这可以使用-master_clock选项实现,只需指定参数为master_clock的名字即可。在创建了生成时钟后,开发工具将基于master_clock的属性派生生成时钟的属性(如波形、周期等)。
在这里有必要说明一下,定义生成时钟的必要性。有人可能会认为,根据master_clock定义生成时钟是不必要的,可以让开发工具自行推断出最后生成的时钟而不去单独创建。但这是错误的,比如对于图1的分频器,如果只在clk处定义了时钟,开发工具不会认为clk_1和clk_2处生成的是时钟信号,因为所有时钟信号在传播到触发器的时钟端后即终止传播,如图6的时钟树报告所示,故不能用clk_1和clk_2信号去触发后面的触发器,这导致了后面的触发器是无约束的。此时可以在clk_1和clk_2上定义生成时钟,来约束分频时钟控制的触发器。
图6 时钟树报告
生成时钟命名
和普通的时钟一样,每一个生成时钟对象的创建都会给生成时钟命名,使用-name选项可以指定一个生成时钟名,当没有使用选项指定时,默认使用生成时钟源名作为生成时钟名。在有些情况下,-name选项是必须的,比如当使用了-add选项时,关于这点,将在后面进行介绍。
设定生成时钟特性
设定生成时钟的特性可利用以下三个选项当中的一个:
- -edges——选项的参数一个列表,指明了生成时钟的边沿是如何与master_clock的边沿对齐的。列表中的第一个数表示生成时钟的第一个上升沿对应master clock的第几个沿(master clock沿编号是从左到右,不包括0ns时默认的下降沿,从1开始依次增加的),第二个数表示生成时钟的下一个下降沿对应master clock的第几个沿,第三个数表示生成时钟的第二个上升沿对应master clock的第几个沿。列表中需要至少有三个数表示一个完整的周期(上升沿-下降沿-上升沿)。
- -divide by——选项的参数是一个除法因子,表示分频倍数,周期通过这个因子翻倍。
- -multiply_by——选项的参数是一个乘法因子,表示倍频倍数,周期要除以这个因子。
需要注意的是,尽管时钟是通过周期来定义的,但divide by和multiply_by是针对频率而言的。
总的来说,任何使用-divide_by或multiply_by选项来表示的生成时钟,也可以使用-edges来表示,反之则未必正确。参考图1,假设在clk处定义时钟,在clk_1和clk_2上定义生成时钟。
create_clock -period 10 -waveform {10 15} [get_port clk]
create_generated_clock -source [get_port clk]
-divide_by 2 [get_port clk_1]
create_generated_clock -source [get_port clk]
-divide_by 4 [get_port clk_2]
#下面的形式也可以,即其中一种生成时钟的master_clock是另一个生成时钟
create_generated_clock -source [get_port clk]
-divide_by 2 [get_port clk_1]
create_generated_clock -source [get_port clk_1]
-divide_by 2 [get_port clk_2]
#使用-edges也可以
create_generated_clock -source [get_port clk]
-edges {1 3 5} [get_port clk_1]
create_generated_clock -source [get_port clk]
-edges {1 5 9} [get_port clk_2]
create_generated_clock -source [get_port clk]
-edges {1 3 5} [get_port clk_1]
create_generated_clock -source [get_port clk_1]
-edges {1 3 5} [get_port clk_2]
假设使用第一种方法创建了生成时钟,可以使用report_clock报告设计中的各个时钟的情况,如图7所示,可以看到使用-divide_by生成的时钟的第一个上升沿与master clock的第一个上升沿是对齐的,如果使用-edges则没有此要求,生成的时钟的第一个上升沿可以与master clock的任何一个沿对齐。
图7 时钟报告
如果生成的时钟需要取反,可以利用-invert选项完成该项功能,如下所示。但需要注意的是,这个选项可能会翻转t=0ns时的下降沿,也可能在翻转后的首个上升沿前添加其他沿,比如当你翻转一个waveform是{5 10},周期为10的时钟或翻转一个waveform是{11 12},周期为10的时钟时。
create_generated_clock -source [get_port clk]
-divide_by 2 -invert -name clk_n
对于使用-divide by的生成时钟,除了周期有相应改变外,其他性质有什么变化呢?前面其实已经谈到了一个,使用-divide by分频得到的生成时钟的第一个上升沿与master clock的第一个上升沿对齐。对于其他上升下降沿,Design Compiler的处理方式是将周期平均分给所有的上下脉冲,也就是说,无法保证占空比与分频前一致,具体如下例所示。
#定义了一个复杂的时钟波形
create_clock -period 20 -waveform { 2 5 12 15} [get_port clk]
#根据这个时钟使用-divide_by创建分频时钟,结果如图8所示
create_generated_clock -source [get_port clk] -divide_by 2 [get_port clk_0]
图8 上升沿对齐,周期在上下脉冲间均分
对于使用-multiply_by的生成时钟,无法保证倍频得到的生成时钟的第一个上升沿与master clock的第一个上升沿对齐。Design Compiler的处理方式是将所有沿的出现时间除以倍频因子,这样能保证所有脉冲占空比与之前相同,具体如下例所示。
#定义了一个复杂的时钟波形
create_clock -period 20 -waveform { 2 5 12 15} [get_port clk]
#根据这个时钟使用-multiply_by创建分频时钟,结果如图9所示
create_generated_clock -source [get_port clk] -multiply_by 2 [get_port clk_0]
图9 倍频之后的waveform相当于之前的waveform除以倍频因子