ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Quartus报错Can‘t find design entity的排查与解决全攻略

Quartus报错Can‘t find design entity的排查与解决全攻略 1. 问题概述这个报错到底在说什么先说说我自己的经历。刚接触 FPGA 那会儿我用的是 Quartus II 13.1操作系统还是 Windows 7开发板是友晶的 DE0。写了一个很简单的 VHDL 计数器点了一下 Start Compilation结果冒出来一行红字“Can‘t find design entity counter”。我当时第一反应是代码写错了翻来覆去检查了好几遍语法VHDL 的 entity、architecture 写得规规矩矩怎么也想不通哪里出了问题。后来才明白这个报错十有八九跟代码本身没关系而是 Quartus 的工程管理逻辑在“捣鬼”。在这之前先给刚上手的读者解释一下“design entity”是什么。VHDL 里的 design entity设计实体就是你写的一个模块由 entity实体和 architecture结构体两部分组成。entity 定义了模块的输入输出端口architecture 定义了模块内部的行为或结构。比如一个最简单的与门entity and_gate is port ( a : in std_logic; b : in std_logic; y : out std_logic ); end entity and_gate; architecture rtl of and_gate is begin y a and b; end architecture rtl;这里的 and_gate 就是 design entity 的名字。Quartus 报“Can‘t find design entity”就是在告诉你我找不到这个叫 and_gate 的模块。但问题在于你明明写了这个模块它却找不到那一定是“找”的路径或者“找”的方式出了岔子。这个报错几乎不会出现在 ModelSim 里单独仿真的时候因为你仿真时可以直接指定一个文件并编译它。但 Quartus 的工程编译是一个多文件、多步骤的过程它需要先知道哪些文件属于这个工程哪些实体是顶层然后按照依赖关系逐级编译。如果某个环节没有正确配置Quartus 找不到设计实体那编译就直接卡死了。这个问题的覆盖面还挺广的。无论是 VHDL 还是 Verilog无论是刚装好的 Quartus 13.1 还是其他版本都可能遇到。甚至在一些大型项目里几十个文件协同编译时也会因为某个文件没加进工程而导致这个报错。接下来我把实际排查中总结的几种典型原因和对应的解决方法全部列出来。2. 排查思路为什么你写得对Quartus 却说找不到遇到这个报错先冷静下来别急着改代码因为问题很可能出在工程层面。我习惯按照从简单到复杂的顺序逐个排查绝大多数情况下都能迅速定位。2.1 文件是否真的加入了当前工程这是最高频的原因也是新手最容易踩的坑。很多刚接触 Quartus 的开发者会直接用 File - Open 打开一个 .vhd 或 .v 文件改完代码后觉得“文件已经打开了应该就在工程里了”然后点编译结果就报错。Quartus 的逻辑跟文本编辑器不一样。你用 File - Open 打开一个文件它只是把这个文件显示在编辑窗口里方便你查看和修改但这个文件并没有被加入到当前工程的编译列表里。Quartus 编译时只会处理工程中登记过的文件在 Project Navigator 面板的 Hierarchy 标签页里能看到那些只是打开但没有加入工程的文件它根本不会去碰。解决方法很简单。在 Project Navigator 面板中切换到 Files 标签页右键点击空白处选择 Add/Remove Files in Project。在弹出的对话框里找到你的 .vhd 或 .v 文件点击 Add 加入工程然后重新编译。![注意] 如果你用的是 Quartus 的 New Project Wizard 新建工程建议在向导的 Add Files 页面就把所有源文件添加进去省得后面再手动补。2.2 实体名与文件名不一致的问题这个问题在 VHDL 里尤其常见。VHDL 标准规定一个 .vhd 文件里可以包含多个 entity但一个 entity 的最佳实践是一个文件只放一个实体并且文件名最好与实体名保持一致。有些同学会图省事把好几个相关的实体写在一个文件里或者文件名随便起比如 counter_top.vhd 里放的却是 entity divider。那么 Quartus 在编译时会基于文件名去推断这个文件里的顶层实体。当你把 counter_top 设为顶层实体时Quartus 在工程里找一个名为 counter_top 的 design entity但你的文件里只有 divider那自然就会报“Can‘t find design entity”。解决办法有两种将文件重命名使其与实体名一致比如 divider.vhd。在工程设置中明确指定顶层实体为 divider。如果是 Verilog情况稍微不同。Verilog 的 module 名和文件名不一定要求一致但 Quartus 默认会把文件名作为顶层模块名来匹配。如果你把一个 module 名为 divider 的代码存在 counter_top.v 里同样会出问题。所以我的建议是不论 VHDL 还是 Verilog统一做到“一个文件对应一个模块文件名等于模块名”这是最省心的做法。2.3 编译顺序组件还没编顶层就急着编这个问题常见于一个工程里有层次化设计的情况。比如你的顶层文件是 top.vhd它例化了子模块 sub_module而 sub_module 的代码写在另一个文件里。Quartus 编译时按一定的顺序处理这些文件如果它先编译了 top.vhd发现在库里找不到 sub_module 这个实体就会报“Can‘t find design entity”。不过这里有一个细节值得注意Quartus 13.1 对于 VHDL 和 Verilog 的处理方式不完全相同。Verilog 的模块间引用通常不需要显式指定编译顺序因为 Verilog 编译器会先扫描所有源文件建立一个模块符号表然后再进行链接。VHDL 则更严格一些它在编译一个实体时如果发现它引用了尚未编译的实体就会直接报错。但即便 Quartus 的编译器足够聪明也建议你在工程设置里显式指定文件编译顺序。操作方法如下在 Assignments - Settings - Compiler Settings 中找到 VHDL Input 或 Verilog Input 相关的选项或者直接在 Project Navigator 的 Files 标签页中调整文件顺序。原则是先编译底层子模块再编译顶层模块。如果工程比较复杂文件很多你也可以把子模块打包到库中然后在顶层通过 library 和 use 子句引用。这样 Quartus 在编译顶层时会先去指定库中查找设计实体只要库名和实体名对得上就不会报错。2.4 顶层实体设置错误Quartus 的工程里只能指定一个顶层实体。如果你已经把文件加入了工程文件名和实体名也对得上但依然报错那就要检查一下顶层实体的设置是否正确。在 Project Navigator 面板中右键点击你想要作为顶层实体的文件选择 Set as Top-Level Entity。设置完成后这个文件的名字会变成加粗显示并且在 Hierarchy 标签页中显示为顶层节点。有时候工程里文件很多你上一次编译用的顶层的 A 模块这一次需要把 B 模块设为顶层但忘了改设置。这时候 Quartus 依然会按照上次的设置去编译 A 模块。如果 A 模块不在当前工程的文件列表里或者 A 模块的代码已经被改得没法独立编译了就会出现“Can‘t find design entity”的报错。检查方法在 Assignment - Settings - General 中查看 Top-level entity 一栏填的是什么确保它是你期望的那个设计实体。3. 进阶排查工程文件和库管理的隐藏陷阱如果按照上面几个方法做了问题依然存在那就要往更深层的地方排查了。Quartus 的工程管理有一些历史遗留的“坑”在 13.1 版本里尤其明显。3.1 工程路径和文件名的“禁区”Quartus II 13.1 发布年代比较早对中文路径的支持并不完善。如果你的工程路径或者文件名里包含中文、空格、特殊字符比如 #、 等Quartus 在处理时可能会出现各种奇怪的问题其中就包括“Can‘t find design entity”。举个例子有人把工程放在D:\课程设计\电子钟\目录下文件名是时钟分频.vhd。Quartus 在读取这个文件时文件名中的中文字符可能没法被正确解析导致工程数据库里记录的实体名乱码或者为空编译时自然找不到实体。解决办法很粗暴把所有工程相关的文件复制到一个纯英文、无空格的路径下比如D:\FPGA\clock_dev\然后把文件名改成clk_div.vhd重新建立工程或者重新添加文件。这一步虽然麻烦但能解决大量奇怪问题。另外一个与路径相关的坑是当你把一个工程文件夹移动位置后Quartus 会找不到原有的文件关联。这时候打开工程它会提示你定位缺失的文件。如果你点了“忽略”或者定位错了文件后续编译时也容易出幺蛾子。所以我每次移动工程文件夹都会重新生成一次工程文件而不是直接打开旧的 .qpf。3.2 文件被排除或者类型不对在 Project Navigator 的 Files 标签页中每个文件前面有一个复选框。如果复选框没有被勾上就代表这个文件被排除在工程之外Quartus 编译时不会处理它。有时候你不小心取消了勾选或者某个默认操作把它排除了就会导致编译器找不到对应的实体。[注意] 被排除的文件在列表中会显示为灰色一眼就能辨认。右键文件选择 Enable 可以重新启用。还有一种情况是文件类型不对。比如你写的是 VHDL 代码文件后缀却是 .vVerilog 的扩展名Quartus 在解析时可能会按 Verilog 语法来处理导致无法识别实体。反过来也一样。解决办法是确保文件扩展名与内容一致VHDL 用 .vhd 或 .vhdlVerilog 用 .v。3.3 库名引用错误VHDL 中的库管理是一个容易忽视的细节。默认情况下所有编译的设计实体都会放在 work 库中如果你在代码里通过library work; use work.all;引用一般不会出问题。但有些开发者习惯把子模块放在自定义库里比如library mylib; use mylib.all;如果 Quartus 工程里没有创建名为 mylib 的库或者子模块没有被编译进 mylib 库那么编译器在查找实体时就会扑空报出“Can‘t find design entity”或者类似的错误。解决方法是在工程设置中创建对应的库Assignments - Settings - Libraries在 Project libraries 区域添加库名 mylib并指定它对应的文件夹。然后确保所有需要放进 mylib 库的源文件在编译时被标记为 “Compile into mylib”。不过说句实在话对于中小型项目我建议大家别折腾自定义库统一用默认的 work 库就好了。自定义库虽然看起来清晰但它引入了额外的管理复杂度很多时候错误都出在库配置上而不在代码本身。3.4 Quartus 工程缓存损坏这种情况相对少见但一旦碰上就很棘手。Quartus 的工程在编译过程中会产生大量的中间文件和缓存数据比如 db 文件夹、incremental_db 文件夹等。如果这些文件损坏比如异常断电、磁盘写满、杀毒软件误删Quartus 内部维护的模块信息可能就乱了编译时报什么错都有可能包括“Can‘t find design entity”。判断是不是缓存损坏的办法有两个重新编译一次看报错信息是否每次都在同一个地方。新建一个工程把源文件全部添加进去编译试试。如果新工程没问题而旧工程一直报错那大概率就是旧工程缓存坏了。解决办法也很直接关闭 Quartus删除工程目录下的 db 和 incremental_db 文件夹然后重新打开工程并编译。这相当于强制 Quartus 重新建立所有的中间信息虽然编译时间会变长一些但通常能解决问题。这里再多说一句Quartus 13.1 是 32 位软件内存占用管理方面有些局限。如果你编译的工程特别大它可能会因为内存不足而出现一些奇奇怪怪的编译错误。这种情况下建议把工程拆分成多个子模块分别编译或者升级到 64 位的 Quartus 版本比如 Quartus Prime。4. 实操演示从零开始走一遍完整流程前面几节讲的是原理和排查方法这一节我用一个实际例子把完整的操作流程走一遍方便新手直接照着做。假设我们要完成一个简单的 4 位二进制计数器文件规划如下counter.vhd二进制计数器模块segment_decoder.vhd七段数码管译码模块top_counter.vhd顶层模块连接 counter 和 segment_decoder这是一个典型的层次化设计非常适合用来复现和解决之前提到的各种问题。第一步创建工程。 打开 Quartus II 13.1选择 File - New Project Wizard。工程名命名为 counter_top工程目录选择纯英文路径比如 D:/FPGA_work/counter_top。在 Add Files 页面暂时不添加任何文件直接点 Next 直到 Finish。第二步新建三个 VHDL 文件并编写代码。 这一步大家应该都会我直接列出核心代码重点看后面编译环节的操作。counter.vhdlibrary ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity counter is port ( clk : in std_logic; rst_n : in std_logic; count : out std_logic_vector(3 downto 0) ); end entity counter; architecture rtl of counter is signal cnt_reg : std_logic_vector(3 downto 0); begin process(clk, rst_n) begin if rst_n 0 then cnt_reg (others 0); elsif rising_edge(clk) then cnt_reg cnt_reg 1; end if; end process; count cnt_reg; end architecture rtl;segment_decoder.vhdlibrary ieee; use ieee.std_logic_1164.all; entity segment_decoder is port ( bin_in : in std_logic_vector(3 downto 0); seg_out : out std_logic_vector(6 downto 0) ); end entity segment_decoder; architecture dataflow of segment_decoder is begin with bin_in select seg_out 1000000 when 0000, 1111001 when 0001, 0100100 when 0010, 0110000 when 0011, 0011001 when 0100, 0010010 when 0101, 0000010 when 0110, 1111000 when 0111, 0000000 when 1000, 0010000 when 1001, 1111111 when others; end architecture dataflow;top_counter.vhdlibrary ieee; use ieee.std_logic_1164.all; entity top_counter is port ( clk : in std_logic; rst_n : in std_logic; seg : out std_logic_vector(6 downto 0) ); end entity top_counter; architecture structural of top_counter is component counter is port ( clk : in std_logic; rst_n : in std_logic; count : out std_logic_vector(3 downto 0) ); end component; component segment_decoder is port ( bin_in : in std_logic_vector(3 downto 0); seg_out : out std_logic_vector(6 downto 0) ); end component; signal count_internal : std_logic_vector(3 downto 0); begin u_counter : counter port map ( clk clk, rst_n rst_n, count count_internal ); u_segment : segment_decoder port map ( bin_in count_internal, seg_out seg ); end architecture structural;第三步把文件添加到工程。 在 Project Navigator 的 Files 标签页右键选择 Add/Remove Files in Project把三个 .vhd 文件全部添加进去。注意检查它们前面的复选框是否处于勾选状态。第四步设置顶层实体。 在 Project Navigator 中右键 top_counter.vhd选择 Set as Top-Level Entity。此时 Hierarchy 标签页的顶层应该显示为 top_counter 节点。第五步编译。 点击工具栏上的 Start Compilation 按钮。正常情况下应该能够顺利通过编译。为了把这个问题讲透我再刻意制造一个错误场景。假如第三步中我只添加了 top_counter.vhd 和 counter.vhd漏了 segment_decoder.vhd。编译时Quartus 就会在综合阶段报出类似这样的错误Error (12007): Top-level design entity top_counter is undefined或者Error (10482): VHDL Object segment_decoder is not declared如果 Quartus 的报错直接指向 segment_decoder 找不到那就说明问题出在漏文件或者编译顺序上。这时候回到 Files 标签页把 segment_decoder.vhd 添加进来重新编译问题即可解决。5. 常见问题速查与经验总结为了更直观地帮助大家定位问题这里整理了一份速查表把常见的报错原因、特征和解决方法对应起来。常见原因典型特征解决方法文件未加入工程文件在编辑器里能打开但编译时报找不到实体右键 Files 面板添加文件到工程实体名与文件名不一致代码中实体名和文件名对不上通常 VHDL 多见统一文件和实体名或在工程设置中指定顶层实体顶层实体设置错误编译时使用了错误的顶层模块右键文件选择 Set as Top-Level Entity编译顺序错误顶层引用子模块但子模块尚未编译调整文件顺序先编译底层再编译顶层文件被排除文件在 Files 面板显示为灰色勾选文件前面的复选框或右键 Enable扩展名错误.vhd 文件被写成 .v 后缀或反之修改文件扩展名使其与代码内容匹配库引用错误顶层代码中引用了自定义库但库并不存在在 Settings 中创建并指定库或改用 work 库中文路径或特殊字符工程路径包含中文、空格等特殊字符将工程移动至纯英文路径Quartus 缓存损坏多种奇怪报错反复编译都无法消除删除 db 和 incremental_db 文件夹后重新编译工程文件被移动位置打开工程时提示文件找不到重新定位文件或直接重建工程这些原因里面前四个占了大约八成以上的情况。如果你遇到的问题不在这张表里那大概率属于比较特殊的场景可以参考下面几个进阶排查技巧。技巧一查看完整编译信息。在 Quartus 底部的 System 窗口里切换到 Processing 标签页点开有红色错误标志的行确认错误编号和具体信息。不同错误编号对应的问题根源差别很大例如 Error 12007 通常是顶层实体问题Error 10482 通常是引用的子模块未定义把错误编号记下来去搜索可以更快找到解决方案。技巧二用 ModelSim 单独编译验证代码。如果你的 VHDL 代码在 ModelSim 里能正常编译和仿真那就基本证明代码语法和实体定义没有问题问题一定出在 Quartus 工程配置上。这可以帮助你把问题的排查范围缩小一半。技巧三新建工程重新添加文件。Quartus 的工程文件有时会因为版本兼容问题而变得混乱。如果你现有工程怎么修都修不好不妨新建一个空白工程把所有源文件重新添加然后设置顶层实体再编译。这个“笨办法”其实特别高效我至少用这个方法解决过十几次疑难杂症。技巧四注意版本差异。Quartus II 13.1 和 Quartus Prime 在处理某些 VHDL 语法上是有差异的。如果你的代码在 13.1 上报错但语法本身符合 VHDL-2008 标准那可能是 13.1 不支持标准里的某些新特性。这种情况建议查阅软件的 Language Templates看看官方支持的语法范围。6. 补充一个容易忽略的点VHDL 与 Verilog 的处理差异上面大部分内容同时适用于 VHDL 和 Verilog但两者在处理“设计实体”这个问题上确实有一些差异单独拿出来说说。对于 Verilog 用户Quartus 在编译时对模块名的匹配相对宽松。只要你的 module 名称在某个添加进工程的文件里是唯一的编译器通常都能找到。Verilog 不太容易出现“Can‘t find design entity”的报错即使出现了原因也多半是文件没加进工程或者文件被排除了。不过 Verilog 有一个特殊情况如果你使用 include 语句包含了其他文件但这些被包含的文件没有单独添加到工程里Quartus 在编译时也能通过 include 指令找到它们。但如果你同时把被包含的文件也添加进了工程并且该文件里没有独立的 module 定义Quartus 可能会因为没有可编译的模块而报警告。这种情况虽然不会直接导致“Can‘t find design entity”但也容易让人误解。对于 VHDL 用户我额外提醒一点component 声明里的实体名必须以编译过的实体为准。比如你在顶层写了component counterQuartus 在编译时会在 work 库里查找名为 counter 的实体。如果 counter 实体的文件存在但编译失败了比如语法错误那么顶层也会因为找不到 counter 而跟着报错。所以当顶层报错时不妨先看看底层文件有没有编译错误底层一旦报错顶层常常会伴生“找不到实体”的假象。7. 后续扩展建议这节聊聊“接下来还能怎么做”这个问题解决了之后可以往哪些方向继续深入。第一学习使用 Tcl 脚本管理 Quartus 工程。Quartus 支持 Tcl 命令行操作包括创建工程、添加文件、设置顶层实体等。对于一个包含几十个文件的工程用 Tcl 脚本批量管理比手动操作高效得多。我通常在工程根目录下维护一个 setup.tcl 文件里面写好所有文件列表和编译选项下次重装软件或者换电脑时直接执行一条命令就能恢复整个开发环境。第二理解层次化设计的工程组织方式。在大型 FPGA 项目中设计会被拆成多个子模块每个子模块对应一个文件目录各目录之间通过顶层模块连接。这种组织方式下“Can‘t find design entity”这种报错考验的其实是开发者对工程结构和依赖关系的理解。你可以尝试用 Quartus 的 Block Diagram File.bdf来图形化搭建层次结构这会有助于直观理解设计层次。第三建立一个“工程自查清单”。把本节速查表里的内容整理成一个文档每次新建工程、添加文件、编译前都快速过一遍。开发中很多时间浪费在找这种低级报错上而清单能大大减少重复踩坑的概率。我现在每开始一个新项目都会先检查路径是否合规、文件是否添加完整、顶层实体是否正确确认无误后才开始写代码。这样做的好处是写代码的过程不会被工程配置问题打断专注度会高很多。根据我个人的经验Quartus II 13.1 虽然是个老版本但在教学和中小型项目里依然非常稳定可靠。“Can‘t find design entity”这个报错本质上不是代码问题而是工程管理问题。把工程配置理顺了这个报错自然就消失了。如果你按照今天文章里的流程走一遍绝大多数情况下都能在十分钟之内解决问题。
返回列表