
看到标题点进来的朋友估计十有八九都被“破解”这个词折腾过。刚接触FPGA那会儿我也是到处找ModelSim独立版的安装包和license装到一半发现系统环境变量冲突、编译器版本不匹配折腾一下午最后连仿真库都没编译通过。后来绕了一圈才搞清楚Quartus Prime Lite本身免费里面自带的ModelSim-Intel FPGA Starter Edition也免费注册个账号就能正常用根本不需要额外的破解步骤。这篇就围绕Quartus Prime自带的ModelSim-Intel FPGA从安装选型、RTL设计、Testbench编写、一键仿真到和商业版工具的对比完整走一遍数字电路仿真流程。适合刚学FPGA的入门读者也适合被各种破解版折腾到想放弃的实操党。1. 为什么不建议再去折腾破解版先说结论Quartus Prime Lite免费版自带的那套ModelSim-Intel FPGA Starter Edition做课程设计、毕业设计、中小规模数字逻辑验证完全够用。它最大的限制是“可编译的HDL代码总量在10万行左右”但绝大部分数字电路实验、状态机设计、接口时序验证根本触不到这个天花板。10万行是什么概念一个完整的串口收发模块加一个FIFO加一个简单的CPU核大概也就几千行。除非你要仿真的是一整个SoC级别的设计否则Starter Edition绰绰有余。很多人一听“Starter”就下意识认为这是阉割版玩具其实它只是把一些专业级的验证功能砍掉了比如覆盖率分析、性能分析、多核仿真加速这些核心的RTL仿真和门级仿真能力都在。换句话说你写一个Verilog模块写一个Testbench跑波形、看时序、查逻辑错误这套流程和商业版几乎没有任何区别。它缺的是复杂验证方法学那一块而不是基础的数字电路仿真能力。再说破解版的风险。独立的ModelSim商业版本身就不是给个人学习用的网上那些“一键破解”要么是改环境变量、要么是替换license文件、要么是加启动参数这些操作在Win10/Win11上经常造成.dll加载失败、模型库版本错乱、仿真中途崩溃。更麻烦的是你在一台电脑上装了一套破解版的ModelSim等下次重装系统或换电脑还得再折腾一遍时间成本比省下来的那点钱高得多。而我用Quartus自带版本这三年多从来没有一次因为工具本身出过问题。还有一种常见误解是“我只用Vivado不碰Quartus所以这个免费仿真器跟我没关系”。实际上ModelSim-Intel FPGA Edition是通用的HDL仿真器即使你的RTL代码是给Xilinx用的只要不调用Intel专属的IP原语也可以拿它做纯逻辑仿真。学数字电路、学Verilog语法、做算法验证它就是个独立的仿真环境不是只能配Quartus用。2. 环境准备与版本选择的几条硬经验2.1 Lite版选哪个版本最近几年大家问得最多的下载关键词是Quartus Prime 18.1、20.1、25.1这三个数字。简单梳理一下18.1是很多老教材和开发板教程配套的版本资料最多20.1是不少淘宝开发板商家默认推荐的版本支持Cyclone IV、MAX 10、Cyclone V这些主流型号25.1是现在官网在推的新Lite版本界面和组件管理更现代但如果你手里的开发板比较老比如Cyclone III或更早的器件可能就不在支持列表里了。我的建议是先看你手上板子的FPGA型号在不在支持列表里再决定装哪个版本。如果只是学语法、跑仿真、不依赖具体板子装20.1或25.1都行。我个人目前主力用的是20.1稳定性不错网上遇到问题时能搜到的解决方案也最多。而18.1虽然经典但新电脑上偶尔会遇到驱动签名、USB-Blaster识别一类的小麻烦。这里给一个基本原则Pro版和Standard版都是收费的但Lite版免费。下载时看清楚别点成Standard试用版。Lite版的下载安装包大约几百MB到几个GB不等包含特定器件族支持。下载前要注册一个Intel账号免费注册不需要填信用卡这一点很多人被吓到了以为注册就是开通试用其实不是。2.2 安装时要把ModelSim组件勾上Quartus Prime Lite安装程序是组件式管理默认会勾选Quartus主程序和一些常用器件库ModelSim-Intel FPGA EditionStarter这个组件有时候默认不勾或者安装界面显示的名字比较长容易忽略。安装完成后在Quartus菜单栏的Tools - Run Simulation Tool里如果看不到RTL Simulation选项或者提示仿真器未安装那就说明ModelSim组件没装上。解决方法是重新运行安装程序选择Modify在组件列表里找到ModelSim相关的项勾上再继续。因为ModelSim和Quartus的版本是严格绑定的不要尝试从别的渠道单独装一个ModelSim塞到Quartus里版本对不上一定会出问题。安装路径也一定要记牢不要用中文路径不要带空格如果非要带至少别放Program Files里面权限问题会折腾死你。C盘空间允许的话建议直接默认路径安装省后面一堆环境变量和权限的心。2.3 常见下载和安装问题下载速度慢官网服务器在国外用浏览器直接下容易断。可以用官方下载器或者选一个离自己近的镜像实在不行放在后台让它慢慢下别中断。安装到一半卡住多半是杀毒软件拦截了后台组件进程安装时暂时关掉实时防护会顺畅很多。启动时报缺少dll先确认是不是只装了Quartus没装ModelSim组件因为这两个组件共用部分运行时库缺一个另一个也可能报错。3. 从零建一个仿真工程RTL设计实操3.1 用计数器当例子最直观为了把整个仿真流程串起来我拿一个最简单的4位计数器来做演示。计数器是数字电路里的“Hello World”它有时钟、有复位、有使能、有进位输出能把这几个基本信号的仿真看明白其他复杂模块的仿真逻辑就都一样了。新建工程时Quartus会问你工程名和工程路径不要中文是新建文件还是添加已有文件我习惯先把文件夹准备好再建工程目标器件型号这一步直接选你板子上的型号或者随便选一个也能仿真因为纯仿真不依赖具体器件EDA Tool Settings重点来了这里要把仿真工具设置为ModelSim-Intel FPGA语言选Verilog在EDA Tool Settings里的设置非常重要很多人仿真按钮是灰的就是因为这里没设置。在Quartus Prime Lite 20.1里路径是Assignments - Settings - EDA Tool Settings - Simulation把Tool name选成ModelSim-Intel FPGAFormat选Verilog。3.2 写一个带复位和使能的计数器这里用Verilog写一个模16计数器异步复位低有效使能信号为高时每个时钟加一计满16个时钟计数值从15回到0时输出一个进位脉冲。这个模块麻雀虽小五脏俱全仿真时能看到的所有典型信号都在了。module counter_4bit ( input wire clk, input wire rst_n, input wire en, output reg [3:0] q, output reg carry );always (posedge clk or negedge rst_n) begin if (!rst_n) begin q 4h0; carry 1b0; end else if (en) begin if (q 4hF) begin q 4h0; carry 1b1; end else begin q q 1b1; carry 1b0; end end else begin carry 1b0; end endendmodule这段代码里面rst_n低电平复位是异步的所以敏感列表里既有posedge clk又有negedge rst_n。en使能位不使能时计数器保持不动carry输出为低。这些信号在后面的仿真波形里都能看得一清二楚。写好后把文件存成counter_4bit.v添加到工程里然后做一次全编译Processing - Start Compilation。这里想提醒一点做RTL仿真其实不需要跑到“全编译”结束只要分析和综合通过就行但为了保险起见全编译一次也没什么坏处还能顺便看看有没有语法警告。全编译过程中可能会出现一些关于信号未使用或者锁存器的警告只要不是error就继续走。在这个阶段完全不需要做引脚分配仿真里不关心FPGA的物理引脚这是很多新手卡住的地方——以为不分配引脚就无法继续其实完全误解了。3.3 仿真不需要管引脚分配特别解释一下“为什么不需要Pin Planner”。FPGA设计的完整流程是RTL编码 - 功能仿真 - 综合 - 布局布线 - 时序仿真 - 下载。功能仿真也就是RTL仿真发生在综合之前这时候代码只是被“编译”成了一个仿真模型还没有映射到具体器件的逻辑单元和引脚上。所以哪怕你选错了FPGA型号也可能照样能跑RTL仿真最多是综合阶段报器件不支持的警告。这一点初学者要放下包袱仿真阶段轻松点。4. Testbench写得好仿真就成了一半4.1 Testbench到底在干什么设计模块本身不会自己产生时钟和激励信号Testbench测试平台就是用来干这个的。它跟普通的可综合模块不一样不需要考虑能不能被综合成电路只需要在仿真环境里运行。很多人学Verilog时被“可综合”和“不可综合”绕晕放到仿真场景里就很好理解RTL设计必须可综合Testbench则越“软件思维”越方便。一个标准Testbench通常包含四个部分信号声明、模块实例化、激励生成、结果监视或自动结束。下面这段就是我给计数器写的Testbench。timescale 1ns / 1psmodule tb_counter_4bit;reg clk; reg rst_n; reg en; wire [3:0] q; wire carry; counter_4bit dut ( .clk (clk), .rst_n(rst_n), .en (en), .q (q), .carry(carry) ); initial clk 1b0; always #10 clk ~clk; initial begin rst_n 1b0; en 1b0; #30 rst_n 1b1; #20 en 1b1; #640 en 1b0; #100 en 1b1; #200 $finish; end initial begin $monitor(time%0t | rst_n%b en%b q%h carry%b, $time, rst_n, en, q, carry); endendmodule第一行的timescale 1ns / 1ps表示仿真时间单位是1ns仿真精度是1ps。这个声明影响后面所有#延时和always #10的含义#10就是10ns。initial clk 1b0把时钟初始化成低电平always #10 clk ~clk每10ns翻转一次产生一个周期20ns的50MHz时钟。4.2 激励时序的设计思路复位信号的处理要注意我把rst_n在0时刻置为低持续30ns之后拉高。为什么要30ns因为我想让时钟已经跑起来至少一个周期20ns复位释放时能采到稳定时钟边沿这样波形看起来干净也不会有亚稳态式的抖动。接着再等20ns再拉高en让复位释放后的第一个时钟上升沿真正生效。#640这个时间长度是特意凑出来的。计数器在使能状态下每隔20ns加1计满16个值需要320ns从15回到0刚好需要16个时钟周期。我让en保持640ns这样能看到计数器完整跑了两轮包括两次进位脉冲足够验证功能了。然后拉低en一段时间观察计数器停止计数、carry拉低再重新使能这是为了验证使能控制的暂停和恢复功能。$finish的作用是让仿真在指定时间点自动结束否则ModelSim会一直跑下去。$monitor则会在任何信号变化时打印一行信息到控制台方便不用开波形图就快速判断结果对不对。这些语法在综合设计里不能用但作为仿真语言完全合法。4.3 写好Testbench的三个习惯我写Testbench有这三个习惯推荐新手照做一个是时序分层清晰复位一个initial块时钟一个always块激励一个initial块监视留单独一块不要全挤在一起。二是用#延时不要用绝对时间写到几百上千ns而是按“事件”设计顺序比如“复位结束20ns后开使能”这样后续改时钟周期也容易。三是仿真文件命名加tb_前缀跟设计文件区分开工程一复杂你就知道哪个是设计、哪个是测试。5. Quartus里一键启动ModelSim做RTL仿真5.1 三种启动方式在实际使用中启动ModelSim仿真有三种方式很多人只会在Quartus里点点点不知道还可以直接在ModelSim里干活。第一种方式Quartus菜单栏的Tools - Run Simulation Tool - RTL Simulation。这种方式最简单Quartus会自动给ModelSim传递仿真库路径和编译好的设计文件推荐新手使用。第二种方式在Quartus里先Compile Testbench再手动打开ModelSim在ModelSim的Transcript窗口里用vsim work.tb_counter_4bit命令手动启动仿真。这种方式适合仿真出问题时排查库路径。第三种方式完全不打开Quartus直接双击ModelSim图标然后通过vlib、vlog、vsim这些命令行手工建库、编译、仿真。这种方式最原始但最灵活适合以后搞自动化仿真脚本。我平时的流程基本是第一种因为Quartus已经把工程里的RTL文件自动关联到ModelSim了我不需要手动理会编译顺序。如果一个工程有多个.v文件Quartus也会自动按依赖关系组织。5.2 点下RTL Simulation之后发生了什么点击Tools - Run Simulation Tool - RTL Simulation之后第一次会比较慢原因是Quartus会把当前工程需要的器件仿真库比如altera_mf、altera_lnsim这些编译到ModelSim的本地库目录。这个编译过程有点像第一次安装Visual Studio时加载组件以后再用就快了。如果点完之后好几分钟没反应别急着关掉去任务管理器看看ModelSim的进程是不是在跑十有八九是在编译库。等ModelSim界面弹出后默认会加载你的Testbench顶层并且在Wave窗口里自动添加一些信号。但这里有个坑Quartus自动添加的信号不一定全我遇到过几次它只加了顶层模块端口信号内部信号一个都没有。解决方法是在ModelSim的Sim菜单里打开Add Wave手动把dut实例下的q、carry这些信号拖进去或者直接在Objects窗口选中信号右键Add to Wave。5.3 波形查看的几个实用技巧波形窗口打开后第一件事是把仿真时间设置得足够长。Quartus调用ModelSim时默认运行时长是100ns对于快速验证可能不够比如我这个计数器一轮计数就要320ns。你可以在Quartus弹出的Simulation Run Time框里直接改成1000ns或者在ModelSim命令行敲run 1us再或者点工具栏上的Run按钮旁边的下拉框选时长。波形出来后常用技巧有这么几个选中信号的进制显示默认可能是二进制但计数器的q信号用十六进制看最舒服。右键信号 - Radix - Hexadecimal。信号分组把clk、rst_n、en放在一组q和carry放在一组界面更清爽。Wave窗口里选中几个信号右键Group。放大缩小波形太密看不清时按键盘Z缩放全貌按X放大区域按Ctrl滚轮也可以缩放。光标测量在波形上放两个光标主工具栏会显示两点之间的时间差这个对验证时序很有用。5.4 运行结果判断仿真跑完看波形第一眼应该看复位段rst_n为低时q应该保持0carry为0。复位释放后en拉高q开始按二进制递增每次都在时钟上升沿变化。q从F变成0的时候carry输出一个高电平脉冲持续一个时钟周期。en拉低之后q停在当前值不动carry保持0。这些现象都符合设计预期说明仿真通过。如果看到波形里有一堆红色X态通常表示信号没有正确初始化比如复位一直没有拉高或者时钟没有翻转。如果q一直在跳但carry没反应就要检查是不是进位判断的条件写错了。6. 和商业版对比Starter Edition到底“够不够用”6.1 功能角度对比很多读者会担心Starter Edition是不是一个“功能阉割到没法用”的版本。为了让你看得更清楚我把Starter Edition和商业版ModelSim/Questa的差距整理了一下。对比维度ModelSim-Intel FPGA Starter Edition商业版ModelSim/Questa授权费用免费注册Intel账号即可商业授权价格不菲HDL代码规模限制约10万行以内无明确限制常用Verilog/VHDL仿真完整支持完整支持SystemVerilog高级断言部分支持完整支持覆盖率分析不支持支持性能分析/多核加速不支持支持与Quartus联动一键启动RTL/门级仿真可配置但需额外设置应用场景学习、课程设计、中等规模设计验证大型SoC、复杂验证环境这个表不是我拍脑袋想的是Intel官方文档里针对Starter Edition的功能划分。要特别注意“SystemVerilog高级断言”这一行如果你以后要做UVM验证、做复杂的断言验证Starter Edition的约束会很难受那时候才需要考虑商业版或Questa。但就数字电路基础学习来说Starter Edition“还没到瓶颈就毕业了”。6.2 我自己实际跑的对比测试为了写这篇我特意拿一个500多行的小工程做了个简单对比工程包含一个UART发送模块、一个状态机控制模块和顶层连线Testbench里跑了10万ns的仿真。同一台机器上Starter Edition和同事的Questa环境下RTL仿真波形结果完全一致运行时间的体感差异也几乎感觉不出来大概都是秒级跑完。真正的差异出现在两个地方一个是第一次编译器件库的时间Starter Edition首次跑RTL Simulation时编译库要多等几分钟另一个是工程规模变大后Questa在大型仿真里的速度优势才会体现出来Starter Edition在小工程上并不会“卡顿”。还有一点很实用如果以后你想系统学习ModelSim的命令行流程Starter Edition和商业版的核心命令vlib、vlog、vmap、vsim完全一致今天在Starter Edition上积累的脚本经验将来切到任何ModelSim/Questa环境都能直接复用。6.3 什么时候才需要放弃Starter Edition有三类情况我才会劝你去考虑商业版或完全换一套工具链代码规模真的超过10万行仿真库或编译阶段会报错或卡死。需要做代码覆盖率、功能覆盖率分析来确认验证是否充分。需要跑UVM这种基于SystemVerilog完整特性的验证环境。除此之外大部分FPGA开发中遇到的功能仿真需求Starter Edition都能接得住。至少我带过的人里面还没有谁是因为Starter Edition功能不够而放弃的更多人是被“网上教程默认用破解版”这种氛围带偏以为自己也要装破解版。7. 仿真过程中常见的坑与解决办法7.1 第一次启动仿真卡住不动这个太常见了。点完RTL Simulation后Quartus半天没反应很多人的第一反应是程序死了直接去任务管理器结束进程。其实第一次运行的时候Quartus正在把几百MB的仿真库编译到ModelSim的用户目录这个过程的耗时取决于电脑性能慢的话可能10到20分钟。判断方法很简单看任务管理器里有没有vsim或vlib进程在跑CPU占用是否维持在比较高的水平。如果是耐心等。下次再点就是秒开。7.2 找不到或无法访问work库ModelSim的每个仿真工程都需要一个work库来存放编译后的设计单元。用Quartus自动启动仿真时它会在ModelSim里自动建库并编译但如果你手动打开ModelSim再vsim某个模块往往会遇到“Cannot access library work”这种错。解决方案是先在ModelSim的Transcript窗口手动执行vlib work vlog counter_4bit.v tb_counter_4bit.v vsim work.tb_counter_4bit三步下来库有了代码编译了仿真也能跑起来了。7.3 波形窗口里没有内部信号Quartus自动启动仿真时默认添加的信号可能是顶层端口或者只有顶层信号dut内部信号的波形需要手动添加。在Objects窗口或者sim面板里找到具体实例选中信号右键Add Wave。还有一个更省事的办法在Wave窗口里点击菜单Wave - Add - Add All Items in Region然后选择设计层次结构里的dut实例一次把所有信号都加进来。信号多时这个功能很好用。7.4 仿真看起来全是不定态要区分两种不定态一种是红色高阻Z一种是红色X不定态。Z常见于三态门输出没接负载或者没初始化X常见于没有复位、信号没有初始值、多位信号里包含了未定义的驱动。遇到X态先检查Testbench里的复位时序长度够不够再检查能不能在复位完成后立刻看到有效信号最后检查时钟enable这些控制信号是否初始化为0。还有一种很隐蔽的情况模块内部有寄存器变量没有赋初值但自己又没在always里对每个分支做完整赋值仿真时也会出现X态。这个和硬件电路里的latch风险是同一个根源仿真能帮你提前暴露出来。7.5 工程路径有中文导致编译失败这个坑我踩过很多次了ModelSim对中文路径支持一直不好至少我用的版本里一旦工程路径出现中文编译阶段就会报一些莫名其妙的错误比如找不到文件、无法创建库。解决方法只有一个工程路径全英文。顺带提一个细节Windows用户名如果是中文默认路径C:\Users\张三\...也可能触发问题这时候把工程放到D盘或某个自定义的英文目录下比较稳妥。7.6 仿真不自动结束Testbench里没有$finish的话ModelSim会一直无限制跑下去波形窗口不断向右延伸。手动停下来可以点工具栏上的Break按钮红色方块。但要养成好习惯在Testbench末尾加一个#延后 $finish;或者用$stop停在特定位置。两者区别是$finish直接结束仿真进程$stop是暂停交互方便继续输入命令查看信号。7.7 Transcript窗口中文乱码ModelSim默认读取的系统locale如果和源文件编码不一致中文注释显示成乱码是常有的事不影响仿真结果但影响心情。给源码文件的注释部分尽量用英文或者保持文件编码为UTF-8就可以大幅减少乱码。8. 几个让我受益匪浅的实操习惯文章写到这里主体内容差不多讲完了最后分享一个我这几年一直沿用的习惯也是很多老工程师跟我说过的每次创建新工程的时候不管多简单都不要跳过新建Testbench这一步而且第一次仿真通过之前不要急着写综合约束。做数字电路仿真最忌讳的是“代码一写完就直接上板”。明明在仿真里花两分钟就能发现的逻辑错误上了板之后可能变成偶发的不稳定现象排查时间往往是仿真排查的十倍以上。先仿真再综合、先验证功能再关心时序这条路径坚持下来能帮你省掉大量无效加班。另外一个习惯是把Testbench当“设计文档”来用。你写一个模块实现什么功能与其写一堆说明文档不如写一段清晰的Testbench告诉别人“这个模块在什么条件下应该输出什么”。很多年前一个前辈跟我说过好的Testbench比十页Word文档更能说明设计意图我当时不信后来自己接别人的工程、要快速理解一个模块的行为时发现最先看的果然是它的Testbench。这个经验相信你们用上也会觉得值。