第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综合的完整流程。从读入设计到生成报告,每一步都有它的意义。你可能会觉得步骤有点多,但做熟了就会发现,其实就那几条命令来回用。

下一章,咱们聊聊时序约束的进阶技巧。比如多时钟域怎么处理、异步路径怎么约束——这些才是真正考验功力的地方。

记住一句话:综合不是终点,而是起点。后端的布局布线、时序签收,每一步都离不开综合阶段打下的基础。