第1章:DC综合流程实战
说实话,DC综合是每个数字IC工程师的必修课。我刚开始接触时,觉得这工具就是个黑盒子——RTL代码扔进去,门级网表吐出来。但做了几个项目后才发现,中间的门道多着呢。
今天咱们就一步步走一遍DC综合的完整流程。从读入设计到生成报告,每个环节我都会结合自己的实战经验来讲。你跟着走一遍,基本就能上手了。
1.1 读入设计:analyze & elaborate
DC支持两种读入方式。我个人习惯用analyze + elaborate的组合,而不是直接用read_verilog。为什么?因为前者能帮你提前发现语法问题。
analyze负责检查语法,把RTL代码解析成中间格式。elaborate则把这些模块实例化,构建出设计的层次结构。
核心命令示例:
# 第一步:分析所有源文件
analyze -format verilog {top.v sub_module.v ram.v}
# 第二步:例化顶层模块
elaborate top -architecture verilog -library WORK
# 第三步:检查链接状态
link
这里有个坑,我曾经踩过好几次——文件顺序很重要。被例化的子模块要放在前面,顶层模块放最后。否则DC会报"undefined module"的错误。
我的小技巧:写个脚本自动扫描文件依赖关系,按拓扑排序后生成文件列表。省心省力,还不会出错。
1.2 定义工作环境:set_operating_conditions
芯片在不同工艺角下的表现天差地别。DC需要知道你的设计在什么条件下工作,才能做出合理的优化。
set_operating_conditions就是干这个的。它定义了工艺、电压、温度三个维度。
# 设置最差情况(WC)条件
set_operating_conditions -analysis_type on_chip_variation \
WCCOM
# 或者设置最好情况(BC)条件
set_operating_conditions BCCOM
嗯,这里要注意:综合时通常用最差条件(WCCOM),保证setup时序能收敛。但如果你做的是低功耗设计,可能还需要考虑BC条件来检查hold时序。
避坑指南:我曾经在一个项目中,只设了WC条件就跑了综合。结果后仿时发现hold违例严重,差点导致流片延期。后来我养成了习惯——综合阶段至少检查两个工艺角。
1.3 设置时序约束
时序约束是综合的灵魂。没有约束,DC就不知道往哪个方向优化。说白了,约束就是告诉工具:你的设计要跑多快,输入信号什么时候到,输出信号什么时候要。
1.3.1 创建时钟:create_clock
时钟是时序分析的基准。你想想看,没有时钟,工具怎么计算路径延迟?
# 创建主时钟,频率100MHz
create_clock -name clk -period 10 [get_ports clk]
# 创建分频时钟
create_generated_clock -name clk_div2 \
-source [get_ports clk] \
-divide_by 2 \
[get_pins u_div/clk_out]
我个人习惯给每个时钟起个有意义的名字,别用默认的。否则报告里一堆"clock_1、clock_2",看都看不懂。
1.3.2 设置输入延迟:set_input_delay
输入延迟描述了外部信号到达芯片引脚的时间。这个值通常来自上一级芯片的数据手册。
# 设置输入延迟,相对时钟上升沿
set_input_delay -clock clk -max 2.5 [get_ports data_in*]
set_input_delay -clock clk -min 0.5 [get_ports data_in*]
这里有个关键点:max和min要分开设。max用于setup检查,min用于hold检查。我见过有人只设一个值,结果hold分析完全不准。
1.3.3 设置输出延迟:set_output_delay
输出延迟是下游芯片对信号到达时间的要求。说白了,就是你的输出信号要在什么时间内稳定下来。
# 设置输出延迟
set_output_delay -clock clk -max 3.0 [get_ports data_out*]
set_output_delay -clock clk -min 1.0 [get_ports data_out*]
实战经验:输出延迟的值别拍脑袋定。我曾经接手一个项目,前任设的输出延迟全是2ns,结果综合出来的面积大了30%。后来我重新分析了接口时序,把值调到了合理范围,面积立马降下来了。
1.4 综合与优化:compile
前面所有准备工作做完,终于可以跑综合了。DC的compile命令有几个常用选项:
# 标准综合
compile_ultra -gate_clock -no_autoungroup
# 或者用增量模式(适合迭代优化)
compile_ultra -incremental -gate_clock
compile_ultra是DC的旗舰命令,比老版的compile优化效果更好。我一般第一次跑用标准模式,后续迭代用增量模式,省时间。
综合过程中,DC会做三件事:
- 架构优化:资源共享、运算单元选择
- 逻辑优化:布尔化简、冗余消除
- 门级映射:把RTL映射到目标库的单元
嗯,这里要提醒一句:别指望一次综合就能收敛。我做过最夸张的项目,综合迭代了20多版才把时序跑通。
1.5 生成报告
综合完不看报告,等于白做。DC的报告能告诉你设计到底行不行。
1.5.1 时序报告:report_timing
# 报告最差路径
report_timing -delay_type max -nworst 10 > timing.rpt
# 报告hold违例
report_timing -delay_type min -nworst 10 > timing_hold.rpt
看时序报告时,我习惯先看slack。正数说明时序有余量,负数说明有违例。然后看路径的起点和终点,找到瓶颈在哪。
1.5.2 面积报告:report_area
report_area > area.rpt
面积报告会显示组合逻辑、时序逻辑、总面积的数值。我一般关注组合逻辑和时序逻辑的比例。如果组合逻辑占比过高,说明设计可能不够优化。
1.5.3 功耗报告:report_power
report_power > power.rpt
功耗报告分动态功耗和静态功耗。动态功耗跟翻转率有关,静态功耗跟漏电流有关。低功耗设计时,这两个都要盯紧。
我的习惯:每次综合完,我会把时序、面积、功耗三个报告的关键数据摘出来,做成一个表格。这样不同版本之间对比一目了然。
小结
这一章咱们走完了DC综合的完整流程。从读入设计到生成报告,每一步都有它的意义。你可能会觉得步骤有点多,但做熟了就会发现,其实就那几条命令来回用。
下一章,咱们聊聊时序约束的进阶技巧。比如多时钟域怎么处理、异步路径怎么约束——这些才是真正考验功力的地方。
记住一句话:综合不是终点,而是起点。后端的布局布线、时序签收,每一步都离不开综合阶段打下的基础。