Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Verilog RTL ConnectorNew to Visual Studio Code? Get it now.
Verilog RTL Connector

Verilog RTL Connector

frankxie

| (1) | Free
Visual drag-and-drop Verilog/SystemVerilog module interconnection with auto wire-matching and top-level wrapper code generation.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Verilog RTL Connector

A VS Code extension that lets you visually interconnect Verilog / SystemVerilog modules and auto-generate a top-level wrapper with correct port lists, internal wire declarations and instance port-maps. Think of it as a lightweight, open-source alternative to the (closed-source) verilogCCN connector — built so you can read, extend and own the code.

New here? Read the user manual (中文使用手册) in MANUAL.md — quick start, every command in detail, the full rule tables of the RTL Code Check, a command cheat-sheet and the FAQ.

Features

  • Workspace scan — parses every *.v / *.sv file and extracts module name, parameters, port names, directions (input/output/inout) and bus widths ([7:0]).

  • Explorer-style module tree — the Modules panel is an Explorer-style tree (folder > file > module), with chevrons to expand/collapse and a + button on each module to add it to the canvas.

  • Working panel — a second sidebar to the right of Modules that lists every module currently on the canvas, with a × button to remove it. Both sidebars are independently resizable.

  • Visual canvas — click a module's + to drop it on the canvas as a draggable card with a header showing the module name and its source file path, and port dots on its left (inputs) / right (outputs). Drag the card header to move a module.

  • Drag-to-connect — drag from one port dot onto another to draw an orthogonal wire. Direction compatibility is checked (output → input; inout / unknown connect freely).

  • Auto Connect — wires ports across all modules by matching signal name (stripping _i / _o suffixes and matching parameters by name). Rule: only real signal flow is wired (output drives input; inout / unknown connect freely). All modules are treated as peers — there is no special TOP node.

  • No TOP designation needed — every canvas node is just an instantiated submodule. Any port you leave unconnected automatically becomes a top-level port of the wrapper; ports that share the same name and direction (e.g. clk on every submodule) are merged into a single top-level port, so clocks/resets surface as one clk/rst_n driving all instances.

  • Spec-compliant RTL — generated code follows a standard RTL coding style: standardized file header, `default_nettype none / `default_nettype wire, 2-space indentation, grouped input wire / output wire port declarations, aligned internal wire declarations, and u_<module> instantiations with aligned port maps and // input / // output comments. Internal connection wires are named from the port base without _i / _o suffixes.

  • Generate — emits <wrapperName>.v into the workspace root and opens it. Every submodule is instantiated with all of its ports; connected ports share an internal wire, unconnected ports become the wrapper's top-level ports.

  • Create Testbench… — Command Palette → Verilog RTL Connector: Create Testbench…, or right-click a .v / .sv file in the Explorer (also in the editor context menu). Generates <module>_tb.v next to the module: the DUT is instantiated as u_<module> with named connections and every interface signal is declared reg with exactly the port name; clock generation, reset release (polarity taken from the name), a stimulus skeleton with TODO markers, parameters mirrored as localparams, a watchdog, an `ifdef DUMP_WAVE VCD dump and the spec file header are all included. An existing .v file is never overwritten silently (Overwrite / Save As…).

  • Insert Comment Banner… — Command Palette → Verilog RTL Connector: Insert Comment Banner…, or the editor right-click menu of a .v / .sv file. Inserts the project's section banner above the current line, with the current line's indentation:

      //==========================================================================
      // xxxxxxxxxx
      //==========================================================================
    

    The picker offers the banner titles already used in the file (first entry: Custom title…), so a file keeps a consistent set of section names. The // + 74 = format is identical to the banners in the RTL spec and in the generated code.

  • Create Spec-Compliant Wrapper (Ctrl+Shift+P → Create Spec-Compliant Wrapper…) — finds modules whose ports break the interface rules of the project RTL spec (missing _i / _o / _b suffix, ascending bit ranges such as [0:7]) and generates a wrapper that exposes a compliant pin list while instantiating the original module 1:1 inside. The wrapper gets the standard file header, `default_nettype guards, the source's own //$port_g interface groups, a 44-column aligned pin list (or keyword groups when the source has no markers), a u_<module> instantiation with // input / // output comments, and keeps port-level `ifdef blocks. Clock / reset / interrupt / bus ports are exempt from the suffix rule.

  • Create Filelist (.f) — two ways in, one command:

    • right-click a folder in the Explorer → Verilog RTL Connector: Create Filelist (.f). Writes <folder>.f (next to the folder) with the absolute path of every .v / .sv below it (recursive, sorted, quoted when they contain spaces) and one +incdir+<absolute directory> line per directory holding a .vh (deduplicated, listed first). Hidden folders and node_modules are skipped.
    • Ctrl+Shift+P → Create Filelist (.f) → pick a folder in the dialog. Nothing is written to disk: the same filelist content is inserted at the cursor of the active editor (handy to edit by hand or to paste into an existing .f). The block uses the editor's line endings and only adds a line break where the cursor line really holds code — on an empty line you get exactly the paths, with no leading/trailing blank line. Ctrl+Z undoes it.
  • Create Simulation Environment… — Ctrl+Shift+P → Verilog RTL Connector: Create Simulation Environment…, or right-click a .v / .sv file in the Explorer (also in the editor context menu, next to Create Testbench…): the right-click route uses the file you clicked instead of the active editor (with the in-editor content when it is the same file). With the module's file known (pick the module when the file has several), choose a folder and the extension creates sim_<module>/ inside it, filled with the bundled VCS + Verdi + SpyGlass simulation template (sim_test/): compile.sh, simulate.sh, coverage.sh, cov_analyze.py, run_verdi.sh, sim_lib.sh, lint_extra.tcl, sim.cfg, both example lists and the template READMEs — 12 files, all copied byte for byte except the three that depend on the design:

    • sim.cfg → TOP / TB_TOP (rest untouched),
    • filelist.f → the module's own source, relative to the environment folder (../rtl/<module>.v, forward slashes, absolute when it lives on another drive),
    • tb_filelist.f → the testbenches next to the module (tb_*.v|sv, *_tb.v|sv; its own <module>_tb.v first), or a TODO comment when there is none.

    Paths are never quoted (the template's list parser matches whole lines), so a path with a space gets a WARN comment instead; the generated lists always use LF. The environment is created next to the module by default, an existing sim_<module>/ asks before overwriting (files you added there survive) and sim.cfg is opened afterwards — the notification reminds you to chmod +x *.sh once on Linux and to review the template's remaining example values (TB_DEFINES / MACRO_ALIASES / COV_TREES).

  • Wire Modules… (Auto-Wire) — from the Command Palette: pick the driver and the receiver module with searchable, mouse-wheel-scrollable drop-downs, then add one row per signal (name + width + optional driver/receiver port). All the controls of a row sit on one line with a uniform height; there is no Chinese label anywhere in the panel.

    • Show Hierarchy draws the path driver … common parent … receiver as an SVG (the signal turns around at the common parent; instance names and the wire label are shown);
    • Preview Code lists every file/module that will change, with the exact lines and // auto-wire: <start> -> <end> : <sig> comments;
    • Generate Code inserts the internal wire, the missing ports (auto-created as xxx_o / xxx_i when no port matches), the .port (signal) connections and the pass-through assigns directly into the original files (undoable with Ctrl+Z).
  • Verilog / SystemVerilog syntax highlighting — the extension ships its own TextMate grammars (.v → source.verilog, .sv → source.systemverilog) plus a language configuration, so both languages are tokenised even without any other Verilog extension. Run Verilog RTL Connector: Apply Vivid Verilog Colors (offered once on first activation) to paint keywords, types, directions, numbers, strings, comments, $tasks, macros and module/function names with a vivid, easily distinguishable palette — written into editor.tokenColorCustomizations for your current theme only (your own rules are kept; … Remove Vivid Verilog Colors reverts it). Dark and light variants are chosen automatically.

  • Verilog completion (templates + name hints) — no command needed, it works while you type in .v / .sv files (the extension activates via onLanguage:verilog / workspaceContains:**/*.v): type always and get the clocked block in the project format (always @(posedge clk or negedge rst_n) → if (!rst_n) reset branch → else main branch, §6.1); type case, function or task for their templates, or type fsm for the three-stage state machine (state register / next-state logic / output logic, §7.1 — localparam ST_* states, <fsm>_cs / <fsm>_ns, a default assignment plus a default: branch so it is latch-free). The FSM template is already recognised by Generate FSM Diagram…. Every template follows xxx项目_数字设计RTL规范.md, is inserted at the cursor with tab stops and is unit-tested to be complete (end / endcase / endfunction / endtask always present, block keywords balanced). On top of that, names already written above the cursor (ports, wires, regs, parameters, modules, instances) are offered as completions, and similar but different spellings are flagged with the reason (prefix, the xxx_o ↔ xxx_i direction pair §10.3, letter case, or 1–2 characters off). Toggle it with verilog-rtl-connector.completion.enable / .templates / .names.

  • Generate Ports from Table… (Port Table) — Ctrl+Shift+P → Generate Ports from Table…. Type the module name and one row per port (Port name, Direction input/output/inout, Width as the number of bits — 8 becomes [7:0], 1 / empty is a single bit — and an optional Comment) and use the three panel buttons:

    • Check — reports every problem with a rule number, the row and a suggested value: Verilog itself (V01 illegal identifier, V02 reserved keyword, V03 duplicate port, V04 width syntax, V05 module name, V06 port named like the module, V07 case-only duplicate, V08 empty table, V09 comment with a line break) plus the project RTL spec (missing _i / _o / _b suffix §10.1, ascending range §3.2, 31-character names §11.1, clock/reset first §3.1). One click on Apply fixes the field;
    • Suggest Names — a compliant name per row from xxx项目_数字设计RTL规范.md §10 / §11 (clock→clk, err→error, address→addr, enable→en, camelCase→lower_case, the direction suffix with the §10.2 exemptions…), each with its reason and an Apply / Apply all button;
    • Generate Code — the spec-style port list (grouped by interface with //=== banners, aligned columns, comments) inserted at the cursor of the active .v / .sv editor; with no editor available it creates <module>.v in the workspace root with the full spec skeleton (§1 header + §2 `default_nettype guards). Nothing is generated while Check still reports Verilog errors.
  • Check RTL Code… (Lint) — static review of a .v file with fix suggestions (.sv files are not checked). Open it from the Command Palette (Shift+Ctrl+P, then pick a .v file — the file of the current editor comes first) or by right-clicking a .v file in the Explorer. It reports, with line numbers and a suggested fix for every item:

    • syntax errors (unbalanced ()/[], module/endmodule, unbalanced begin/end, case/endcase, function/task/generate/fork pairing — reported per broken block with the exact line range L12–L40 (where the opener sits and where the closer has to be added), plus a stray closer as its own single line, unterminated comments and `ifdef, missing ;, duplicate modules/ports/signals, case without default, if without parentheses, = in an if condition, assign with <=, unterminated strings, module header without ;, nested modules, else without if, comma errors / a port connected twice in a port map, a case item without :, duplicate default:, a signal that is used but never declared);
    • port-map checks against the workspace (the module index is built once and cached): an instantiated module that cannot be found, a port that does not exist in that module, a width mismatch on a connection and ports that are left unconnected;
    • not-synthesizable code (initial, # delays — only real ones: #10, #(1), assign #2; the #(...) parameter list of module m #(...) and of an instantiation is not reported, $display/$finish, fork/join, force/release, wait/while, disable, x/z, casex, clock without edge, always without an event control, <= in combinational logic, = in clocked logic, if without else (latch), mixed =/<=, assignment to an input port or to a wire in a procedural block, a signal driven from two blocks, real/time);
    • optimisation suggestions from the project RTL spec (xxx项目_数字设计RTL规范.md) — port suffixes _i/_o/_b (§10.1), ascending ranges (§3.2), named port connections (§9.1), internal signals without _i/_o (§10.4), port groups / clock first (§3.1), the file header (§1) and the `default_nettype guard (§2).

    The report opens in a panel beside the editor (click a line number to jump to it, press Re-check after editing) and every finding is also published to the Problems view. The top of the report shows N error(s) / N warning(s) / N suggestion(s) and the number of rule classes; the findings are then split into three sections — Syntax / usage, Not synthesizable and RTL spec suggestions — and each section title prints its own severity mix, so the section numbers always add up to the chips above. Findings of the same rule are grouped into one collapsible block (group header = rule, count, severity and one generic fix hint; the line numbers of identical findings are listed side by side, each with the offending code and its specific fix in the tooltip), so a file with dozens of findings stays short and readable. If one rule has findings of different severities the header shows mixed and every row is tagged with its own error / warning / suggestion badge. A finding that spans several lines (a begin that is never closed) is shown as L12–L40, hovering it explains the range, clicking it selects exactly those lines, and the Problems view underlines the whole range.

  • Block keyword pairing highlight — put the cursor on a begin (or end, case, endcase, function, endfunction, task, endtask, generate, fork, join, …) and the keyword you are on and the one it pairs with are both boxed in yellow, so the other half of a long block is visible at a glance (an overview-ruler mark shows where it is when it is off screen). Nested blocks pair up level by level, clicking the end finds its begin too, and a keyword without a partner is boxed in orange as a hint. No command needed; switch it off with verilog-rtl-connector.blockMatch.enable.

Usage

  1. Open your Verilog project as a folder in VS Code.

  2. Open the command palette (Ctrl+Shift+P) → Verilog RTL Connector: Open Top Connector.

  3. In the Modules tree on the left, click a module's + to add it to the canvas. The Working panel on the right shows what you've added.

  4. Drag a card header to move a module; drag a port dot onto another port to connect. Or press Auto Connect to match by name (with _i/_o suffix stripping).

  5. Set a Wrapper name and click Generate (ports you leave unwired become top-level I/O).

  6. To make a legacy module comply with the interface spec there are two entry points:

    • Command Palette (Ctrl+Shift+P) → Verilog RTL Connector: Create Spec-Compliant Wrapper… — scans the whole workspace and lists every module whose ports break the spec.
    • Right-click a .v / .sv file — in the Explorer file list or inside the editor — → Verilog RTL Connector: Create Spec-Compliant Wrapper… (only that file's modules; when the file has exactly one module to fix the picker is skipped).

    Either way the extension creates <module>_wrapper.v next to the module it wraps and opens it. That file contains module <module>_wrapper (spec-compliant port list) plus one instantiation u_<module> of the original module — the wrapped .v file itself is never modified (if <module>_wrapper.v already exists you are asked to overwrite or save as).

  7. To build a compile filelist: right-click a folder in the Explorer → Verilog RTL Connector: Create Filelist (.f). <folder>.f is created next to the folder with the absolute path of every .v / .sv inside it plus +incdir+ entries for every directory that contains .vh files. (From the Command Palette the same command asks you for a folder and inserts the content at the cursor instead of creating a file — use that when you want to assemble or edit a .f by hand.)

  8. To start simulating a module: open its .v / .sv file (or right-click it in the Explorer — the file you click wins), then Ctrl+Shift+P → Verilog RTL Connector: Create Simulation Environment… → pick the folder that should contain the environment. sim_<module>/ is created there with the bundled VCS / Verdi / SpyGlass template (compile, simulate, coverage, waveform and lint scripts) and the three design-dependent files (sim.cfg, filelist.f, tb_filelist.f) are pointed at the module you ran it on. sim.cfg opens right after; on Linux run chmod +x *.sh once inside the new folder.

  9. To wire two modules together: Ctrl+Shift+P → Verilog RTL Connector: Wire Modules… (Auto-Wire) → choose the Driver module and the Receiver module (type to search, or scroll the list with the mouse wheel) → add a row per signal with its Signal name, Width (8, [7:0], W-1:0, empty = 1 bit) and the Driver port / Receiver port ((auto match) by default, (auto create new port) to force a new port, or pick any existing port). Then:

    • Show Hierarchy — visualize the hierarchy path and the connection from start to end (the common parent is the turning point; every edge shows its instance name and its port mapping);
    • Preview Code — see the files/modules/comments that will be modified;
    • Generate Code — modify the original files: the connection is created and marked as added by the auto-wiring tool. New ports are inserted at the head of the port list, and a level that only receives (or only drives) the signal is connected port-to-port (no extra internal wire / assign); the internal wire is only created at the common parent. Running it twice changes nothing (already wired = skipped).
  10. To create a new module's port list: Ctrl+Shift+P → Verilog RTL Connector: Generate Ports from Table… → fill the module name and one row per port (name / direction / width in bits, e.g. 8 / optional comment) → Check to validate the naming (Verilog

    • the project spec, with one-click fixes) → Suggest Names for spec-conform names → Generate Code, which inserts the grouped port list at the cursor of the active .v / .sv editor (or creates <module>.v with a full spec skeleton when no editor is open).

Example

Given the sample in sample/example.v (u_src → u_proc, plus top_iface), with only u_src.data → u_proc.data and u_src.valid → u_proc.valid connected (everything else left unconnected), Generate produces a spec-styled wrapper:

`default_nettype none

module top_wrapper (
  //======================================================================
  // Clock and Reset
  //======================================================================
  input  wire       clk,
  input  wire       rst_n,

  //======================================================================
  // External Interfaces
  //======================================================================
  output wire       done,
  output wire [7:0] result
);

  //==========================================================================
  // Internal Wires declarations
  //==========================================================================
  wire [7:0] data;
  wire       valid;

  //==========================================================================
  // Sub-Module Instantiation
  //==========================================================================

  // Module      : top_iface
  // Instance    : u_top_iface
  u_top_iface u_top_iface (
    .clk    (clk   ),  // input
    .rst_n  (rst_n ),  // input
    .result (result),  // output
    .done   (done  )  // output
  );

  // Module      : u_src
  // Instance    : u_src
  u_src u_src (
    .clk   (clk  ),  // input
    .rst_n (rst_n),  // input
    .data  (data ),  // output
    .valid (valid)  // output
  );

  // Module      : u_proc
  // Instance    : u_proc
  u_proc u_proc (
    .clk    (clk   ),  // input
    .rst_n  (rst_n ),  // input
    .data   (data  ),  // input
    .valid  (valid ),  // input
    .result (result),  // output
    .done   (done  )  // output
  );

endmodule
`default_nettype wire

Develop

npm install
npm run compile      # tsc -> out/
# Press F5 in VS Code with this folder open to launch the Extension Development Host.

Run the logic tests (parser + code generator) without VS Code:

npm run compile
node test/run-tests.js

Package (build a local .vsix)

npm install -g @vscode/vsce      # one-time
vsce package --allow-missing-repository
# On Windows PowerShell the .ps1 launcher may be blocked; use the .cmd:
vsce.cmd package --allow-missing-repository

This runs vscode:prepublish (tsc) then produces verilog-rtl-connector-<version>.vsix. test/, sample/ and the source artwork are excluded via .vscodeignore. Install it in VS Code via Extensions → ⋯ → Install from VSIX….

Limitations (intentional MVP scope)

  • Port parsing targets the common ANSI style (module m (input wire clk, ...)). Non-ANSI separated declarations are partially supported; very unusual port constructs may need manual wiring.
  • The RTL Code Check is a static, heuristic checker (no compiler / no full parser): it catches the common mistakes listed above, it is not a replacement for a real simulator or a linter such as Verilator. It checks .v files only. There is no syntax highlighting of our own — pair this with mshr-h.veriloghdl or AndrewNolte.vscode-system-verilog for that.
  • Auto Connect only wires real signal flow (output → input); it does not auto-drive a net from one input to another. That is intentional — input↔input pairs are simply left unconnected and therefore surface as top-level wrapper ports (e.g. a shared clk becomes one top-level clk driving every instance).

License

MIT — do whatever you like, just keep the header.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft