3. 逻辑综合优化:逻辑级数概念、重定时技术、操作符平衡、资源共享与逻辑复制

逻辑综合优化,说白了就是让工具帮你把RTL代码翻译成更快的电路。我刚开始做后端时,总觉得综合是前端的事,跟我没关系。后来被一条关键路径折磨了三天,才发现——综合阶段埋下的坑,后端流片前才能发现,那时候改就晚了。

这一节我们聊聊综合优化的几个核心手段。你想想看,工具不是万能的,你得告诉它往哪个方向使劲。

3.1 逻辑级数:时序的“罪魁祸首”

什么是逻辑级数?简单说,就是两个寄存器之间,串了多少个逻辑门。一级就是一组逻辑门,两级就是两组。

举个例子:

// 逻辑级数 = 3
assign c = a & b;   // 第一级
assign d = c | e;   // 第二级
assign f = d ^ g;   // 第三级

每多一级,信号传播就多一个门延迟。级数越多,路径越慢。

为什么逻辑级数这么重要?

因为时序违例的本质,就是信号在时钟周期内跑不到终点。逻辑级数直接决定了路径延迟的上限。

经验法则:在先进工艺下(7nm/5nm),单周期路径的逻辑级数建议控制在 8-12 级以内。超过 15 级,基本就要出事了。

我在项目中遇到过一条 22 级的路径,综合工具死活优化不下去。后来发现是设计里有个巨大的组合逻辑块,把几十个信号揉在一起算。拆成三级流水线,立马解决。

3.2 重定时(Retiming):让寄存器“搬家”

重定时技术,说白了就是让工具自动把寄存器往前或往后挪一挪,平衡路径延迟。

你想想看,如果一条路径前半段慢、后半段快,那前半段就是瓶颈。重定时会把寄存器往前推,让前半段变短、后半段变长,整体就平衡了。

重定时的两种方式:

  • 前向重定时(Forward Retiming):寄存器往后挪,适合前半段快、后半段慢的情况
  • 后向重定时(Backward Retiming):寄存器往前挪,适合前半段慢、后半段快的情况

举个例子:

// 原始:前半段慢(5级),后半段快(2级)
reg_a -> [5级逻辑] -> reg_b -> [2级逻辑] -> reg_c

// 重定时后:前半段3级,后半段4级
reg_a -> [3级逻辑] -> reg_b -> [4级逻辑] -> reg_c

嗯,这里要注意:重定时不是万能的。它只能移动寄存器,不能减少逻辑级数。如果整条路径都慢,重定时也救不了。

我的习惯:在综合脚本里加上 set_retiming_options -effort high,让工具尽量做重定时。但记得检查功能是否正确——重定时会改变寄存器的位置,仿真时要小心。

3.3 操作符平衡(Operator Balancing):让加法器“排队”

操作符平衡,说白了就是调整加法、乘法这些运算的顺序,减少关键路径的级数。

举个例子:

// 不平衡:串行加法,级数 = 3
assign sum = a + b + c + d;
// 综合工具可能实现为:((a+b) + c) + d

// 平衡:树形加法,级数 = 2
assign sum = (a + b) + (c + d);

你想想看,四个数相加,串行要三级,树形只要两级。级数少了,速度就快了。

操作符平衡的常见场景:

  • 加法树:多个数相加,用树形结构
  • 乘法链:多个数相乘,同样用树形
  • 比较器:多个条件比较,用树形或并行

我在项目中遇到过一个大位宽加法器,32个16位数相加。如果不做平衡,级数能到 30 级。用了树形结构,降到 5 级,时序直接达标。

避坑指南:我曾经以为工具会自动做操作符平衡,结果发现有些综合工具默认不开。记得在脚本里加上 set_operator_balancing true,或者用括号手动指定运算顺序。

3.4 资源共享与逻辑复制:一对“矛盾兄弟”

资源共享和逻辑复制,听起来是反着来的。一个想省面积,一个想省时间。但实际项目中,两者都要用。

资源共享:省面积,但可能牺牲时序

资源共享,就是把多个功能相同的模块合并成一个,减少面积和功耗。

举个例子:

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

// 资源共享后:一个乘法器,分时复用
always @(posedge clk) begin
  if (sel) begin
    result1 <= a * b;
  end else begin
    result2 <= c * d;
  end
end

嗯,这里要注意:资源共享会增加控制逻辑,可能引入额外的 MUX 延迟。如果路径本来就紧,共享反而会坏事。

逻辑复制:用面积换时间

逻辑复制,就是把一个逻辑块复制多份,减少扇出,缩短路径。

你想想看,如果一个信号要驱动 100 个负载,那它的延迟会很大。复制一份,每个只驱动 50 个,延迟就降下来了。

逻辑复制的典型场景:

  • 高扇出信号:时钟、复位、使能信号
  • 关键路径:路径上的大负载,复制后分担
  • 多路选择:MUX 的输入信号,复制后减少级数

经验之谈:我一般先做资源共享,把面积压下来。然后看时序,哪里紧张就在哪里做逻辑复制。说白了,面积和时序是 trade-off,没有的好坏。

3.5 知识体系总览

下面这张图,是我自己总结的逻辑综合优化知识体系。你可以把它当成一个检查清单,做综合时对照着看。

逻辑综合优化知识体系 逻辑综合优化 逻辑级数 重定时 (Retiming) 操作符平衡 资源共享与复制 门延迟累加 路径深度控制 8-12级经验值 前向重定时 后向重定时 平衡路径延迟 加法树 乘法链 树形结构优化 资源共享省面积 逻辑复制提速度 面积与时序权衡 核心目标:在面积、时序、功耗之间找到最优平衡

这张图把四个核心知识点串起来了。逻辑级数是基础,重定时和操作符平衡是具体手段,资源共享与逻辑复制是策略选择。做综合时,我习惯先看逻辑级数,再决定用哪种优化手段。

一个小技巧:综合报告里有个 logic_depth 字段,直接告诉你每条路径的逻辑级数。我每次跑完综合,第一件事就是看这个字段。超过 15 级的,标记出来,后面重点优化。

好了,这一节的内容就到这里。逻辑综合优化这块,说白了就是跟工具“斗智斗勇”。你理解得越深,工具就越听话。下次遇到时序违例,别急着改代码,先看看逻辑级数,想想能不能用重定时或操作符平衡来解决。

可可精品资料库