DC是一个约束驱动的综合工具,它的综合结果是跟设计施加的一些时序约束条件密切相关的。DC的综合过程其实是一个不断迭代的过程,我们去拿RTL代码去做综合,如果发现不满足时序约束的需求,我们需要重新去修改RTL代码,然后再来做综合,一直迭代到时序满足。
1、综合简介:
-
综合就是将RTL(Verilog代码)转换成逻辑门级网表。转换的门级网表也是.v的Verilog代码,但是里面并没有我们所写的always或者assign这种语句,而是将标准单元例化并进行连接。
-
综合也可以理解为是将RTL映射成标准单元的连接。综合主要包括三个阶段:转换(translation)、优化 (optimization)与映射(mapping)。
-
转换阶段综合工具将RTL描述的电路用门级的逻辑来实现,DC用标准单元去搭建 HDL 语言描述的电路,最终形成一个初级的、未优化的电路。
-
优化与映射是综合工具对已有的初始电路进行分析,去掉电路中的冗余单元,并对不满足限制条件的路径进行优化,然后将优化之后的电路映射到由制造商提供的工艺库上。
2、综合准备:
- RTL描述
描述idea的代码,并且已经过验证。 - 标准单元库、IO、Memory库
工艺库(Target Library):是标准单元库,基础的。DC读入的HDL代码首先由synopsys自带的GTECH库转换成DC内部交换的格式,然后经过映射到工艺库和优化生成门级网表。一般是.db的格式,不能由文本方式打开。
符号库 (Symbol Library):标准单元的符号库,用于显示电路的连接关系的符号库。
链接库(Link Library):一般不仅包括基础的标准单元库,还包括一些其他的IP库,比如ROM,Pad,PLL,Memory。 - 运行脚本
综合脚本可以根据设计的需要进行调整,一般脚本都是重复使用的。
脚本的目的是设置综合环境,负载模型,电路的时序setup time、hold time要求、面积等约束,使得综合器在满足约束的情况下将RTL转换成能够用于最终布局布线的网表文件。
而且约束越严格,综合器综合的时间越长,电路的鲁棒性越高。
DC支持脚本和图形化两种操作方式,我们在图形化的设置都对应脚本里面的一条语句,由于DC过于复杂,所以一般都采用脚本的方式运行。
3、综合步骤:
- 在得到最终的RTL代码和库文件后,就可以进行我们的综合了。
综合我们需要做的就是给电路施加约束,使得综合器按照我们的约束对电路进行综合和优化,约束又分为 时序约束和DRC约束。 - 时序约束主要是 setup time和hold time的约束。时序路径可以分为4类:输入到寄存器的路径,寄存器到寄存器之间的路径,寄存器到输出的路径,输入直接到输出的路径。
- DRC约束主要是最大扇入扇出,传输延迟,面积,负载等约束。
通常DRC约束有三种。第一种是set_max_transition,set max transition是约束design 中的信号、端口、net最大transition不能超过这个值,越小越严苛。第二种是set_max_fanout:对design,net,output port进行操作,设定的不是具体的电容值。扇出负载值是用来表示单元输人引脚相对负载的数目,它并不表示真正的电容负载,而是个无量纲的数字。第三种是set_max_capacitance基于工艺库的信息进行设定。以上三个由工艺厂商提供。
在了解基础知识之后,就可以打开DC软件执行操作了!!
首先打开DC综合器图形化界面(cmd : gui_start)
综合主要分为五步:
1、设置综合环境,包括搜索路径、库文件路径。
set std_path "/home/**/dc" #设置库的路径
set search_path [list $std_path/ ] #设置搜索路径
set target_library "YourDB1.db YouDB2.db" #设置工艺库
set link_library "* $target_library" # 设置链接库
2、读入RTL代码,分析代码,将代码与标准单元链接,设置顶层文件。
set top "TopName" # 设置顶层模块名字
set rtl_dir /home/**/Test/rtl # 设置代码搜索路径
analyze -format verilog [glob $rtl_dir/*.v] # 读入分析设计
elaborate $top # 设置顶层模块
check_design # 检查设计
Link # 链接设计,link后可看到代码映射的标准单元的连接,如下图:
3、添加时序约束
set CLK_PERIOD 1 # 设置时钟周期 1ns
create_clock -period $CLK_PERIOD [get_ports clk] # 给电路 clk端口添加刚刚设置好的时钟
set_input_delay 0.2 -clock clk [all_inputs] # 给所有输入端口设置0.2ns的延时
set_output_delay 0.2 -clock clk [all_outputs] # 给所有输出端口设置0.2ns的延时
set_clock_uncertainty -setup 0.1 clk # 时钟不理想性的约束,0.1ns的setup time
set_clock_uncertainty -hold 0.2 clk # 时钟不理想性的约束,0.2ns的hold time
set_clock_transition 0.2 clk # 时钟不理想性的约束,0.2ns的传输延时
4、添加DRC约束
current_design $top # 指定当前设计的顶层模块
set all_in_ex_rstn [remove_from_collection [all_inputs] [get_ports rst_n]]
set all_in_ex_clk_rstn [remove_from_collection $all_in_ex_rstn [get_ports clk]]
set_wire_load_model -name "16000" -library LibName
set_driving_cell -lib_cell CellName -library LibName $all_in_ex_clk_rstn
# 给时钟和复位端口设置驱动,驱动器件是LibName 的CellName
set_fanout_load 2 [all_outputs] # 给所有输出端口设置负载
5、编译,保存产生的网表文件和约束文件。
Compile 或者 Compile_ultra # 编译
write -hierarchy -format verilog -output ../mapped/$top.mapped.v
write_sdf ../mapped/$top.sdf
write_sdc -version 1.9 ../mapped/$top.sdc
report_area -hierarchy > ../rpts/$top.area.rpts
report_power > ../rpts/$top.power.rpts
report_constrain -all_violators > ../rpts/$top.violators.rpts
report_net_fanout > ../rpts/$top.net_fanout.rpts
report_timing > ../rpts/$top.timing.rpts
# 上面都是保存输出文件和报告(时序、面积、功耗报告)
以上每一步都可以单独写一个脚本文件,然后依次运行脚本即可。