nextpnr 资源放不下速查:over-utilized 报错与逐类回收的排查主线
更新时间:2026-10-23。FAQ 速查页,属于 FPGA 工具报错排错系列。开源工具链(yosys 综合 + nextpnr 布局布线)上,yosys 那一步往往顺顺当当过完,一进 nextpnr 就被一句
ERROR: ... over-utilized或failed to place打回——逻辑明明「看着不大」,怎么就放不下了。真相几乎总是某一类资源被打满:LUT、触发器、BRAM、DSP、引脚、全局时钟缓冲,任何一类超限 nextpnr 都直接拒绝。本篇给出报错原文、分流图与逐类回收动作;Quartus 闭源侧同主题的对照见 Quartus 资源不够放不下速查,yosys 阶段自身的资源与内存超限见 Yosys 资源超限排查。
本文要回答的问题
ERROR: ... over-utilized到底是哪一类资源超了?- 总利用率没到 100%,为什么照样 failed to place?
- 怎么判断 BRAM 被推断成了分布式 RAM、白白吃掉 LUT?
- 进位链和全局时钟(GBUFF)这种「隐性资源」超限去哪里看?
- 不换芯片的前提下,yosys 侧有哪些立即可做的降载手段?
一、报错原文与现象
nextpnr 在布局阶段打印的利用率报告长这样(ice40 示意,数值为演示):
Info: Device utilisation:
Info: ICESTORM_LC: 8123/ 7680 105%
Info: ICESTORM_RAM: 28/ 32 87%
Info: SB_IO: 96/ 256 37%
Info: SB_GB: 9/ 8 112%
ERROR: Design exceeds device capacity: ICESTORM_LC over-utilized (105%).
ERROR: Packing design failed.ecp5 版本语义相同,资源名换成 TRELLIS_SLICE、DP16KD、MULT18X18D。最容易误读的一点:LUT 一栏 105% 的同时 SB_GB(全局缓冲)112%——两处独立超限,修好一个另一个照样让布线失败。开源工具链的利用率表是逐类列出、逐类判定,没有「平均分」这一说,任何一项破百都是硬拒绝。
另一个迷惑点:yosys 综合结束时打印的统计是「网表名义值」,nextpnr 落位之后才是真实值。名义值 95% 看似有富余,进位链展开、控制集合并之后局部拥塞照样 failed to place。评估余量一律以 nextpnr 报告的 utilisation 为准,yosys 统计只当早期预警。
二、排查决策流程图
先读 utilisation 表找破百项,再进对应通道——这是唯一正确的顺序,不要先动 RTL。
读这张图抓住主线:红色是入口现象与「确实装不下」的最终判决,蓝色是按资源类型分出的五条诊断通道,橙色是对应的回收动作,绿色是沉淀。颜色即角色。最常见的白跑是:LUT 超了去改引脚约束、RAM 超了去砍状态机——通道不对,改一整晚利用率纹丝不动。
三、病因速查表
| 现象 / 报错锚点 | 根因 | 一判据 | 处置方向 |
|---|---|---|---|
| LC/SLICE 一栏超 100% | 芯片选型偏小或逻辑确实过多 | utilisation 表 LC 行破百 | 砍功能、降并行度、换大芯片 |
| BRAM 没用几块但 LUT 爆炸 | RAM 被推断成分布式 RAM | yosys 统计里 RAM 进了 LC 而非 RAM 块 | 改同步读、去异步复位、显式原语 |
| DP16KD/SB_RAM 破百 | 存储总量真超块 RAM 容量 | RAM 行破百且块数对得上 | 砍缓存深度、换大芯片 |
| MULT18X18D 超核数 | DSP 硬核数不够 | DSP 行破百 | 对齐位宽、小乘法改走逻辑 |
| SB_IO 破百或 pcf 约束冲突 | 引脚数超封装 | IO 行破百、引脚约束报错 | 减引脚、换封装、复用引脚 |
| SB_GB 超 8 | 全局时钟缓冲用完 | GB 行破百 | 减独立时钟域、共用全局网络 |
| 各项都未超但 failed to place | 布局碎片、进位链太长放不下 | 换 seed 重跑偶发成功 | 多试 seed、拆长链、降扇出 |
| yosys 未开优化直接综合 | 网表冗余没收敛 | 未加 -retime、abc 轮次少 | synth_ice40 -retime 重综合 |
四、逐条排查
LUT/FF 超容量。 先让 yosys 按模块打印层级统计(stat 命令加 -top 与层级展开),从占用最大的模块砍起。可回收的口子:one-hot 状态机改 binary,寄存器数量直接降一个量级;并行处理改时分复用;确认没有重复例化。综合策略上,synth_ice40 -retime(ecp5 为 synth_ecp5 -retime)让寄存器跨逻辑重平衡,常常能省出一截 LUT;abc 优化轮次加足(如 -abc2 或多跑一遍 abc -dress)也有百分之几的净收益。这些开关不动 RTL,是第一批该试的手段。
BRAM 被推断成分布式 RAM。 这是开源链上性价比最高的一条修复通道。yosys 对异步读 RAM、读口带异步复位的写法无法映射进块 RAM,会退化成一堆 LC 拼出来的分布式存储——BRAM 行没怎么涨,LC 行却爆了。判据是 yosys 统计里大块数组出现在 LC 侧而不是 RAM 侧。修法:读口加一拍寄存、复位改同步或去掉,仍不识别就显式例化 SB_RAM40_4K / DP16KD 原语,把推断的不确定性一次性消掉。
DSP 超核数。 乘法器没进硬核的常见原因:位宽超过单块能力又没给工具拆分的余地,或乘法两侧嵌了不认的组合逻辑。按目标芯片的推断模板重写乘法并加流水线级。反方向也成立:8 乘 8 之类小乘法与其占 DSP,不如强制走逻辑(在属性里指定 logic 实现),把硬核留给真正的大位宽乘法。
引脚与全局时钟。 SB_IO 破百就是封装引脚真不够,只能减引脚、复用或换封装,没有软件解。SB_GB 超限更隐蔽:ice40 每片只有 8 个全局缓冲,每个独立时钟域、每个高扇出使能网络都可能占一个。把时钟域合并、把低频时钟改使能脉冲,GBUFF 用量立刻下来。
都没超却放不下。 碎片化场景:总量够但长进位链(超位宽加减法、大计数器)无法在一列里连续落位,或局部拥塞。nextpnr 的布局是随机化算法,换 --seed 多跑几次常常就能放下;结构上把超长链手动拆段、降关键信号扇出。偶发成功偶发失败是这一类问题的典型指纹。
五、防复发
- 每次成功构建归档 utilisation 报告,红线按单类型设(建议各类 80%),不看总量均值。
- RAM 写法固定在「同步读、无复位」模板,关键存储直接例化原语,把推断坑消灭在综合之前。
- 选型按估算值的 1.3 倍留档:HX1K 顶到 90% 就直接上 HX4K/HX8K,比在 98% 利用率下死磕 seed 便宜。
- 引脚约束(pcf/lpf)在原理图阶段锁定,别等 RTL 写完倒挤。
- 综合脚本固化
-retime等优化开关,CI 里同配置复跑,避免本地过了、服务器上放不下。 - 新引入的模块先单独综合一次记底数,「莫名放不下」多半是新模块一口吃掉了大半 LC 或 RAM,有底数才能一眼定位。
这一篇在知识体系里的位置
本篇是 FPGA 工具排错速查簇中「资源触顶」的开源工具链分流页:yosys 综合阶段本身的资源与内存超限见 Yosys 资源超限排查;同主题在 Quartus 闭源侧的对应物(Fitter 报错与块 RAM 推断修复)见 Quartus 资源不够放不下速查,两边「按单类型分诊、先读报告再动手」的思路同构,可以对照阅读。
一句话总结
nextpnr 报 over-utilized 时先别改代码,读 utilisation 表找破百项:LC 超了砍逻辑并给 yosys 加 -retime 与 abc 优化;BRAM 没用几块但 LUT 爆炸九成大数组被推断成分布式 RAM,改同步读或例化块 RAM 原语;DSP 超了按模板重写乘法、小乘法强制走逻辑;引脚与 SB_GB 超限减引脚、并时钟域;各项都没超却放不下是碎片化,换 seed、拆长进位链;真装不下就换大容量芯片,并把单类型 80% 利用率红线归档成纪律。