3. RTL 综合基础:使用 yosys 进行逻辑综合
RTL 综合,说白了就是把我们写的 Verilog 代码,翻译成芯片能用的门级网表。这个过程有点像把建筑设计图转成施工图——你画的是功能模块,综合工具给你换成具体的门电路和连线。
我刚开始接触综合时,总觉得这步很简单。直到有一次,我写了一个看起来很漂亮的状态机,综合出来面积大得吓人。嗯,从那以后我才明白,综合不是简单的翻译,而是一场性能、面积、功耗的博弈。
3.1 综合的本质:从行为到结构
综合工具到底在做什么?我习惯把它拆成三步:
- 解析:读入 RTL 代码,理解你的设计意图
- 转换:把行为级描述转成布尔逻辑表达式
- 映射:把逻辑表达式映射到目标工艺库的单元上
你想想看,同样的功能,用不同的写法,综合出来的结果可能天差地别。举个例子:
// 写法一:case 语句
always @(*) begin
case (sel)
2'b00: out = a;
2'b01: out = b;
2'b10: out = c;
2'b11: out = d;
endcase
end
// 写法二:if-else 链
always @(*) begin
if (sel == 2'b00) out = a;
else if (sel == 2'b01) out = b;
else if (sel == 2'b10) out = c;
else out = d;
end
这两种写法功能完全一样,但综合出来的电路结构不同。case 语句会生成优先级编码器吗?不会,它生成的是并行多路选择器。而 if-else 链会生成优先级结构——这在时序上可能有隐患。
3.2 yosys 实战:从 RTL 到网表
好,理论说完了,咱们直接上手。用 yosys 做综合,我一般按这个流程走:
# 1. 读取设计文件
read_verilog counter.v
# 2. 指定顶层模块
hierarchy -top counter
# 3. 预处理:展开宏、处理参数
proc
opt
# 4. 技术映射到标准单元
techmap
opt
# 5. 输出门级网表
write_verilog counter_synth.v
这个流程看起来简单,但每一步都有讲究。我重点说说几个关键命令:
| 命令 | 作用 | 我踩过的坑 |
|---|---|---|
proc |
把 always 块转成逻辑表达式 | 不执行 proc 直接 techmap,会报错 |
opt |
逻辑优化,消除冗余 | 优化力度不够时,面积会偏大 |
techmap |
映射到工艺库 | 库文件路径不对,映射会失败 |
dfflibmap |
映射触发器 | 时序单元映射要单独处理 |
synth 命令做粗略综合。我在项目中通常先用 synth -top top_module 快速验证功能,再用完整流程做精细综合。
3.3 综合策略:面积、速度、功耗的三角博弈
综合不是一键搞定的事。你需要告诉工具:你更看重什么?
我一般把综合策略分成三类:
- 面积优先:资源共享、逻辑复用、减少冗余
- 速度优先:展平逻辑、减少级数、插入流水线
- 功耗优先:门控时钟、操作数隔离、低功耗单元
这三者往往互相矛盾。你想想看,要速度快,就得用并行结构,面积自然就大了。要面积小,就得共享资源,时序就会变差。
我在一个无线通信项目中就遇到过这种困境。客户要求芯片面积控制在 5mm² 以内,同时要跑 500MHz。我试了三次综合:
- 第一次:面积优先,结果时序违例 200ps
- 第二次:速度优先,面积超标 30%
- 第三次:手动调整关键路径,面积刚好达标,时序留了 50ps 余量
嗯,综合策略不是选一个就完事了,很多时候需要手动干预。
3.4 约束:告诉工具你的真实需求
约束是综合中最容易被忽视的部分。没有约束,工具就不知道你的目标是什么。
我常用的约束包括:
- 时钟约束:频率、占空比、抖动
- 输入延迟:数据从外部到达芯片的时间
- 输出延迟:数据从芯片输出到外部的时间
- 伪路径:不需要时序检查的路径
- 多周期路径:需要多个时钟周期才能稳定的路径
在 yosys 中,约束通常通过 SDC 文件传入。不过 yosys 对 SDC 的支持有限,我一般用 Tcl 脚本直接设置:
# 设置时钟周期为 10ns(100MHz)
create_clock -name clk -period 10 [get_ports clk]
# 设置输入延迟
set_input_delay -clock clk 2 [get_ports data_in]
# 设置输出延迟
set_output_delay -clock clk 3 [get_ports data_out]
# 标记伪路径
set_false_path -from [get_ports rst_n]
3.5 综合结果分析:别只看面积和频率
综合完成后,你会得到一堆报告。我建议重点看这几个指标:
| 指标 | 含义 | 我的经验值 |
|---|---|---|
| Cell Count | 标准单元数量 | 控制在预估的 ±10% 以内 |
| Area | 总面积(μm²) | 不要超过预算的 5% |
| Worst Slack | 最差时序余量 | 至少留 50ps 余量 |
| Fanout | 最大扇出 | 超过 8 就要考虑插入缓冲器 |
| Transition | 信号跳变时间 | 不要超过库规定的 80% |
有一次,我看到综合报告里面积很小,但时序余量是负的。我以为是约束设错了,查了半天才发现是某个模块的扇出太大——一个信号驱动了 32 个触发器,导致跳变时间过长。插入两级缓冲器后,时序就收敛了。
3.6 知识体系总览
下面这张图总结了 RTL 综合的核心流程和关键决策点:
这张图把整个综合流程串起来了。从 RTL 代码、工艺库、约束三个输入开始,经过 yosys 引擎的处理,再根据你的策略偏好进行优化,最终输出门级网表。最后一步是分析结果,看看是否满足你的预期。