Quartus 未定义符号/对象速查(undefined entity / identifier not declared)
更新时间:2026-10-23。FAQ 速查页,面向第一次撞上 Quartus 编译「对象找不到」类报错的同学。语法错误(Error 10170)请先看语法本身;「工程里明明有这个模块却报找不到」的场景本篇收口,姊妹篇 Quartus 找不到模块速查 讲更宽泛的 module not found 家族,Xilinx 侧对应问题见 Vivado 未定义符号速查。
报错原文长什么样
Quartus 的「找不到定义」类报错有很高的辨识度,先对号入座:
Error (12007): Top-level design entity "top" is undefined
Error: Node instance "u_fifo" instantiates undefined entity "my_fifo"
Error (10482): VHDL error at ctrl.vhd(23): object "data_in" is used but not declared
Error (10500): VHDL syntax error ... near text "ieee"; expecting an identifier
Error (10170): Verilog HDL syntax error at top.v(41) near text: "wire"; expecting an identifier
Error (10028): Can't resolve multiple constant drivers for net "cnt" at top.v(55)
Warning (10236): Verilog HDL Implicit Net declaration for "rst_n" creates implicit wire
Error: Can't find port "clk" in entity "pll_0"注意最后一类 multiple constant drivers(多重驱动)经常被误搜成「未定义」——它不是找不到定义,而是两个 always 块同时驱动同一根网线,属于另一类问题,本篇不收口,但列在这里帮你分流。
把报错先按阶段分成两类:Top-level design entity is undefined 和 instantiates undefined entity 属于分析与综合(Analysis & Synthesis)阶段——Quartus 在展开层级时找不到定义体;object ... used but not declared、identifier not declared 属于编译单元内部——声明顺序或库引用问题;Can't find port ... in entity 则是例化点与声明对不上。三类根因不同,修法也不同。
一句话根因
Quartus 未定义符号 = 编译器展开设计或编译某个文件时引用了一个名字,但这个名字的定义既不在当前工程的文件列表里,也没有由库(library)、IP 生成文件或预处理展开提供。 根因几乎总落在六类:文件声明了但没加进工程、端口/例化名与声明不符、VHDL 缺 library/use 或 package 没编译、宏与 include 路径问题、default_nettype none 禁掉隐式网线后报未声明、IP 核仿真模型与综合模型混用。
排查决策流程
读这张图抓住一条主线:红色是入口现象,蓝色五个判定节点对应六类根因中的五个查法(端口名与防复发合并在内),每个蓝节点只回答一个 yes/no 问题,命中哪个就走对应的橙色修复,最后汇到绿色「重新 Analysis 通过」和紫色防复发。不要跳过蓝节点直接改代码——先判定根因落在哪一类,一次只修一处。
原因速查表
| 根因 | 典型报错 | 快速验证 | 处置 |
|---|---|---|---|
| 1 文件没进工程 | instantiates undefined entity / Top-level design entity is undefined | Project Navigator → Files 看文件是否在列表;grep -rn "module xxx" ./ 确认磁盘上存在 | Project → Add/Remove Files,或在 qsf 加 set_global_assignment -name VERILOG_FILE xxx.v |
| 2 端口/例化名不符 | Can't find port "clk" in entity | 逐字对比例化点与 module/entity 声明(大小写、下划线) | 改例化点或改声明,Verilog 大小写敏感 |
| 3 VHDL 缺 library/use 或包未编译 | object "ieee" is used but not declared / 包内符号 not declared | 文件头是否有 library ieee; use ieee.std_logic_1164.all;;自定义 package 文件是否在引用文件之前加入工程 | 补库引用;把 package 文件加进工程并保证编译顺序 |
| 4 include/宏问题 | 报 macro 未定义或 include 文件找不到 | 查 qsf 里 SEARCH_PATH / VERILOG_INCLUDE_FILE 是否含头文件目录 | 在 Settings → Verilog HDL Input 补 include 路径 |
| 5 default_nettype none 次生报错 | near text: "wire"; expecting an identifier 或 net 未声明 | 文件头有 `default_nettype none,而代码靠隐式网线 | 给隐式用到的网线显式 wire 声明,或在文件尾恢复 `default_nettype wire |
| 6 IP 模型混用 | 报 IP 单元 undefined,或端口对不上 | IP 是否重新 Generate HDL;例化的是 xxx.v(综合模型)还是 xxx_sim.v(仿真模型) | Quartus 里重新 Generate;综合工程引用综合模型,仿真工程引用仿真模型,别混 |
| 7 顶层实体名指错 | Top-level design entity "xxx" is undefined | Settings → General → Top-level entity 名字与 RTL 顶层是否逐字一致 | set_global_assignment -name TOP_LEVEL_ENTITY 正确名 |
逐条排查步骤
还有一个高频变体值得先排掉:顶层实体名指错。Top-level design entity "top" is undefined 经常不是文件缺失,而是 Settings → General 里的 Top-level entity 填了旧名字,或者从别人的工程拷贝 qsf 时顶层名没改。处理顺序是先核对顶层名设置,再去查文件列表,顺序反了会白加一堆文件。
第 1 条(文件没进工程)是 beginner 工程里命中率最高的一类。 Quartus 与 Vivado 一样对源文件做「惰性登记」:Project Navigator 里看到的是文件清单,真正编译时才按层级展开找定义。「文件在磁盘目录里」和「Quartus 看得见」是两回事——必须出现在 Files 列表。命令行核实方式:在工程目录跑 grep -n "VERILOG_FILE\|VHDL_FILE" *.qsf,看报错模块对应的文件行是否存在;缺失就加文件后重跑 Analysis & Synthesis。
第 2 条端口名不符有一个 Quartus 特有的坑:错误信息指到例化点那一行,而真正的拼错可能在声明处。Can't find port "clk" in entity "pll_0" 的意思是「pll_0 这个 entity 的端口表里没有 clk」,常见真相是 IP 重新生成后端口名从 clk 改成了 refclk,例化代码没跟着改。逐字对比端口表 10 秒能做完,先做。
第 3 条 VHDL 库问题分两种形态:一是文件头缺 library ieee; use ieee.std_logic_1164.all;,std_logic 这类类型直接报 not declared;二是自定义 package 文件加了但排在引用它的文件之后——Quartus 默认按 qsf 中文件顺序编译,包必须在前。把 package 文件在 Files 列表里上移,或直接调整 qsf 中 assignment 的顺序。
第 5 条 default_nettype none 是「为了代码规范引入的报错」:团队为了抓隐式网线拼写错误,在文件头加了 `default_nettype none,结果所有靠隐式声明的网线(比如 assign led = cnt[25]; 里没声明的 led)全部变成「expecting an identifier」或未声明错误。正确修法不是去掉这条指令,而是给每个用到的网线补显式 wire 声明;确实要放宽,就在该文件末尾恢复 `default_nettype wire,只影响本文件。
第 4 条 include/宏的判断手法:报错名字是宏(如 WIDTH)或报 include 文件打不开时,先在工程目录跑 grep -rn "define WIDTH" . 确认宏定义在哪个头文件里,再检查 Settings → Verilog HDL Input 的 include 路径是否覆盖那个目录。头文件和源文件同目录时 Quartus 通常找得到,跨目录就必须显式加路径。
第 6 条 IP 模型混用:Quartus 的 IP(Platform Designer 或 IP Catalog 生成)通常同时产出综合用 HDL 和仿真用 *_sim 模型。综合工程里引用仿真模型(或反之)会出现「单元存在但端口/参数对不上」或干脆 undefined。处理纪律:升级 Quartus 版本后所有 IP 重新 Generate HDL;qsf 里引用的生成文件路径指向当前版本的输出目录。
修复后验证
处置完别直接跑全编译,先单点验证:
quartus_map <project> --rev=<revision>quartus_map 只做 Analysis & Synthesis,分钟级出结果,不再出现 undefined / not declared 字样才算定义链完整。GUI 党对应 Processing → Start → Start Analysis & Synthesis。确认通过后再跑全量 Fitter。
防复发
- qsf 进版本库,工程用脚本重建。Quartus 的 IP 生成目录(
ip/、qsys/中间产物)通常不入库,换机器后未定义符号成片出现——用project_archive或 Tcl 重建脚本保证可复现。 - 升级 Quartus 版本后第一件事重新 Generate 所有 IP,旧版生成文件与新版本端口定义可能不一致。
- VHDL 工程固定文件顺序约定:package 文件命名加
00_前缀排在最前,避免顺序漂移。 default_nettype none全工程统一:要么全用并补显式声明,要么不用,别一半一半。- 例化 IP 后端口改名要全局搜:IP 重新生成端口变化时,
grep -rn "u_pll" rtl/把例化点一次改全。
一句话总结
Quartus 未定义符号的本质是「编译器引用了一个名字但找不到定义体」:按「文件进没进工程 → 端口/例化名逐字比对 → VHDL library/use 与包顺序 → include 路径与 default_nettype none → IP 综合/仿真模型是否混用」六类根因逐条收敛,修复后先跑 quartus_map(或 Start Analysis & Synthesis)单点验证再全编译;防复发靠 qsf 版本化、升级后重新生成 IP、包文件置前三条工程纪律。