3. 逻辑综合优化:综合策略、资源利用率与面积优化

逻辑综合,说白了就是把你的 RTL 代码翻译成门级网表。这一步做得好不好,直接决定了你的芯片能跑多快、占多大面积、功耗高不高。我刚开始做 FPGA 设计那会儿,总觉得综合是工具自动干的事,跟我没啥关系。后来被坑了几次才明白——不懂综合优化,你写出来的代码可能就是一颗定时炸弹

3.1 综合策略的选择:速度优先还是面积优先?

综合工具通常提供几种策略。最常见的就是「速度优先」和「面积优先」。你可能会问:我能不能既要速度又要面积?嗯,理论上可以,但现实中你得做取舍。

我个人习惯的做法是:先跑一次默认策略,看看时序和资源报告。如果时序紧张,就切到速度优先;如果资源快爆了,就切到面积优先。别一上来就选极端策略,那样反而容易出问题。

核心原则:综合策略不是一成不变的。同一个设计,在不同阶段可能需要不同的策略。前期验证阶段我通常用面积优先,因为跑得快;后期时序收敛阶段再切到速度优先。

3.2 资源利用率的监控与优化

资源利用率,说白了就是你的芯片用了多少 LUT、FF、BRAM、DSP。我见过不少新手,写代码时完全不考虑资源,结果综合出来发现 LUT 用了 120%,然后开始疯狂改代码……

这里我分享一个我在项目中用过的技巧:用综合报告里的「资源占用明细」来定位问题。比如某个模块 LUT 占用特别高,那多半是组合逻辑写得太复杂了。

资源类型 常见浪费原因 优化方向
LUT 复杂的组合逻辑、多级 MUX 拆分逻辑、使用查找表替代
FF 不必要的流水线、冗余寄存器 精简流水线深度、合并寄存器
BRAM 大位宽小深度、未对齐的数据宽度 调整位宽与深度比例、使用分布式 RAM
DSP 乘法器未复用、位宽浪费 共享 DSP 单元、截断位宽

小技巧:综合报告里有个「资源利用率百分比」,别只看这个数字。我建议你重点关注「LUT 与 FF 的比例」。如果 LUT 比 FF 多很多,说明你的设计偏组合逻辑,时序可能不好收敛。

3.3 面积优化的核心方法

面积优化,说白了就是让芯片更小、更省资源。我总结了几种最实用的方法:

3.3.1 资源共享

这是最直接的面积优化手段。比如两个模块都用到了乘法器,但不同时工作,那就可以共用一个 DSP。我曾经在一个视频处理项目中,通过资源共享把 DSP 用量从 48 个降到了 16 个。

// 不共享:两个乘法器
assign result1 = a * b;
assign result2 = c * d;

// 共享:一个乘法器,通过 MUX 选择输入
assign mul_in1 = sel ? a : c;
assign mul_in2 = sel ? b : d;
assign mul_out = mul_in1 * mul_in2;
assign result1 = sel ? mul_out : 0;
assign result2 = sel ? 0 : mul_out;

3.3.2 状态机优化

状态机的编码方式对面积影响很大。我建议:状态数少于 16 个时用独热码,多于 16 个时用二进制编码。独热码虽然占的 FF 多,但译码逻辑简单,LUT 用得少。

注意:别为了省面积把状态机写成「格雷码」。格雷码虽然省 FF,但译码逻辑复杂,反而可能增加 LUT 用量。我踩过这个坑,后来老老实实按状态数选编码方式。

3.3.3 数据路径优化

数据路径的位宽直接影响面积。比如你只需要 8 位精度,就别用 32 位总线。我见过有人把整个设计都定义成 32 位,结果资源翻了好几倍。

另外,能用移位代替乘除法的,尽量用移位。比如乘以 2 用左移一位,除以 4 用右移两位。这样能省下 DSP 资源。

3.4 综合优化的知识体系

下面这张图是我自己总结的综合优化知识体系,你可以对照着看看自己哪块还不太熟:

逻辑综合优化 综合策略 速度优先 面积优先 平衡策略 资源利用率 LUT 利用率 FF 利用率 BRAM 利用率 DSP 利用率 面积优化 资源共享 状态机优化 数据路径优化 逻辑简化 三者相互影响,需要根据设计目标权衡 速度优先 → 资源利用率高 → 面积大 面积优先 → 资源利用率低 → 速度慢

3.5 综合优化的避坑指南

做综合优化这么多年,我踩过的坑不少。这里挑几个典型的说说:

  • 别过度优化:我曾经为了省几个 LUT,把代码改得面目全非,结果综合出来时序全乱了。后来我学乖了——先保证功能正确和时序收敛,再考虑面积优化
  • 综合报告要仔细看:很多人只看资源利用率,忽略了「警告信息」。其实很多警告都在提示你代码有问题,比如「inferred latch」、「unused signal」这些。
  • 不同工具结果不同:Vivado 和 Quartus 的综合策略不一样。同一个代码,在 Vivado 上可能资源很省,换到 Quartus 就爆了。所以别只依赖一个工具的报告

我的经验:综合优化不是一蹴而就的。我通常的做法是:先写代码 → 综合看报告 → 定位瓶颈 → 局部优化 → 再综合验证。这样迭代 3-5 轮,基本就能达到满意的效果。

3.6 综合优化的实践建议

最后,我总结几条实践建议:

  1. 写代码时就要考虑综合:别等到综合出问题了再改。比如写组合逻辑时,尽量用 case 代替 if-else 链,这样综合出来的 LUT 更少。
  2. 善用综合属性:Vivado 里有 KEEP、DONT_TOUCH 这些属性,可以控制综合工具的行为。比如某个关键路径,你可以用 KEEP 防止工具优化掉。
  3. 多做对比实验:同一个功能,用不同的写法综合,结果可能差很多。我习惯把几种写法都跑一遍综合,选资源最省的那个。

嗯,综合优化这块内容不少,但核心就三点:选对策略、盯紧资源、持续优化。你只要把这三点做到位,综合这一步基本不会出大问题。

专注资料整理