Quartus 语法错误(Error 10170 / 10500 syntax error)速查
更新时间:2026-10-23。FAQ 速查页,面向 FPGA 入门 阶段的同学。症状很典型:点了 Start Compilation,Processing 窗口第一屏就是红色的
Error (10170): Verilog HDL syntax error at xxx.v(23) near text ...,而报错那一行看着人畜无害。本篇只回答一件事:Quartus 的解析器读不下去你的 RTL 时,怎么在十分钟内找到真正的断点。
本文要回答的问题
- 报错行号指向的那一行语法明明正确,为什么真正的错误常在它的上一行、甚至上一个文件?
- 同一份 SystemVerilog 文件,仿真器能过、Quartus 却报
near text "logic",问题出在哪? - Verilog 的
Error (10170)和 VHDL 的Error (10500)排查思路有什么异同? - 全角分号、中文括号、BOM 这类肉眼看不见的问题为什么会让 Quartus 报满屏语法错?
- generate 块、宏定义为什么也会让报错位置「说谎」?
一、报错原文:先看 Quartus 真实长什么样
Quartus 的语法报错在 Analysis & Synthesis 阶段抛出,Verilog 系错误号以 10170 为中心,VHDL 系以 10500 为中心,文案风格与 Vivado 明显不同——它会明说「expecting」什么:
Error (10170): Verilog HDL syntax error at demo_top.v(23) near text: ";". Expecting ")", or ","
Error (10170): Verilog HDL syntax error at demo_top.v(45) near text: "end". Expecting ".", or "(", or "[", or "::"
Error (10500): VHDL syntax error at demo_top.vhd(40) near text "process"; expecting "begin", or a declaration statement
Error (10170): Verilog HDL syntax error at demo_top.v(8) near text: "logic"读懂这三行就拿到了排查的一半答案:
at xxx.v(n)是「发现处」:解析器读到第 n 行的那个 token 才确定前面收不住,病灶常在上一行结尾;near text是肇事 token:指到logic、always_ff这类 SV 专有符号,先怀疑文件被按老 Verilog 解析;指到普通分号括号,才是源码本身写错;Expecting ...是解析器当时的期望:Expecting ")"说明括号没收尾,Expecting "begin"说明 VHDL 声明区缺东西。这串清单是 Quartus 报错比别家友好的地方,值得逐字读。
排查永远从第一条 Error 开始——一个语法错会引发后面几十条连锁报错,只修第一条、重跑、再读新的第一条。
二、排查决策树
先按 near text 的 token 分流:SV/VHDL 专有符号走「文件类型与语言标准」,普通标点走「回读上一行找配对」,第一条就是非法字符或 line 1 报错直接查隐藏字符与编码。
读这张图抓住「先分流、再回溯」:红色是报错入口,蓝色是排查动作,橙色是两类修复(改文件类型设置或改源码字符),绿色是干净重跑。任何一层命中就在那一层修,不要同时动文件属性和源码,否则修好了也不知道是哪一刀生效的。
三、病因处置速查表
| 报错现象 | 可能原因 | 处置 |
|---|---|---|
near text: "logic"/"always_ff"/"package" | .sv 被按 Verilog-2001 解析:文件加进工程时类型选错 | 文件属性改 SystemVerilog;qsf 里 set_global_assignment -name SYSTEMVERILOG_FILE xxx.sv |
VHDL 报 near text "process"、Expecting "begin" | VHDL 声明区与 begin 之间顺序错,或 entity/architecture 缺 end | 回读 architecture 声明段;核对 end entity / end architecture 配对 |
| 报错行正确、上一行结尾可疑 | 缺分号、缺逗号,解析器下一行才发现 | 回读上一行;重点查端口表、参数表、case 分支 |
突然报 near text: "endmodule" 或 EOF | begin/end、case/endcase、module/endmodule、generate/endgenerate 不配对 | 编辑器括号配对高亮逐层数;最小化注释二分 |
| generate 区域大片报错 | generate 里写了 always @(clk) 这类直接语句,或 for-generate 缺 genvar / 缺标签 | for-generate 必须 genvar i + 循环体加命名标签 begin : gen_blk |
Verilog 文件里出现 signal、downto、std_logic | 从 VHDL 示例抄代码贴进了 .v 文件(语法串台) | 按目标语言重写;Verilog 用 wire/reg 与 [7:0] |
端口声明混写 wire、reg、logic 后报语法错 | Verilog-2001 模式不支持 logic;ANSI 端口声明里类型位置写错 | SV 模式才用 logic;Verilog 模式输出端口要重复声明 output reg |
| line 1 或满屏连环非法字符 | 全角分号 ;、中文括号 ()、零宽字符、BOM 混入 | 编辑器开「显示不可见字符」;全角改半角;文件存为 UTF-8 无 BOM |
| 宏展开处报 token 错 | `define 的值带分号/运算符,展开后语法错位;`ifdef 段整段消失 | 宏值不带分号;核对 `ifdef 配对与编译顺序 |
四、逐条排查展开
第一步:确认 Quartus 按什么语言在读它。 这是 Quartus 与 Vivado 最大的差异点:Quartus 按文件加入工程时登记的 HDL 类型解析,而不是只看后缀。.sv 文件如果用「Add File」时被认成 Verilog HDL File,logic、always_ff 全部报 10170。GUI 里在 Project Navigator 右键文件 → Properties,把 Type 改成 SystemVerilog HDL File;脚本工程直接写 qsf:
# qsf 里显式声明语言标准——SV 文件必须用 SYSTEMVERILOG_FILE,不是 VERILOG_FILE
set_global_assignment -name SYSTEMVERILOG_FILE rtl/demo_top.sv
set_global_assignment -name VERILOG_FILE rtl/legacy/old_ip.v
set_global_assignment -name VHDL_FILE rtl/uart_rx.vhd一个快速判据:near text 是 logic、bit、always_ff、interface 之一,而文件确实是 SV 写的,九成是文件类型登记错了。改完类型重跑 Analysis & Synthesis 即可,不用动源码。
第二步:语言标准对仍报错,从报错行的上一行回读配对。 Quartus 的 Expecting 清单直接告诉你它当时想要什么:Expecting ")" 就是括号没收尾、Expecting ";" 就是上一句缺分号、Expecting "end" 就是块没收住。高发顺序:端口表或参数表少一个逗号、always 块漏 begin ... end、case 漏 endcase、module 漏 endmodule。肉眼数不过来时用最小化二分:把可疑块整段注释掉让解析器先过,再一段段放回来——断点重新出现的那一段就是病灶。
第三步:generate 块与宏是「报错位置说谎」的惯犯。 for-generate 在 Quartus 里有硬性格式:必须声明 genvar、循环体必须带命名标签:
genvar i;
generate
for (i = 0; i < 4; i = i + 1) begin : gen_delay // 缺 genvar 或缺标签都报 10170
always @(posedge clk) d[i+1] <= d[i];
end
endgenerate宏这边,`define WIDTH 8 的值里如果误带分号,展开后语句中间会多出一个分号,报错落在使用宏的那一行而不是定义处;`ifdef 包住的端口在宏未定义时整段消失,后面的端口表错位,报错会落在几十行后的某个分号上。遇到「报错行完全无辜」的情况,先把宏全部展开想一遍。
第四步:语法串台——VHDL 写法混进 Verilog 文件。 从网上抄示例最容易犯:把 VHDL 的 signal cnt : integer range 0 to 7;、downto、rising_edge(clk) 贴进了 .v 文件,或者反过来把 always @(posedge clk) 贴进了 .vhd。Quartus 会在第一个不认识的 token 处报 10170/10500,文案看着像缺分号,实际是整段语言不对。处置不是补标点,而是按目标语言重写那一段。
第五步:隐藏字符用编辑器现形。 从 PDF、聊天工具、Word 粘贴代码最容易混入全角分号 ;、中文括号 ()、中文引号,它们和半角符号视觉差异极小,但 Quartus 会直接报非法字符或莫名 token 错。编辑器开启「显示空白字符与不可见字符」,全角符号会显出异常宽度;文件头几个字节就报错的,检查是否带 BOM——另存为「UTF-8 无 BOM」即可。粘贴过的代码整段重敲可疑标点是最稳的办法。
第六步:修完重跑,只认第一条报错。 Quartus 菜单 Processing → Start → Start Analysis & Synthesis 单跑语法阶段即可,不必全编译。语法错会引发连锁反应,一次只修第一条、重跑、再读新的第一条,比一口气改十处高效得多。
五、预防与纪律
- 编辑器实时语法检查:VS Code 装 Verilog/SystemVerilog 插件或接 verilator 做 linter,缺分号、括号不配在保存时就标红,不把问题留到综合。
- 文件类型一次登记对:SV 文件进工程时就在 Add File 对话框选好 SystemVerilog HDL File;脚本工程 qsf 里
SYSTEMVERILOG_FILE与VERILOG_FILE分开写,不混用。 - 团队约定语言不串台:示例代码先看它是什么语言再抄;VHDL 与 Verilog 文件分目录放,命名不混。
- 宏集中管理:条件编译宏在头文件统一定义并注释用途,宏值不带分号;include 文件只放宏与参数,不放模块定义。
- 粘贴代码先过纯文本:从文档/网页贴 RTL 后先肉眼扫一遍标点再保存,编辑器常开不可见字符显示。
这一篇在知识体系里的位置
本篇是 FPGA 排错速查簇的一员,处理「文件在工程里、但 Quartus 读不下去」的解析阶段;语法能过但找不到模块定义,见 Quartus 找不到模块速查;elaboration 阶段的未定义符号与黑盒,见 Quartus 未定义符号速查;同款问题在 Vivado 侧的报错文案与排查(read_verilog -sv 路线),见 Vivado 语法/解析报错速查。
一句话总结
Quartus 语法错误先看 near text 的 token 与 Expecting 清单:指到 logic、always_ff 等 SV 专有符号就是文件类型登记错(工程属性改 SystemVerilog HDL File,qsf 用 SYSTEMVERILOG_FILE),指到普通标点就从报错行的上一行回查分号与 begin/end、case/endcase、module/endmodule 配对;generate 缺 genvar/标签、宏展开错位、VHDL 与 Verilog 语法串台会让报错位置「说谎」,全角标点与 BOM 靠编辑器显示不可见字符现形,修完单跑 Analysis & Synthesis、一次只认第一条报错,配合编辑器 linter 与文件类型一次登记对即可把这类问题挡在综合之前。