欢迎使用优快云-markdown编辑器

本文详细介绍了DC工具在时序约束和综合优化方面的应用,包括时钟建模、输入输出延迟、负载预算、多时钟同步设计、异步时钟约束等,并探讨了静态时序分析、优化策略以及网表生成。通过实例解析了if、if-else、case语句在综合中的表现,为数字集成电路设计提供了深入理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 时钟为什么建模?

背景:

默认情况下,即使一个时钟要驱动很多寄存器,DC也不会在时钟连线上加clock buffer。Clock buffer 或时钟树,一般由后端工具完成。为了准确的描述时钟树,使综合结果与版图的结果匹配,需要为时钟树建模。

Set_clock_uncertainty、set_clock_latency 、set_clock_transtion

理想的时钟网络latency、skew、transition默认是零。时钟网络还是理想的,但是原来的零值,由这些命令中指定的值替代。

Set_clock_uncertainty ——模拟skew和jitte之和

set_clock_latency —— 模拟 时钟源延迟或连线延迟

set_clock_transtion —— 模式转换时间

2 说明两点

Set_clock_uncertainty —setup 0.5 给时钟赋予建立时间

Set_clock_transition —setup 给时钟赋予上升转换时间。

两个都有setup选项,但是不是一回事。

set_clock_latency –source :时钟源延迟,指时钟信号从其实际时钟原地到设计中时钟定义点的传输时间(P94会体会到)。

set_clock_latency : 时钟信号从其定义的点到寄存器时钟引脚的传输时间。

(1) Set_input_delay,和set_output_delay

是通过设置外部电路的延迟,来用时钟周期相减,计算留给内部要综合电路的做大延迟。

注意:1)设置的数值是外部的数值,

  2)最大延迟是,内部要综合电路的最大延迟

  3)只作用于同步电路,内部和外部时钟一致,而不适用于异步打拍的电路。

(2) 建立时间预算

背景:如果不知道外部输入延迟和外部输出的建立要求,则需要通过建立时间预算time budget,为输入/输出口设置约束。

一般假设:输入和输出的内部电路仅仅用了时钟的40%(即ts=tt=40%),还有20%富裕量包括tclkq+tsetp。

注:

1)因此需知道,通过time budget如何设置值?

设置值为60%Tperiod,也就是留给内部的Tn+Tsetup 只有40%。

2)如果模块划分,以寄存器输出进行划分,时间预算将变得简单。

但是实际中很少完全这样划分。

Set_input_delay –max clktoqclockCLKall_in_ex_clk

Set_output_delay –max [expr 10 - $clk_to_q] –clock CLOCK [all_outputs]

设置环境约束

目的:上面的set_input_delay是提供了约束,但要计算路径的延迟,才能知道和约束是否满足。

背景:为了保证输入/输出路径(除时钟外)延时约束的精确性,还需提供环境属性。

1) 输出端,电容负载

为了精确计算输出电路的时间,DC需要知道,输出单元驱动的总负载电容。

默认情况下,DC外部电容负载为0.

DC中用set_load: 说明输入或输出上外部电容负载。

   Load_of:   说明电容负载值为工艺库中某一单元引脚的负载。

2) 输入端,转换时间

为了精确计算输出电路的时间,DC需要知道,输入端口的转换时间transition。

Set_driving_cell 说明输入端口是由一个真实的外部单元驱动。

通过驱动,计算输入转换时间:

默认情况下,DC假设输入端口上外部型号转换时间为0. Set_driving_cell命令在输入端口上加上一个驱动单元,DC将计算输入信号的实际转换时间。

3) 负载预算(load budget)

背景:

模块划分时,设计者不知道输入端口的外部驱动单元或输出端口的负载,需要通过负载预算,设置环境约束。

负载预算规则:

  1. 保守起见,假设输入端口由驱动能力弱的单元驱动

  2. 限制每一个输入端口的输入电容(负载)

  3. 估算输出端口的驱动模块数目。

规则2,可以通过加限制性的设计规则做到,工艺库中设计规则分别是

”max_capacitance, max_transition, max_fanout”

 注:
  1. set_load不仅可,用于设置输出负载,也可用于设置输入负载

  2. max_capacitance ,限制每一个输入端口的输入电容(负载)

门延迟和连线延迟

门延迟采用非线性延迟模型。由输入转换时间和输出负载,查查门的延迟及输出转换时间,输出转换时间,又做下一级的输入转换时间。

连线延迟:由线负载模型估算。

  1. 线负载模型

根据扇出数fanout,估算连线长度,库中提供连线单位长度的电阻值R、电容值C和面积。根据这些值,DC计算连线的延迟。T=RC?

延迟如何算?

根据RC来计算延迟时间。

Set_wire_load_model和set_wire_load_mode区别:

Set_wire_load_model:连线的线负载模型

set_wire_load_mode:连线穿越不同层次边界时,选择的模式(enclosed或top)

多时钟同步设计的时钟约束

1) 虚拟时钟

背景:所有的时钟信号来自同一个时钟源,经过不同的分频电路产生。但在我们要综合的电路中,只有一个时钟端CLKC;但其它的时钟如CLKA、CLAB,用作外部电路,在要综合的电路中没有时钟端口,虽然是同步时钟,但是因为频率不同,主要用作输入/输出端口作约束,可能出现一个端口多个约束的情况(输出端口会出现)。这样将执行最严格的约束。

目的:

在多时钟同步设计中,要综合的电路只有CLKC端口,同步时钟CLKA、CLKB、CLKD

用在外部输入或外部输出,因此在综合的电路中不驱动任何寄存器,主要说明相对于时钟I/O端口的约束,因频率不同,DC根据这些约束执行最严格的约束。

方法:

虚拟时钟不驱动,要综合的寄存器,所以没有源端口,因为没有对应的时钟端口,必须给它取个名字。

Create_clock -period 20 -name CLKA 虚拟时钟

Create_clock -period 20 [get_ports CLKC]

Set_input_delay 5.5 -clock CLKA -max [get_ports IN1]

a) 为什么出现一个端口多个约束呢?

因为频率不同,画出时序图可知,会出现发射沿 到采样沿,出现2个不同的时间。

b) 输入/输出约束差异

Set_input_delay 、和set_output_delay是通过设置外部电路约束的值,来约束要综合电路的。

输入:

一个输入端口一般只有一个输入,不会出现多驱动;所以set_input_delay只有一个设置值。

输出:

一个输入会带多个负载,两个负载是不同频率的同步时钟时,就会出现set_out_delay有两个设置值。

异步时钟约束

对穿越异步路径的任何路径,必须禁止对这些路径作约束。不要浪费DC的时间,试图使异步路径满足时序要求。

Set_false_path –from [get ports CLKA] -to [get ports CLKC]

时序路径的终点:不是输出端口或寄存器的数据输入端口么?为什么这里是两个CLK.

复杂时序约束

1) 多时钟周期约束

Hold分析时间:

重点:默认的hold分析时间在setup分析时间的前一个周期。但是在多时钟周期中,没有意思,这样会增加电路的复杂度;因此我们需要对保持时间做调整,在0ns时做hold检查。

原因:因为是时序电路,在后级寄存器把数据采到寄存器时,前及寄存器的输出也可能会变化。

Create_clock -period 10 [get_ports CLK]

Set_multicycle_path –setup 6 –to [get_pins C_reg[*]/D]

Set_multicycle_path –hold 5 –to [get_pins C_reg[*]/D] 必不可以少

这里用-hod 5 代替了默认的-hod 0

-hold 5:表示在0ns做检查

-hold 0:表示在建立时间的前一个周期做hold检查

2) 门控时钟约束

门控电路分两种:基于锁存器的和不基于锁存器的门控时钟单元。

3) 多路传输电路(时钟上带mux)

内部时钟连接到mux输出,如果不告诉DC要用哪个时钟,DC会自己选择一个,可能会出现DC选择不同的时钟做建立和保持分析。

Create _clock ext_clk –period 10

Create _clock test_clk –period 10

Set_dont_touch_network [get_clocks ext_clk]

Set_dont_touch_network [get_clocks test_clk]

Set_disable_timing CLOCK_GEN/U1 -from a –to y

如何选择呢通过mux的时钟呢?

Set_false_path命令不起作用:因为从mux引脚a和b到mux输出y是一条理想的时钟路径,不受约束。

方法1) Set_disable_timing,使库单元的时间弧无效(相当于断开)

方法2)使用模式分析特征(case analysis feature)对电路进行约束.

     Set_case_analysis 0[get_pins U1/sel]

  或

     Set_case_analysis 0 [get_ports sel]

Set_case_analysis 会增加DC时间,但是使用简单。

4) 分频电路

时钟信号可以通过任何组合逻辑,但终止于寄存器。DC并不知道寄存器的输出是时钟信号还是非时钟信号。

Create_clock -period 50 [get_ports ext_clk]

Create_clock -name –int_clk –per 100 [get_pins CLOCK_GEN/U2/Q]

或Create_generate_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_clock int_clk] (注:这里的-source指的是从实际时钟输入,即输入port口ext_clk ,而不是int_clk.

Set_clock_latency 0.5 [get_clock int_clk]

  1. 设计规则

Set_max_capacitance输入端口的最大电容设置

注意:set_load 用于设置输入或输出口的外部负载。

输入端口的最大内部负载 = 输入驱动的Set_max_capacitance —set_load(输入端口)。

Set_load和set_max_fanout的差别?

散出负载和散出数目的差别?

输入口和输出口约束的差别?

Set_max_fanout 使用的是扇出负载,表示一个扇出负载值,而不是扇出数目。

a) 扇出数目的作用:

线负载模型根据连线的扇出数目,估算连线的电阻和电容,而计算连线的延迟。

扇出数目:单元的输出引脚与其它单元的输入引脚之间连接的数目。

b) 扇出负载的作用:

扇出负载值是附加在输入端口。表示单元输入引脚相对负载的数目,并不是一个真正的电容负载,无量纲。

Set_max_fanout 1.0 [all_input]

也可以在输出端口上指定扇出负载值。

例:一个内部单元驱动几个其它内部单元且同时驱动一个输出端口。Set_load命令指定那个输出端口的实际电容负载。DC综合时遵从驱动单元的最大电容设计原则,但该命令没有为驱动单元的扇出提供约束,在输出端口使用set_fanout_load(?不是set_max_fanout?)命令时,可以为输出端口建立额外的预期扇出负载模型,DC综合也会使内部驱动单元的最大扇出遵从设计规则。

一、 静态时序分析:

起点:

输入端口

寄存器的CLK脚

终点:

输出端口

时序器件除时钟外的所有输入引脚(包括rst、clr)

1) 路径分组:

根据控制它们终点时钟进行分组;不被时钟控制的路径被分为default路径组。

2)路径的延迟与起点的边沿有关。

DC步骤:

1) 设计分路径组

2) 每条路径计算2次延迟,一次起点为上升沿,一次起点为下降沿;

3) 在每个路径组里找出关键路径

4) 显示每个路径组的时间报告

二、 优化

1) 结构级的优化

结构级的优化:用共用子表达式来减少逻辑,在电路中加入中间变量和逻辑结构。

a) 设计结构的选择

b) 数据通路的优化

c) 共享共同的子表达式

d) 资源共享(少用算术运算符)算术运算资源共享的默认策略是约束驱动的。

最好在代码编写阶段注意,少用运算,多用mux。

结构优化命令:Set_structure true

2) 逻辑级的优化

e) 结构优化

结构级的优化:用共用子表达式来减少逻辑,在电路中加入中间变量和逻辑结构。

共用子表达式:结构级指算术电路的共用子表达式,逻辑级指门电路的,

f) 展平优化

指把组合逻辑减少为2级,变为乘积之和,即先与后或的电路。做速度优化,电路面积会很大。

Set_flatten ture –effort low |medium |high

3) 门级优化

门级优化会做组合功能和时序功能的映射。

包含4个步骤

延迟优化;

设计规则修整;

以时序为代价的设计规则修整;

面积优化

映射过程中,DC会检查电路是否满足设计规则的约束,如有违反之处,DC会插入一些buffer和修改电路的驱动能力进行设计规则的修整。

三、 优化策略

综合优化,会有很多违反设计约束和设计规则的地方,需要分析结果,采取适当的措施解决。

对大的问题,修改代码和约束,再编辑修改

对于小的问题,时序违反在时钟周期的10%~25%或更小,采用以下方式

1) 使用compile_ultra命令

为算术运算选择适当的宏单元;选择最好的数据通路;映射宽扇入以减少逻辑级数;逻辑复制;在关键路径自动取消层次划分

Set compile_ultra_ungroup_dw true 所有的层次会被取消。

2) 边界优化

传递常数和没连接的引脚

3) Behavior retiming(BRT)技术对门级网表优化

两个命令:

a) optimize_register 适用于包含寄存器 寄存器之间的冗余前移

b) pipeline_design 适用于纯组合逻辑 组合逻辑中插入寄存器改善时序

4) 适用compile –scan –inc命令

5) 适用自定义路径组合关键范围:即在综合脚本中进行路径分组

DC默认行为是为关键路径做优化,当不能找到更好的优化解决时,综合停止,DC不会对次关键路径做优化。

默认情况下,所有路径属于同样的时钟组。

Group_path –name INPUT –from [all_inputs]

Group_path –name OUTPUT –from [all_outputs]

Group_path –name COMNO –from [all_inputs] –to [all_outputs]

三个自定义的路径组,加上原有的路径组(寄存器到寄存器的路径组),共4个路径组。

问题:静态时序分析中指出路径组划分是,终点被控制的时钟来划分,不被时钟控制的被划分为默认路径组和这里的不是矛盾么?

四、 网表的生成格式和处理

完成综合和时序分析后,需要把设计和约束以某种格式存储好,作为后端工具的输入。

把设计存档时,需要去掉assign指令,该指令会使非synopsys的工具产生问题;此外要保证网表中没有特别字符。写出网表中的“\”,不同的工具会有不一样的理解。

多端口连线,即一条连线连接多个端口,会在网表中产生assign指令。如果设计中有多端口连线,应该在编辑过程中将它们去掉,使用如下命令:

Set_fix_multple_port_net –all -buffer_constants [get_design *]

Compile -incr

特别字符指字母、数字、下划线以外的任何字符,chang_names将设计中的特别字符取消。

1)模块之间输入和输出寄存问题

在ASIC芯片内部模块之间可以采用组合逻辑输入和输出,因为芯片内部的时延迟比较小(在不影响性能的情况下,采用寄存器锁存输入和输出会更好);对不同的ASIC芯片之间的输入和输出必行采用寄存器,因为芯片之间的板间时延往往比较大,如果不采用寄存器会大大增加后端实现的难度。

2)芯片的可测性设计

两种:串行扫描技术和内建自测BIST(build in self-test)

2) 同步时钟的FIFO

FIFO的结构:分为数据存储区及逻辑控制。

实现的两种方式:数据移动型(采用寄存器阵列实现的)和读写指针移动型(memroy)

基于存储器结构的:

当fifo为满时,fifo需要反馈回上游节点,通知上游节点停止发数据,在这个通讯过程中,上游节点可能还在发数据,这就需要预留几个数据存储单元。

寄存器阵列:ASIC中常用这种实现

特点:可以自由配置FIFO的宽度和深度

大的寄存器阵列将影响后端实现布局布线,所以采用寄存器阵列实现的,不宜实现深度很深的FIFO。

设计思想:

数据在相邻的cell之间移动达到先进先出的目的。首先实现FIFO中一个最基本的单元cell逻辑,根据深度和宽度,将最基本的单元cell进行编号,并串联起来组成所需要的规格。

当读操作时:fifo的第一个cell输出数据,并且后面的数据将依次向前移动一个cell;当写操作时,数据被写入fifo中空cell中编号最小的一个。读写操作可以同时进行,只需要一个周期完成读写操作。

基本单元cell的逻辑行为:

Cell控制逻辑需完成以下操作:

1) 根据读写控制信号及相邻cell的空满信号改变自身的空满信号。

2) 根据读写控制信号及相邻cell的空满信号控制cell中寄存器阵列中数据的读出和写入。

当同时对FIFO进行读写操作时,不改变当前cell的空满状态。

说明:先进先出原则

1) 因为读操作,从编号最小的cell中出,最左端要输入0;如果next_cell为空,左边的cell均为空。

2)写操作,写入编号最小的一个cell,如果last_cell为满,右边的cell均为满。

3)!next_cell_full &&cell_full 表示cell是编号最大的非空cell;Last_cell_full &&!cell _ full 表示cell是编号最小的空cell。

DC - 天涯 - yxwyangxinwei的博客

异步FIFO:

组成:基于memory和读写控制

空满标志的产生:

1)当读写地址相同的时,表示空或满。为区分,加一个标志bit位。当读写地址完全相同时,表示FIFO空;当低bit相同而最高bit不同时,表示FIFO满。

问题:异步fifo,不能采用寄存器阵列结构的么?

编码风格:思考

为什么要将时序和组合分开:感觉可以合并在一起的逻辑。

1) 是写的复杂?

2) 便于用case?而不用if_else? 条件复杂?

3) 便于组合逻辑。不能用太多的时序电路?

个人观点:

定义一些变量,这样代码清晰,否则条件判断上逻辑复杂,代码可读性差

BFM:

1)基于任务级的BFM:一般用于任务级的测试

2)基于状态机的BFM :适合系统级的,有多个总线

代码综合:

If、if-else、case比较

1) if结构

多种if是有优先级结构的,最后一个if的优先级最高。

原因:多重if中最后的条件优先级最高,因为是顺序执行的,同时满足条件时,前面的会被覆盖。

lf_elseif_else :还是认为有优先级

没有优先级结构,各个选择路径延迟相同,但是要多用与门(书上的说法)。从下面实际综合结构看,if—elseif_else 也是有优先级的,if的优先级最高,也没有多消耗与门,跟自己的想法一致。(可能是综合工具和工艺库不同)

Case:

Case 没有优先级,各个路径的延迟相同。这也许就是为什么

always @(*)

begin

z=0;

if(sel[0]) z=a;

if(sel[1]) z=b;

if(sel[2]) z=c;

if(sel[3]) z=d; //优先级最高

end

always @(*)

begin

z=0;

if(sel[0]) z=a; //优先级最高

else if(sel[1]) z=b;

else if(sel[2]) z=c;

else if(sel[3]) z=d;

end

always @(*)

begin

case(sel)

4’b0001 : z=a;

4’b0010 : z=b;

4’b0100 : z=c;

4’b1000 : z=d;

default : z=0;

endcase

end

上面三种方式综合后门电路如图:

If—if结构

DC - 天涯 - yxwyangxinwei的博客

If_else结构

DC - 天涯 - yxwyangxinwei的博客

书上说的的if_else结构如下,这种mux不是最终的门级结构,

Case结构

DC - 天涯 - yxwyangxinwei的博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值