> VSCode 完整配置指南,面向 Verilog/SystemVerilog FPGA 开发:LSP 搭建、跨文件导航、代码片段模板、外部工具集成。
Veridian 是专为 Verilog/SystemVerilog 设计的 LSP,具备强大的跨模块导航能力。
# 下载最新的 Veridian 发布版本
# 访问 https://github.com/veridian-language-server/veridian/releases
# 或克隆并自行构建:
git clone https://github.com/veridian-language-server/veridian.git /home/user/tools/veridian
cd /home/user/tools/veridian
cargo build --release
# 服务器二进制文件所在位置:
# target/release/veridian
VSCode 配置(.vscode/settings.json):
{
"veridian.languageServer.path": "/home/user/tools/veridian/target/release/veridian",
"veridian.languageServer.arguments": ["--lsp"],
"veridian.documentSymbols.enabled": true,
"veridian.navigation.documentLinks": true,
"veridian.diagnostics.enabled": true,
"veridian.completion.enabled": true
}
# 通过 npm 安装
npm install -g @imc-trading/svlangserver
# 或从源码克隆构建
git clone https://github.com/imc-trading/svlangserver.git /home/user/tools/svlangserver
cd /home/user/tools/svlangserver
npm install
npm run build
VSCode 配置:
{
"svlangserver.path": "/home/user/tools/svlangserver/bin/svlangserver",
"svlangserver.launchConfiguration": "/home/user/work/FPGA_Prj/Project/.svlint.yaml",
"svlangserver.formatCommand": "verible-verilog-format"
}
# 下载预编译的二进制文件
VERIBLE_VERSION="v0.0-3724-gdec461c4"
wget https://github.com/chipsalliance/verible/releases/download/${VERIBLE_VERSION}/verible-${VERIBLE_VERSION}-linux-x86_64.tar.gz
tar xzf verible-${VERIBLE_VERSION}-linux-x86_64.tar.gz -C /home/user/tools/
ln -s /home/user/tools/verible-${VERIBLE_VERSION} /home/user/tools/verible
# 添加到 PATH
echo 'export PATH="/home/user/tools/verible/bin:$PATH"' >> /home/user/.bashrc
Verible 工具集:
| 工具 | 用途 |
|---|---|
verible-verilog-lint |
风格与语法检查 |
verible-verilog-format |
代码格式化 |
verible-verilog-syntax |
语法检查 |
verible-verilog-kythe-extractor |
为 LSP 提取交叉引用索引 |
verible-verilog-ls |
语言服务器 |
{
"verilog.languageServer": "verible",
"verible.path": "/home/user/tools/verible/bin",
"verilog.linting.linter": "verible",
"verilog.formatting.verilogHDL.formatter": "verible",
"[systemverilog]": {
"editor.defaultFormatter": "mshr-h.veriloghdl"
}
}
Verilog-HDL 扩展(mshr-h 开发)是 VSCode 与 LSP 之间的主要桥梁:
# 通过 VSCode CLI 安装
code --install-extension mshr-h.veriloghdl
# 或在 VSCode 内部操作:
# Ctrl+Shift+X → 搜索 "Verilog-HDL/SystemVerilog" → 安装
创建 /home/user/work/FPGA_Prj/Project/.veriloglint.yaml:
# Verible 代码检查配置
rules:
# 风格规则
module-filename: true
module-parameter: true
module-port: true
forbid-consecutive-null-statements: true
forbid-defparam: true
# 命名约定
explicit-function-lifetime: true
generate-label-prefix: "gen_"
instance-name-style: "lower_snake_case"
module-name-style: "lower_snake_case"
# 常见模式的豁免
line-length:
enabled: true
length: 120
no-trailing-spaces: true
no-tabs: true
# 禁用过于嘈杂的规则
interface-name-style: false
package-filename: false
VSCode 的 Verilog LSP 需要知道去哪里查找模块定义。如果没有正确配置,它会将子模块标记为"未知",尽管综合工具能找到它们。
.vscode/settings.json 中配置包含路径
{
"verilog.languageServer.verible": {
"includePaths": [
"/home/user/work/FPGA_Prj/Project/Common/rtl",
"/home/user/work/FPGA_Prj/Project/Common/sim",
"/home/user/work/FPGA_Prj/Project/Top/rtl",
"/home/user/work/FPGA_Prj/Project/WebServer/rtl",
"/home/user/work/FPGA_Prj/Project/Sensor/rtl",
"/home/user/work/FPGA_Prj/Project/Camera/rtl",
"/home/user/work/FPGA_Prj/Project/Common/ip",
"/home/user/work/fpga_ila/rtl"
],
"fileExtensions": [
".v",
".sv",
".vh",
".svh"
]
}
}
.vscode/filelist.f)创建 /home/user/work/FPGA_Prj/Project/.vscode/filelist.f:
# filelist.f -- 用于 LSP 索引的所有 Verilog 源文件
# 此文件镜像 Vivado 的编译顺序
# Common 库
/home/user/work/FPGA_Prj/Project/Common/rtl/common_defines.vh
/home/user/work/FPGA_Prj/Project/Common/rtl/reset_sync.sv
/home/user/work/FPGA_Prj/Project/Common/rtl/cdc_sync.sv
/home/user/work/FPGA_Prj/Project/Common/rtl/axi_stream_fifo.sv
# 顶层
/home/user/work/FPGA_Prj/Project/Top/rtl/Top.v
/home/user/work/FPGA_Prj/Project/Top/rtl/clock_gen.sv
# WebServer 模块
/home/user/work/FPGA_Prj/Project/WebServer/rtl/http_parser.sv
/home/user/work/FPGA_Prj/Project/WebServer/rtl/tcp_stack.sv
/home/user/work/FPGA_Prj/Project/WebServer/rtl/eth_mac.sv
# Sensor 模块
/home/user/work/FPGA_Prj/Project/Sensor/rtl/spi_master.sv
/home/user/work/FPGA_Prj/Project/Sensor/rtl/sensor_reader.sv
# Camera 模块
/home/user/work/FPGA_Prj/Project/Camera/rtl/camera_top.sv
/home/user/work/FPGA_Prj/Project/Camera/rtl/pixel_pipeline.sv
# ILA 调试
/home/user/work/fpga_ila/rtl/soft_ila_top.sv
/home/user/work/fpga_ila/rtl/ila_hub_top.sv
在 VSCode 设置中引用此文件:
{
"verilog.includePathSupport": true,
"verilog.languageServer.verible": {
"fileList": "/home/user/work/FPGA_Prj/Project/.vscode/filelist.f"
}
}
#!/bin/bash
# generate-filelist.sh -- 通过扫描目录自动生成 filelist.f
# 从项目根目录运行
OUTPUT="/home/user/work/FPGA_Prj/Project/.vscode/filelist.f"
echo "# 自动生成的文件列表 $(date)" > "$OUTPUT"
echo "" >> "$OUTPUT"
# 扫描标准目录
for dir in */rtl */sim */ip */include; do
[ -d "$dir" ] || continue
echo "# ${dir}" >> "$OUTPUT"
find "$dir" -type f \( -name "*.v" -o -name "*.sv" -o -name "*.vh" -o -name "*.svh" \) \
| sort >> "$OUTPUT"
echo "" >> "$OUTPUT"
done
echo "已生成:$OUTPUT($(grep -c '.v\|.sv\|.vh' "$OUTPUT") 个文件)"
#!/bin/bash
# vivado-filelist-to-vscode.sh -- 将 Vivado .prj 转换为 LSP 文件列表
# 用法:vivado-filelist-to-vscode.sh Top.xpr
XPR_FILE="$1"
OUTPUT="/home/user/work/FPGA_Prj/Project/.vscode/filelist.f"
# 从 Vivado 项目 XML 中提取源文件
grep -oP 'FilePath="\K[^"]+' "$XPR_FILE" \
| grep -E '\.(v|sv|vh|svh)$' \
| sort > "$OUTPUT"
echo "从 Vivado 项目中提取了 $(wc -l < "$OUTPUT") 个源文件"
# 更新 filelist.f 后,验证 LSP 能否识别模块:
# 在 VSCode 中,打开任意 .sv 文件
# Ctrl+Shift+P → "Verilog:重启语言服务器"
# 打开模块实例化行,将鼠标悬停在模块名称上
# 应该出现一个显示模块定义的工具提示
# 故障排查:
# Ctrl+Shift+U → 输出面板 → 从下拉菜单选择 "Verilog"
# 检查错误消息,例如:
# "Module 'xxx' not found in include paths"
# "Failed to parse file: ..."
/home/user/work/fpga.code-workspace
{
"folders": [
{
"name": "所有 FPGA 项目",
"path": "FPGA_Prj/Project"
},
{
"name": "Common IP",
"path": "FPGA_Prj/Project/Common"
},
{
"name": "Top 顶层设计",
"path": "FPGA_Prj/Project/Top"
},
{
"name": "WebServer",
"path": "FPGA_Prj/Project/WebServer"
},
{
"name": "Sensor",
"path": "FPGA_Prj/Project/Sensor"
},
{
"name": "Camera",
"path": "FPGA_Prj/Project/Camera"
},
{
"name": "FPGA ILA",
"path": "fpga_ila"
},
{
"name": "文档",
"path": "FPGA_Prj/Doc"
}
],
"settings": {
// Verilog LSP 配置(应用到所有目录)
"verilog.languageServer.verible": {
"includePaths": [
"${workspaceFolder:Common IP}/rtl",
"${workspaceFolder:Common IP}/sim",
"${workspaceFolder:Common IP}/ip",
"${workspaceFolder:Top 顶层设计}/rtl",
"${workspaceFolder:WebServer}/rtl",
"${workspaceFolder:Sensor}/rtl",
"${workspaceFolder:Camera}/rtl",
"${workspaceFolder:FPGA ILA}/rtl"
],
"fileExtensions": [".v", ".sv", ".vh", ".svh"]
},
// Verilog 编辑器设置
"[verilog]": {
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.formatOnSave": true,
"editor.wordWrap": "off",
"editor.rulers": [100, 120]
},
"[systemverilog]": {
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.formatOnSave": true,
"editor.wordWrap": "off",
"editor.rulers": [100, 120]
},
// 文件排除(避免构建产物干扰搜索)
"files.exclude": {
"**/.git": true,
"**/*.bit": true,
"**/*.dcp": true,
"**/*.runs": true,
"**/*.sim": true,
"**/*.cache": true,
"**/vivado.jou": true,
"**/vivado.log": true,
"**/xsim.dir": true,
"**/.Xil": true
},
"search.exclude": {
"**/.git": true,
"**/*.bit": true,
"**/*.dcp": true,
"**/vivado*": true,
"**/xsim*": true
},
// 文件关联
"files.associations": {
"*.v": "verilog",
"*.sv": "systemverilog",
"*.vh": "verilog",
"*.svh": "systemverilog",
"*.xdc": "tcl",
"*.sdc": "tcl",
"*.f": "tcl",
"*.tcl": "tcl"
}
},
"extensions": {
"recommendations": [
"mshr-h.veriloghdl",
"eirikpre.systemverilog",
"mshr-h.veriloghdl-utils",
"surfer-project.surfer",
"josef.verilog-testbench",
"marlonjames71.better-comments",
"gruntfuggly.todo-tree",
"teros-technology.teroshdl",
"eamodio.gitlens",
"trabpukcip.waveform-render"
]
}
}
每个项目文件夹可以有自己的 .vscode/settings.json 用于项目特定的覆盖:
// /home/user/work/FPGA_Prj/Project/Top/.vscode/settings.json
{
"verilog.languageServer.verible": {
"topModule": "Top",
"includePaths": [
"${workspaceFolder}/rtl",
"${workspaceFolder}/../Common/rtl",
"${workspaceFolder}/../Common/ip"
]
},
"verilog.linting.linter": "verible",
"verilog.formatting.verilogHDL.formatter": "verible"
}
在正确配置 LSP(Veridian 或 Verible + Verilog-HDL 扩展)后:
| 操作 | 快捷键 | 功能 |
|---|---|---|
| 跳转到定义 | F12 |
跳转到模块/函数/参数的定义处 |
| 速览定义 | Alt+F12 |
在当前窗口内联预览定义 |
| 跳转到引用 | Shift+F12 |
查找符号的所有使用位置 |
| 跳转到文件中的符号 | Ctrl+Shift+O |
列出当前文件中的模块/函数 |
| 跳转到工作区中的符号 | Ctrl+T |
跨所有文件搜索模块/函数 |
| 查找所有引用 | Shift+Alt+F12 |
在侧边栏列出所有引用 |
| 向后导航 | Ctrl+Alt+- |
返回上一个位置 |
| 向前导航 | Ctrl+Shift+- |
向前跳到导航之后的位置 |
// 点击 "spi_master" 然后按 F12
spi_master #(
.CLK_FREQ(100_000_000),
.SPI_FREQ(10_000_000)
) u_spi_master (
.clk(clk),
.rst_n(rst_n),
// ...
);
// → 跳转到 spi_master.sv 模块定义
2. 查找信号的所有使用位置:
// 在 spi_master.sv 中,点击 "sclk" 然后按 Shift+F12
// 列出所有读取/写入 sclk 的文件
3. 浏览模块结构:
# 在任意 .sv 文件中按 Ctrl+Shift+O 会显示:
# module spi_master
# input clk
# input rst_n
# output sclk
# output mosi
# input miso
# ...
# 点击任一端口可跳转到对应位置
{
"verilog.languageServer.verible": {
// 提高跨文件引用的索引深度
"projectMode": true,
// 使用 Kythe 索引实现"查找所有引用"
"indexing": {
"kind": "kythe",
"kytheDirectory": "${workspaceFolder}/.vscode/kythe-index"
}
}
}
| 扩展 | ID | 用途 |
|---|---|---|
| Verilog-HDL/SystemVerilog | mshr-h.veriloghdl |
主要 Verilog 语言支持和 LSP 桥接 |
| Verilog-HDL Utils | mshr-h.veriloghdl-utils |
额外的 Verilog 实用工具 |
| SystemVerilog | eirikpre.systemverilog |
备选的 SV 语法高亮 |
| TerosHDL | teros-technology.teroshdl |
完整的 HDL IDE 体验 |
| 扩展 | ID | 用途 |
|---|---|---|
| WaveTrace | trabpukcip.waveform-render |
VSCode 内的 VCD 波形查看器 |
| Surfer | surfer-project.surfer |
现代波形查看器 |
| Digital IDE | sterben.fpga-support |
数字电路可视化 |
| Draw.io | hediet.vscode-drawio |
框图编辑 |
| 扩展 | ID | 用途 |
|---|---|---|
| Better Comments | aaron-bond.better-comments |
彩色注释标签(TODO、FIXME、NOTE) |
| Todo Tree | gruntfuggly.todo-tree |
跨项目聚合 TODO/FIXME |
| GitLens | eamodio.gitlens |
Git blame、历史、比较 |
| Bookmarks | alefragnani.bookmarks |
代码书签 |
| Error Lens | usernamehw.errorlens |
行内错误/警告显示 |
| Bracket Pair Colorizer | 内置 | 高亮匹配的 begin/end 配对 |
code --install-extension mshr-h.veriloghdl
code --install-extension mshr-h.veriloghdl-utils
code --install-extension eirikpre.systemverilog
code --install-extension trabpukcip.waveform-render
code --install-extension surfer-project.surfer
code --install-extension aaron-bond.better-comments
code --install-extension gruntfuggly.todo-tree
code --install-extension eamodio.gitlens
code --install-extension alefragnani.bookmarks
code --install-extension usernamehw.errorlens
文件:/home/user/.config/Code/User/snippets/systemverilog.json
{
"模块模板": {
"prefix": "svmodule",
"description": "包含标准端口的 SystemVerilog 模块",
"body": [
"//==============================================================================",
"// 模块: ${1:module_name}",
"// 用途: ${2:描述}",
"// 作者: ${3:BuckHuang}",
"// 日期: ${CURRENT_DATE}",
"//==============================================================================",
"",
"module ${1:module_name} #(",
" parameter int CLK_FREQ = 100_000_000,",
" parameter int DATA_WIDTH = ${4:32}",
") (",
" input wire clk,",
" input wire rst_n,",
"",
" // ${5:控制信号}",
" input wire ${6:start},",
" output wire ${7:done},",
"",
" // ${8:数据接口}",
" input wire [DATA_WIDTH-1:0] ${9:data_in},",
" output wire [DATA_WIDTH-1:0] ${10:data_out}",
");",
"",
" //==========================================================================",
" // 内部信号",
" //==========================================================================",
" ${11:logic internal_signal;}",
"",
" //==========================================================================",
" // ${12:核心逻辑}",
" //==========================================================================",
" ${0:// 实现代码}",
"",
"endmodule // ${1:module_name}"
]
},
"模块实例化模板": {
"prefix": "svinst",
"description": "带命名端口的 SystemVerilog 模块实例化",
"body": [
"${1:module_name} #(",
" .${2:PARAM1}(${3:value1}),",
" .${4:PARAM2}(${5:value2})",
") u_${6:instance_name} (",
" .clk (clk),",
" .rst_n (rst_n),",
" .${7:port_a} (${8:signal_a}),",
" .${9:port_b} (${10:signal_b}),",
" .${11:port_c} (${12:signal_c})",
");"
]
},
"Always FF 块": {
"prefix": "svff",
"description": "带异步复位的同步 always_ff 块",
"body": [
"always_ff @(posedge clk or negedge rst_n) begin",
" if (!rst_n) begin",
" ${1:signal} <= '0;",
" end else begin",
" ${1:signal} <= ${2:next_value};",
" end",
"end"
]
},
"Always Comb 块": {
"prefix": "svcomb",
"description": "always_comb 块",
"body": [
"always_comb begin",
" ${1:signal} = ${2:expression};",
"end"
]
},
"FSM 模板(双 always 块)": {
"prefix": "svfsm",
"description": "双 always 块 FSM 模板",
"body": [
"// FSM 状态编码",
"typedef enum logic [${1:STATE_WIDTH}-1:0] {",
" S_IDLE = '0,",
" S_${2:STATE1},",
" S_${3:STATE2},",
" S_${4:DONE}",
"} state_t;",
"",
"state_t state_q, state_nxt;",
"",
"// 状态寄存器",
"always_ff @(posedge clk or negedge rst_n) begin",
" if (!rst_n) begin",
" state_q <= S_IDLE;",
" end else begin",
" state_q <= state_nxt;",
" end",
"end",
"",
"// 次态逻辑",
"always_comb begin",
" state_nxt = state_q;",
" case (state_q)",
" S_IDLE: begin",
" if (${5:condition})",
" state_nxt = S_${2:STATE1};",
" end",
"",
" S_${2:STATE1}: begin",
" ${0:// ...}",
" end",
"",
" S_${3:STATE2}: begin",
" // ...",
" end",
"",
" S_${4:DONE}: begin",
" state_nxt = S_IDLE;",
" end",
"",
" default: state_nxt = S_IDLE;",
" endcase",
"end"
]
},
"AXI-Stream 接口": {
"prefix": "svaxis",
"description": "AXI-Stream 接口端口",
"body": [
"// AXI-Stream ${1:direction} 接口",
"${2:input} wire ${3:prefix}_tvalid,",
"${2:input} wire ${3:prefix}_tready,",
"${2:input} wire [${4:DATA_W}-1:0] ${3:prefix}_tdata,",
"${2:input} wire [${4:DATA_W}/8-1:0] ${3:prefix}_tkeep,",
"${2:input} wire ${3:prefix}_tlast"
]
},
"Testbench 模板": {
"prefix": "svtb",
"description": "带时钟生成的 SystemVerilog Testbench",
"body": [
"`timescale 1ns / 1ps",
"",
"module tb_${1:dut_name};",
"",
" // 时钟生成",
" logic clk = 0;",
" logic rst_n = 0;",
"",
" parameter int CLK_PERIOD = ${2:10}; // ns",
"",
" always #(CLK_PERIOD/2) clk = ~clk;",
"",
" // 复位序列",
" initial begin",
" rst_n = 0;",
" repeat(10) @(posedge clk);",
" rst_n = 1;",
" repeat(5) @(posedge clk);",
"",
" // ${3:测试激励}",
" ${0}",
"",
" $display(\"TB:测试完成\");",
" $finish;",
" end",
"",
" // DUT 实例化",
" ${1:dut_name} #(",
" .CLK_FREQ(100_000_000)",
" ) u_dut (",
" .clk(clk),",
" .rst_n(rst_n),",
" // ... 连接端口",
" );",
"",
" // 波形导出",
" initial begin",
" $dumpfile(\"tb_${1:dut_name}.vcd\");",
" $dumpvars(0, tb_${1:dut_name});",
" end",
"",
"endmodule"
]
},
"文件头注释块": {
"prefix": "svhead",
"description": "标准文件头注释",
"body": [
"//==============================================================================",
"// 文件: ${TM_FILENAME}",
"// 项目: ${1:FPGA_Prj}",
"// 作者: BuckHuang",
"// 日期: ${CURRENT_DATE}",
"//",
"// 描述:",
"// ${2:本模块的简要描述}",
"//",
"// 修订历史:",
"// ${CURRENT_DATE} - 初始版本",
"//=============================================================================="
]
},
"ILA 调试插入点": {
"prefix": "svila",
"description": "ILA 调试钩子插入",
"body": [
"//==========================================================================",
"// ILA 调试钩子(自动生成:${CURRENT_DATE})",
"//==========================================================================",
"wire [${1:TRIG_WIDTH}-1:0] ila_trig;",
"",
"soft_ila_top #(",
" .DATA_WIDTH(${1:TRIG_WIDTH}),",
" .SAMPLE_DEPTH(${2:4096})",
") u_soft_ila (",
" .clk (clk),",
" .rst_n (rst_n),",
" .trig (ila_trig),",
" .trig_en (${3:1'b1})",
");",
"",
"// 将调试信号连接到 ILA 触发器",
"assign ila_trig = {",
" ${4:signal_a},",
" ${5:signal_b},",
" ${6:signal_c}",
"};"
]
}
}
在任意 .sv 或 .v 文件中,输入前缀然后按 Tab 键:
| 前缀 | 结果 |
|---|---|
svmodule |
包含端口的完整模块模板 |
svinst |
命名端口实例化 |
svff |
带异步复位的 always_ff 块 |
svcomb |
always_comb 块 |
svfsm |
双 always 块 FSM 模板 |
svaxis |
AXI-Stream 端口声明 |
svtb |
含时钟 + 复位的 Testbench |
svila |
ILA 调试插入 |
svhead |
文件头注释 |
文件:/home/user/work/FPGA_Prj/Project/.vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Vivado:打开项目(Top)",
"type": "shell",
"command": "/opt/Xilinx/Vivado/2024.1/bin/vivado",
"args": [
"-source", "/home/user/work/FPGA_Prj/Project/Top/vivado/open_project.tcl"
],
"options": {
"cwd": "/home/user/work/FPGA_Prj/Project/Top"
},
"group": {
"kind": "build",
"isDefault": false
},
"problemMatcher": []
},
{
"label": "Vivado:综合(Top)",
"type": "shell",
"command": "/opt/Xilinx/Vivado/2024.1/bin/vivado",
"args": [
"-mode", "batch",
"-source", "/home/user/work/FPGA_Prj/Project/Top/vivado/run_synthesis.tcl",
"-nojournal",
"-nolog"
],
"options": {
"cwd": "/home/user/work/FPGA_Prj/Project/Top"
},
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Vivado:生成比特流(Top)",
"type": "shell",
"command": "/opt/Xilinx/Vivado/2024.1/bin/vivado",
"args": [
"-mode", "batch",
"-source", "/home/user/work/FPGA_Prj/Project/Top/vivado/run_bitstream.tcl"
],
"options": {
"cwd": "/home/user/work/FPGA_Prj/Project/Top"
},
"group": "build",
"dependsOn": ["Vivado:综合(Top)"]
},
{
"label": "ModelSim:运行仿真(Top)",
"type": "shell",
"command": "/opt/ModelSim/modeltech/bin/vsim",
"args": [
"-c",
"-do", "run -all; quit",
"work.tb_Top"
],
"options": {
"cwd": "/home/user/work/FPGA_Prj/Project/Top/sim"
},
"group": {
"kind": "test",
"isDefault": false
}
},
{
"label": "Verilator:代码检查",
"type": "shell",
"command": "verilator",
"args": [
"--lint-only",
"-Wall",
"--top-module", "Top",
"-f", "/home/user/work/FPGA_Prj/Project/.vscode/filelist.f"
],
"options": {
"cwd": "/home/user/work/FPGA_Prj/Project/Top"
},
"group": "test",
"problemMatcher": {
"owner": "verilog",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": {
"regexp": "^(%-E|%-W|%Error|%Warning)[^:]*:\\s*(.*)$",
"message": 2
}
}
},
{
"label": "Verible:格式化所有文件",
"type": "shell",
"command": "/home/user/tools/verible/bin/verible-verilog-format",
"args": [
"--inplace",
"--failsafe_success=true"
],
"options": {
"cwd": "/home/user/work/FPGA_Prj/Project"
},
"group": "none",
"problemMatcher": []
},
{
"label": "Icarus:编译 + 运行 TB",
"type": "shell",
"command": "iverilog",
"args": [
"-g2012",
"-o", "simv",
"-f", "/home/user/work/FPGA_Prj/Project/.vscode/filelist.f",
"${file}"
],
"options": {
"cwd": "${fileDirname}"
},
"group": {
"kind": "test",
"isDefault": true
},
"dependsOrder": "sequence",
"dependsOn": []
},
{
"label": "Icarus:查看波形",
"type": "shell",
"command": "gtkwave",
"args": [
"${fileDirname}/tb_${fileBasenameNoExtension}.vcd"
],
"options": {
"cwd": "${fileDirname}"
},
"group": "none",
"dependsOn": ["Icarus:编译 + 运行 TB"]
}
]
}
文件:/home/user/work/FPGA_Prj/Project/.vscode/keybindings.json(或用户按键绑定)
[
{
"key": "ctrl+shift+b",
"command": "workbench.action.tasks.runTask",
"args": "Vivado:综合(Top)"
},
{
"key": "ctrl+shift+t",
"command": "workbench.action.tasks.runTask",
"args": "Icarus:编译 + 运行 TB"
},
{
"key": "ctrl+shift+alt+f",
"command": "workbench.action.tasks.runTask",
"args": "Verible:格式化所有文件"
}
]
文件:/home/user/work/FPGA_Prj/Project/Top/vivado/open_project.tcl
# open_project.tcl -- 从 VSCode 打开 Vivado 项目
set project_name "Top"
set project_dir [file dirname [info script]]
# 如果项目不存在则创建
if {![file exists "$project_dir/$project_name.xpr"]} {
create_project $project_name $project_dir -part xc7z020clg400-1
add_files -fileset constrs_1 -norecurse "$project_dir/constraints/Top.xdc"
source "$project_dir/vivado/add_sources.tcl"
} else {
open_project "$project_dir/$project_name.xpr"
}
# 启动 GUI(批处理模式下不启动)
if {[lindex $argv 0] ne "-batch"} {
start_gui
}
文件:/home/user/work/FPGA_Prj/Project/.vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
// --- 综合流水线 ---
{
"label": "FPGA:完整构建(Top)",
"dependsOrder": "sequence",
"dependsOn": [
"FPGA:Verible 代码检查",
"FPGA:Vivado 综合",
"FPGA:Vivado 实现",
"FPGA:Vivado 比特流"
],
"group": "build",
"problemMatcher": []
},
// --- 各独立步骤 ---
{
"label": "FPGA:Vivado 综合",
"type": "shell",
"command": "/opt/Xilinx/Vivado/2024.1/bin/vivado",
"args": ["-mode", "batch", "-source", "vivado/run_synthesis.tcl"],
"options": { "cwd": "${workspaceFolder}/Top" },
"group": "build"
},
{
"label": "FPGA:Vivado 实现",
"type": "shell",
"command": "/opt/Xilinx/Vivado/2024.1/bin/vivado",
"args": ["-mode", "batch", "-source", "vivado/run_impl.tcl"],
"options": { "cwd": "${workspaceFolder}/Top" },
"group": "build"
},
{
"label": "FPGA:Vivado 比特流",
"type": "shell",
"command": "/opt/Xilinx/Vivado/2024.1/bin/vivado",
"args": ["-mode", "batch", "-source", "vivado/run_bitstream.tcl"],
"options": { "cwd": "${workspaceFolder}/Top" },
"group": "build"
},
// --- 代码检查 ---
{
"label": "FPGA:Verible 代码检查",
"type": "shell",
"command": "/home/user/tools/verible/bin/verible-verilog-lint",
"args": [
"--rules_config=${workspaceFolder}/.veriloglint.yaml",
"-f", "${workspaceFolder}/.vscode/filelist.f"
],
"options": { "cwd": "${workspaceFolder}" },
"group": "test",
"problemMatcher": {
"owner": "verilog",
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(error|warning)\\s+(.*)$",
"file": 1, "line": 2, "column": 3, "severity": 4, "message": 5
}
}
},
{
"label": "FPGA:Verible 格式检查",
"type": "shell",
"command": "/home/user/tools/verible/bin/verible-verilog-format",
"args": [
"--verify", "-f", "${workspaceFolder}/.vscode/filelist.f"
],
"options": { "cwd": "${workspaceFolder}" }
},
// --- 仿真 ---
{
"label": "仿真:Icarus 编译",
"type": "shell",
"command": "iverilog",
"args": [
"-g2012",
"-o", "${fileDirname}/simv",
"-I${workspaceFolder}/Common/rtl",
"-I${workspaceFolder}/Common/sim",
"${file}"
],
"options": { "cwd": "${fileDirname}" },
"group": "test"
},
{
"label": "仿真:运行 + GTKWave",
"type": "shell",
"command": "vvp",
"args": ["${fileDirname}/simv"],
"options": { "cwd": "${fileDirname}" },
"dependsOn": ["仿真:Icarus 编译"]
},
{
"label": "仿真:ModelSim(GUI)",
"type": "shell",
"command": "/opt/ModelSim/modeltech/bin/vsim",
"args": ["-gui", "work.tb_${fileBasenameNoExtension}"],
"options": { "cwd": "${fileDirname}" },
"group": "test"
},
{
"label": "仿真:Verilator 检查 + 仿真",
"type": "shell",
"command": "verilator",
"args": [
"--binary",
"--top-module", "tb_${fileBasenameNoExtension}",
"--timing",
"-Wall",
"-Wno-fatal",
"${file}"
],
"options": { "cwd": "${fileDirname}" },
"group": "test"
},
// --- Git 工作流 ---
{
"label": "Git:状态总览",
"type": "shell",
"command": "/home/user/.local/bin/status-all.sh",
"options": { "cwd": "/home/user/work" },
"group": "none",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Git:拉取所有仓库",
"type": "shell",
"command": "/home/user/.local/bin/pull-all.sh",
"options": { "cwd": "/home/user/work" },
"group": "none"
},
{
"label": "Git:所有仓库打快照标签",
"type": "shell",
"command": "/home/user/.local/bin/tag-all.sh",
"options": { "cwd": "/home/user/work" },
"group": "none"
},
// --- 实用工具 ---
{
"label": "工具:生成文件列表",
"type": "shell",
"command": "find",
"args": [
"${workspaceFolder}",
"-type", "f",
"(", "-name", "*.v", "-o", "-name", "*.sv", "-o", "-name", "*.vh", "-o", "-name", "*.svh", ")",
"|", "sort",
">", "${workspaceFolder}/.vscode/filelist.f"
],
"options": { "cwd": "${workspaceFolder}" }
},
{
"label": "工具:清理构建产物",
"type": "shell",
"command": "find",
"args": [
"${workspaceFolder}",
"(", "-name", "*.jou", "-o", "-name", "*.log", "-o", "-name", "*.str", "-o",
"-name", "*.dcp", "-o", "-name", "*.bit", "-o", "-name", "*.bin", "-o",
"-name", "*.backup.jou", "-o", "-name", "*.backup.log", ")",
"-delete"
],
"options": { "cwd": "${workspaceFolder}" }
}
]
}
全新 Ubuntu 机器的推荐配置步骤:
#!/bin/bash
# vscode-verilog-setup.sh -- 一键 VSCode Verilog 配置
VSCODE_USER_DIR="/home/user/.config/Code/User"
SNIPPETS_DIR="$VSCODE_USER_DIR/snippets"
mkdir -p "$SNIPPETS_DIR"
# 1. 安装扩展
echo "正在安装扩展..."
code --install-extension mshr-h.veriloghdl
code --install-extension trabpukcip.waveform-render
code --install-extension surfer-project.surfer
code --install-extension aaron-bond.better-comments
code --install-extension gruntfuggly.todo-tree
code --install-extension eamodio.gitlens
code --install-extension usernamehw.errorlens
# 2. 复制代码片段文件
echo "正在配置代码片段..."
# (上文中的 snippet 内容)
# 3. 在 settings.json 中设置文件关联
echo "正在配置文件关联..."
# 追加到用户 settings.json
echo "VSCode Verilog 配置完成。"
| 问题 | 症状 | 解决方案 |
|---|---|---|
| "未知模块"错误 | 模块实例化处出现红色波浪线 | 检查 settings.json 中的 includePaths;添加模块源文件目录 |
| LSP 未启动 | 无语法高亮 | 检查 verible.path 或 veridian.languageServer.path |
| 索引速度慢 | VSCode 启动时挂起 | 从工作区中排除 Vivado 构建目录 |
| 代码片段不生效 | 输入前缀,无补全提示 | 在设置中检查 editor.snippetSuggestions:"top" |
| 保存时格式化无效 | 无自动格式化 | 验证 editor.formatOnSave:true 以及格式化工具路径 |
| GTKWave 打开失败 | 空白波形窗口 | 检查 .vcd 文件是否存在且有数据 |
| 工作区中找不到模块 | Ctrl+T 无返回结果 |
重新生成 filelist.f,重新加载 LSP |
导航
F12 跳转到定义(模块、函数、参数)
Alt+F12 速览定义(内联预览)
Shift+F12 查找所有引用
Ctrl+Shift+O 跳转到文件中的符号
Ctrl+T 跳转到工作区中的符号
Ctrl+Alt+- 向后导航
编辑
Ctrl+Shift+P → 格式化文档 格式化当前文件
Ctrl+Space 触发代码补全建议
svmodule + Tab 模块模板代码片段
svinst + Tab 实例化模板代码片段
svtb + Tab Testbench 模板代码片段
任务
Ctrl+Shift+B 运行构建任务(综合)
Ctrl+Shift+P → 任务:运行任务 → 选择任意任务
LSP
Ctrl+Shift+P → Verilog:重启语言服务器
Ctrl+Shift+U → 输出面板 → 选择 "Verilog" 查看日志
工作区
文件 → 从文件打开工作区 → fpga.code-workspace