本来希望用轻量级编辑器写Verilog,结果VScode的linter插件太过低能,网上的方法大抵解决了很简单的场景,这次我设计CPU的过程,为了贴近工业场景,专门添加了很多目录,还专门为单周期CPU和流水线CPU的划分而多开工作区,其中module和引入文件的报错真的很打击人,不过经过努力,现在我大抵是有了合适的解决方案(但不一定全面,只是学习过程的记录)。

首先要了解报错原因:
一般的场景就是:用 VS Code 编写 Verilog,并且代码没写错,但 include 和模块实例化的地方却疯狂飘红报错(提示 Include file not found 或 No top level modules),
VS Code 的 Verilog 插件(基于 Icarus Verilog)有三大底层“暗坑”:
- 临时文件夹陷阱:为了做实时检查,它会把代码复制到系统 Temp 目录下运行,导致普通相对路径瞬间失效。
- 不支持递归搜索:
-y参数必须把每一个子文件夹都写得清清楚楚,它不会自动钻进子目录找代码。 - 工作区层级覆盖:在多项目工作区下,它会强行无视子文件夹里的
.vscode配置,并且对${workspaceFolder}这种高级宏变量的解析极其弱智。
然后要了解参数的意义,一般将两个参数都使用上就基本解决了
-I <path>(Include dir):专门用来告诉编译器去哪里找`include指令引入的文件。-y <path>(Library dir):专门用来告诉编译器,当代码里实例化了一个模块,但在当前文件找不到定义时,去哪个目录里自动搜索与模块同名的.v文件。
针对不同的项目复杂度,请对号入座选择你的解决方案:
注意:下面的方案都建立在你会在每个文件上写上必要的
include来引入.vh和.v文件)
设置后如果报错依然在,将报错的include一行删了重新添加或者刷新VSCode,强迫重新检查,可以看到效果
🟢 单文件夹扁平结构
适用场景:比如早期的“单周期 CPU”,所有的 .v 和 .vh 文件全塞在同一个文件夹里,没有子目录。
如何配置: 在项目根目录新建 .vscode/settings.json:
{
"verilog.linting.iverilog.arguments": "-g2012"
}
直接写 `include "definition.vh"。 说明:因为全在同一层,插件闭着眼睛也能摸到所有文件。
🟡 标准嵌套子文件夹结构
适用场景:项目开始分类,比如有 rtl/core(核心代码)、rtl/include(头文件)、rtl/common 等。单独使用 VS Code 打开这个项目文件夹。
避坑核心:必须强迫插件“站在当前文件所在的目录” 来计算路径,使用相对路径叠加。
如何配置: 在项目根目录的 .vscode/settings.json 中配置:
{
"verilog.linting.iverilog.runAtFileLocation": true,
"verilog.linting.iverilog.arguments": "-g2012 -I ../include -y . -y ../common -y ../hazard"
}
代码写法:依然保持最纯净的 `include "definition.vh"。 说明:runAtFileLocation: true 是关键。当你在 core 里写代码时,插件站在 core 往上一级找 ../include,完美命中。
🔴 多根工作区 + Git 管理大库
适用场景:最硬核的结构。最外层是 Git 大仓库 CPU,里面平级放着 single-cycle-cpu 和 pipeline-cpu。希望在 VS Code 里同时打开它们并互不干扰。
避坑核心:子文件夹里的 .vscode 会失效,宏变量 ${workspaceFolder} 也会翻车。必须使用 “保存工作区 (Code Workspace)” 加上 “万能相对路径叠加法”。
如何配置:
- 点击 文件 -> 将工作区另存为…,在大本营
CPU/目录下保存为CPU.code-workspace。 - 删掉各个子目录里的
.vscode文件夹。 - 打开
CPU.code-workspace,写入以下“全包容”配置:
{
"folders": [
{ "path": "."},
{ "path": "pipeline-cpu" },
{ "path": "single-cycle-cpu" }
],
"settings": {
"verilog.linting.iverilog.runAtFileLocation": true,
"verilog.linting.iverilog.arguments": "-g2012 -I . -I ../include -y . -y ../common -y ../hazard"
}
}
说明:当你打开单周期代码,-I . 生效;当你打开流水线代码,-I ../include 生效。一套配置,双端完美运行!
无奈之举
如果你按照上述配置后,因为电脑没装 ctags 或者插件抽风依然弹乱码报错,那么就关掉linter。
直接在配置里加上这句:
{
"verilog.linting.linter": "none"
}
你的代码依然有漂亮的高亮颜色,所有的红线假报错全部消失。 真理只存在于终端里,在测试目录下写个 sim.f 文件列表,敲下 iverilog -o sim.out -c sim.f,终端说没报错,你的代码就是完美的!
我想以后如果有时间真的可以去研究下插件,设计一个可以智能点的Verilog插件。




