Quartus 未解析引用报错(can't resolve reference)速查
更新时间:2026-10-23。FAQ 速查页,面向 FPGA 入门 阶段的同学。症状很典型:模块明明在工程里、名字看着也对,但 Quartus 跑到 Analysis & Elaboration(细化)阶段就报
can't resolve reference——顶层例化某个子模块时,编译器死活解析不出这个引用指向谁。它和 Quartus 找不到模块速查 是近亲,但侧重不同:那一篇偏「.qsf没把模块文件登记进工程」的工程组织角度,本篇偏「实例化引用在 elaboration 期解析失败」的语义角度——包括参数传错、IP 未生成、generate 分支剪掉这类「文件在、名字对、就是接不上」的情况。
本文要回答的问题
can't resolve reference to object和module not found是一回事吗?- 源文件明明加进工程了,为什么 elaboration 还是解析不出实例?
- 参数化模块
#(...)传参写错会报这个错吗? - IP 核加了
.qip为什么还提示解析不到实例? generate if里的实例报未解析引用,是哪里出了问题?
一、报错原文:细化期的统一文案
Quartus 在 Analysis & Elaboration 阶段要把每一条例化语句绑定到一个真实存在的模块定义上,绑定失败就抛「未解析引用」。典型文案:
Error (10054): Verilog HDL File I/O error at top.v(45): can't resolve reference to object "uart_rx"
Error (12007): Top-level design entity "top" is undefined
Error: Node instance "u_rx" instantiates undefined entity "uart_rx"SystemVerilog / 参数化场景的变体:
Error (10170): Verilog HDL syntax error at top.v(45) near text "("; expecting ".", or an identifier
Error (10228): Verilog HDL error at uart_rx.v(3): module "uart_rx" cannot be declared more than once
Warning (12125): Instance "u_rx" has no actual parameter named "BAUD_RATE"VHDL 侧对应的文案:
Error (10485): VHDL error at top.vhd(60): component "fifo_ctrl" is not declared
Error (10481): VHDL Use Clause error: design library "old_lib" does not contain primary unit "fifo_ctrl"读这类报错抓住两个字段:实例名(u_rx)和被引用对象名(uart_rx)。elaboration 报错的行号在例化语句处,病根却几乎都在别处——文件没进工程、名字对不上、参数不匹配、IP 没生成。先拿被引用对象名去做全局搜索,比盯着例化行有效得多。分不清 Quartus 各阶段报错链路的,先看 Quartus 语法/解析报错速查 的阶段划分。
二、病因速查表
| 报错现象 | 最可能根因 | 快速验证 | 处置 |
|---|---|---|---|
| 全工程搜不到被引用模块名 | .v/.sv 源文件没加进工程(.qsf 无 VERILOG_FILE 行) | grep -i "uart_rx" myproject.qsf 无命中 | Project Navigator → Add File,或补 .qsf assignment |
| 搜得到模块但名字差一点 | 实例名与模块名大小写/拼写不一致(uart_Rx vs uart_rx) | 报错对象名与定义处逐字符比对 | 统一为定义处的名字,Verilog 大小写敏感 |
| 参数化模块例化报错 | #(...) 传参名写错或传了不存在的参数 | Warning 12125 提示的参数名与模块定义比对 | 按模块定义的 parameter 名改例化 |
| 实例名是 IP 核 | .qip/.qsys 未生成(Generate 没跑过)或未加入工程 | ip/<name>/synthesis/ 下是否有生成的 wrapper | 重新 Generate,把 .qip 加进工程 |
| VHDL 组件报 not declared | 组件在 work 以外的库,缺 library/use 声明 | 组件源文件的 -library 归属 | 顶层补 library x; use x.comp.all; |
报错对象是 `include 里的模块 | include 文件路径不在搜索路径,展开失败 | Compile 日志搜 include 文件名 | .qsf 加 SEARCH_PATH 或用相对路径 |
实例在 generate if 里 | 条件分支被剪掉,但别处又引用了该实例的输出 | 查 generate 条件的常量表达式取值 | 修正条件或给被剪分支的输出赋默认 |
三、排查决策图
读这张图顺着三级蓝色判定走:第一级问「工程里到底有没有这个模块」——没有就是 .qsf 漏登记或 IP 没 Generate,这条线修好之前不用往下查;第二级问「名字是否逐字符一致」——Verilog 大小写敏感,uart_Rx 和 uart_rx 是两个符号;第三级才进入参数化、VHDL 库、generate 分支这些语义层问题。三级判定从粗到细,跳级查只会绕弯;绿色收尾是统一动作,因为 Quartus 的增量数据库可能拿旧解析结果掩盖修复。
四、逐条排查展开
第一步:确认源文件真的进了工程。 「文件在目录里」不等于「文件在工程里」——Quartus 只编译 .qsf 里登记的源文件,一行一条:
grep -i "uart_rx" myproject.qsf没有命中就去 Project Navigator → Files 页右键 Add/Remove Files 把文件加进来,或者手工在 .qsf 补一行 set_global_assignment -name VERILOG_FILE rtl/uart_rx.v(SystemVerilog 用 SYSTEMVERILOG_FILE,VHDL 用 VHDL_FILE)。注意 Quartus 对顶层实体名也有要求:Error (12007): Top-level design entity "top" is undefined 多半是 Settings 里 Top-level entity 名字和实际顶层模块名对不上,Assignments → Settings → General 里改对即可。
第二步:逐字符比对名字。 Verilog 是大小写敏感语言,定义 module uart_rx 却例化 uart_Rx u_rx (...),elaboration 就报未解析引用——而且 Quartus 的报错文案不会好心提示「你是不是想写 uart_rx」。把报错里的对象名复制下来,去定义处比对:大小写、下划线位置、结尾有没有多一个 _d。VHDL 虽然不区分大小写,但拼写错误同样走这个文案。团队里如果有人习惯驼峰、有人习惯蛇形,这类错会周期性复发,值得在代码规范里定死。
第三步:参数化模块对齐 parameter 名。 例化带参数的模块时,#(.BAUD_RATE(115200)) 里的参数名必须和模块定义里的 parameter BAUD_RATE 逐字符一致。写错名字(比如定义叫 BAUD 却传 BAUD_RATE)时,Quartus 先抛 Warning (12125): Instance has no actual parameter named ...,随后 elaboration 因参数表对不上而解析失败。修法:打开模块定义,把 parameter 清单抄下来,逐条对齐例化处。SystemVerilog 的 localparam 不能从外部覆盖,误传也会触发同类报错。
第四步:IP 核确认生成状态。 IP 核的典型翻车路径是:Platform Designer 里搭好了,但 Generate HDL 没跑(或跑了但失败了),.qip 指向的 wrapper 文件根本不存在;或者工程迁移后 .qip 没被加进新工程。验证方法很直接:看 ip/<name>/synthesis/ 目录下有没有生成出的 .v/.sv wrapper,没有就回去重新 Generate;有就在 .qsf 里确认有 set_global_assignment -name QIP_FILE ip/<name>.qip 这一行。只加 .qip、不手工加生成物目录——生成物目录入工程是另一种病(重复定义),见 Quartus 依赖缺失速查 里关于 IP 产物链路的说明。
第五步:VHDL 组件补 library 声明。 Quartus 默认所有文件编进 work 库,但如果组件源文件在 .qsf 里指定了 -library old_lib(常见于旧 IP 或第三方库),顶层直接例化就会报 component is not declared。修法是在顶层文件头部补声明:
library old_lib;
use old_lib.fifo_ctrl.all;如果报错文案是 design library "old_lib" does not contain primary unit "fifo_ctrl",说明 library 声明有了、但那个库里确实没有这个单元——回去查 .qsf 里该文件的 -library 归属和文件名是否对应。
第六步:include 路径与 generate 分支。 被引用模块写在 .vh / .svh 头文件里时, `include "defs.vh" 能否展开取决于搜索路径:Quartus 默认只搜当前文件目录和 .qsf 里 SEARCH_PATH 列出的目录。报错对象是 include 里的符号时,在 .qsf 补 set_global_assignment -name SEARCH_PATH rtl/include 即可。generate if 分支问题更隐蔽:条件是常量表达式,不满足的分支在 elaboration 时整段剪掉,如果分支外又引用了该分支里实例的输出信号,就会报未解析引用。修法二选一:把 generate 条件改成实际需要的取值,或在分支外给被剪路径的输出赋默认值。
五、修复后验证与防复发
修完先 Project > Clean Project(或删掉 db/、incremental_db/)再全量重编——elaboration 的结果会被增量数据库缓存,不干净重跑可能看到「修好了还报错」的假象。确认 Error 清零后再看一眼 Messages 窗口:未解析引用相关的 Warning(未使用实例、参数未连接)也顺手清掉,它们是下一批 Error 的苗床。
防复发靠四条习惯:一是新文件随写随加工程,加完立刻 grep 一次 .qsf 确认登记成功,提交前把 .qsf 一起提交——「我这边能编过」多半是 .qsf 没进版本库;二是工程里模块名统一蛇形小写,例化名与模块名的映射关系一眼可读;三是 IP 核 Generate 之后立即编一次最小工程验证 wrapper 可用,工程迁移时 .qip 随 .qsf 一起迁移;四是 generate 条件只用顶层 parameter/localparam 推导,被剪分支的输出在分支外显式赋默认。同簇的「工程层级找不到模块」问题(.qsf 漏登记的更一般形态)见 Quartus 找不到模块速查,外部库/文件整条链路缺失的场景见 Quartus 依赖缺失速查。
这一篇在知识体系里的位置
本篇属于 FPGA 工具报错速查簇,与 Quartus 找不到模块速查(工程组织角度的姊妹篇)、Quartus 依赖缺失速查(外部库/文件缺失链路)、Quartus 语法/解析报错速查(解析期问题,比 elaboration 更前一个阶段)互为姊妹篇。
一句话总结
Quartus 未解析引用报错的本质是 elaboration 期例化语句绑定不到模块定义,先取报错里的被引用对象名做全局搜索:搜不到就查 .qsf 漏登记或 IP 未 Generate,搜得到就逐字符比对大小写拼写,再往下查参数化传参、VHDL library 声明、include 搜索路径和 generate 分支剪掉这四级;根治靠新文件随写随登记、.qsf 进版本库、IP Generate 后立即验证、generate 分支输出赋默认,修完 Clean Project 干净重编闭环。