Quartus 改了代码编译结果没变:构建缓存陈旧速查
更新时间:2026-10-23。FAQ 速查页,面向已经会用 Quartus 做日常开发的中级读者。先建立一个正确预期:Quartus 不是每次编译都从头读你磁盘上的源文件——它维护着
db/与incremental_db/两套编译数据库,里面缓存着上次综合、适配(Fitter)的中间结果。改了一行 RTL 就点编译,Quartus 会先判断"哪些输入变了、哪些可以复用",判断对了叫增量编译、是提速特性;判断错了,你拿到的比特流就是上一轮的旧产物,板上行为和改动前一模一样。这类"Quartus 改了代码编译结果没变"的工单,九成根因都在这套缓存与工程登记的对应关系上,而不是你的 RTL 没保存。工具侧另一类常见问题——编译本身卡住不出结果——是另一个方向,见 Quartus 编译卡死速查。
本文要回答的问题
- RTL 明明改了也保存了,重编译后下载到板子,行为为什么和改之前完全一样?
- 文件都从工程里删掉了,编译为什么还报那个文件里的错?
db/和incremental_db/两个目录各自缓存什么,什么时候该删哪个?.qsf里挂着两份同名文件时,Quartus 到底用哪一份?- 为什么 IP 核重新 generate 了,综合结果还是旧的?
- 怎么确认"这次编译真的吃进了我的改动"?
一、典型现象:三种长相,同一个病根
这类问题在真实工作里有三种常见长相,先对号入座再排查。
长相一:安静的旧结果。 改了计数器位宽或者状态机跳转条件,编译顺利通过、没有 warning 异常,sof 文件生成时间也是新的,但下载到板子上行为纹丝不动。重新看 RTL 文件,改动确实在磁盘上。这种情况最迷惑,因为整个流程没有任何报错——编译"成功"了,只是编译的不是你以为的那份代码。
长相二:幽灵报错。 某个模块已经从工程里移除、文件也删了,Analysis & Synthesis 阶段却仍然报那个文件里的语法错误或端口不匹配。报错信息里的路径点开一看,文件明明不存在。这是 .qsf 或编译数据库里还残留着旧登记信息的典型信号。
长相三:改了没反应、改回去反而报错。 这是网络盘或多机协作场景的特产:文件服务器和工作站的时间不同步,你保存的文件 mtime 比编译产物还旧,Quartus 比对时间戳后认为"输入没变化",直接复用缓存;而某些操作(比如从别处拷文件覆盖)反而可能触发一连串莫名报错。
二、原因速查表
按下表先分诊,命中哪一行就先验证哪一行,不要上来就全删重编。
| 现象 | 根因 | 快速验证 | 处置 |
|---|---|---|---|
| 改 RTL 后行为不变、编译很快 | 增量编译复用 db/ 旧结果 | 看编译耗时是否异常短;对比 sof 生成时间与源文件 mtime | Project > Clean Project,或删 db/、incremental_db/ 后全量重编 |
| 删掉的文件仍报错 | .qsf 里残留 set_global_assignment -name VERILOG_FILE 登记 | 用文本编辑器搜 .qsf 里的文件名 | 在 .qsf 里删掉对应行,或 Project Navigator 里 Remove 后重编 |
| 改动的内容不生效、像改了空气 | .qsf 挂了两份同名文件(不同路径),改的是没登记的那份 | grep 源文件名,看 .qsf 里登记的是哪个路径 | 删除错误路径的登记,只保留你实际维护的那份 |
| 仿真对、上板不对 | 仿真用的是另一份源文件(如 tb 目录下的副本),综合走的是工程登记的那份 | 对比仿真脚本文件列表与 .qsf 登记列表 | 统一源文件入口,仿真与综合引用同一路径 |
| IP 改参数后端口对不上或行为旧 | 重新 generate 了 IP,但 Quartus 没有重新综合 | 看 .qip 时间戳与最近一次综合日志时间 | generate 后执行 Analysis & Synthesis,必要时 Clean Project |
| 网络盘工程时好时坏 | 文件服务器与工作站时间不同步,mtime 误判 | stat 源文件对比编译产物时间,看是否"源比产物旧" | 工程放回本地盘;或保存后 touch 强制刷新 mtime |
| 怎么改都像没改、报错路径也对不上 | 打开的工程不是你以为的那个(多工程并存、快捷方式指错) | 看 Quartus 标题栏的 .qpf 完整路径 | 确认并关闭多余工程,从正确 .qpf 重新打开 |
| 团队里只有一个人编译结果不对 | 其本地 db/ 里混入了旧分支/旧版本产物 | 对比各人 db/ 目录体积与生成时间 | 该成员删 db/、incremental_db/ 全量重编,产物目录统一不入版本库 |
三、排查决策图
先确认"编译的是不是你以为的工程与文件",再决定清缓存的粒度,是这类问题最短的路径。
颜色按角色区分:红色是问题入口,蓝色是两步排查动作,橙色是两类修复手段,绿色是验证通过的收尾,紫色是长期预防。读这张图抓住一条主线:先排除"开错工程、改错文件"这类低级但高发的乌龙,再动缓存——真实工单里"改的是没被工程登记的那份同名文件"占比高得惊人,直接删 db/ 重编半小时,不如先花两分钟核对 .qsf。
四、逐条排查
第一步,确认打开的是正确的工程。 Quartus 标题栏显示当前 .qpf 的完整路径,多看一眼。多人协作或本机存了多份工程副本时,"在 A 副本里改代码、在 B 副本里编译"是最常见的乌龙,没有之一。
第二步,核对 .qsf 的源文件登记。 .qsf 是文本文件,用编辑器搜你改动的那个文件名。如果搜出两行 set_global_assignment -name VERILOG_FILE,路径不同、文件名相同——问题就找到了:Quartus 只编译登记的那一份,你改的可能是另一份。删掉错误行,保留唯一正确路径。删除文件后仍报错的"幽灵报错"同理:文件删了但登记还在,清掉对应行即可。
第三步,怀疑缓存就清,粒度由小到大。 首选菜单 Project > Clean Project,它会清掉编译数据库但保留工程设置,是最稳妥的一档。如果 Clean 之后行为仍旧,关掉 Quartus,手工删除工程目录下的 db/ 与 incremental_db/ 两个文件夹再重开重编——这相当于强制全量编译,基本能排除一切缓存因素。注意 incremental_db/ 是增量编译(Incremental Compilation)特性的缓存,开了增量编译分区的工程才会大量用到;没开这个特性的普通工程,主力缓存在 db/。
第四步,IP 核改参数后必须让综合感知。 在 Platform Designer(Qsys)或 IP 参数编辑器里重新 generate,只更新了 IP 的生成产物;Quartus 的综合器未必会立刻重跑。正确顺序是:generate 完成 → Analysis & Synthesis 重跑 → 全量编译。如果 .qip 文件的时间戳比最近一次综合日志还新,基本可以断定综合吃的是旧 IP。
第五步,验证"改动真的被吃进去了"。 三个可操作的检查:编译耗时——全量重编明显比增量复用慢,秒级结束的"编译"多半没干活;综合日志——在 Compilation Report 的 Analysis & Synthesis 小节里能看到实际读入的源文件列表,确认你改的那份在列;md5sum 或哈希对比——对关键源文件算哈希,确认磁盘上的内容就是你以为的内容(网络盘场景尤其值得一算)。
五、防复发:四条纪律
db/、incremental_db/永远不进版本库。 这两个目录是机器相关的编译缓存,提交进 git/svn 只会在切分支、换机器时制造"别人编的和我编的不一样"的灵异事件。.gitignore里把db/、incremental_db/、output_files/(按需)、*.qws都列上。- 源文件入口唯一。 同一个模块只允许存在一个路径、一处登记;仿真脚本(ModelSim/Questa 的
.do或文件列表)和.qsf引用同一份文件,杜绝"仿真改了 A、综合用 B"。 - 工程放本地盘。 网络盘的 mtime 不同步问题无解,只能绕开——工程在本地 SSD,版本库做同步,两头好处都占。
- 改动后固定动作成习惯。 改 RTL → 保存 → Clean Project(或确认增量判定正常)→ 全量编译 → 看综合日志源文件列表。把这个序列变成肌肉记忆,比事后排查省得多。
跨工具的同类问题可以对照着看:Xilinx 阵营的对应机制是 runs 状态机与 .runs/.gen/.cache 产物目录,症状相似、处置命令不同,见 Vivado 构建缓存陈旧速查。
这一篇在知识体系里的位置
本篇是 FPGA 工具排错速查簇中"构建产物一致性"节点在 Quartus 侧的 FAQ 页,与 Xilinx 侧的 Vivado 构建缓存陈旧速查 互为镜像;编译过程本身卡住不动的问题走 Quartus 编译卡死速查。两篇合起来覆盖 Quartus 编译期的两大高频抱怨:"结果不对"看本篇,"结果不出"看卡死篇。
一句话总结
Quartus 改了代码编译结果没变,病根几乎都在"编译的输入和你以为的输入不一致":db/ 与 incremental_db/ 缓存陈旧、.qsf 登记了两份同名文件而你改了没登记的那份、仿真与综合各走一份源、IP 重新 generate 后没重综合、网络盘时间戳骗过增量判定、或者干脆开错了工程;排查先核对标题栏工程路径与 .qsf 登记,再 Project > Clean Project 或手删 db/、incremental_db/ 全量重编,最后看综合日志的源文件列表确认改动被吃进去;长期靠缓存目录不入版本库、源文件入口唯一、工程放本地盘、改 IP 后固定重综合四条纪律防复发。