VSCode 代码导航与 Verilog 开发环境配置

> VSCode 完整配置指南,面向 Verilog/SystemVerilog FPGA 开发:LSP 搭建、跨文件导航、代码片段模板、外部工具集成。


目录


Verilog/SystemVerilog LSP 配置

方案 1:Veridian(推荐用于 Verilog/SystemVerilog)

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
}

方案 2:svlangserver(SystemVerilog LSP)


# 通过 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"
}

方案 3:Verible(Google 的 SystemVerilog 工具链)


# 下载预编译的二进制文件
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 语言服务器
VSCode 集成:

{
  "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 扩展

Verilog-HDL 扩展(mshr-h 开发)是 VSCode 与 LSP 之间的主要桥梁:

# 通过 VSCode CLI 安装
code --install-extension mshr-h.veriloghdl

# 或在 VSCode 内部操作:
# Ctrl+Shift+X → 搜索 "Verilog-HDL/SystemVerilog" → 安装

LSP 配置文件

创建 /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 需要知道去哪里查找模块定义。如果没有正确配置,它会将子模块标记为"未知",尽管综合工具能找到它们。

解决方案 1:在 .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"
    ]
  }
}

解决方案 2:项目文件列表(.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"
  }
}

解决方案 3:自动生成文件列表


#!/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") 个文件)"

解决方案 4:从 Verdi/Vivado 项目文件导入


#!/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+- 向前跳到导航之后的位置

典型的 Verilog 导航场景

1. 从模块实例化跳转到定义:

// 点击 "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"
    }
  }
}


推荐扩展列表

核心 Verilog 扩展

扩展 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 文件头注释

与 Vivado/ModelSim 集成

外部工具启动器

文件:/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:格式化所有文件"
  }
]

Vivado 集成 TCL 脚本

文件:/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
}


任务自动化

完整的 tasks.json(所有项目共用)

文件:/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}" }
}
]
}

设置每个用户的 VSCode 配置

全新 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.pathveridian.languageServer.path
索引速度慢 VSCode 启动时挂起 从工作区中排除 Vivado 构建目录
代码片段不生效 输入前缀,无补全提示 在设置中检查 editor.snippetSuggestions:"top"
保存时格式化无效 无自动格式化 验证 editor.formatOnSave:true 以及格式化工具路径
GTKWave 打开失败 空白波形窗口 检查 .vcd 文件是否存在且有数据
工作区中找不到模块 Ctrl+T 无返回结果 重新生成 filelist.f,重新加载 LSP

快速参考:VSCode + Verilog 速查表


导航
  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