ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

VSCode关联Vivado高效编写Verilog:从配置到实战

VSCode关联Vivado高效编写Verilog:从配置到实战 做FPGA开发的人十有八九都吐槽过Vivado自带的编辑器。代码一长高亮跟不上跳转靠肉眼搜补全看运气想多开几个文件标签页都卡顿得难受。我陆陆续续用了两年多实在扛不住前阵子彻底把Verilog代码编辑都搬进了VSCodeVivado只负责综合、仿真和下载。折腾完才发现VSCode关联Vivado编辑Verilog这事其实不难关键是要把三层东西理顺编辑器本身、语法检查/代码补全用的工具链、以及Vivado工程文件的关联方式。这篇就把我的完整配置过程和踩过的坑都写出来配置照着抄坑替你提前踩。1. 整体设计思路为什么非要把VSCode和Vivado绑在一起1.1 Vivado自带编辑器的三个槽点咱们得先搞清楚一个核心问题到底是Vivado编辑器真不行还是我们不会用我的结论是真不行而且是原理上就不行。第一Vivado编辑器本质上是一个嵌在IDE里的文本控件设计目标就是让你能改代码而不是高效地改代码。它没有现代编辑器那种基于语言服务器的架构所以代码补全只能靠简单的关键字匹配跨文件的模块实例化提示基本等于零。第二当你的工程里积累了上百个模块文件想从一个顶层往下追信号Vivado编辑器里只能一个个文件打开、搜索效率极低。第三它几乎不支持自定义快捷键和代码片段每个团队想统一代码风格只能靠人肉复制粘贴模板。这三点叠加在一起FPGA工程师每天花在编辑器里的时间就变得非常不值。我在一个中型项目中大概统计过其中有相当一部分时间是在文件之间来回跳、查信号定义、改格式对齐。这些工作在VSCode里几乎开箱即用。1.2 方案选型对照VSCode凭什么胜出市面上能替代Vivado编辑器的选项不少我把实际用过的都摊开对比了一下方案语法高亮代码跳转代码补全与Vivado集成成本上手难度Vivado自带编辑器一般基本没有弱天然集成免费无VSCode Verilog插件优秀强跨文件中等偏上可配置外部编辑器/手动关联免费低Notepad / Sublime一般无无手动免费/付费低UltraEdit中等弱弱手动付费低Emacs/EV宏强但需要配置强强手动免费高我最终选VSCode核心原因有三点。一是插件生态几乎碾压Verilog-HDL/SystemVerilog、TerosHDL这些插件把语法高亮、格式化、代码补全、Linter集成全做了。二是它天生支持多平台Windows、Linux、WSL都能跑配置也能跨机器同步。三是它的设置是JSON文件可以放进Git仓库里做版本管理整个团队的开发环境能保持一致。这一条很多团队没意识到等换了机器或者来了新人就知道有多省事。1.3 这套方案的核心原理编辑器、工具链与工程组织的解耦想彻底搞明白怎么把VSCode和Vivado绑在一起还得分清三个层面的东西别混着用。编辑层VSCode负责打开、编辑、格式化、补全。它只是代替Vivado里面的那个文本编辑器不参与综合、实现、仿真。静态检查层VSCode里的插件本身不会解析Verilog它需要调用外部工具来做语法检查和代码跳转。常用的有两个iverilog和Verilator它们都是开源工具。插件负责把检查结果显示出来实际干活的是这些外部工具。工程组织层Vivado的工程文件.xpr本质上是一个XML文件里面记录着所有源文件、约束文件、IP核、综合策略。VSCode不需要解析这个XML只需要你告诉它这个工程的源文件在哪儿它就能建立索引提供跳转和补全。想清楚这三层关系后面所有配置就顺理成章了。很多人配置失败就是把VSCode要直接打开.xpr当成了目标其实VSCode打开的是源码目录Vivado才是管工程的人。2. 环境准备与插件选型装好工具别让版本坑了你2.1 VSCode安装与最小配置这部分只说容易出错的地方。VSCode装好后第一件事不是装插件而是把基础设置搞对尤其是文件编码策略。我的建议是把VSCode的files.autoGuessEncoding设为true把files.encoding设置成gbk这个问题的前因后果放到第3章讲乱码时细说。安装VSCode时如果系统里装了360、火绒这类软件第一次安装尽量选择默认路径避免后续插件更新时权限不足。另一个小坑是VSCode会自动更新Vivado这种重型工具倒是无所谓但如果你在工程里写了复杂的Task脚本VSCode版本大跨度升级后插件兼容性偶尔会出问题我一般把更新模式改成manual。如果你在Windows上用建议同时安装一个Git Bash后面配置iverilog命令行工具时很多命令在Git Bash里跑比在CMD里舒服而且VSCode的终端能直接调用Git Bash省去切窗口的麻烦。2.2 核心插件推荐Verilog-HDL/SystemVerilog与TerosHDL怎么选现在VSCode里跟Verilog相关的插件不少真正值得装的就两类。第一类是Verilog-HDL/SystemVerilog插件ID是mshr-h.veriloghdl。这是目前综合体验最好、社区活跃度最高的插件支持语法高亮、格式化、必选符号跳转、模块实例化模板、代码补全。它的代码跳转基于静态分析不依赖实际综合速度很快。我在一个大型工程中测试过顶层模块实例化跳转基本能做到毫秒级响应。这个插件还能自动生成testbench框架选中模块后右键就能生成写仿真时非常方便。第二类是TerosHDL。这个插件面向高级用户自带了多种工具链集成iverilog、verilator、GHDL、Vivado等能在插件里直接跑仿真、看波形还能管理source文件列表。它的界面更复杂如果你对Vivado的Simulator已经很熟了可以不用TerosHDL用mshr-h.veriloghdl加终端命令行完全够用。但如果想省去在两个软件间切换的麻烦TerosHDL值得研究。另外还有两个辅助插件值得装。一个是vscode-verilog-generator它可以从已有的模块定义生成实例化代码比手动敲端口节省大量时间。另一个是Doxygen Documentation Generator虽然它不是为Verilog设计的但能辅助生成注释风格统一的模块头。2.3 关于SystemVerilog支持一个重要提醒你的工程如果是纯Verilog那mshr-h.veriloghdl表现很好。但如果你用了SystemVerilog尤其是interface、struct、class这些高级语法需要注意。mshr-h.veriloghdl的SystemVerilog支持主要靠的是语法高亮和部分关键字识别对于复杂类型系统的跳转和补全目前仍不够用。TerosHDL在SystemVerilog的解析上做得相对好一些但也没法保证100%覆盖。我的建议是如果是学习、参加竞赛、写教程直接用SystemVerilog如果是公司量产项目的维护绝大多数团队还是在使用旧版本Vivado和Verilog-2001风格纯Verilog配合mshr-h.veriloghdl已经足够了。有时候工具的保守反而是好事因为老项目不怕折腾。3. Vivado与VSCode关联配置实操从打开文件到一键编译3.1 方法A通过Vivado GUI注册外部编辑器现在进入核心环节怎么让Vivado在打开源文件时调用VSCode而不是内置编辑器。Vivado提供了一个外部编辑器接口它的本质是告诉你当你双击某个文件时Vivado调用你指定的可执行文件并把文件路径作为参数传给它。Windows下VSCode的可执行文件是Code.exeLinux下是code。具体操作分三步。第一步打开Vivado进入Tools - Settings - General - Editor Preferences。第二步在Preferred Text Editor这一栏不要选Vivado内部编辑器选择Custom editor。第三步把命令行填成C:\Users\你的用户名\AppData\Local\Programs\Microsoft VS Code\Code.exe -g [file name]:[line number]这里的[file name]和[line number]是Vivado内置的占位符它会自动替换成当前打开的文件路径和光标所在行号。填完点OK再双击工程里的源文件Vivado就会调用VSCode打开了。这个方法的优点是方便鼠标双击就够了。缺点是如果Vivado报错时你想直接跳转到错误行Vivado默认的打开文件就只会打开文件并不一定定位到行号需要你自行判断。另外不同版本的Vivado对占位符的支持有细微差异。我实测过2019.1到2022.2的几个版本只要用的是Custom Editor模式占位符都有效。3.2 方法BTcl命令行配置一步到位如果嫌GUI点来点去太繁琐或者你经常在Vivado里用Tcl脚本管理工程那就直接用Tcl设置。Vivado的Tcl环境跟VSCode的配置其实互不相干设置好后每次打开同一个工程都会记住。在Vivado的Tcl Console里执行set_msg_config -enable_msg_config_check 0 set_property PRE_SYNTHESIS_FILE {} [get_files -all] set_param general.ignoreCompressedProjects 1 config_port -exclude_projects true注意第一行set_msg_config和第二行set_property是我为了忽略某些与外部编辑器无关的消息提示加的不代表这些命令和编辑器绑定。真正设置外部编辑器用到的是param不同版本环境下需要搜索对应接口。更稳妥的通用做法是直接在Vivado Tcl Console执行set_param general.editor C:/Users/你的用户名/AppData/Local/Programs/Microsoft VS Code/Code.exe -g [file name]:[line number]执行完就完事了比GUI路径快得多。唯一的坑是Tcl里反斜杠会被当作转义符所以路径一定要用正斜杠写。3.3 用VSCode直接打开Vivado工程目录上面两种方法解决的是从Vivado跳转到VSCode的单向问题。但VC开发中更常见的场景是打开VSCode直接浏览整个工程的源码目录搜索、编辑、跳转然后切到Vivado综合仿真。这才是最舒服的状态。实现方式很简单在VSCode里选择打开文件夹定位到Vivado工程目录就可以了。Vivado工程目录里通常有一个.srcs文件夹里面放着source文件还有各种.runs、.cache之类的文件夹那些是中间产物不需要管。建议在VSCode里创建一个.vscode文件夹然后写一个settings.json把不需要的文件过滤掉这样插件索引时就不会被上千个缓存文件拖慢速度{ files.exclude: { **/.runs: true, **/.cache: true, **/reports: true, **/.asy: true, **/.gen: true, **/.hw: true, **/.ip_user_files: true, **/.sdk: true, **/.Xil: true } }如果你的工程里用了大量的IP核也可以把IP生成的目录排除掉这样跳转和搜索都会更快。3.4 中文注释乱码的恢复方法这个难题我深有体会。Vivado装在Windows上时默认的源文件编码是GB2312本地化系统而VSCode默认用UTF-8读取文件。两者不一致就会出现老工程打开后全是乱码或者添加中文注释后保存再回到Vivado打开注释已经变成一堆乱码。处理原则很简单要么让VSCode用GBK读文件要么让Vivado用UTF-8读文件。但Vivado对编码的支持很弱基本强依赖系统区域设置所以最稳妥的办法是让VSCode侧适应。在VSCode右下角点击编码按钮选择Reopen with Encoding再选择Chinese (GB2312)即可正确显示中文。如果想让所有Verilog文件默认都用GBK打开设置里加上{ [verilog]: { files.encoding: gbk }, [systemverilog]: { files.encoding: gbk } }但这里有个大坑mshr-h.veriloghdl插件在处理GBK编码时某些版本的代码格式化功能会失效或者格式化后中文被替换成问号。所以我的建议是如果你遇到中文注释乱码前所未有地先将文件另存为UTF-8编码然后再让VSCode与Vivado都统一使用UTF-8。操作方法是在VSCode里打开乱码文件 - 点击右下角编码 - Convert to UTF-8 - 保存并关闭 - 在Vivado里重新打开。如果Vivado里的中文还乱多半是Vivado以ANSI模式读取了UTF-8文件此时把文件另存为带BOM的UTF-8即UTF-8-BOM通常就能两边都正确显示。经验之谈老项目我统一转成带BOM的UTF-8存档新项目从一开始就直接用UTF-8写中文注释从源头避免后续折腾。4. 语法检查与代码辅助实战让每行Verilog都过检查4.1 Linter原理与选择iverilog vs VerilatorVSCode插件本身不会帮你检查语法它依赖外部Linter。所谓Linter就是一个小工具它会把你写的Verilog文件当作输入尝试解析它如果解析失败就报出错行和错误信息。插件负责在界面中标红真正干活的是Linter。常见的Linter有两个iverilog和Verilator。iverilog是Icarus Verilog的编译器前端它支持Verilog-2001和大部分Verilog-2005对SystemVerilog支持有限。Verilator是一个非常快的Verilog编译器支持SystemVerilog和很多复杂语法而且能把Verilog转换成C/SystemC模型常用于仿真加速。对大多数写FPGA的人来说我建议装iverilog因为它的安装包可以直接从官网下载Windows下也有exe安装程序用起来几乎没有门槛。Verilator在Windows上原生支持比较麻烦一般要在WSL或者Linux里用。如果你的工程里有复杂的SystemVerilog语法Verilator可能更合适但为了一个Linter去配WSL性价比有点低。我的建议是Windows下能用iverilog解决就绝不碰Verilator除非你本身就在Linux环境下开发。务必记住Linter的目的只是让你写代码时就能发现低级错误并不能替代综合和仿真这一点是用来防止你过度依赖它的。4.2 配置Lintersettings.json逐项说明安装完iverilog后先确认一个关键点VSCode里运行终端输入iverilog -v看能否正常输出版本号。如果不认识这个命令说明安装时没有把安装目录加入系统PATH这是配置Linter时最容易卡住的地方。然后需要在VSCode的settings.json里配置插件与iverilog的关联。逐项说明如下{ verilog.linting.linter: iverilog, verilog.linting.iverilog.path: C:\\iverilog\\bin\\iverilog.exe, verilog.linting.iverilog.arguments: [ -g2012, -Wall, -I${workspaceFolder}/src ], verilog.linting.enabled: true, verilog.linting.verilator.arguments: -Wall --timing }解释一下每个字段的含义。第一个verilog.linting.linter告诉插件要用iverilog做静态检查。第二个iverilog.path指定iverilog可执行文件的绝对路径。第三个iverilog.arguments是用来传给iverilog的参数这是很多人调不通的根源。其中-g2012表示使用SystemVerilog-2012语法模式。如果是纯Verilog工程可以改成-g2005或-g2001。注意参数里必须加-I${workspaceFolder}/src否则当你编辑的顶层模块里include了其他目录的文件时iverilog会因为找不到头文件而报错进而影响Linter对整体语法的判断。第四个verilog.linting.enabled总开关。第五个verilator.arguments是给Verilator用的如果你没用Verilator可以不管它。配置好后VSCode会自动加载在打开的文件里触发检查。有问题的地方会标红色波浪线把鼠标悬停上去会有错误的具体信息。如果错误信息里出现了ERROR: Unknown module之类的字样别急着怀疑代码先检查是不是- I路径没配好。4.3 include路径、宏定义与库文件的处理在实际工程里Verilog代码经常使用include语句把公共头文件引进来也常用define定义宏。Linter如果不知道这些头文件在哪儿就会报cannot open include file烦人得很。解决方案是在iverilog.arguments里增加路径。假设你的工程结构是这样project/ ├── src/ │ ├── top.v │ ├── uart_tx.v │ └── include/ │ └── defines.vh └── sim/ └── tb_top.vtop.v里有include include/defines.vh那arguments里一定要加-I${workspaceFolder}/src/include或者更简单一点直接-I${workspaceFolder}/src。注意iverilog的-I参数和头文件内引用路径是相对包含文件所在目录还是相对当前工作目录行为有微妙差别。这个差别会在不同版本的iverilog中引发困惑所以我的经验是头文件里一律写相对路径并且用package或include相对路径时避免加前缀这样最省心。宏定义也一样在arguments里用-D宏名值传入。比如verilog.linting.iverilog.arguments: [ -g2012, -Wall, -D FPGA_DEVICE7A35T, -I${workspaceFolder}/src/include ]Linter收到-D后就相当于在所有文件开头加了define FPGA_DEVICE 7A35T宏相关的条件编译代码就能被正确解析。4.4 在VSCode中一键编译并跳转行号静态检查发现问题后最终还是要回到Vivado里做综合和仿真。但综合一遍往往要等好几分钟如果你只是想快速验证语法是否有低级错误直接在VSCode里调用iverilog就能省不少时间。一种做法是打开终端手动执行iverilog -g2012 -o /tmp/sim_top.vvp sim/ tb_top.v src/top.v src/uart_tx.v vvp /tmp/sim_top.vvp但每次都敲全路径太烦了。我习惯在.vscode/tasks.json里定义两个Task一个叫Compile and Run Simulation另一个叫Compile Only.这样在VSCode里按CtrlShiftB就能快速编译按自定义快捷键就能跑仿真。下面是tasks.json的简化版{ version: 2.0.0, tasks: [ { label: iverilog compile, type: shell, command: iverilog -g2012 -o ${workspaceFolder}/sim/sim.vvp ${workspaceFolder}/sim/tb_top.v ${workspaceFolder}/src/*.v vvp ${workspaceFolder}/sim/sim.vvp, group: build, problemMatcher: [] } ] }一个比较实用的小技巧是把problemMatcher配置成$verilog这样编译输出的错误信息会被VSCode解析点击错误信息就能直接跳转到源码对应行。不过iverilog的错误格式和VSCode内置的匹配器不一定完全兼容实测下来有时点击跳转会进入错误信息所引用的路径才行。如果跳转不准也别太纠结先把程序跑起来再说定位问题还是要靠Vivado的详细报告。5. 高频问题排查与效率技巧乱码、跳转和模板那些事5.1 常见问题速查表把我在每个项目里都会遇到、以及帮同事排查过的问题整理成速查表碰到同类问题先看这张表能省不少时间现象常见原因解决方案Vivado双击文件打不开VSCode外部编辑器命令路径没填对检查Code.exe路径注意32/64位安装目录差异Vivado双击文件能打开但总定位到文件开头缺少-g参数命令里必须加-g标志和[line number]占位符VSCode中文注释乱码VSCode以UTF-8读取GBK文件用Reopen with Encoding选择GBK或统一转UTF-8-BOM写代码时红色波浪线一片iverilog路径配置错误或include路径缺失确认iverilog -v可用检查arguments里的-I路径跳转定义时出现多个模块名插件的静态索引与实际文件不符在VSCode里执行Reload Window重建索引模块实例化补全不出来插件有没有识别到文件列表检查文件是否在打开的工作区内或者Usereset index database使用SystemVerilog的interface时报错mshr-h.veriloghdl对SV支持不够换TerosHDL或确保Linter用-g2012代码格式化后整个文件对齐错乱插件内置格式化和GBK编码冲突先转成UTF-8再格式化或者改用TerosHDL格式化器打开Vivado工程时VScode卡顿索引了.runs和.cache目录用files.exclude排除中间产物目录5.2 几个容易踩的深坑详解第一个深坑是iverilog版本与Vivado版本差异导致的语法兼容问题。Vivado里的综合器和iverilog对某些语法细节的解释不一样最典型的就是always块里对reg变量赋值的时序建模。比如你在iverilog里写了always (*)配合task调用Linter可能0错误但Vivado综合出来却报task used in unsynthesizable manner。这种问题VSCode是发现不了的它只做语法级检查不判断可综合性。所以别把Linter的结果当成能综合的金标准它只能称作不是明显的语法胡闹的检查工具。第二个深坑是路径中含中文字符。Vivado工程如果在中文路径下VSCode插件在跳转和Linter读取文件时偶尔会出问题特别是Windows上。建议工程路径里始终只用英文和下划线无论是放VSCode还是放Vivado都省心。如果公司里已经有中文路径的老工程放在中文路径下跑的也没问题只是每次Linter里遇到中文字符路径时报错信息会显示成unicode转义序列看着非常别扭。第三个深坑跟Vivado安装驱动无法识别板子这个搜索词常一起出现的场景。其实很多这样的问题跟VSCode完全无关它出现在Vivado的硬件管理器里通常是因为驱动没安装或版本不匹配。但很多人会把VSCode和Vivado的配置混在一起排查折腾一天发现方向就错了。我给的判断标准是如果Vivado本身能打开工程、能综合只有下载板子时报错那问题就在Digilent/官方下载驱动那边跟编辑器毫无关系。5.3 提高效率的模板、快捷键与小技巧配置好联动之后写Verilog的效率提升主要来自三个点自定义代码模板、快速跳转、以及格式化。代码模板方面用VSCode的snippets来实现模块头注释、always块、状态机三段式模板。拿状态机模板举例在项目里新建.vscode/样板.code-snippets文件写入自己的片段后输入FSM就能自动展开。我常用的三段式状态机模板是这样的{ FSM three-stage: { prefix: fsm3, body: [ // , // State definitions, // , localparam IDLE 3d0, S1 3d1, S2 3d2;, , reg [2:0] state, next_state;, , // FSM 1: state register, always (posedge clk or negedge rst_n) begin, if (!rst_n) state IDLE;, else state next_state;, end, , // FSM 2: next state logic, always (*) begin, case (state), IDLE: next_state ...;, S1: next_state ...;, S2: next_state ...;, default: next_state IDLE;, endcase, end, , // FSM 3: output logic, always (*) begin, case (state), ..., endcase, end ], description: Three-stage FSM template } }如果你写的是UART收发、I2C读写EEPROM这类经典外设模块模板库的价值更大。把常用的状态机、计数器、FIFO读写的标准框架存起来新项目开局就是复制粘贴改端口的事情非常节省时间。快捷键方面我建议把几个关键操作绑定到顺手的按键上格式化文档、快速打开文件、命令面板、以及切换终端的焦点。具体配置在keybindings.json里每个人习惯不同不展开细说。另外熟练使用CtrlShiftO跳转到文件内符号CtrlT跨文件跳转到模块名这两个操作在维护大工程时是神器。结尾我用这套配置跑了两个完整的FPGA项目一个是通信基带里的UART多字节收发模块一个是I2C读写EEPROM的控制逻辑。整个过程中VSCode butiverilog Vivado三者的分工非常清晰VSCode负责编辑、检索、写代码时检查低级错误iverilog负责仿真前快速验证逻辑Vivado负责真正的综合和布局布线。即便中间换了两次机器配置文件同步到新装的VSCode后十分钟内就能恢复所有工作环境。最后再分享一个体会。很多新人会花大量时间追求编辑器的完备性总想让VSCode像Vivado一样把所有东西都集成进来反而忽略了FPGA开发的真正重点理解硬件时序、考虑资源占用、把状态机设计合理。工具链只是放大器永远替代不了你对电路的理解。但在理解到位的前提下把工具调顺了确实能把每天从重复劳动里省出来的几十分钟用到真正值得思考的地方去。
返回列表