Yosys 引用无法解析报错(referenced ... is not part of the design)速查
更新时间:2026-10-23。FAQ 速查页。症状很典型:RTL 文件明明都读进来了,
synth跑到一半 Yosys 却抛出ERROR: Module 'xxx' referenced in module 'yyy' ... is not part of the design——顶层例化了某个子模块,但 elaboration(细化)阶段解析不出这个引用指向谁。它和 Yosys 找不到模块速查 是近亲但侧重不同:那一篇偏「read_verilog压根没读到文件」的输入链路角度,本篇偏「文件读了、符号在库里,例化引用却绑定不上」的语义角度——包括读取顺序、generate 分支、参数化名字、黑盒 IP 这类「东西在、就是接不上」的情况。
本文要回答的问题
is not part of the design和Can't resolve module name有什么区别?- 子模块定义明明在文件里,为什么 elaboration 还说引用了不存在的东西?
read_verilog的读取顺序会影响模块解析吗?-defer是干什么的?- 参数化实例
#(...)为什么会让模块名「对不上」? - 第三方 IP 只给了接口没有 RTL,Yosys 怎么过 elaboration?
一、报错原文:elaboration 期的统一文案
Yosys 在 hierarchy 阶段(synth 流程内部会调)要把每一条例化语句绑定到一个已读入的模块定义上,绑定失败就抛这类错。典型文案:
ERROR: Module `uart_rx' referenced in module `top' in cell `u_rx' is not part of the design.hierarchy -check 显式跑时的变体:
ERROR: Module `\fifo_ctrl' referenced in module `\dma_engine' in cell `\u_fifo' is not part of the design.参数化/派生模块场景的文案:
ERROR: Can't resolve module name `$paramod$abcd1234' referenced in module `top'!读这类报错抓两个字段:被引用模块名(uart_rx)和例化单元名(u_rx)。报错的归属文件是顶层文件,病根却几乎都在别处——读文件顺序、参数名不匹配、generate 分支被剪、IP 只有黑盒。先拿被引用模块名在整个 RTL 目录里做全局搜索,比盯着顶层文件有效得多。分不清 Yosys 各阶段报错位置的,先看 Yosys 语法/解析报错速查 的阶段划分。
二、病因速查表
| 报错现象 | 最可能根因 | 快速验证 | 处置 |
|---|---|---|---|
| 全目录搜不到被引用模块名 | 子模块文件没进 read_verilog 清单 | grep -rl "module uart_rx" rtl/ 无命中 | 把文件补进 read 清单或 read 整个目录 |
| 模块在后读文件里、顶层在前 | 老版本 Yosys 顺序解析,前向引用失败 | 调 swap 两个文件 read 顺序复现 | 升级版本,或先读被引用模块,或加 -defer |
报错对象是 $paramod$... | 参数化例化传参失败,派生模块没生成 | yosys -p "read_verilog x.v; hierarchy -check" 看 paramod 名 | 对齐例化 #(...) 的参数名与定义 |
实例在 generate if 里 | 分支被剪掉,但分支输出在分支外被引用 | 查 generate 条件常量取值 | 修条件,或分支外给输出赋默认 |
| 模块来自第三方 IP 无 RTL | 只有接口/仿真模型,综合侧是黑盒 | IP 目录里有无 .v 综合模型 | 写空壳模块加 (* blackbox *) 属性 |
| 模块名带转义/大小写特殊 | 定义用 \foo_bar 转义名,例化名对不上 | 定义处 module 关键字后逐字符比对 | 统一命名,例化名与定义逐字符一致 |
| 层次化大设计漏读子目录 | 深层子目录的文件没加进 read 列表 | ls 子目录对照 read 清单 | 用 read_verilog dir/*.v 或脚本枚举 |
三、排查决策图
读这张图顺着三级蓝色判定走:第一级问「RTL 里到底有没有这个模块」——没有就是 read 清单漏文件或子目录没枚举,这条线修好之前不用往下查;第二级问「读取顺序是否满足先定义后引用」——老版本 Yosys 按 read 顺序解析,被引用模块读在例化它的文件之后就绑定失败;第三级才进入参数化派生名、generate 分支、黑盒 IP、转义名这些语义层问题。三级从粗到细,跳级查只会绕弯;绿色收尾统一用 hierarchy -check 验证,因为它比完整 synth 跑得快、报错也更聚焦。
四、逐条排查展开
第一步:确认模块真的进了 read 清单。 Yosys 没有工程文件概念,读什么全靠脚本里的 read_verilog 行,「文件在目录里」不等于「读进来了」。先全局搜:
grep -rn "module uart_rx" rtl/搜不到就是文件漏读:要么 build 脚本的 read 清单里没列这个文件,要么用了逐个文件名罗列而新增的子目录文件没人补。批量场景建议直接 read_verilog rtl/*.v rtl/sub/*.v 或写个小脚本枚举,避免手工清单漂移。层次化大设计里这类漏读最常见,和 Yosys 找不到模块速查 的排查思路一致,但本篇更偏「读进来了却绑定不上」的后续链路。
第二步:检查读取顺序与 -defer。 老版本 Yosys(以及 -noautowire 等严格模式下)按 read 顺序做增量解析:如果 top.v 先读、它例化的 uart_rx.v 后读,读到 top 时引用还解析不了。两个稳妥解法:一是把被引用的基础模块放在 read 清单前面;二是给 read_verilog 加 -defer,让所有模块先登记占位、读完全部文件后再统一绑定,顺序就无关紧要了。新版本 Yosys 默认两阶段解析,顺序问题已大幅缓解,但脚本里沿用老式逐文件 read 的工程仍值得显式加 -defer 消掉这类不确定性。
第三步:参数化例化对齐 parameter 名。 参数化模块例化后,Yosys 会生成派生模块名(报错里的 $paramod$... 就是它)。派生失败的常见原因是 #(...) 里的参数名和定义处对不上:
uart_rx #(.BAUD_RATE(115200)) u_rx (...); // 定义里叫 BAUD,这里传 BAUD_RATE参数名必须和模块定义里的 parameter 逐字符一致,写错时 Yosys 解析不出派生模块、elaboration 期报引用失败。修法:打开定义把 parameter 清单抄下来逐条对齐;localparam 不能从外部覆盖,误传也触发同类错。参数值本身超范围(如宽度参数传 0)也会让派生失败,顺手检查。
第四步:generate 分支被剪掉。 generate if (COND) 的条件是常量表达式,不满足的分支在 elaboration 时整段剪掉——分支里的实例随之消失。如果分支外又引用了该实例的输出信号,引用就落空了:
generate if (USE_FIFO) begin : g_fifo
fifo_ctrl u_fifo (...); // USE_FIFO=0 时这个实例不存在
end endgenerate
assign dout = g_fifo.u_fifo.data_out; // 引用落空修法二选一:把条件改成实际需要的取值,或在分支外用 else begin : g_nofifo assign ... 给被剪路径的输出显式赋默认。调参数复现工程时(比如同一个顶层配 USE_FIFO=0/1 两个变体)这类错会周期性出现。
第五步:黑盒 IP 给空壳模块。 第三方 IP 常见形态是只给接口文档和仿真模型,没有可综合 RTL——Yosys 读不到定义,自然报 is not part of the design。标准做法是写一个只有端口声明的空壳模块,打上 blackbox 属性:
(* blackbox *)
module pll_ip (input wire clkin, output wire clkout, output wire locked);
endmodule把这个空壳读进工程,elaboration 就能绑定成功,后续 synth 也会把它当黑盒保留接口、网表交接给后端工具时再链接真实实现。注意空壳的端口名和宽度必须和真实 IP 逐一对齐,否则在后端工具那里又会炸一次。
第六步:转义名与大小写。 Verilog 允许 \foo_bar 这类转义标识符(报错文案里带反斜杠的就是),例化名必须和定义逐字符一致——包括大小写(Verilog 大小写敏感)和转义符本身。团队里有人习惯驼峰、有人习惯蛇形时这类错高发。排查时直接把报错里的模块名原样(含反斜杠)拿去 grep,比对定义处 module 关键字后面的名字。
五、修复后验证与防复发
修完先单独跑 yosys -p "read_verilog ...; hierarchy -check"——它只做层级绑定检查,秒级出结果,比跑完整 synth 等几分钟高效得多。Error 清零后再跑完整流程,并顺手看一眼 Warning 里的未连接端口、未使用实例,它们是下一批 Error 的苗床。
防复发靠四条习惯:一是 build 脚本里 read 清单用目录通配或自动生成,新文件随写随进构建,提交前跑一遍最小 elaboration 验证;二是统一加 read_verilog -defer,从机制上消掉顺序依赖;三是参数化模块的 parameter 名在团队规范里定死命名风格,例化处只允许按名传参(#(.NAME(v)))禁止按位传参;四是黑盒 IP 的空壳模块随 IP 一起进版本库,端口对齐写进 review 检查单。生成阶段更靠后的「信号被优化掉」类问题见 Yosys 信号被优化速查,Quartus 侧同类 elaboration 引用问题的对照见 Quartus 未解析引用速查。
这一篇在知识体系里的位置
本篇属于 FPGA 工具报错速查簇,与 Yosys 找不到模块速查(输入链路角度的姊妹篇)、Yosys 语法/解析报错速查(解析期问题,比 elaboration 更前一个阶段)、Quartus 未解析引用速查(同一类问题在 Quartus 侧的对照)互为姊妹篇。
一句话总结
Yosys 引用无法解析报错的本质是 elaboration 期例化语句绑定不到已读入的模块定义,先取报错里的被引用模块名全局搜索:搜不到补 read 清单,搜得到查读取顺序(统一加 -defer 根治),再往下对齐参数化传参名、检查 generate 分支被剪、给黑盒 IP 写带 blackbox 属性的空壳模块、逐字符比对转义名与大小写;修完用 hierarchy -check 快速验证,防复发靠 read 清单自动化、按名传参规范和空壳模块随 IP 进版本库。