综合(Synthesis)基础:从代码到网表的桥梁
综合,说白了就是把我们写的 RTL 代码(Verilog/VHDL)翻译成芯片能理解的底层电路结构。这个过程不是简单的「翻译」,而是包含了逻辑优化、结构映射、时序预估等一系列操作。
我刚开始学 FPGA 时,总觉得综合就是个「黑盒子」——代码写进去,网表出来,中间发生了什么完全不知道。直到有一次,我写了一个看起来很漂亮的状态机,综合后资源爆了,才逼着我去搞懂综合到底在干什么。
综合到底做了什么?
综合工具的核心工作可以分为三步:
- 翻译(Translation):把 RTL 代码解析成通用的逻辑表达式(与或非门网络)。
- 优化(Optimization):根据面积、速度、功耗等约束,对逻辑网络进行化简和重组。
- 映射(Mapping):把优化后的逻辑网络映射到目标 FPGA 的底层资源(LUT、FF、DSP、BRAM 等)。
关键认知:综合后的输出是 网表(Netlist),不是比特流。网表描述的是逻辑单元之间的连接关系,它还是「电路图纸」,不是「实物」。从网表到比特流,中间还有布局布线和比特流生成两步。
我见过不少新手,综合完看到资源利用率就以为能下载了,结果布局布线时报错一堆。嗯,这里要记住:综合只是第一步。
综合工具的基本操作
目前主流的两大工具是 Vivado(Xilinx) 和 Quartus(Intel/Altera)。操作逻辑大同小异,我分别说一下。
Vivado 综合操作
我个人习惯用 Tcl 脚本做综合,但 GUI 方式更适合初学者理解流程。
- 创建工程,添加 RTL 源文件和约束文件(.xdc)。
- 在 Flow Navigator 中点击 Run Synthesis。
- 综合完成后,打开 Synthesis Design,查看资源利用率、时序报告。
- 如果发现问题,修改代码或约束,重新综合。
用 Tcl 脚本的话,核心命令就几行:
# 创建工程
create_project my_project ./my_project -part xc7a35tcsg324-1
# 添加源文件
add_files -fileset sources_1 ./src/top.v
add_files -fileset constrs_1 ./src/top.xdc
# 启动综合
launch_runs synth_1
wait_on_run synth_1
# 打开综合设计
open_run synth_1
我的习惯:在综合前,我会先检查一下约束文件。特别是时钟约束,如果时钟没定义对,综合出来的时序报告全是假的。我曾经因为漏写了一个生成时钟的约束,浪费了整整两天去追一个「不存在」的时序违例。
Quartus 综合操作
Quartus 的操作逻辑和 Vivado 类似,但菜单名称略有不同:
- 创建工程,选择器件型号,添加源文件。
- 点击 Analysis & Synthesis(注意,Quartus 把分析和综合合并了)。
- 完成后查看 Compilation Report 下的 Analysis & Synthesis 部分。
Quartus 的 Tcl 命令也差不多:
# 创建工程
project_new my_project -overwrite
set_global_assignment -name FAMILY "Cyclone IV E"
set_global_assignment -name DEVICE EP4CE10F17C8
# 添加文件
set_global_assignment -name VERILOG_FILE ./src/top.v
set_global_assignment -name SDC_FILE ./src/top.sdc
# 启动综合
execute_module -tool analysis_and_synthesis
综合后的资源利用率报告解读
这是综合环节最实用的技能。资源利用率报告告诉你:你的设计占用了多少 FPGA 资源,以及有没有资源瓶颈。
我截取一个典型的 Vivado 资源报告片段来说明:
| 资源类型 | 已用 | 可用 | 利用率 |
|---|---|---|---|
| Slice LUTs | 12456 | 63400 | 19.65% |
| Slice Registers | 8923 | 126800 | 7.04% |
| Block RAM (36K) | 12 | 135 | 8.89% |
| DSP48E1 | 8 | 240 | 3.33% |
| BUFG | 4 | 32 | 12.50% |
怎么看这个表?我一般按这个顺序:
- 先看 LUT 和 Register:这两个是基础逻辑资源。如果利用率超过 80%,布局布线可能会很困难。我遇到过 LUT 用到 95% 的设计,布线器跑了 6 个小时还没跑通。
- 再看 BRAM 和 DSP:这两个是专用硬核。如果 BRAM 用超了,工具会自动用 LUT 搭分布式 RAM,但面积和延迟都会变差。DSP 同理。
- 最后看 BUFG:全局时钟缓冲器。如果时钟域太多,BUFG 可能不够用。我记得有个项目用了 35 个时钟域,而芯片只有 32 个 BUFG,最后不得不合并时钟域。
避坑指南:综合报告里的资源利用率是「预估」值,不是最终值。布局布线后,资源利用率可能会因为布线拥塞而略微上升。我曾经在综合报告里看到 LUT 利用率只有 60%,但布局布线后涨到了 72%。所以,我一般会留 20% 的余量。
综合后的知识体系
下面这张图总结了综合阶段的核心概念和流程:
综合中的常见问题与避坑
综合阶段最容易踩的坑,我列几个:
- 资源利用率虚高:有时候综合报告显示 LUT 用了很多,但实际代码逻辑并不复杂。这往往是因为代码中写了大量的
case或if-else嵌套,综合器生成了优先级编码器。我建议用casez或并行case来避免。 - 推断出意外的硬件:比如你想写一个组合逻辑,但漏写了
else分支,综合器给你推断出锁存器(Latch)。锁存器在 FPGA 中通常是不推荐的,会带来时序问题。 - 时钟域未正确约束:如果设计中存在多个时钟域,但没有在约束文件中定义跨时钟域路径,综合器会默认按同步路径分析,导致时序报告完全不可信。
我的检查清单:每次综合完成后,我会做三件事:① 检查是否有 Latch 被推断出来(Vivado 的 Report Methodology 会标记);② 检查时钟约束是否完整(特别是生成时钟和异步时钟组);③ 检查资源利用率是否在合理范围内(LUT+FF 不超过 80%)。
综合后的下一步
综合完成后,我们得到了网表和初步的资源利用率报告。但这还不是终点。接下来,我们需要把网表「放」到 FPGA 的物理位置上,并连接它们——这就是布局布线(Place & Route)。不过,那是下一阶段的内容了。
嗯,综合阶段的核心就这些。记住:综合报告是你的「体检报告」,学会读懂它,你就能在设计早期发现问题,而不是等到板级调试时才手忙脚乱。