每次在Vivado里写Verilog,我都觉得回到了十年前——编辑器没有代码补全,信号跳转靠眼力,语法错误要到综合阶段才爆出来。后来花了一个周末,把Vivado和VSCode串成了完整工作流,从此写RTL、跑仿真、查时序全在VSCode里完成,Vivado只负责最后综合和布局布线。这篇文章就把我踩过的坑、最终稳定运行的配置方案完整分享出来,写给被Vivado编辑器折磨的FPGA工程师和正在入门Verilog的同学。
这套方案解决的核心问题是:用VSCode做Verilog代码编写、语法检查、快速仿真,用Vivado做综合、实现和上板调试。两边通过文件列表和脚本任务打通,日常工作基本不用切窗口。我会从工具选型讲起,再到插件安装、核心配置、Vivado联动、常见问题排查,每一步都给可直接抄的配置代码。
1. 方案选型与整体思路
1.1 为什么非要在VSCode里写Verilog
Vivado自带的文本编辑器不是不能用,但用习惯了VSCode之后确实回不去。核心痛点有三个:第一,Vivado编辑器没有像样的代码补全,wire、reg、assign这些高频关键字全靠手敲,parameter和localparam写多了特别容易拼错;第二,跨模块信号追踪非常吃力,想看一个信号在哪里驱动、在哪里使用,只能用全局搜索,模块多了效率极低;第三,Vivado的UTF-8支持在Windows上一直是玄学,中文注释经常乱码。
VSCode生态里最活跃的Verilog插件,比如Verilog-HDL/SystemVerilog和TerosHDL,把现代IDE的补全、跳转、悬浮预览、格式化、Linter全部带到了Verilog开发中。写代码的体验从“记事本级别”直接跳到“IDE级别”。
1.2 整体工作流的组织方式
我的核心思路是:VSCode负责代码编写与逻辑验证,Vivado负责工程构建与硬件验证。具体分工是这样的:
| 环节 | 工具 | 说明 |
|---|---|---|
| 代码编辑、补全、格式化 | VSCode + Verilog插件 | 日常95%的工作在这里 |
| 语法检查、快速仿真 | VSCode + iverilog | 秒级反馈,不等Vivado启动 |
| 综合、实现、生成比特流 | Vivado batch mode | 通过VSCode任务调用脚本 |
| 约束编辑、时序分析、上板调试 | Vivado GUI | 这些环节VSCode替代不了 |
这个方案对Windows和Linux都适用。我主要用Windows环境,下面的配置都基于Windows,Linux下只需调整路径和调用方式。
1.3 需要准备的软件清单
- VSCode:官网下载即可,建议装最新稳定版。
- Verilog-HDL/SystemVerilog插件:搜索
mshr-h.verilog,这个是核心。 - TerosHDL插件:可选,功能更全但配置更重,后面会细说。
- Vivado:我是用2020.1版本做的验证,2018.3到2022.2均可。
- Icarus Verilog(iverilog):用于语法检查和快速仿真,Windows下装官方exe包即可。
提示:iverilog一定要装,它是整个方案里性价比最高的一环。没有它,VSCode只能做代码编辑,没法做语法校验和快速仿真,体验直接打对折。
2. 环境准备与插件安装
2.1 VSCode基础配置
装完VSCode后,先做两件小事。第一,打开设置界面(Ctrl+,),把files.autoGuessEncoding开启,让VSCode自动猜测文件编码,这一项能救回一半的中文乱码问题。第二,如果你的Vivado工程文件是在Windows中文环境下创建的,文件可能是GB2312编码,统一编码的事情放到第四章细说,这里先把自动猜测打开。
安装插件直接在扩展商店搜索就行。我建议按顺序装:先装mshr-h.verilog,再装TerosHDL,最后装个中文字体相关的设置。mshr-h.verilog是现在社区维护最活跃的Verilog插件,语法高亮、跳转、格式化都靠它。
2.2 Verilog-HDL/SystemVerilog 插件关键配置
装好插件后,按Ctrl+Shift+P打开命令面板,输入“Open User Settings”,然后在settings.json里做以下配置:
{ "verilog.linting.linter": "iverilog", "verilog.linting.iverilog.args": [ "-g2012", "-Wall" ], "verilog.linting.iverilog.path": "C:/iverilog/bin/iverilog.exe", "verilog_linting.linter": "iverilog", "verilog.formatting.verilogFormatter.enable": true }解释一下这几项。verilog.linting.linter设为iverilog,插件就会在你保存文件时自动调用iverilog做语法检查,错误会以波浪线和“问题”面板的方式展示,再也不用等综合到一半才报语法错误了。verilog.linting.iverilog.args里的-g2012是指定SystemVerilog-2012标准,如果你的代码用了logic、always_comb这些SV语法,这个参数必须要有。
第二行verilog_linting.linter是某些旧版本插件的配置项,我新旧两个都写了,为的是兼容。如果你发现语法检查不生效,检查一下插件版本,新版本用verilog.linting.linter,旧版本用verilog_linting.linter。
2.3 TerosHDL 带来的额外能力
TerosHDL是一个功能更全面的插件,集成了文档浏览器、状态机可视化、波形查看等功能,还能直接管理Vivado和Quartus工程。我的使用习惯是:主用Verilog-HDL/SystemVerilog做日常编辑,TerosHDL只用来生成模块文档和查看模块结构。
TerosHDL的配置项比较多,新手容易劝退。如果你只需要代码补全和语法高亮,只装mshr-h.verilog就完全够了。想进一步做模块结构可视化的时候再装TerosHDL也不迟。
2.4 安装并验证iverilog
iverilog安装包从官网下载后一路next就行。装完后在命令行执行:
iverilog -V能输出版本号就说明OK。如果提示找不到命令,把C:/iverilog/bin加到系统环境变量path里。我建议在VSCode设置里直接用绝对路径指向iverilog.exe,避免插件找不到可执行文件。
验证iverilog与VSCode的联动也很简单,随便写一个只有一个错误的Verilog文件,保存后看“问题”面板是否出现红色波浪线。这一步通了,后续的快速仿真才有基础。
3. 核心细节解析与实操要点
3.1 代码补全和信号跳转的使用技巧
mshr-h.verilog插件的跳转功能在打开工程文件夹时会自动索引所有.v和.sv文件。跳转的使用方式是按住Ctrl键,鼠标点击信号名,就会跳到信号定义的位置;Alt+左右方向键可以回退/前进。
要支持跨文件跳转,必须用VSCode打开“工程根目录”,而不是单独打开某个.v文件。我第一次用的时候只打开了常用模块文件,结果跨模块跳转全部失效,还以为是插件问题。后来改成打开整个工程目录后,跳转就正常了。
有个小技巧:如果你用include指令引入了头文件,插件可能跳不到头文件里定义的参数。这时候需要把include的路径配到verilog.includes里:
"verilog.includes": [ "C:/project/include" ]3.2 语法检查的配置细节
语法检查是这套方案里最关键的环节。保存即检查,秒级反馈,比Vivado的综合报告快太多。
具体配置上面已经给过了。这里补充几个容易踩的坑:
iverilog默认支持Verilog-2001,如果你写了always_ff、logic这类SystemVerilog语法,必须在参数里加-g2012,否则会报一堆莫名其妙的语法错误。- 如果工程里用了Vivado的IP核,IP核的输出文件往往用了Vivado专属的
*_clk_wiz.v等模板,iverilog不一定能编译通过。我的做法是:语法检查时排除IP文件,或者只在iverilog的编译列表里放自己写的RTL文件。 -Wall会输出很多非致命警告,比如位宽不匹配、隐式线网定义等,建议一直开着,能帮你提前发现潜在的仿真与综合行为不一致的问题。
3.3 代码格式化方案
Verilog的代码风格,每个团队都有自己的一套。VSCode里最稳定的格式化工具是Verible,Google开源的Verilog解析器,格式化后风格非常规范,支持always_ff和always_comb的自动调整。
安装方式分两步。第一步,安装Verible,从GitHub下载Windows版本,解压后把verible-verilog-format.exe所在目录加进环境变量。第二步,在VSCode里安装zhuanhao.verilog-formatter插件,然后在settings.json里配置路径:
"verilog-formatter.verible.executablePath": "C:/verible/bin/verible-verilog-format.exe"格式化操作是Shift+Alt+F,或者右键选择“格式化文档”。我建议在保存时自动格式化,配置项:
"editor.formatOnSave": true,但要注意,如果你在写状态机或宏定义多的代码,自动格式化可能会把宏定义的对齐打乱。这种情况可以临时按Ctrl+Z撤销格式化,或者只选定区域格式化。
3.4 中文注释乱码的终极解决
“Vivado中文注释乱码如何恢复”是热词里非常高频的一个问题。乱码的根本原因是编码不一致:Windows中文环境下,Vivado默认按本地编码(GB2312/GBK)读写文件;VSCode默认按UTF-8读写文件。两边一换手,中文注释必然乱。
我的解决办法分两种情况:
情况一:乱码已经出现在VSCode里。打开那个文件,点击右下角的状态栏编码按钮(显示“UTF-8”或“GB2312”的地方),选择“通过编码重新打开”,然后选“GB2312”或“GBK”,乱码就会恢复。如果文件变成了问号,说明原文件已经被保存成了另一种编码,找回起来比较麻烦,只能靠版本管理或备份恢复。
情况二:从源头统一编码。在Vivado里新建一个文本文件,用记事本打开后另存为UTF-8编码,再回到工程里使用。或者在VSCode中打开工程根目录,新建文件时选UTF-8,把整个工程的所有.v、.xdc文件统一转为UTF-8。我自己是把所有工程文件都转成UTF-8,然后在VSCode里设置:
"files.encoding": "utf8", "files.autoGuessEncoding": true这样VSCode这边永远没乱码,Vivado虽然读取UTF-8的编码能力弱一些,但现在新版本Vivado对UTF-8的支持已经好很多了,实测2020.1以上版本基本没问题。
3.5 Linter与常见误报处理
用iverilog当Linter会遇到一些误报情况,最常见的是IP核文件和Vivado自动生成文件。这类文件里会有timeunit、timeprecision等只在仿真环境里有效的关键字,或者依赖Vivado库函数,iverilog不认。
处理方式是在工程根目录建一个.vscode/settings.json,把误报文件排除在验证范围之外:
{ "verilog.linting.iverilog.exclude": [ "**/ip/**", "**/xilinx/**", "**/*_b.d/*.v" ] }另外,mshr-h.verilog插件有两种Linter模式:一种是用iverilog直接编译所有打开文件,另一种是做增量检查。增量模式误报更少但配置更复杂。我建议先用好简单的全量检查模式,误报多的时候再用排除列表过滤。
4. Vivado联动:顺着一个工作流跑通综合与仿真
4.1 从Vivado导出文件列表,VSCode中打开
VSCode本身不管理Vivado工程,它只需要拿到工程的源码文件列表。我建了一个Tcl脚本,在Vivado的Tcl Console里跑一下,就能把RTL源文件列表导出为一个文件列表:
set fp [open "filelist.f" w] foreach f [get_files -filter {FILE_TYPE == Verilog || FILE_TYPE == SystemVerilog}] { puts $fp $f } close $fp这样生成的filelist.f就列出了工程里所有Verilog源码的绝对路径。然后在VSCode里打开工程根目录,把filelist.f也拖进资源管理器。以后加删文件,重新跑一遍这个脚本就行。
还有更自动化的做法:Vivado里的RTL源文件列表存储在.xpr工程文件里,VSCode的mshr-h.verilog插件可以直接读取Xilinx工程的源文件列表,只要你在工作区里打开.xpr所在目录。这个功能在插件版本较新时可用,但不是所有场景都稳定。
4.2 在VSCode中调用Vivado命令行综合
要让VSCode能够直接调用Vivado,先确保vivado命令能在终端里直接运行。Vivado安装后在Windows的“开始菜单”里有“Vivado xxxx.x Tcl Shell”快捷方式,但直接在VSCode的bash里运行vivado通常会提示找不到命令。需要把Vivado的bin目录加到PATH,比如:
C:/Xilinx/Vivado/2020.1/bin添加到系统PATH后,重启VSCode,在终端里执行vivado -version能输出版本号就可以了。
接着在工程根目录建一个scripts/synth.tcl,内容根据你的工程需求来写。最简单的一版:
open_project C:/project/myproj.xpr launch_runs synth_1 -jobs 4 wait_on_run synth_1 launch_runs impl_1 -to_step write_bitstream -jobs 4 wait_on_run impl_1然后回到VSCode,按Ctrl+Shift+B打开构建任务,配置tasks.json:
{ "version": "2.0.0", "tasks": [ { "label": "Vivado: 综合并生成比特流", "type": "shell", "command": "vivado -mode batch -source scripts/synth.tcl", "group": { "kind": "build", "isDefault": true }, "problemMatcher": [] }, { "label": "Vivado: 打开工程GUI", "type": "shell", "command": "vivado C:/project/myproj.xpr", "group": "build", "problemMatcher": [] } ] }按Ctrl+Shift+B选择任务,VSCode终端里就开始跑Vivado综合流程了。输出会直接显示在VSCode面板里,省去在Vivado GUI里点按钮的时间。配合“问题匹配器”(problemMatcher)还能把综合报错直接跳转到代码行。不过Vivado的报错格式跟标准gcc格式略有差异,如果不显示跳转链接,就手动看报告文件,或者做一个简单匹配规则。
4.3 用iverilog做RTL快速仿真
vivado做仿真太慢,每次启动都要加载库,我只在需要做后仿真或IP相关仿真时才用它。日常的逻辑验证,我全部用iverilog + GTKWave。
在VSCode终端里,一条命令就搞定了:
iverilog -g2012 -o sim.out -s tb_top tb_top.v uart_tx.v uart_rx.v vvp sim.out gtkwave dump.vcd我可以把上面的命令封装成一个shell脚本scripts/run_sim.sh,然后用VSCode任务来触发:
{ "label": "Sim: 运行iverilog仿真", "type": "shell", "command": "bash scripts/run_sim.sh", "group": "build", "problemMatcher": [] }在Windows下跑bash脚本,需要在VSCode里安装Git Bash支持,或者直接用CMD运行.bat脚本。我自己的开发机装了Git Bash,所以写得比较顺手。如果你用Windows的cmd,写对应的.bat文件也可以。
这个流程最大的价值在于:写代码、查语法、跑仿真、看波形全部在VSCode里完成,只有最后确认无误了,才需要打开Vivado GUI做上板验证。每次综合前的迭代时间从原来的“Vivado启动+综合十几分钟”缩短到“秒级语法检查+分钟级仿真”。
4.4 约束文件、比特流生成与硬件下载
在VSCode里写好约束文件后,建议用Vivado的GUI确认引脚分配,因为大部分板卡引脚都在开发板原理图里定义,手动写容易出错。生成比特流的流程已经在4.2的Tcl脚本里包含了,跑完write_bitstream之后,Vivado会产出.bit文件。
硬件下载还是需要Vivado的硬件管理器,在GUI里连接开发板,然后加载比特流。VSCode这边主要做的是快速迭代RTL代码,上板调试的几个环节还是留在Vivado里更稳。
有一个小经验:Vivado在Windows下使用驱动有时会识别不到板子。如果“无法识别板子”,先去设备管理器看驱动是否装好,再看Vivado版本与开发板型号的兼容性。确认驱动没问题之后,再打开硬件管理器连接。
5. 常见问题速查与避坑技巧
5.1 语法高亮突然失效
现象:代码颜色全部变成白色,完全没有任何高亮。
原因与排查:最常见的是插件把文件识别成了纯文本,或者文件扩展名不在插件识别范围内。比如.vh、.svh这类文件,部分插件版本需要手动指定语言模式。点击VSCode右下角“纯文本”几个字,输入“Verilog”或“SystemVerilog”,重新选择语言模式即可。
另外一个隐蔽原因是文件过大,超过插件高亮的性能上限。几十MB的网表文件就别指望插件的语法高亮了,这种文件直接用Vivado打开更合适。
5.2 跳转失效或跳错位置
现象:Ctrl+点击信号无法跳转,或者跳到了同名但不同作用域的信号。
原因与解决:跳转依赖插件对工程所有文件的索引。如果文件不在工作区里、或者这个文件最近才从资源管理器移入,索引没有刷新,跳转就会失效。解决办法是先保存所有文件,再执行一次“重新索引工作区”的命令(有的版本叫Verilog: Re-index workspace)。
SV作用域跳错的问题比较麻烦,插件对大工程的interface、package支持有限。我自己的实践是尽量少用interface和package做跨模块通信,这不仅是跳转问题,仿真和综合的行为差异也容易在这里出现。
5.3 Verilog仿真报License错误
现象:运行iverilog时提示failure to obtain a verilog simulation license。
这个不是VSCode的问题,是Vivado自带的仿真器(xsim)没拿到许可。在命令行里运行xvlog、xelab这些命令时会检查Vivado license,许可配置不对就会报错。
解决办法:检查Vivado license是否激活,用vivado -mode tcl进入Tcl shell后执行check_license查看。如果你是教育版用户,记得用教育版Hub激活。我用到2020.1版本时也遇到过类似提示,换用iverilog做日常仿真之后,这个问题基本就绕开了。
5.4 常见问题速查表
| 现象 | 可能原因 | 解决方式 |
|---|---|---|
| VSCode中文注释乱码 | 文件编码为GBK,VSCode按UTF-8读取 | 右下角编码按钮→重新打开→选GB2312/GBK |
| 保存即报错但代码看着没问题 | 缺-g2012参数或include路径没配 | settings.json里加-g2012,配置verilog.includes |
| 综合任务在VSCode里跑不了 | Vivado未加入系统PATH | 把C:/Xilinx/Vivado/2020.1/bin加入PATH |
| 语法检查不触发 | 插件版本与配置项不匹配 | 同时配置新旧两个linter名 |
| Vivado生成的IP文件误报 | iverilog不认IP模板 | 在Linter的exclude列表加**/ip/** |
| 波形文件打不开 | 文件路径中包含中文或空格 | 让脚本统一生成ASCII路径 |
| 综合报错但问题面板无跳转 | 问题匹配器格式不匹配 | 手动查看Vivado log,或自定义problemMatcher |
5.5 团队协作的两个建议
如果你的团队多人开发FPGA工程,有两个点特别值得注意。第一,统一编码。全组统一用UTF-8,避免有人用Windows记事本打开后又另存为ANSI,导致中文注释变成“锟斤拷”。第二,源码管理建议调整成VSCode友好结构——让工程根目录就是Git仓库根目录,filelist.f不提交生成文件,从*.xpr实时同步。
我见过很多FPGA团队还在用Vivado的“Copy project to new location”方式维护版本,这种方式换个机器就要重新改路径。如果迁移到VSCode + 命令行 + Git,整个工程可以做到路径无关,报错信息、仿真脚本、综合参数都能版本化追踪,后期维护省心很多。
6. 一些真实的个人使用体会
这套方案我稳定使用快两年了,从2019.1到2022.2版本的Vivado工程都跑过。我最满意的不是VSCode的界面好看,而是整个迭代流程的反馈速度被彻底拉快了。
过去在Vivado里改一个模块,保存后要到“Sources”窗口右键“Generate output products”,然后启动综合,等三五分钟看有没有语法错误。现在在VSCode里,Ctrl+S触发语法检查,有错直接定位;逻辑行为问题放到iverilog里秒级仿真,波形一拉就知道数据对不对。
我目前写RTL的固定流程是这样的:用VSCode打开工程根目录,写代码、格式化、保存检查、快速仿真,逻辑调通后,跑一次Vivado综合任务,最后打开Vivado GUI连接硬件上板验证。整个过程VSCode占了八九成的工作时间,Vivado只在我需要看时序报告、跑布局布线结果的时候才出现。
最后分享两个小技巧。一个是在VSCode里把快捷键Ctrl+Shift+B设置成Vivado综合任务,这样“改代码→保存→一键综合”的肌肉记忆特别顺。另一个是终端里始终开一个Tcl Shell窗口,遇到需要在两条工具链之间传递文件或检查资源占用的时候,直接在VSCode终端里敲命令就行,不用切到Vivado的Tcl Console。
配置这套环境第一次弄可能会花一到两个小时,但换来的日常效率提升是长期的。你只要按着上面的步骤走,哪怕第一天只用上语法检查和代码格式化,也比在Vivado编辑器里硬写要舒服得多。