很多刚接触FPGA的朋友,第一次打开Quartus II的时候都有点懵——界面上一堆面板、菜单、按钮,不知道从哪下手。网上能找到的教程要么是十年前的截图,要么是直接甩一堆步骤让你照做,做完了也不知道每一步到底在干什么。我当年第一次装完这个软件,光是搞清楚"新建工程"和"新建文件"的区别就折腾了半个下午。这篇内容就是想用图文解说的思路,把Quartus II从安装到跑通第一个工程的完整链路拆开讲清楚,每一步都说明白为什么这么做、不做会怎样。不管你是电子类专业的学生要做课程设计,还是刚转岗到数字逻辑方向的工程师,看完都能自己独立走通一遍流程,并且知道后面遇到问题该往哪个方向排查。
1. 装完之后先别急着建工程,把这几件事理清楚
1.1 Quartus II到底是个什么东西
先把定位说清楚。Quartus II是Altera(后来被Intel收购)推出的FPGA/CPLD开发工具,核心工作是把用硬件描述语言(Verilog或VHDL)写的逻辑代码,经过综合、布局布线,最终变成能烧进芯片里的配置文件。你可以把它理解成"代码到芯片"之间的翻译官加施工队:综合负责把代码翻译成门级网表,布局布线负责在芯片内部安排这些门电路的实际位置和连线,最后生成一个可以下载到板子上的文件。
这里有个新手特别容易混淆的点:Quartus II不是仿真工具。虽然它自带一个波形仿真器,但业界更常用ModelSim或者QuestaSim做功能仿真。Quartus II的核心价值在于"实现"——把逻辑真正映射到具体型号的芯片资源上。所以你在学的时候要建立一个概念:写代码是一回事,仿真验证是一回事,综合实现是另一回事,烧到板子上跑又是另一回事。这四步各有各的工具和关注点,Quartus II主要管后两步。
版本选择上也有讲究。Quartus II有多个版本分支,Web Edition(免费版)对大部分学习和中小规模项目够用,但支持的器件型号有限;Standard Edition和Pro Edition功能更全,但需要授权。如果你只是学习入门,直接装Web Edition就行,别一上来就折腾授权文件,那是给自己找麻烦。另外要注意,不同版本对器件系列的支持不一样,比如较新的Cyclone V、Cyclone 10系列在某些老版本里根本找不到,装之前先确认你手头的开发板用的是哪个系列的芯片。
1.2 安装路径和工程路径的坑,提前避开
安装本身没什么难度,一路下一步就行,但有两个地方我踩过坑,值得单独拎出来说。
第一个是安装路径不要带中文和空格。这个不是Quartus II独有的毛病,但它在路径处理上确实比较敏感。我见过有人把软件装在"Program Files"下面没问题,但工程放在"我的文档/FPGA学习/实验一"这种路径下,综合的时候报一堆莫名其妙的错,查了半天才发现是路径里的中文导致的。稳妥的做法是:软件装在纯英文路径下,工程也放在纯英文、无空格的目录里,比如D:/fpga_work/lab01这种。
第二个是工程路径不要太深。Windows对路径长度有260字符的限制,Quartus II在生成中间文件时会创建多层目录,如果工程路径本身就很深,很容易触发路径过长的问题,表现是综合到一半突然报文件找不到。我的习惯是在D盘根目录建一个fpga_work文件夹,所有工程都放在这一层下面,路径短、好找、不容易出问题。
提示:安装完成后第一次启动,软件会提示你指定license文件或者选择免费模式。选免费模式即可,Web Edition不需要license。如果弹窗提示找不到器件库,检查一下安装时有没有勾选对应的器件系列。
1.3 界面布局先认个脸
第一次打开Quartus II,主界面大致分几块:左边是Project Navigator(工程导航),显示工程里的文件层级;中间是工作区,打开代码文件或者图形化设计时在这里编辑;右边和下边是各种信息面板,包括编译消息、任务列表等。顶部是菜单栏和工具栏,常用的操作比如新建工程、编译、下载都在工具栏上有快捷按钮。
新手最容易犯的错是在工作区直接新建一个Verilog文件就开始写,写完发现编译不了——因为还没有建工程。Quartus II的逻辑是"工程"是容器,所有源文件、约束文件、设置都挂在工程下面,没有工程就没有编译的上下文。所以正确的顺序永远是:先建工程,再往工程里加文件。这个顺序搞反了,后面会各种别扭。
2. 从零建一个工程,每一步都在做什么
2.1 新建工程向导里的关键选项
点File → New Project Wizard,会弹出一个向导。第一页是工程路径、工程名和顶层实体名。这里有个细节:工程名和顶层实体名可以不一样,但强烈建议保持一致。顶层实体名对应你Verilog代码里那个module的名字,如果两者不一致,编译时会报"top-level entity not found"之类的错。我一般直接把工程名、顶层实体名都设成同一个英文名,比如led_blink,省得后面自己搞混。
第二页是添加已有文件,第一次建工程直接跳过。第三页选器件型号,这一步很关键。你需要知道自己开发板上芯片的具体型号,比如Cyclone IV系列的EP4CE6E22C8,每一位都有含义:EP表示Altera的产品前缀,4CE6表示Cyclone IV系列6K逻辑单元,E22表示封装类型和引脚数,C8表示速度等级和温度范围。选错了型号,后面引脚分配和编译都会出问题。如果你不确定型号,看开发板上的芯片丝印,或者问卖家要资料。
第四页选EDA工具,默认就行,除非你打算用第三方仿真工具,可以在这里指定ModelSim的路径。第五页是总结页,确认无误点Finish。
2.2 建完工程之后先加文件还是先写代码
工程建好后,Project Navigator里会显示一个空的工程结构。这时候可以新建一个Verilog文件:File → New → Verilog HDL File。新建的文件默认没有保存,先Ctrl+S保存到工程目录下,文件名建议和顶层实体名一致,比如led_blink.v。
这里说一个很多人不知道的点:Quartus II不会自动把新文件加入工程。你保存完文件后,需要手动在Project Navigator里右键 → Add/Remove Files in Project,把文件加进去。或者更省事的办法是保存文件时直接保存在工程目录下,然后在向导里勾选"Add file to current project"。如果忘了这一步,编译时会提示找不到顶层实体,新手经常卡在这里。
代码写完之后,还要做一件事:设置顶层实体。在Project Navigator里找到你的文件,右键 → Set as Top-Level Entity。虽然工程向导里已经指定过顶层实体名,但如果你后来改了module名或者加了新文件,这一步要重新确认。
2.3 引脚分配:把代码里的信号和物理引脚对上
代码里写的input clk、output led只是逻辑上的端口,芯片上具体哪个物理引脚对应哪个信号,需要你来指定。这一步叫引脚分配(Pin Assignment),在Assignments → Pin Planner里做。
打开Pin Planner,会看到一个芯片的引脚分布图,下面是引脚列表。在列表里找到你要用的引脚,填入对应的信号名。比如你的开发板上LED接在引脚PIN_A1上,就在PIN_A1那一行的Location栏填led。填完之后关掉窗口,设置会自动保存。
引脚分配有两个坑要提醒。第一,别随便选引脚,一定要对照开发板的原理图或者引脚说明文档。有些引脚是专用引脚(比如配置引脚、时钟专用引脚),乱用会导致下载后不工作甚至无法配置。第二,时钟信号尽量分配到专用的时钟引脚上,这些引脚在芯片内部有专门的时钟网络,走普通引脚会导致时钟质量差、时序问题多。原理图上一般会标注哪个是CLK引脚。
注意:引脚分配完成后,建议在Assignments → Device → Device and Pin Options里检查一下未使用引脚的状态。默认可能是"As input tri-stated",如果你的板子上某些引脚外部有上拉或下拉,这个设置可能引起意外功耗或干扰,一般建议设为"As input tri-stated with weak pull-up"或者根据实际情况调整。
3. 编译流程拆开看,每个阶段在干什么
3.1 一次完整编译包含哪些步骤
点工具栏上的编译按钮(或者Processing → Start Compilation),Quartus II会依次执行一系列步骤。很多人只知道点一下等结果,其实展开任务列表能看到完整流程:Analysis & Synthesis(分析与综合)、Fitter(布局布线)、Assembler(生成配置文件)、TimeQuest Timing Analyzer(时序分析)。每一步的作用不一样,出问题时的表现也不一样。
Analysis & Synthesis阶段检查代码语法,把Verilog转换成门级网表。这一步报错通常是代码写错了,比如少分号、模块端口不匹配、使用了不支持的语法。Fitter阶段把网表映射到芯片的具体资源上,分配逻辑单元、布线资源。这一步报错通常是资源不够或者引脚冲突。Assembler生成最终的.sof或.pof文件,用于下载。TimeQuest做时序分析,报告建立时间、保持时间是否满足。
理解这个流程的意义在于:当编译报错时,你能快速判断问题出在哪个环节。语法错误在综合阶段就挂了,引脚冲突在布局布线阶段才暴露,时序不满足则是最后分析阶段才报。知道这个,排查效率会高很多。
3.2 编译报错怎么读消息
编译完成后,下方的Messages面板会显示所有消息,分Error、Warning、Info几个级别。新手容易犯的错是只看有没有Error,忽略Warning。有些Warning是无害的,但有些Warning其实预示着问题,比如"found clock signal without clock constraint"这种,说明你的时钟没有加约束,时序分析结果不可信。
读Error消息有个技巧:从第一条Error开始看,因为后面的错误往往是第一条引起的连锁反应。比如第一条报某个信号未定义,后面可能跟着十几条"cannot resolve"之类的错误,其实改掉第一个就全好了。另外,双击Error消息一般能跳转到代码中对应的行,善用这个功能能省不少时间。
如果编译通过了但下载到板子上不工作,先别怀疑代码逻辑,检查这几项:引脚分配对不对(对照原理图再核一遍)、时钟有没有接对、复位信号极性对不对、下载文件是不是最新的。我遇到过好几次是引脚分配时把两个信号填到了同一个引脚上,编译不报错但行为完全不对。
3.3 时序约束:入门阶段要不要管
严格来说,时序约束(SDC文件)是做时序分析的前提,没有约束的时序报告基本没有参考价值。但入门阶段做点灯、按键这类低速逻辑,时钟频率低、逻辑简单,时序一般不会出问题,可以先不深究。不过有个最低限度的约束建议加上:用create_clock命令给你的主时钟加一个周期约束。
具体做法是在工程里新建一个SDC文件(File → New → Synopsys Design Constraints File),写入类似这样的内容:
create_clock -name clk -period 20.000 [get_ports clk]这表示时钟周期20ns,对应50MHz。加上这个约束后,TimeQuest的时序报告才有意义。等你后面做更复杂的逻辑,比如跨时钟域、高速接口,时序约束就是必修课了,入门阶段先把这根弦绷上,知道有这么回事。
4. 下载到板子上跑起来,以及跑不通怎么查
4.1 下载工具和下载文件的区别
编译成功后,在工程目录的output_files文件夹里能找到.sof文件。.sof是SRAM Object File,下载到FPGA后掉电就丢失,适合调试阶段用。.pof是Programmer Object File,烧写到配置芯片里,掉电不丢失,适合最终产品。入门阶段用.sof就行,每次上电重新下载一次,方便反复修改。
下载用Tools → Programmer打开下载工具。第一次用需要配置硬件:点Hardware Setup,选择USB-Blaster(如果你用的是USB下载器)。如果列表里没有,说明驱动没装好,去设备管理器里看看有没有未识别的设备,装一下驱动。硬件配置好后,在Programmer窗口里添加.sof文件,勾选Program/Configure,点Start就开始下载。
4.2 下载成功但现象不对的排查顺序
下载进度条走完显示100%成功,但板子上没反应,这是最常见的情况。排查按这个顺序来,能覆盖大部分问题:
第一,确认引脚分配和原理图一致。这是最高频的错误来源。特别是LED和按键,不同开发板的引脚定义差别很大,别照抄别人的分配表。
第二,确认时钟。如果你的逻辑依赖时钟,检查时钟引脚分配对不对、板子上的晶振频率是不是你代码里假设的频率。有人代码里按50MHz写分频,板子上却是25MHz晶振,现象就是LED闪得比预期慢一倍。
第三,确认复位逻辑。很多代码用了低电平复位,但板子上的复位按键按下是高电平,导致系统一直处于复位状态。看原理图确认按键的有效电平。
第四,确认下载的是最新编译的文件。改了代码忘了重新编译,或者Programmer里加载的还是旧文件,这种情况我也干过。
4.3 一个最小验证工程的做法
如果你是完全的新手,建议第一个工程不要写复杂逻辑,就做一个最简单的:一个计数器分频后驱动一个LED闪烁。代码大概是这样:
module led_blink( input clk, input rst_n, output reg led ); reg [24:0] cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt <= 25'd0; led <= 1'b0; end else if (cnt == 25'd24_999_999) begin cnt <= 25'd0; led <= ~led; end else begin cnt <= cnt + 1'b1; end end endmodule假设时钟50MHz,计数到2500万翻转一次,LED闪烁周期就是1秒亮1秒灭。这个工程足够简单,能把"建工程→写代码→分配引脚→编译→下载"整条链路走通,而且现象直观,LED闪了就说明全流程没问题。等这个跑通了,再去加按键消抖、数码管显示这些,循序渐进。
引脚分配就三个:clk接时钟引脚,rst_n接复位按键引脚,led接一个LED引脚。分配完编译下载,如果LED不闪,按上面4.2的顺序排查。这个最小工程的价值在于:它把所有环节都串起来了,任何一环出问题都会表现为LED不闪,你通过排查这个过程,能把整个工具链的理解打通。
5. 几个让效率翻倍的操作习惯
5.1 用好工程模板和复制工程
每次新建工程都走一遍向导、重新分配引脚,很浪费时间。更高效的做法是:把调通的最小工程保存为模板,以后新工程直接复制整个工程文件夹,改个名字,然后清理掉旧的编译产物(db、incremental_db、output_files这些文件夹可以删),再改代码和引脚分配。这样能省掉大量重复配置的时间。
复制工程时要注意,.qpf(工程文件)和.qsf(设置文件)里的工程名和路径信息可能需要手动改,或者干脆在Quartus II里用Project → Save Project As另存为新工程,这样软件会自动处理路径和名称。我一般用另存为的方式,稳妥。
5.2 版本管理和备份
FPGA工程的版本管理有个麻烦点:编译产生的中间文件很多、很大,不适合全部纳入版本管理。合理的做法是只管理源文件(.v)、约束文件(.sdc)、设置文件(.qsf)和引脚分配,中间产物用.gitignore排除掉。如果你用Git,在工程根目录建一个.gitignore,写入:
db/ incremental_db/ output_files/ *.sof *.pof这样仓库干净,每次提交只包含真正有价值的源文件。另外,每次重大修改前手动备份一份工程文件夹,命名带上日期,比如led_blink_20240115,这是最朴素但最可靠的保险。
5.3 常见报错速查
把入门阶段最常遇到的几个报错整理成表,方便对照排查:
| 报错信息关键词 | 可能原因 | 处理方向 |
|---|---|---|
| Top-level entity not found | 顶层实体名和工程设置不一致,或文件未加入工程 | 检查module名,确认文件已Add to Project |
| Can't find port in design | 引脚分配里的信号名和代码端口名不一致 | 核对Pin Planner里的信号名拼写 |
| Pin has multiple drivers | 同一个引脚被分配了多个信号 | 检查引脚分配表有无重复 |
| Insufficient resources | 逻辑资源超出芯片容量 | 优化代码或换更大器件 |
| Timing requirements not met | 时序不满足 | 检查时钟约束,降低频率或优化逻辑 |
这张表覆盖不了所有情况,但入门阶段八成的报错都能在里面找到方向。遇到表里没有的,把Error消息完整复制出来去搜,比只看关键词搜准确得多。
5.4 关于图形化设计和代码设计的取舍
Quartus II支持图形化输入(Block Diagram/Schematic File),拖拽逻辑门和元件连线来设计。入门阶段有人喜欢用图形化,觉得直观。我的建议是:图形化可以用来理解电路结构,但真正做项目还是老老实实写Verilog。原因很简单,图形化设计在复杂逻辑下会变得极其混乱,而且不利于版本管理和复用。用代码写,逻辑清晰、可参数化、可移植,这是行业通行做法。图形化最多用来画个顶层框图,把各个模块连起来,作为代码的补充。
6. 从跑通第一个工程到真正会用,中间还差什么
跑通点灯工程只是起点,离"会用Quartus II"还有距离。接下来要补的几块:一是仿真验证,学会用ModelSim或者Quartus II自带的仿真器做功能仿真,养成"先仿真后上板"的习惯,能省掉大量反复下载调试的时间;二是时序约束和分析,理解建立时间、保持时间的概念,学会看TimeQuest的时序报告;三是IP核的使用,Quartus II自带很多IP核(PLL、RAM、乘法器等),学会用MegaWizard配置IP核是提升效率的关键;四是脚本化流程,Quartus II支持Tcl脚本,把常用操作写成脚本能大幅提升重复工作的效率。
我个人在实际操作中的体会是,Quartus II这个工具本身不难,难的是建立对整个FPGA开发流程的认知——知道每一步在干什么、出了问题往哪查。工具只是载体,真正值钱的是你对数字逻辑和硬件行为的理解。点灯工程跑通之后,别急着做复杂项目,先把仿真流程走一遍,把时序报告看懂,把IP核用熟,这些基础打牢了,后面做再复杂的项目都是水到渠成的事。另外提醒一句,不同版本的Quartus II界面和菜单位置有差异,网上找教程时注意看对方用的版本,遇到菜单找不到的情况,先确认版本是否一致,别怀疑自己操作错了。