asic设计流程

本文为《高级asic芯片综合》的阅读笔记

整体流程

主要流程为:

  1. RTL实现
  2. 动态仿真
  3. 约束、综合和扫描插入: 提供单元库和时序约束生成门级网表的过程。此外结合DFT还可以插入BIST、JTAG等测试部件
  4. 形式验证: 验证RTL与门级网表的等价性。
  5. 静态时序分析: 使用PrimeTime进行静态时序分析
  6. 布局、布线和验证: 通过布图规划(floorplan)根据时序约束放置单元,然后插入时钟树。这一阶段将反复迭代直至满足时序需求,并且在下单(tape-out)前还需要进行LVS(版图对原理图)和DRC(设计规则检查)
  7. 工程改变命令(ECO): 这是正常设计流程中的意外,当布局布线完成之后,如果此时测试发现错误,可以只将受影响的部分修改,它需要修改金属层的布线,因此这一过程称为金属掩模改变。

tcl基础

置换与赋值

赋值与输出命令: set、puts

置换:分为变量置换、命令置换、反斜杠置换

1
2
3
set y $x + 1 // 变量置换
set y [expr $x + 1] // 命令置换
set msg multiple\ space // 反斜杠置换

在双引号与花括号中特殊字符不做处理

1
2
3
4
// 双引号中还是会进行变量置换
set y "$x add" // 100 add
// 花括号所有特殊字符都不进行处理
set y {/n$x [expr 10+100]} // /n$x [expr 10+100]

数组

使用 花括号可以得到一个数组。此外还有一些内置函数处理数组

命令 功能
concat 合并数组
lindex 选取数组中的某一个元素
llength 数组长度
lappend 在尾端添加元素
lsort 排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set list1 {bufx1 bufx2 bufx4} 
set list2 {ivtxl ivtx2 ivtx4}

set l [list Hello World] # 通过list命令设置列表

concat $list1 $list2
#输出结果为bufx1 bufx2 bufx4 ivtxl ivtx2 ivtx4
llength $list1 #输出结果为3
llength [concat $list1 $list2] #输出结果为6
lindex $list1 1 #输出结果为bufx2
lindex $list1 [expr [llength $list1] - 1] #输出结果为bufx4
lappend list1 bufx5 #输出结果为bufx1 bufx2 bufx4 bufx5
set list3 {4 1 2 3 2 1}
lsort -real $list3 #按数字大小排序,输出结果为1 1 2 2 3 4
lsort -unique $list3 #按唯一性输出1 2 3 4

控制流

分支

1
2
3
4
5
6
7
if { $x > 0} { // {需要和if在同一行
...
} elseif { $x == 1 } {

} else {

}

循环

1
2
3
4
5
6
7
8
9
10
11
foreach i $list1 {
puts $i
}

while { $i > 0 } {
lindex $list1 i
}

for {set i 3}{$i > 0}{incr i -1} {
puts $i
}

函数

1
2
3
proc proc_name {argument} {
return return_value
}

synopsys tcl常用语句

获得实例

1
2
3
4
5
6
7
get_ports 端口名称
get_cells 单元名称
get_nets 网表名称
get_pins 管脚名称

可以使用*通配
get_ports I* # 返回所有以I开头的端口名称


属性获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14

get_attribute [get_cells 单元名] ref_name
#单元对象 的 ref_name 属性:用来保存其映射到参考单元的名称

get_attribute [get_nets 网表名] full_name
#网表对象 的 full_name 属性:用于保存网表名称

get_attribute [get_pins 单元/引脚] owner_net
#引脚对象 的 owner_net 属性:用来保存与之相连的网表名称

get_attribute [get_ports 单元名] direction
#端口对象 的 direction 属性:用来保存端口的方向


综合

综合即将RTL代码转化为门级网表的过程,它包含转换(translate)、优化(optimization)、映射(mapping)三个过程。其中转换为RTL转换为GTECH网表,映射将GTECTH网表转换为门级网表。

综合通常使用Design Compiler或Physical Compiler,PhyC除了包含DC的所有功能外,还提供了根据设计的时序和面积约束优化放置单元的能力。

当运行DC时,首先将执行.synopsys_dc.setup文件。这个文件中通常包含以下命令

1
2
3
4
5
set search_path [list . ./library/std_cells ./include_path]
set target_library [list std_cells_lib.db]
set physical_library [list std_cells_lib.pdb]
set link_library [list {*} std_cells_lib.db]
set symbol_library [list std_cells_lib.sdb]
  • search_path: 库文件及include文件的搜索路径
  • target_library: 工艺库,映射时所需的库
  • link_library: 链接库,包含工艺库及一些其他的宏单元(RAM、ROM等)
  • physical_library: 物理库,后端使用
  • symbol_library: 符号库,单元的图形化显示,在图形化界面中使用

库的结构

库分为逻辑库和物理库,逻辑库中包含引脚到引脚的时序、面积、引脚类型和功耗等信息。逻辑库是一个文本文件(.lib),通过Library Compiler编译后生成”.db”文件供DC使用。

逻辑库包含如下信息:

  • 库类
  • 库级属性
  • 环境描述
  • 单元描述

库类

库类指定库名,里面包含库的描述

1
2
3
library (ex25) {
<library description>
}

库级属性

库级属性包含了库的特征信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
library (ex25) {
technology(cmos);
delay_model: table_lookup;
date: "Feb 29,2000";
revision: "1.0";
current_unit: "1A";
time_unit: "1ns";
voltage_unit: "1V";
pulling_resistance_unit: "1kohm";
capactive_load_unit (1.0, pf);
default_inout_pin_cap: 1.5;
default_input_pin_cap: 1.0;
default_output_pin_cap: 0.0;
default_max_fanout: 10.0;
default_max_transition: 3.0;
default_operating_conditions: NOMINAL;
in_place_swap_mode: match_footprint;
}

环境描述

对温度、电压、工艺的偏差建模。还包括用于估算连线延迟的线载模型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 比例因子k,对标准温度电压,工艺等的缩放
k_process_fall_transition: 1.0;
k_process_rise_transition: 1.2;
k_process_fall_propagation: 0.4;
...

// 工作条件,指定温度、电压、工艺及RC树模型

operating_conditions (WORST) {
process: 1.3;
temperature: 100.0;
voltage: 2.75;
tree_type: worst_case_tree;
}
operating_conditions (NOMINAL) {
process: 1.0;
temperature: 25.0;
voltage: 3.00;
tree_type: balanced_tree;
}

// 线载模型,包括一些用于估计互联线延迟的信息

wire_load (SMALL) {
resistance: 0.2; // 单位长度互联线的电阻
capacitance: 1.0; // 单位长度互联线的电容
area: 0;
slope: 0.5;
fanout_length (1, 0.02); // 扇出相关的连线长度值
fanout_length (2, 0.042);
fanout_length (3, 0.064);
...
fanout_length (1000, 20);
}

tree_type定义了环境互联模型,DC在计算互联延迟时会使用合适的公式。worst_case_tree是负载引脚在距离驱动最远的连线端的极端情况进行建模。这种情况下负载引脚承受整个连线的电容和电阻。base_case_tree中负载引脚只承受连线电容而没有电阻。电阻会减慢速度。

单元描述

单元包括功能、面积、端口、时序等信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cell(BUFFD0) {
area: 5.0;
pin (Z) {
max_capacitance: 2.2;
max_fanout: 4.0;
function: "I";
direction: output;
timing() {
...
}
related_pin: "I";
}
}
pin(I) {
direction: input;
capacitance: 0.04;
fanout_load: 2.0;
max_transition: 1.5;
}

被驱动单元的每个输入引脚的所有fanout_load值的总和不能超出驱动器引脚输出的max_fanout。例如一个BUFFD0(max_fanout=4)最多驱动两个同类单元(fanout_load=2)

max_transition通常用于输入引脚。他指定任何转换时间大于max_transition的连线不能连接到该引脚。max_capacitance通常用于输出引脚。他指定任何总电容大于max_capacitance的连线不能连接该引脚。

延时计算

Synopsys支持一些延迟模型,包括CMOS通用延迟模型,CMOS分段线性延迟模型和CMOS非线性查表模型(NLDM)。前两种不能有效表示VDSM几何尺寸引起的真实延迟,目前通常使用NLDM模型。

NLDM模型使用转换时间和输出负载电容来决定一个单元的延时。
进行延时计算需要用到输入转换时间和输出电容负载。输入转换时间要以前一单元转换延迟为基础,并且需要用最坏转换时间进行估算。

一般在最大延迟环境检查建立时间,在最小延迟环境检查保持时间

如图所示U2的输入转换时间将使用reset的转换时间(2ns)。如果不想用reset的转换时间,可以使用set_disable_timing U1 -from A -to Z排除。

输入

可以使用两类命令读取RTL文件

  • read
  • analyze/elaborate

Synopsys最初使用read命令,他无法传递参数也无法保存中间结果。analyze将分析文件并将中间结果存储于work目录下。elaborate利用中间文件生成对应的模块。

如果想要在综合时屏蔽某些代码,可以使用//synopsys translate_off关闭转换,然后再使用//synopsys translate_on开启。

约束

通过对面积、时序等信息进行约束,DC可以利用这些信息进行优化使其符合设计规范。

  • set_min_library: 用于指定最坏和最佳情况的库
  • set_operating_conditions: 描述设计的PVT,通常使用WORST,TYPICAL,BEST描述。例如set_opearting_conditions -min BEST -max WORST
  • set_wire_load_model: 设置线载模型,在工艺库中通常有许多线载模型,例如set_wire_load_model -name MEDIUM
  • set_drive: 指定输入端口的驱动强度。例如set_drive 0 {CLK RST}
  • set_load: 设置电容负载。set_load 1.5 [all_outputs]

时序相关命令:

  • create_clock: 定义时钟.create_clock -period 40 -waveform [list 0 20] CLK
  • create_generated_clcok: 分频时钟.create_generated_clock -name CLK_DIV2 -source CLK -divide_by 2
  • set_dont_touch_network: 用于时钟网络或复位,在进行优化时,不会对原有器件替换
  • set_ideal_network: 0转换时间,0延时,所有cell和net都有dont_touch属性
  • set_input_delay: 指定输入信号的延时,例如一个30ns周期的时钟,使用set_input_delay -max 23 -min 2 -clock CLK {datain}。那么在[2,23]内数据是不稳定的。因此保持时间最多为2,建立时间最多为7
  • set_output_delay: 输出端口定义在时钟边沿到来之前数据有效所需时间。set_output_delay -max 19.0 -clock CLK {dataout}.
  • set_clock_latency: 时钟网络插入延迟.set_clock latency 3.0 [get_clocks CLK]
  • set_clock_uncertainty: 时钟抖动偏移等信息.set_clock_uncertainty -setup 0.5 -hold 0.25 [get_clocks CLK]
  • set_false_path: 忽略某一路径的时序。例如一些异步路径
  • set_multicycle_path: 设定多周期路径
  • group_path: 用于将时序关键路径绑定到一起计算,使得该组合路径优先于其他路径。

优化

优化的目标是使得面积最小并最大化速度,默认的优化优先级为时序>面积。

编译命令:

1
2
3
4
5
6
7
8
9
10
compile -map_effort <low | medium | high>
-area_effort <none | low | medium | high>
-power_effort <none | low | medium | high>
-incremental_mapping
-ungroup_all
-boundary_optimization
-gate_clock
-in_place
-no_design_rule | -only_design_rule
-scan

map_effort表示在构建和映射上所消耗的时间。默认为medium, 如果约束无法满足可以调为high。scan表示添加可测性测试。gate_clock表示添加门控时钟

展平和构造

展平可以减少组合逻辑的层次,主要用于优化算数电路,并不是减少模块层次的含义。
这一选项默认未开启,可以使用set_flatten true开启展平,这种方式会增加面积。

构造是根据指定的规则优化,他通过分解中间变量使得逻辑共享,从而减少面积。例如

1
2
3
4
5
6
7
构造前:
P = ax + ay + c
Q = x + y + z
构造后:
P = aI + c
Q = I + z
I = x + y

然而通过构造会使得扇出增加,并可能增加线延迟,从而影响时序。构造分为两种: 时序(默认开启)和布尔优化,布尔优化可以有效减小面积,但会对时序造成更大影响。布尔优化适用于非关键时序,开启命令为set_structure -boolean true

消除层次

在默认情况下,DC综合时保持原有层次,也就是有许多模块。层次实际上是一个逻辑边界,它防止DC跨边界优化。因此可以将所有模块进行合并,从而使得DC可以更好的进行优化。优化命令为ungroup -flatten -all

在消除层次之后,变量名称发生改变,这会给时序检查带来麻烦。

命名优化

为了在布图时进行时钟树综合,必须唯一化DC中的网表。因此需要对设计中多次例化的子模块生成唯一的模块定义。使用uniquify命令可以完成这一操作。

而verilog网表中可能存在一些特殊名称的线网。例如,DC中会产生以”*cell*“或”-return”结尾的信号名。因此需要规范化命名。

1
2
3
4
5
define_name_rules BORG -allowed {A-Za-z0-9_} \
-first_restricted "0-9_\[]"
-max_length 30
-map {{"*cell*", "mycell"}, {"*-return","myreturn"}}
change_names -hierarchy -rules BORG // 执行命名规则

移除未连接的端口

1
2
remove_unconnected_ports [get_cells -hier{*}]
check_design

特殊线网

DC为inout生成tri连线,为了避免生成tri,可以使用set verilog_no_tri true。当该设置为真时,tri被定义为wire

如果模块包含直接连接到同一模块输出端口的输入端口,穿通就会出现。或者输出端口接地,或者由常量驱动,这些都会生成assign语句。

为了避免穿通,可以使用set_fix_multiple_port_nets -feedthroughs。这将会在输入输出之间插入缓冲器

而为了处理常量驱动的端口,可以使用set_fix_multiple_port_nets -all -buffer_constants

如果进行上述步骤之后仍会生成assign,可能是由于dont_touch导致的,可以使用remove_attribute [get_nets <net_name>] dont_touch移除dont_touch属性。

静态时序分析

SDF生成

SDF文件包含所有单元的时序信息。基本的时序数据由以下部分组成:

  1. IOPATH延迟: 单元延迟,依据输出连线负载和输入信号转换时间
  2. INTERCONNECT延迟: 驱动单元的输出到被驱动单元的输入之间的连线延迟
  3. SETUP时序检查
  4. HOLD时序检查

SDF生成命令

1
2
3
4
5
DC
write_timing -format sdf-v2.1 -output <filename>

PT
write_sdf -version 2.1 <filename>

Prime Time

虽然DC也可以进行静态时序分析,但是PT可以提供更多功能。它的命令和DC类型,使用transcript dc_script pt_script可以将DC的命令转换为PT的命令。

PT不能读取RTL文件,他只能读取网表文件。可以使用read_verilog命令进行读取。

时序分析命令:

  • set_input_transition: 它设置不依赖于连线负载的固定转换时间。例如set_input_transition 0.2 [all_inputs]
  • set_timing_derate: 用于减免时序报告中的延迟值。在生成时序报告前需要和这个数相乘。例如set_timing_derate -min 0.2 -max 1.2
  • set_propagated_clock: 设置传播时钟。在读取反标注文件之后,可以使用真实的网络延迟进行计算。set_propagated_clock [get_clocks clk]
  • set_case_analysis: 用于给端口设定固定值。例如set_case_analysis 0 scan_mode。此时与scan_mode相关的时序弧将失效。
  • remove_case_analysis
  • report_timing: 生成时序报告。report_timing -from [all_inputs] -to [all_registers -data_pins]
  • report_constraint: 报告相关违例。例如report_constraint -all_violators
  • report-bottleneck: 确定对设计中多个违例有贡献的叶单元。


静态时序分析中通常需要对四类路径进行分析

  • 输入到触发器: report_timing -from [all_inputs] -to [all_registers -data_pins]
  • 触发器到触发器: report_timing -from [all_registers -clock_pins] -to [all_registers -data_pins]
  • 触发器到输出: report_timing -from [all_register -clock_pins] -to [all_outputs]
  • 输入到输出: report_timing -from [all_inputs] -to [all_outputs]

asic设计流程
https://www.xinhecuican.tech/post/366cbde5.html
作者
星河璀璨
发布于
2025年4月12日
许可协议