A Verilog/SystemVerilog code formatter for VS Code with granular control over formatting features.
Features (More to be added)
This formatter provides comprehensive formatting capabilities with individual control over each feature:
- Module header formatting with port alignment
- Assignment alignment
- Wire/reg/logic declaration alignment
- Parameter/localparam alignment
- Module instantiation formatting
- Always/initial block indentation
- Case statement indentation
- If/else block begin/end enforcement
- For loop begin/end enforcement
- Generate block indentation
- Comment column alignment
- Ifdef/else/endif annotation
- Trailing whitespace removal
- Blank line compression
Installation
From VSIX (Local Install)
- Download
verigood-verilog-formatter-1.0.0.vsix
- Open VS Code
- Press
Ctrl+Shift+P → "Extensions: Install from VSIX..."
- Select the downloaded
.vsix file
From Marketplace
- Open VS Code Extensions (
Ctrl+Shift+X)
- Search for "VeriGood - Verilog Formatter"
- Click Install
Usage
- Keyboard:
Shift+Alt+F (Windows/Linux) or Shift+Option+F (macOS)
- Context Menu: Right-click → "Format Document"
- Command Palette:
Ctrl+Shift+P → "Format Document"
- Keyboard:
Shift+Alt+F (Windows/Linux) or Shift+Option+F (macOS) with text selected
- Context Menu: Right-click on selected text → "Format Selection"
- Command Palette:
Ctrl+Shift+P → "Format Selection"
Recommended Keybindings
For the best experience, add these keybindings to your keybindings.json (File → Preferences → Keyboard Shortcuts → Open Keyboard Shortcuts JSON):
{
"key": "shift+alt+f",
"command": "editor.action.formatDocument",
"when": "editorTextFocus && !editorHasSelection"
},
{
"key": "shift+alt+f",
"command": "editor.action.formatSelection",
"when": "editorTextFocus && editorHasSelection"
}
This allows Shift+Alt+F to automatically format the entire document when nothing is selected, or format just the selection when text is selected.
Add to your settings.json:
{
"[verilog]": {
"editor.defaultFormatter": "internal.verigood-verilog-formatter",
"editor.formatOnSave": true
},
"[systemverilog]": {
"editor.defaultFormatter": "internal.verigood-verilog-formatter",
"editor.formatOnSave": true
}
}
Configuration & Examples
Each feature can be individually enabled or disabled. Below are before/after examples for each setting.
Setting: "verilogFormatter.formatModuleHeaders": true
Before:
module my_module #(parameter WIDTH = 8, parameter DEPTH = 16) (
input clk, input rst, output [WIDTH-1:0] data);
After:
module my_module #(
parameter WIDTH = 8 ,
parameter DEPTH = 16
) (
input clk ,
input rst ,
output [WIDTH-1:0] data
);
2. Assignment Alignment
Setting: "verilogFormatter.alignAssignments": true
Before:
assign data_out = data_in;
assign valid = ready & enable;
assign count_next = count + 1'b1;
After:
assign data_out = data_in ;
assign valid = ready & enable;
assign count_next = count + 1'b1 ;
3. Wire/Reg Declaration Alignment
Setting: "verilogFormatter.alignWireDeclSemicolons": true
Before:
wire [7:0] data_in;
wire valid;
wire [15:0] address;
After:
wire [7:0] data_in;
wire valid ;
wire [15:0] address;
4. Parameter Alignment
Setting: "verilogFormatter.alignParameters": true
Before:
parameter WIDTH = 8;
parameter DEPTH = 256;
parameter ADDR_WIDTH = 10;
After:
parameter WIDTH = 8 ;
parameter DEPTH = 256;
parameter ADDR_WIDTH = 10 ;
5. Always Block Indentation
Setting: "verilogFormatter.indentAlwaysBlocks": true
Before:
always @(posedge clk) begin
if (rst) begin
data <= 0;
end
end
After:
always @(posedge clk) begin
if (rst) begin
data <= 0;
end
end
6. Enforce Begin/End Blocks
Setting: "verilogFormatter.enforceBeginEnd": true
Before:
if (enable)
data_out <= data_in;
else
data_out <= 8'h00;
for (i = 0; i < 8; i = i + 1)
mem[i] <= 0;
After:
if (enable) begin
data_out <= data_in;
end else begin
data_out <= 8'h00;
end
for (i = 0; i < 8; i = i + 1) begin
mem[i] <= 0;
end
7. Case Statement Indentation
Setting: "verilogFormatter.indentCaseStatements": true
Before:
case (state)
IDLE: next_state = ACTIVE;
ACTIVE: next_state = DONE;
default: next_state = IDLE;
endcase
After:
case (state)
IDLE: next_state = ACTIVE;
ACTIVE: next_state = DONE;
default: next_state = IDLE;
endcase
8. Generate Block Indentation
Setting: "verilogFormatter.indentCaseStatements": true (uses same setting)
Before:
generate
if (USE_FEATURE) begin
my_module inst (.clk(clk));
end
endgenerate
After:
generate
if (USE_FEATURE) begin
my_module inst (.clk(clk));
end
endgenerate
Setting: "verilogFormatter.formatModuleInstantiations": true
Formats module instantiations with aligned ports and parameters, including comprehensive support for:
- Single-line and multiline port connections
- Multiline concatenations with nested patterns
- Replication patterns:
{COUNT{signal}}
- Double-replication patterns:
{{COUNT{signal}}}
- Array indices with slicing:
signal[BIT-1:0]
- Nested concatenations:
{signal1, signal2, {signal3[7:0]}}
- Complex mathematical expressions in parameters
Before:
my_module #(.WIDTH(8), .DEPTH(16)) inst (.clk(clk), .data(data));
After:
my_module #(
.WIDTH (8 ),
.DEPTH (16)
) inst (
.clk (clk ),
.data (data)
);
Multiline Concatenation Example:
// Before
u_parity_check (
.idata ({{CMDQ_W{cmdq_pop}}, {RESPQ_W{respq_pop}}, {RXDQ_W{rxdq_pop}}}),
.idata_enable ({{CMDQ_PAR_W{cmdq_en}}, {RESPQ_PAR_W{respq_en}}, {RXDQ_PAR_W{rxdq_en}}})
);
// After - all commas and closing braces aligned
u_parity_check (
.idata ({{CMDQ_W{cmdq_pop}} ,
{RESPQ_W{respq_pop}} ,
{RXDQ_W{rxdq_pop}} }),
.idata_enable ({{CMDQ_PAR_W{cmdq_en}} ,
{RESPQ_PAR_W{respq_en}} ,
{RXDQ_PAR_W{rxdq_en}} })
);
Setting: "verilogFormatter.commentColumn": 40
Before:
wire [7:0] data; // Data signal
wire valid; // Valid flag
After:
wire [7:0] data; // Data signal
wire valid // Valid flag
Setting: "verilogFormatter.annotateIfdefComments": true
Before:
`ifdef DEBUG
// Debug code
`else
// Release code
`endif
After:
`ifdef DEBUG
// Debug code
`else // DEBUG
// Release code
`endif // DEBUG
12. Trailing Whitespace Removal
Setting: "verilogFormatter.removeTrailingWhitespace": true
Removes all trailing spaces and tabs from line endings.
13. Blank Line Compression
Setting: "verilogFormatter.maxBlankLines": 1
Before:
wire [7:0] data;
wire valid;
After:
wire [7:0] data;
wire valid;
All Available Settings
{
"verilogFormatter.indentSize": 2,
"verilogFormatter.maxBlankLines": 1,
"verilogFormatter.alignPortList": true,
"verilogFormatter.alignParameters": true,
"verilogFormatter.wrapPortList": true,
"verilogFormatter.lineLength": 160,
"verilogFormatter.removeTrailingWhitespace": true,
"verilogFormatter.alignAssignments": true,
"verilogFormatter.alignWireDeclSemicolons": true,
"verilogFormatter.commentColumn": 40,
"verilogFormatter.formatModuleInstantiations": true,
"verilogFormatter.formatModuleHeaders": true,
"verilogFormatter.indentAlwaysBlocks": true,
"verilogFormatter.enforceBeginEnd": true,
"verilogFormatter.indentCaseStatements": true,
"verilogFormatter.annotateIfdefComments": true
}
Changelog
Version 1.2.7 (2025-11-05)
Selection Formatting & Wire Declaration Improvements
- ✨ Macro Annotation in Selection -
ifdef/else/endif comment annotation now works in selection formatting
- ✨ Comment Column Alignment in Selection - Comment column alignment now applied in selection formatting
- ✨ Blank Line Compression in Selection - Blank line compression now works in selection formatting
- 🐛 Simple Wire Alignment - Simple wire declarations (no ranges, no init) now use minimal spacing with aligned semicolons
- 🐛 Wire Name Parsing - Fixed issue where trailing spaces in wire names caused semicolons to shift right on repeated formatting
- 🐛 Indent Preservation - Wire declarations now preserve original indentation instead of normalizing to minimum
- 🔧 Alignment Stability - Added checks to prevent re-formatting when declarations are already correctly aligned
Version 1.2.6 (2025-11-05)
Module Instantiation Enhancements
- ✨ Nested Concatenation Support - Full support for complex nested concatenations in multiline port connections
- ✨ Replication Patterns - Handles single
{COUNT{signal}} and double {{COUNT{signal}}} replication patterns
- ✨ Array Index Support - Properly formats signals with array indices including slicing (
signal[BIT-1:0])
- 🐛 Closing Brace Preservation - Fixed issue where closing braces were being removed in deeply nested patterns
- 🐛 Alignment Fixes - All commas and closing braces in multiline concatenations now align at consistent column
- 🐛 Spacing Fixes - Removed extra spaces before closing parentheses in concatenation endings
- 🔧 Selection Formatting - All nested pattern improvements applied to both full document and selection formatting
Version 1.2.5 (2025-11-04)
Module Header & Cleanup Improvements
- Fixed trailing blank lines being added at end of file
- Added blank line after module header closing parenthesis
- Improved module instantiation closing parenthesis alignment
Version 1.2.4 (2025-11-04)
Multiline Formatting Enhancements
- Added comprehensive multiline parameter and port formatting
- Support for mathematical expressions in parameters
- Support for ifdef/else/endif within parameter lists
- Improved multiline concatenation formatting
Version 1.2.3 (2025-11-04)
Bug Fix
- Fixed format selection for wire/reg/logic declarations with initialization
- Range formatting now properly handles declarations like
wire [7:0] data = 8'h00;
- Initialization values are aligned when present in selected range
Version 1.2.2 (2025-11-04)
Bug Fix
- Reverted assignment bracket alignment - assignments no longer align closing brackets
- Assignment LHS (including brackets) is now treated as a single unit for alignment
- Only declarations (wire/reg/logic/input/output/inout) align closing brackets
Version 1.2.1 (2025-11-04)
Alignment Improvements
- Changed range/bracket alignment to align closing bracket
] instead of opening bracket [
- Applies to wire/reg/logic declarations:
wire [7:0] data; instead of wire [7:0] data;
- Applies to port declarations:
input [15:0] address; with aligned closing brackets
- Makes bit-width patterns more visually consistent and easier to read
Version 1.2.0 (2025-11-03)
Range Formatting Enhancements
- Added intelligent structure detection for range formatting
- Complete structures (always, initial, generate, for, case, if/else blocks) now receive full formatting including indentation fixes when selected
- Partial selections only apply alignment-based formatting without changing indentation
- Extended range formatting to support all declaration types and module instantiations
- All alignment calculations (assignments, wires, parameters, ports) are now based solely on selected lines
Version 1.1.1 (2025-11-03)
Format Selection Support
- Added DocumentRangeFormattingEditProvider for format selection feature
- Fixed line ending handling (Windows \r\n vs Unix \n)
- Format selection now properly formats only the selected range
Version 1.1.0 (2025-11-03)
Alignment Improvements
- Fixed module instantiation closing parenthesis alignment
- Fixed module header parameter comma alignment
- Improved port list formatting consistency
Version 1.0.0 (2024)
Initial Release
- Full document formatting support
- Module header formatting with port alignment
- Assignment, wire, and parameter alignment
- Module instantiation formatting
- Block indentation (always, initial, case, generate)
- Configurable formatting options
License
MIT License - See LICENSE for details.