
很多朋友装完 Quartus Prime Lite Edition双击图标之后对着界面能愣十分钟——新版界面和网上搜到的那些 Quartus II 老教程完全对不上工具栏密密麻麻的英文按钮新建项目的入口找了半天才摸到结果进了向导又不知道该勾什么、跳过什么。这篇我用自己的实际流程把 Quartus Prime Lite Edition 从新建项目到 ModelSim 仿真的完整过程捋一遍以 Cyclone IV 开发板为例Cyclone V、MAX 10、Cyclone 10 LP 这些学习常用的器件操作完全一致。内容适合刚装好工具、还没跑通第一个仿真的初学者也适合从老版本 Quartus II 迁移过来的朋友照着一步步操作就能看到波形。1. 把话说在前面Lite Edition 和 ModelSim 的搭配逻辑1.1 免费版不是“残废版”先搞清楚它能干什么Quartus Prime Lite Edition 是 Intel 在 Quartus II 基础上改版推出的免费工具很多人一看“Lite”这个词心里就打鼓觉得功能被砍得没法用。实际上对学习、竞赛、毕业设计这个量级的 FPGA 开发来说它支持的范围完全够。Lite 版支持 Cyclone IV、Cyclone V、Cyclone 10 LP、MAX 10、MAX V 这些教学和 DIY 圈最常见的器件家族市面上绝大多数开发板用的芯片都在这个列表里。Standard 版和 Pro 版支持的 Arria、Stratix、Agilex 这些高端系列初学者基本碰不到。所以选型这件事不用纠结官方免费渠道能下载、能正常安装、能长期更新的版本就是 Lite 版。而且它的授权方式也很干脆装完不需要 License 文件不需要额外激活工具本身就能直接用。这点对刚入门的同学特别重要少一个环节就少一个坑。我还想多啰嗦一句网上搜“ModelSim 破解”“ModelSim 激活”之类关键字会出来一堆来路不明的安装包和注册机真的别碰。Quartus Prime Lite 安装包里自带的 ModelSim Intel FPGA Starter Edition 就是免费的功能上和商业版的核心能力基本一致仿真 Verilog 和 VHDL 都没有问题只是仿真性能以及个别高级调试特性有一些限制。对个人学习来说绰绰有余。折腾破解版既浪费时间又容易引入安全风险没必要。1.2 版本匹配是第一道隐形坑这是我见过初学者踩得最多的一处。Quartus Prime 的安装程序和 ModelSim 是组件关系不是两个完全独立的软件。你下载 Quartus Prime Lite 的安装包之后在安装界面勾选组件时一定要留意里面有没有选上 ModelSim具体名称一般是 ModelSim Intel FPGA Starter Edition。安装包默认会勾上但如果你手快把组件列表里的东西全取消了后面想补装就麻烦一些。还有个常见问题是版本错位。如果你电脑里已经装了一个 ModelSim SE 或者别的版本然后又在 Quartus 的仿真设置里手动指到了那个路径经常会出现启动仿真时打不开或者打开后编译报错的情况。最稳妥的做法就是用 Quartus Prime Lite 安装时自带的那个 ModelSim 组件路径也让它自己配好。不同版本之间的兼容性虽然 Intel 官方一般有保证但自己手动混搭版本一旦出问题就很难判断是设计的问题还是工具环境的问题。另外Quartus Prime Lite 加上 ModelSim 全部装完磁盘占用大约十个 G 起步安装时间也比较长。装的时候耐心点不要把安装窗口关了也别边装边去打开其他大型软件我遇到过安装过程中磁盘空间不足导致组件缺失的情况后面排查起来很烦。1.3 打开 Quartus 后先认识这几个地方新版 Quartus Prime 的界面和老的 Quartus II 差别确实不小。最显眼的左边是 Project Navigator 面板里面分了 Hierarchy、Files、Design Units 等几个标签页中间是主工作区显示器件视图或者代码编辑器下方是 Messages 窗口编译信息、错误提示都在这最上面是菜单栏和工具栏。工具栏上最常用的就是那个开始编译的按钮以及启动 RTL Simulation 的入口在 Tools 菜单里这两个后面都会用到。第一次打开可能还会弹出一个欢迎页可以关掉不影响流程。版本之间小界面可能会有细微差别但核心菜单和操作顺序基本是固定的这篇文章里提到的按钮名称你在 20.x、21.x、23.x 这些常见版本里都能找到。2. 新建项目时最关键的三个设置2.1 工程名和目录别用中文路径新建项目是从 File - New Project Wizard 开始的新版首页一般也有 New Project 按钮点进去就是同一个向导。第一步要填 Directory、Name 和 Top-Level Entity。这里有个非常容易忽略的细节工程路径里绝对不能有中文也最好不要有空格。ModelSim 在后台调用编译器时对路径比较敏感路径里有中文会导致编译阶段莫名其妙报错而且报错信息往往不直观让人排查半天。Top-Level Entity 默认会跟着工程名走一般保持默认就行但你要清楚这个字段表示的是顶层模块的名字。这个顶层模块必须和工程里实际存在的模块名一致如果后面你写了模块叫 counter4 但顶层实体名还是别的编译会直接报错。2.2 器件选择看开发板丝印别瞎猜向导中间有一个 family 和 device 选择的步骤。很多人在这一步卡住不知道该选什么芯片。最简单的解决办法看开发板上的芯片丝印。以常见的 Cyclone IV 开发板为例板子上最大的那颗芯片上会印着类似 EP4CE10F17C8 这样的型号你在器件选择界面的 Search 输入框里直接输入型号的一部分或者先选 Family 为 Cyclone IV E再在型号列表里找对应的封装和速度等级。如果你用的板子是官方开发板或者某个大厂出的板卡还可以在向导里选择开发板套件。不过对大多数学习场景来说手动选具体芯片型号更可靠因为兼容板太多套件列表里不一定会收录。这一步选错的话后面的引脚分配和编译都会有问题所以下板之前一定确认好芯片型号。2.3 EDA Tool Settings在这里告诉 Quartus“仿真用 ModelSim”很多初学者新建完项目就开始写代码写完才发现仿真工具没配置。Quartus 里要通过 Assignments - Settings - EDA Tool Settings 找到 Simulation 这一栏然后把 Tool name 选成 ModelSim Intel FPGAFormat 选 Verilog这样才能用 RTL Simulation 一键把 ModelSim 拉起来。这里有一处重点如果你希望 Quartus 启动 ModelSim 时自动编译你的 testbench就得在 Simulation 选项卡里勾选 Compile test bench然后在 Test Benches 弹窗里点 New填上 test bench name、顶层模块名再添加对应的 .v 文件。这一步很多教程没讲透导致不少人进了 ModelSim 之后发现没有仿真模块可用。我建议初学者从一开始就按这个规范来设计文件放工程里testbench 通过 Compile test bench 配置好让工具帮你自动编译。3. 从计数器开始一个能完整跑通仿真的设计3.1 为什么第一个仿真实例选计数器计数器是 FPGA 入门最能说明问题的设计有时钟输入有异步复位有寄存器输出还能用波形直观看到数值变化。你不需要理解复杂协议也不用关心状态机怎么写把代码敲进去、编译通过、仿真看到波形这一整套流程就闭环了。等这个最简单的流程跑通后面写状态机、写通信协议时遇到问题也知道去哪里排查。3.2 先写一个 4 位计数器用 Verilog 描述一个 4 位计数器逻辑上就三件事时钟上升沿触发、复位时清零、否则每个周期加一。完整的模块代码如下module counter4 ( input wire clk, input wire rst_n, output reg [3:0] count ); always (posedge clk or negedge rst_n) begin if (!rst_n) count 4d0; else count count 1b1; end endmodule这里有几个细节值得展开说一下。rst_n是低电平有效的异步复位信号所以敏感列表里用negedge rst_nif 里判断!rst_n。count在always块里被赋值所以声明为reg但它的实际硬件是一个寄存器不是软件概念里的变量。是非阻塞赋值在时序逻辑里必须用这个看起来不起眼的写法用成会导致仿真行为完全不一样。3.3 编译之前先想清楚一件事代码写完之后建议先点击 Processing - Start Analysis Synthesis也就是只做分析和综合快速检查语法和基本连接关系而不要一上来就 Start Compilation。Start Compilation 是全流程综合加布局布线虽然也可以但对第一次跑通流程的人来说Analysis Synthesis 的反馈更直接报错也容易定位。如果编译通过Messages 窗口会给出零错误零警告哪怕有 warning 也别慌很多 warning 只是提醒你没有约束时序初期不影响仿真。如果编译报错最常见的有几种可能模块名和文件名不一致、顶层实体设置错误、endmodule 没写或者多写、信号位宽不匹配。这类错误信息都比较明确顺着报错行号去看就行。3.4 用 RTL Viewer 检查连接关系Analysis Synthesis 通过之后可以顺手打开 RTL Viewer 看一下工具生成的原理图。路径是 Tools - Netlist Viewers - RTL Viewer。这一步强烈建议做一次它能把你的代码翻译成寄存器传输级的电路连接让你直观看到 clk、rst_n、count 之间的关系也能验证代码里端口连接有没有意图之外的结果。我第一次看 RTL Viewer 的时候发现工具把某些信号合并了这才理解综合器会做优化和预想的不完全一样。4. Testbench 的写法先给仿真器一个“激励剧本”4.1 Testbench 和设计代码的本质区别Testbench 在英语里直译是“测试台”它和真正烧到 FPGA 里的设计代码是两套东西。设计代码要能被综合成硬件电路所以里面不能写initial、不能写forever这些语句在综合时没有对应的硬件结构。但 testbench 恰恰相反它跑在仿真器里目的就是产生时钟、复位、数据这些激励所以可以随意使用initial和forever完全不用考虑能不能综合。理解这个区别很重要因为很多初学者会把 testbench 里的initial写到设计代码里然后综合时报一堆语法错误。记住一句话设计代码写给硬件看testbench 写给仿真器看。4.2 时钟和复位信号怎么产生Testbench 里最基础的三件事是初始化信号、生成时钟、生成复位。时钟生成最常见的写法是initial begin clk 1b0; forever #10 clk ~clk; end#10表示延迟 10 个时间单位forever让时钟每 10 个单位翻转一次周期就是 20 个时间单位。配合开头的timescale 1ns / 1ps相当于每隔 10ns 翻转一次得到一个 50MHz 的时钟。复位生成则更简单先把复位拉低一段仿真时间再拉高释放initial begin rst_n 1b0; #100; rst_n 1b1; end这里要注意顺序clk和rst_n必须都要在 initial 块里赋初值。如果只写rst_n 1b0而忘记给clk赋初值仿真的波形里clk就是 X 态红色整个仿真结果都会受影响。这是 ModelSim 波形改成红线的头号原因后面专门说。4.3 一份完整的 Testbench 代码把前面提到的元素拼起来再实例化待测模块 counter4一份完整的 testbench 长这样timescale 1ns / 1ps module counter4_tb; reg clk; reg rst_n; wire [3:0] count; counter4 uut ( .clk (clk), .rst_n (rst_n), .count (count) ); // 时钟50MHz周期 20ns initial begin clk 1b0; forever #10 clk ~clk; end // 复位先拉低 100ns再释放 initial begin rst_n 1b0; #100; rst_n 1b1; end // 仿真到 600ns 时停止 initial begin #600; $stop; end endmoduleuut是 Unit Under Test 的缩写这是业内通用的命名习惯。端口连接用的.clk(clk)这种写法叫名字例化比位置例化安全得多不会因为信号顺序写错导致连接错乱。最后的$stop是告诉仿真器在这里暂停方便你打开波形查看如果用$finish则直接结束仿真。5. ModelSim 波形出炉从启动到红线排查5.1 一键启动 RTL Simulation 背后发生了什么代码和 testbench 都准备好了设置里也配好了 Compile test bench下一步就是点 Tools - Run Simulation Tool - RTL Simulation。这时候 Quartus 会在后台自动调用 ModelSim并传入一个根据当前工程生成的 do 脚本。这个脚本会自动把所有设计文件和 testbench 编译进 work 库然后打开 ModelSim 界面。所以你会看到 ModelSim 启动后 Transcript 窗口里已经有一堆日志滚动这一步是自动完成的不需要你手动去 add file、compile。等日志滚完ModelSim 的 Library 标签页里 work 库下面会出现 counter4_tb 这个编译单元Sim 面板里可以看到你加载的仿真对象。如果你之前没有勾选 Compile test bench此时 work 库里只有设计模块没有 testbench那么你就得手动在 ModelSim 里编译 testbench 文件步骤就繁琐了。这也是前面建议在 Settings 里配置 testbench 的原因。5.2 把信号加进 Wave 窗口ModelSim 打开后默认不一定会显示波形窗口需要手动调出来。菜单栏 View - Wave 打开 Wave 窗口然后在 Sim 面板中选中counter4_tb下的uut实例右键 Add Wave选择 All Items in Region就能把 counter4 内部的所有信号包括 clk、rst_n、count全部添加进去。你也可以同时选中 testbench 层级的 clk、rst_n方便对照激励和输出的关系。如果仿真已经跑完Wave 窗口是空的只要运行仿真后添加的信号就会出现在波形窗口里。这里有个小技巧先添加信号再 run波形窗口会随着仿真自动刷新观感上更流畅。5.3 设置仿真时间并运行ModelSim 默认的 run 长度是 100ns可以在 Wave 窗口工具栏的 Run Length 输入框里改动也可以直接在 Transcript 命令行输入run 600ns或者run -all。因为 testbench 里写了#600; $stop;用run -all会在 600ns 处自动停下来。运行结束后你应该能看到这样的波形刚开始 100ns 内rst_n是低电平count保持 0rst_n拉高之后每个clk上升沿count加一从 0 一直加到 15然后回卷到 0 继续循环。看到这个波形恭喜你Quartus 到 ModelSim 的整条链路已经通了。5.4 红线问题深度排查为什么波形是红线“ModelSim 仿真波形是红线”几乎每个初学者都遇到过我把它单独拿出来讲。ModelSim 默认用红色表示 X 态也就是未知态。X 态在 HDL 仿真里是一种特殊值它不代表 0 也不代表 1而是“不知道”。仿真器不会像真实硬件一样给寄存器一个确定的初值所以你的计数器和信号在仿真刚开始时统统都是 X。如果你是照着上面 testbench 写的那大概不会看到红线因为clk和rst_n都做了初始化。但如果你的 testbench 里漏了某个 reg 的初始化或者你的设计模块里某个寄存器没有复位逻辑就会出现一整片红线或者红白相间的波浪线。排查顺序我建议这样第一步检查 testbench 里所有 reg 是否都在 initial 里赋了初值。漏了 clk 最常见的现象就是 clk 一直是红线。第二步检查设计模块里的寄存器是否有复位逻辑复位信号是否在 testbench 里被正确拉高。如果复位释放之前看波形count 是 X 也算正常但复位释放后应该立刻变为 0。第三步检查例化时端口名字是否对得上。端口漏连或者名字拼错对应信号就会一直 X 或者 Z。第四步如果以上都没问题试着把仿真时间拉长比如run 10us。有时候你只跑了 100ns而复位释放后的第一个时钟边沿恰好在你观察窗口之外看起来就像没有输出。6. 仿真跑不通时的高频问题与解决顺序6.1 找不到 ModelSim 或者路径不对点了 RTL Simulation 之后没有任何反应或者弹窗提示找不到 ModelSim十有八九是路径设置没对上。回到 Assignments - Settings - EDA Tool Settings - Simulation检查 Tool name 是不是 ModelSim Intel FPGA同时看下方有没有 ModelSim 的可执行路径。正常情况下 Quartus 会自己识别安装路径但如果你的 ModelSim 组件是后补装的或者安装路径改过这里就需要手动指一下。路径一般在C:\intelFPGA_lite\xx.x\modelsim_ase\win32aloem\modelsim.exe这样的位置具体看你的安装根目录。6.2 编译报错大部分集中在语法和模块名ModelSim 编译报错有好几种常见体型。cannot find module counter4这类错误说明 testbench 里例化的模块名和设计代码里的模块名不一致或者设计文件没有成功编译进 work 库。如果 Quartus 的 Compile test bench 设置里只添加了 testbench 文件而没添加设计文件就会出现这个问题。解决办法是在 Test Benches 窗口确认设计文件也被工程包含或者检查例化名拼写。syntax error类错误更简单顺着报错行号去改语法就行最常见的是缺分号、endmodule 忘写。还有个容易忽略的场景如果 testbench 文件也作为普通工程文件加入了项目并且被设为了顶层Quartus 在综合时会尝试综合 testbench而 testbench 里的initial和forever不可综合会报一堆难以理解的问题。遇到这类情况打开 Settings - General确认 Top-Level Entity 是设计模块而不是 testbench这才是正确姿势。6.3 改了代码但仿真结果还是老样子这个现象特别迷惑人。你在设计模块里改了逻辑重新点 RTL Simulation结果 ModelSim 里看到的波形和上次一模一样好像改动没生效。其实原因往往是 Quartus 的编译流程没有重新跑或者 ModelSim 打开的还是旧的编译结果。解决办法是在 Quartus 里先重新执行 Analysis Synthesis 或 Start Compilation再启动 RTL Simulation。如果仍然不对在 ModelSim 里执行一次 clean 操作把 work 库里旧的编译产物清掉再重新编译。我个人的习惯是每次改完设计代码先在 Quartus 里编译一遍再启动 RTL Simulation这样能保证 ModelSim 得到的是最新代码。这个看似简单的顺序能避免很多“改了没用”的假象。6.4 功能仿真走通后要不要碰时序仿真RTL Simulation 属于功能仿真它只验证逻辑功能是否正确完全不包含布线延迟和器件内部延迟。对计数器、状态机、接口逻辑这类的学习项目功能仿真已经完全够用。不过你要知道 Quartus 还提供了另一种仿真Gate Level Simulation门级仿真也就是时序仿真。它在完整编译和布局布线之后把路径延迟信息带进仿真能验证时序是否满足要求。时序仿真需要单独配置仿真库过程中会涉及.vo网表文件和.sdo时序文件如果设置不当很容易报错。我的建议是初学阶段别一上来就啃时序仿真先把 RTL 仿真波形看懂把 testbench 写熟练这才是 FPGA 调试的基本功。等你后面用到 PLL、DDR 这类对时序敏感的功能时再回头研究时序仿真那时候你会感谢自己已经能熟练编写各种激励了。