做FPGA这一行,绕不开Quartus这个工具。不管你是电子类专业的学生,还是刚转行做数字逻辑设计的工程师,第一次打开它的时候大概率都会有点懵——菜单栏一堆选项,工程向导一步接一步,器件型号、仿真工具、引脚分配、时序约束,随便点错一个后面就编译不过。我带过几个新人,几乎每个人都在“新建工程”这一步卡过,更别提后面ModelSim联动和Programmer下载时那些莫名其妙的报错。这篇就按我自己的实际使用顺序,把Quartus从选版本、装软件、建工程、写代码、综合布线、仿真验证,一路到下载上板的完整流程捋一遍。文中提到的一些参数取舍和排障思路,都是我在Cyclone IV和MAX 10这两类板子上反复踩坑总结出来的,新手照着走能少走弯路,有基础的朋友也可以挑感兴趣的章节看。工具本身不难,难的是那些官方文档里不写、论坛里又说法不一的小细节,下面咱们一个一个说。
1. 工具选型与安装前的准备工作
1.1 Quartus II 与 Quartus Prime 到底怎么选
很多刚入门的朋友会在搜索框里同时敲“quartus ii”和“quartus prime”,然后被一堆版本号搞晕。简单说,Quartus II是Altera时代的老名字,大概到13.1版本之后就改名成Quartus Prime了。所以你现在如果看到Quartus II 13.0、13.1、15.0这些,都是比较老的版本;而Quartus Prime 18.1、20.1、25.1这些才是新命名体系下的版本。两者内核其实是一条线传承下来的,界面布局、操作逻辑基本一致,老版本对老器件支持好、体积小,新版本对新器件和新的IP核支持更全。
那到底该用哪个?我的建议是看你的板子上焊的是什么芯片。如果是学校里常见的Cyclone IV EP4CE系列,用Quartus II 13.1或者Quartus Prime 18.1都行,13.1的体积只有几个G,装起来快,跑起来也轻。如果板子是Cyclone 10、MAX 10或者更新的Agilex,那就得用较新的Prime版本。这里有个坑要提前说:不是所有芯片都支持所有版本,比如某些老版本根本不认Cyclone 10的器件,你在工程向导里选器件时会发现列表里压根找不到型号,这时候不是操作问题,是版本不支持。
再补一个很多人分不清的点:Quartus Prime本身分三个档——Lite、Standard、Pro。Lite是免费的,支持中小规模器件,学生和爱好者用这个完全够;Standard是收费的,支持中高端器件;Pro面向大规模高端器件,编译策略和Lite差别比较大。网上那些“quartus prime lite 20.1 下载”“quartus prime lite25.1”的搜索量一直很高,就是因为Lite免费且够用,选它准没错。至于Standard和Pro,除非你公司买了授权,否则不用折腾。
1.2 版本与器件库的取舍逻辑
选版本还有一个经常被忽略的维度:器件库(Device Support)。Quartus安装时可以选择只装某些系列的器件库,装得越少,安装包越小、安装越快。但如果你图省事全勾了,安装体积轻松飙到十几G。我第一次装的时候没经验,全选了,结果硬盘直接告急。
实际做法是这样:先确认板子型号,比如Cyclone IV E,那安装时只勾Cyclone IV系列就够了。如果是做课程实验,学校一般用Cyclone IV或Cyclone V,可以一并勾上。器件库在安装器里是可以后续增删的,所以就算第一次漏装了,后面用Device Installer补装也行,不用整个重装。
另外关于“quartus 9.1配套的modelsim”这类搜索,我要提醒一句:Quartus和ModelSim是有版本匹配关系的。老版本Quartus通常配套ModelSim-Altera Starter版,新版本则改用Questa Intel FPGA Starter Edition。如果你把Quartus 18.1和一个很老的ModelSim硬凑在一起,仿真时可能报license或者库不兼容的错。稳妥的做法是用官方配套的那一版,安装器里会一起给你,不用单独去别处找。
1.3 安装与驱动配置实操要点
安装本身没什么难度,一路下一步就行,但有两个地方要注意。第一是安装路径不要有中文和空格,这在EDA工具里是铁律,中文路径会导致综合和仿真时各种找不到文件的诡异报错。推荐类似D:\intelFPGA_lite\18.1这种纯英文短路径。第二是安装过程比较久,尤其是勾了多个器件库的情况,中途不要强退,否则容易装一半留下残留文件,后面得手动清理。
装完之后真正容易卡住的是下载器驱动。很多人搜“quartus下载器驱动在哪个文件夹”,就是因为插上USB-Blaster后电脑没识别,Programmer里也扫不到硬件。驱动一般藏在Quartus安装目录下的quartus\drivers文件夹里,里面会按下载器型号分文件夹,比如usb-blaster、usb-blaster-ii。在设备管理器里找到带黄色感叹号的未知设备,右键更新驱动,手动指向这个文件夹即可。如果指向后还是装不上,多半是驱动签名或者系统权限问题,可以尝试重启后再装,或者换一个USB口,前置面板的USB口供电和信号质量有时确实不如主板后置口。
注意:安装完成后建议重启一次电脑,让环境变量和驱动生效,别装完立刻就开始建工程,很多“找不到器件”“下载器无响应”都是没重启导致的。
2. 新建工程与设计输入的正确姿势
2.1 工程目录结构与命名规范
新建工程看起来是最简单的一步,但恰恰是埋坑最多的地方。我见过太多人工程建完,编译报错,最后发现是目录里混进了中文名或者特殊字符。Quartus的工程文件夹一旦用了中文,综合器读取文件时可能直接失败,而且报错信息往往很含糊,让你根本想不到是路径问题。
我的习惯是这样的:给每个工程单独建一个英文文件夹,文件夹名和顶层模块名保持一致,例如led_blink。工程文件(.qpf)和设置文件(.qsf)都放在根目录,源码放在单独的子文件夹里,约束文件(.sdc)也单独放。这样结构清晰,后面如果要迁移或者交给别人,直接打包整个文件夹就行,不会丢文件。
命名上还有个小门道:顶层模块名、工程名、顶层文件名三者最好一致。不一致其实也能用,但要额外在设置里指定顶层实体,新手容易在这里犯迷糊,编译出来顶层对不上,代码明明没错却功能不对。统一命名能省掉这个麻烦。
2.2 设计输入方式的取舍
Quartus支持三种设计输入方式:原理图(Block Diagram/Schematic)、HDL代码(Verilog/VHDL)、以及IP核例化。这三者用途不同,不是随便选的。
原理图适合教学和特别简单的逻辑,画起来直观,一眼能看出连线,但稍复杂一点就乱成一团,而且可维护性差,改一处要动好几根线。HDL代码是主流,Verilog和VHDL选一个自己顺手的就行,工程上Verilog用得更普遍,语法也相对简洁。IP核则是把一些复杂功能(比如PLL锁相环、RAM、乘法器)用官方提供的模块直接例化,不用自己从零写。
实际项目里通常是HDL代码为主,IP核为辅,原理图只用来看看顶层连接关系。比如你要生成一个50MHz到25MHz的时钟,自己写分频逻辑也行,但更规范的做法是用PLL IP核,稳定性和时序都更好。这里我不建议新手一上来就大用IP核,先把纯HDL的流程跑通,理解综合、布线、时序这些概念,再引入IP核会顺畅很多。
提示:新手第一次做实验,建议从最简单的LED闪烁或分频器开始,代码量小,编译快,出问题也好定位。别一上来就搞复杂的通信协议,那样一旦报错你会完全不知道从哪查。
2.3 顶层文件设置与常见坑
工程建好后,如果你有多个源文件,一定要确认顶层实体(Top-Level Entity)设置正确。Quartus默认会把工程名对应的模块当顶层,如果你顶层模块叫别的名字,就要在Assignments → Settings → General里手动指定。顶层设错会导致编译“成功”但功能完全不对,因为综合器根本没编译你的顶层逻辑。
另一个高频坑是文件没有加入工程。有时候你把.v文件复制进文件夹了,但没在工程里Add File,Quartus压根不认它。这种情况编译时会报“找不到模块”或者模块未定义。解决办法是在Project Navigator里右键Add/Remove Files,把需要的源文件都加进来。我自己的习惯是建工程时就把所有相关文件一次性加进去,后面加新文件也随手加,不攒着。
还有一个细节:Quartus对文件名大小写敏感,但Windows文件系统不敏感,这就导致在Windows下编译通过,换到Linux环境就报找不到文件。所以文件名统一用小写是最保险的,养成习惯后能避免跨平台迁移时的麻烦。
3. 综合、引脚分配与布局布线
3.1 分析与综合的设置技巧
点下“Start Analysis & Synthesis”之后,Quartus会把你写的HDL代码翻译成门级网表。这一步出错通常有两个原因:语法错误和逻辑推断问题。
语法错误好办,Messages窗口会直接告诉你哪一行有问题,双击就能跳过去。真正麻烦的是逻辑推断问题,比如你写了一个带异步复位的寄存器,但复位信号没接对,综合器可能会警告“inferred latch”,意思是它推断出了一个锁存器——这往往不是你想要的。锁存器在FPGA里容易产生毛刺和时序问题,看到这类警告一定要回去检查逻辑,别视而不见。
综合设置里有个参数值得关注:优化目标(Optimization Technique)。默认是Balanced,可以改成Area优先或Speed优先。如果你做的东西逻辑资源紧张,就选Area;如果时序老是过不了,就选Speed。这个改动影响后面Fitter的结果,可以在综合前先定好策略,省得来回改。
3.2 引脚分配与约束文件
引脚分配是新手最容易翻车的地方。你代码写得再对,引脚接错了,板子上就是没反应。分配引脚有两种方式:图形化的Pin Planner和直接写QSF约束文件。Pin Planner直观,点一点就能把信号拖到对应引脚上;QSF文件则适合批量修改和版本管理。
引脚分配前必须先拿到板子的原理图或引脚定义表,确认每个外设连的是哪个FPGA引脚。这个绝对不能猜,猜错了轻则功能不对,重则把外设或IO口烧了。分配时还要注意IO标准(I/O Standard),常见的有3.3V LVTTL、LVCMOS等,要和板子的电平匹配。如果你接的是3.3V器件,却把IO标准设成别的,可能驱动不起来甚至损坏。
还有个必做项:把不用的引脚设为三态输入(As input tri-stated)。默认情况下,Quartus可能把未使用引脚设成输出或弱上拉,这可能导致板上其他电路被意外驱动。在Assignments → Device → Device and Pin Options → Unused Pins里统一设成三态输入,是个好习惯。
3.3 时序约束与Fitter配置
布局布线(Fitter)是把综合后的网表映射到具体器件的物理资源上。这一步能不能过,很大程度上取决于你的时序约束做得对不对。最基本的约束是时钟约束,你要在SDC文件里告诉工具:系统时钟是多少频率。例如:
create_clock -name clk -period 20.000 [get_ports {clk}]这行意思是时钟周期20ns,也就是50MHz。工具会根据这个约束去布局布线,尽量满足时序。如果你不写时钟约束,工具会按默认值去跑,结果可能是“编译通过但实际跑不起来”,因为它在没有约束的情况下根本不知道要优化什么。
时序报告出来后,重点看Setup Slack和Hold Slack,正值表示满足,负值表示违例。Setup违例通常是逻辑路径太长,可以通过流水线、优化代码或降低时钟频率解决;Hold违例相对少见,多半是约束本身或时钟树的问题。新手第一次看到一堆时序报告容易晕,建议先只看时钟域相关的几条关键路径。
Fitter的Effort等级也可以调,从Standard到Fast,等级越高编译越久但结果越好。小工程用默认就行,大工程时序紧的时候再往上调。
4. 仿真验证:ModelSim联动实操
4.1 功能仿真与时序仿真的区别
仿真分两种:功能仿真(Functional/RTL Simulation)和时序仿真(Timing Simulation)。功能仿真不考虑器件延时,只验证逻辑对不对;时序仿真则把布线后的延时信息带进来,验证在真实延时下功能是否还成立。
很多人做完功能仿真就以为万事大吉,其实时序仿真才是接近真实硬件的验证。但时序仿真跑得慢、配置麻烦,实际项目中往往是功能仿真过了就直接上板测,出问题再回头看时序。对于学习和一般项目,先把功能仿真做扎实是性价比最高的做法。
4.2 与ModelSim联调的配置
Quartus和ModelSim的联动是通过NativeLink或者手动配置Testbench实现的。用NativeLink的话,你在Assignments → Settings → EDA Tool Settings → Simulation里指定仿真工具为ModelSim,再指定Testbench文件,点击RTL Simulation就能自动调起ModelSim。
这里常见的报错是“找不到仿真库”或者“ModelSim版本不匹配”。Quartus会在编译时生成仿真用的库文件,如果这些库没编译进ModelSim,仿真就会失败。解决办法是跑一次“Launch Simulation Library Compiler”,把需要的库先编译好。另外要注意,ModelSim的安装路径里不能有中文和空格,否则Quartus调不起来。
4.3 Testbench编写的实用技巧
Testbench是仿真用的激励代码,不参与综合,所以可以随便用不可综合的语法。写Testbench有几个实用技巧:时钟用always块生成,例化被测模块(DUT)时信号名一一对应,输入激励用initial块按时间顺序给。
一个简单的时钟生成写法:
initial begin clk = 0; forever #10 clk = ~clk; // 20ns周期 end#10表示延时10ns,forever让它一直翻转,这样就得到一个50MHz的时钟。测试时给足够的仿真时间,然后在波形窗口看信号变化是否符合预期。养成在关键信号上加观察点的习惯,出问题能快速定位到是哪一级逻辑不对。
提示:Testbench里尽量避免用绝对长时间的仿真,先跑几百纳秒看基本功能,没问题再拉长时间。跑太久的仿真会浪费大量时间,而且在波形里找问题也不方便。
5. 编程下载与板级联调
5.1 Programmer使用与驱动排障
编译综合都过了,最后一步就是下载到板子。打开Programmer,首先要确认Hardware Setup里能看到下载器。如果这里空着,说明驱动没装好或者下载器没识别,回到1.3节的驱动部分排查。
“quartus programmer打开文件时卡顿”是很多人遇到过的问题。卡顿的原因通常是JTAG链扫描慢或者加载的文件太大。JTAG扫描会去探测链上有哪些器件,如果链上有多个器件或者连接不稳,扫描时间会很长,界面就卡住了。可以尝试在Hardware Setup里手动指定器件,或者检查JTAG线缆是否接触良好。如果是SOF文件特别大,那属于正常现象,耐心等一下即可。
另外,如果Programmer里看不到具体器件型号,通常是没有勾选“Auto Detect”或者链上器件和工程设置的型号对不上。手动Add Device或者让工具自动检测都可以。
5.2 SOF与POF的区别与选择
Quartus生成的配置文件有好几种,最常用的是SOF和POF。SOF是SRAM Object File,下载到FPGA的SRAM里,掉电就丢,适合调试阶段反复下载;POF是Programmer Object File,烧到配置芯片(比如EPCS)里,掉电不丢,适合最终产品固化。
调试阶段用SOF,改一次下一个,方便快捷。功能确认无误后再转成POF烧进配置芯片。转换通过File → Convert Programming Files完成,注意选择正确的配置器件型号。烧POF时如果失败,多半是配置芯片型号选错或者JTAG连接问题,仔细核对一下就行。
5.3 上板不工作的排查思路
下载显示成功但板子没反应,这是最让人抓狂的情况。我的排查顺序是这样的:先看时钟——用示波器或者逻辑分析仪确认时钟引脚有波形,没时钟一切免谈;再看复位——复位信号是不是一直是有效状态把逻辑压住了;然后看引脚分配——对着原理图核对输出引脚,别小看这一步,接线错位太常见了;最后看代码逻辑——前面都排除后再回头审代码。
还有一个隐蔽的坑是时钟约束频率和实际时钟不一致。比如你板子是50MHz,约束写成100MHz,工具按100MHz优化,结果实际跑50MHz时某些依赖精确延时的逻辑就乱了。这种情况必须让约束和实际时钟严格对应。
6. 常见问题速查与经验总结
6.1 典型故障速查表
把上面这些高频问题整理成一张表,方便对照排查:
| 现象 | 常见原因 | 解决思路 |
|---|---|---|
| 编译报找不到模块 | 源文件未加入工程 | Add/Remove Files补加 |
| 综合警告inferred latch | 组合逻辑未覆盖所有分支 | 检查if/case是否有else/default |
| 引脚分配后无输出 | 引脚或IO标准接错 | 对照原理图核对,检查电平匹配 |
| 下载器不被识别 | 驱动未安装 | 指向quartus\drivers目录手动装 |
| Programmer打开卡顿 | JTAG扫描慢或文件过大 | 手动指定器件,检查JTAG线缆 |
| 下载成功但板子无反应 | 时钟/复位/引脚/逻辑问题 | 按顺序逐项排查 |
| 时序不满足Setup Slack | 逻辑路径太长 | 流水线拆分或降频 |
| 换电脑后工程打不开 | 缺文件或路径变化 | 打包整个工程文件夹迁移 |
6.2 提升编译效率的实用技巧
最后分享几个提高效率的习惯。第一,善用增量编译(Incremental Compilation),大工程改动一小块时,工具只重编受影响的部分,能省大量时间。第二,把常用约束和设置写进QSF/SDC文件而不是靠界面点,这样工程迁移和版本管理都方便,也便于别人复现。第三,编译前先跑Analysis & Synthesis,语法和基本逻辑问题在这一步就能发现,不用等整个流程跑完。第四,定期清理工程目录里的db和incremental_db文件夹,这些临时文件会越攒越大,偶尔清一次能让工具跑得更利索。
关于“怎么删除quartus”,如果确定不再用了,标准卸载走控制面板即可,但记得手动删掉安装目录残留和C:\Users\你的用户名\AppData\Roaming\下相关的配置文件,否则重装时可能带出旧配置。器件库如果单独装过,也要一并处理。
我个人在实际操作中的体会是,Quartus这套流程说到底就是“配置对了,一切都顺”。新手阶段花时间把版本选型、工程结构、引脚和时序约束这几件事做规范,比我见过的任何“速成技巧”都有用。工具会不断更新版本,但底层这套“设计输入—综合—布线—仿真—下载”的逻辑几十年没变,把这条主线吃透,换个工具或者换个器件系列,上手都不会太难。