Quartus 中文乱码与编码报错速查:GBK、UTF-8 BOM、CRLF 与 locale
更新时间:2026-10-23。FAQ 速查页,面向在 Windows 中文系统上写 RTL、再用 Quartus Prime 编译,或把工程拷到 Linux 服务器跑
quartus_sh批处理的同学。这类问题的共同特征是:报错行号指着一行完全正常的代码,中文注释在 Message 窗口变成问号,而「在记事本里打开明明是好的」是最常听到的辩解。Quartus 对源文件字节编码相当敏感,语法解析类报错的整体排查框架见 Quartus 语法/解析报错速查,Vivado 阵营的同类问题对照见 Vivado 编码/乱码速查。
本文要回答的问题
- RTL 里的中文注释在 Quartus 编辑器或编译日志里变成问号、方块,是谁的问题?
Error (10170): Verilog HDL syntax error指向的一行明明没有语法错误,为什么?- 同一个工程在 Windows 上编译通过,拷到 Linux 上
quartus_map直接报错,差在哪? - 怎么确认一个
.v/.qsf/.tcl文件到底是 GBK 还是 UTF-8、有没有 BOM、行尾是 CRLF 还是 LF? - 命令行跑 Quartus 时输出的中文全乱码,
LANG/LC_ALL要怎么设?
一、报错原文与典型现象
编码类问题的第一信号往往不是「乱码」两个字,而是 Quartus 报出一个和真实原因毫不相干的语法错。以下四类文案最典型,工程名与路径已占位:
1. syntax error 指向明明正常的行(GBK 字节拆进语句区):
Error (10170): Verilog HDL syntax error at top.v(23) near text: "?"; expecting ";", or "."
Error (10170): Verilog HDL syntax error at uart_rx.v(41) near text: ""2. 文件第一行就报错(UTF-8 BOM 被当成第一个 token):
Error (10170): Verilog HDL syntax error at top.v(1) near text: ""; expecting a description
Error: Quartus Prime Tcl script "build.tcl" couldn't be read: invalid character at line 13. 中文注释显示为问号或乱码:
// 源码里写的是: // 串口接收模块,状态机
// Quartus 里看到: // ????ģ?飬?״̬??4. Windows 正常、Linux 编译不过(CRLF 行尾混入 Tcl/QSF):
Error: The Tcl script "pin_assign.tcl" could not be evaluated near line 12: missing close-brace第一条分流判据:报错带行号、指向具体某行代码,就是「文件内容问题」,去查字节编码与行尾;报错说文件读不了、脚本 couldn't be read,多半是 BOM 或路径问题。 两类修法完全不同,顺序不能反。另一个容易误判的信号是「同一个文件在 Quartus 自带编辑器里看着正常、编译却报错」——编辑器按自己猜测的编码显示,编译器按固定规则解析字节,两者结论经常不一致,永远以编译器报错为准。
二、现象到根因总览
| 报错现象 | 可能原因 | 快速确认 | 处置 |
|---|---|---|---|
| syntax error 指向正常行,行附近有中文注释 | 文件是 GBK/GB18030,Quartus 按单字节/UTF-8 解析时中文字节溢出到下一行 | file top.v 显示 ISO-8859 或非 UTF-8 | iconv -f GBK -t UTF-8 转码后重编译 |
| 第 1 行报 syntax error 或 Tcl invalid character | 文件带 UTF-8 BOM(EF BB BF),Quartus 解析器把 BOM 当 token | head -c 3 top.v | hexdump -C 看 ef bb bf | 去 BOM,另存 UTF-8 无 BOM |
| Windows 编译过、Linux 报错或行为不同 | CRLF 行尾,Tcl 续行符 \ 后多了 CR;QSF 解析对行尾敏感 | cat -A build.tcl 看行尾 ^M$ | dos2unix 统一为 LF |
| 编辑器里中文注释是问号/方块 | 文件编码与编辑器打开编码不一致(GBK 文件按 UTF-8 打开) | 换编码重新打开对比 | 确认真实编码,统一为 UTF-8 |
命令行 quartus_sh 输出中文乱码 | 进程 locale 是 C/POSIX,无法输出多字节字符 | locale 查看 LANG/LC_ALL | export LANG=en_US.UTF-8 或 zh_CN.UTF-8 |
| Tcl 脚本里中文路径/中文注释报错 | Tcl 解析器对非 ASCII 字节敏感,尤其旧版 Quartus | 报错行有中文或全角字符 | 路径全英文,注释改英文或确认 UTF-8 |
| Notepad++ 改过之后编译不过 | 存盘编码被切成「UTF-8-BOM」或「ANSI(GBK)」 | 状态栏看编码,或 hexdump 看头部 | 显式选「UTF-8(无 BOM)」重存 |
三、按决策树排查
排查主线只有一条:先看报错原文分流,再看文件字节,最后才动 locale。locale 只影响显示,永远修不好一个本身编码错误的文件。
读这张图抓住一次分流:红色入口是现象;蓝色第一个节点是分流动作——报文带行号走「文件内容」支,报文说读不了文件走「BOM/路径」支;两支汇入橙色修复,每步只做一类转换;绿色是重编译验证通过;紫色收尾是把编码纪律固化进编辑器配置,而不是记住这次手工怎么救回来的。
第一步,探测文件真实编码。 Linux/macOS 上三条命令把嫌疑钉死:
file src/top.v # UTF-8 Unicode text 才是 UTF-8;ISO-8859 多半是 GBK
head -c 3 src/top.v | hexdump -C # 头三字节 ef bb bf 即 UTF-8 BOM
cat -A scripts/build.tcl | head # 行尾出现 ^M$ 即 CRLFfile 报 ISO-8859 text 而内容本该有中文,基本就是 GBK 文件。Windows 上没有这些命令时,用 Notepad++ 或 VS Code 右下角状态栏直接看当前编码。还有一个快速定位「哪一行藏着非 ASCII 字节」的命令:
grep -nP '[\x80-\xff]' src/top.v | head # 列出所有含高位字节的行,逐行核对很多「syntax error 指向正常行」的案件,用这条命令一扫就能发现报错行的上一行注释里藏着 GBK 中文,某个字节溢出后恰好把下一行的分号吃掉了。
第二步,GBK 转 UTF-8。 Windows 简体中文环境下「ANSI」保存就是 GBK,Quartus 在 Linux 下按 UTF-8 读、在部分 Windows 版本按系统区域设置读,多字节中文被拆开后某个字节恰好落在语句区,就报出指向正常行的 syntax error。显式转码,先留底:
iconv -f GBK -t UTF-8 src/top.gbk.v -o src/top.v批量处理整个工程时不要原地覆盖,先转一份再编译验证:
for f in src/*.v; do iconv -f GBK -t UTF-8 "$f" -o "$f.utf8" && mv "$f.utf8" "$f"; doneVS Code 的对应动作是右下角点编码 →「通过编码重新打开」选 GBK 确认中文显示正常 → 再「通过编码保存」为 UTF-8。Notepad++ 在「编码」菜单里直接选「转为 UTF-8(无 BOM)」。注意顺序:必须先用正确编码「重新打开」再转存,直接转存会把已经乱码的字节固化成错误的 UTF-8。
第三步,去 BOM。 部分编辑器保存 UTF-8 时在文件头加 EF BB BF 三个字节。Quartus 的 HDL 解析器和 Tcl 解释器都可能把 BOM 当第一个 token,于是第一行合法代码神秘报错:
sed -i '1s/^\xEF\xBB\xBF//' src/top.v # Linux;macOS 用 sed -i ''第四步,CRLF 收敛为 LF。 Tcl 脚本里反斜杠续行要求 \ 是行尾最后一个字节,CRLF 让它后面多跟一个 CR,续行断裂,报错点指向完全无辜的下一行:
dos2unix scripts/build.tcl
# 没有 dos2unix 时:sed -i 's/\r$//' scripts/build.tcl最后才是 locale。 只有「文件编码正确、GUI 显示正常,但命令行输出中文乱码」这一种情况归 locale 管,在批处理脚本里写死:
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8这只影响进程如何解释和输出多字节字符,修不好一个 GBK 文件本身,所以永远排在最后。判断 locale 是否生效的方法很简单:在设好 LANG 的同一个 shell 里跑 locale 确认输出全是 UTF-8,再重跑 quartus_sh --flow compile <project> 看 Message 输出。
还有一个容易混淆的反向场景:文件本身是合法的 UTF-8,但你在 GBK 终端(如某些 Windows SSH 客户端默认 GBK)里 cat 出来全是乱码。这时不要回头把文件转成 GBK——乱的是终端的解码,不是文件。把终端字符集切成 UTF-8,或者用 iconv -f UTF-8 -t GBK 只在查看时转换,文件保持 UTF-8 不动。
四、防复发
- 源文件三统一:
.v/.sv/.qsf/.tcl一律 UTF-8、无 BOM、LF 换行;VS Code 里固化files.encoding: utf8、files.eol: \n。 - 语句区只放 ASCII:模块名、信号名、引脚约束、Tcl 命令一律英文;中文只允许出现在注释里,且最好整条工具链验证过 UTF-8 注释不炸再放开。
- 工程路径全英文:Tcl 脚本里引用含中文的目录是旧版 Quartus 的高发雷区,建工程第一天起目录名就只用 ASCII;中文说明放 README 而不是目录名。
- 跨平台传文件走二进制模式:SFTP/SCP/压缩包不选文本转换,避免传输工具替你换行;从 Windows 拷工程到 Linux 后先跑一遍
dos2unix再编译,是最便宜的保险。 - 批处理脚本写死 locale:
LANG/LC_ALL写进 CI 或批处理封装,不靠交互 shell 的默认值,换机器、换账号行为一致。 - 团队约定编辑器模板:新人文档里明确写「保存前确认右下角是 UTF-8、无 BOM、LF」,比事后逐个文件救火省事得多。
一句话总结
Quartus 中文乱码先按报错原文分流:带行号的 syntax error 归文件内容,用 file 和 hexdump 认出 GBK 与 UTF-8 BOM,再以 iconv 显式转成 UTF-8 无 BOM;读不了文件归 BOM 或中文路径,去 BOM、路径全英文;Windows 拷到 Linux 炸 Tcl 多半是 CRLF,用 dos2unix 收敛;locale 只管命令行显示、修不好文件本身。根治靠「UTF-8 无 BOM + LF + 语句区纯 ASCII + 全英文路径」四条纪律写进编辑器配置,编码问题就从玄学变成常识。