9、综合策略:OOC综合模式、动态模块的OOC综合、综合后检查

各位好,今天我们聊一个在动态部分重构设计里非常关键的话题——综合策略。说白了,就是怎么让工具把我们的动态模块和静态逻辑“分家”处理,最后还能完美拼回去。

我刚开始接触部分重构时,犯过一个低级错误:直接把整个设计扔给Vivado做全局综合。结果呢?动态模块和静态逻辑搅在一起,工具根本分不清哪些逻辑需要保留、哪些可以优化掉。后来我才明白,OOC(Out-of-Context)综合模式才是正解。

什么是OOC综合模式?

OOC,全称Out-of-Context,翻译过来就是“脱离上下文”。什么意思呢?

传统综合模式下,工具会把整个设计当成一个整体,它会根据顶层模块的接口和约束来优化每个子模块。但OOC不一样——它把每个模块当作独立的单元来综合,不考虑它在顶层里怎么连的。

这样做的好处很明显:

  • 模块复用性高:同一个模块,不管放在哪个项目里,综合结果都一样
  • 综合速度快:只改了一个模块,不用重新综合整个设计
  • 结果可预测:每次综合出来的网表结构基本一致

我个人习惯,只要项目超过5万门,我就会用OOC模式。尤其是做部分重构时,这几乎是必须的。

动态模块的OOC综合

动态模块的OOC综合,和普通模块的OOC综合有区别吗?

有,而且区别不小。

普通模块做OOC综合时,工具会假设所有输入输出端口都是“活的”,它会保留所有逻辑。但动态模块不一样——它需要和静态逻辑通过特定的接口(比如LUTRAM、SRL、三态缓冲等)进行通信。

我建议你在做动态模块的OOC综合时,注意以下几点:

  1. 必须指定重构分区(Pblock):告诉工具这个模块将来要放在哪个物理区域
  2. 接口逻辑要保留:动态模块和静态逻辑的边界处,不能优化掉任何寄存器或LUT
  3. 使用preserve属性:对关键路径上的信号加(* preserve *)或(* keep *)

核心要点:动态模块的OOC综合,本质上是“带约束的独立综合”。约束主要来自两部分——物理位置约束(Pblock)和接口时序约束。

举个例子,我曾经做过一个项目,动态模块里有个状态机,综合后工具把它优化成了几个LUT。结果呢?动态切换时状态机跑飞了。后来我加了preserve属性,强制保留状态寄存器,问题才解决。

综合后检查

综合完了,是不是就可以直接往下走了?

别急。综合后检查这一步,我建议你认真做。我曾经跳过这一步,结果在实现阶段发现时序违例,回头改代码,浪费了整整两天。

综合后检查主要看这几个方面:

检查项 检查内容 常见问题
网表完整性 所有模块是否都被综合了 某个子模块被优化掉了
接口一致性 动态模块和静态模块的接口是否匹配 端口位宽不一致、方向错误
时序约束 时钟、复位、异步信号是否被正确约束 未约束的路径导致时序违例
资源利用率 LUT、FF、BRAM等资源是否在预期范围内 某个模块资源超标,放不进Pblock

嗯,这里要注意一点:综合后检查不是跑一遍就完事了。我习惯用Vivado的report_utilization和report_timing_summary两个命令,生成报告后逐项核对。

小技巧:在Tcl脚本里加一句:

# 综合后自动生成检查报告
report_utilization -file ./reports/post_synth_util.rpt
report_timing_summary -file ./reports/post_synth_timing.rpt

这样每次综合完,报告自动生成,省得你手动点来点去。

OOC综合的典型流程

说了这么多,我们来画个图,把整个流程串起来。

动态部分重构OOC综合流程 1. 划分动态/静态模块 2. 创建Pblock约束 3. 设置OOC综合属性 4. 综合 5. 综合后检查 6. 检查通过? 通过 不通过 7. 进入实现阶段 修改代码/约束 OOC综合 + 综合后检查 = 动态部分重构成功的关键保障 正向流程 反馈修改 通过节点

这个流程看起来简单,但每一步都有坑。我见过不少工程师,在步骤2(创建Pblock约束)上翻车——要么Pblock太小放不下动态模块,要么Pblock形状不规则导致布线困难。

警告:千万不要在综合阶段就急着做物理优化。OOC综合只负责生成网表,布局布线是后面实现阶段的事。你在综合阶段加太多物理约束,反而会限制工具的优化空间。

实战中的避坑指南

最后,分享几个我踩过的坑:

  • 接口信号没加keep属性:综合后接口被优化掉了,导致动态模块和静态逻辑连不上。解决方案:在RTL里对接口信号加(* keep = "true" *)
  • 时钟域没分开:动态模块和静态模块用了同一个时钟,但综合时没做时钟域隔离。结果动态切换时产生毛刺。解决方案:用BUFG或MMCM分别驱动
  • 复位信号没处理好:动态模块的复位信号和静态模块的复位信号连在一起,导致动态切换时静态逻辑也被复位了。解决方案:用独立的复位信号,或者加同步器

嗯,今天就聊到这里。OOC综合和综合后检查,说白了就是让工具“规规矩矩”地干活,别自作主张。你只要把约束写清楚、检查做到位,后面实现阶段就会顺利很多。


公众号:蓝海资料掘金营,微信deep3321