Skip to content

Formatter Options ​

All options live under [format] in lazyverilog.toml. The formatter never changes anything but whitespace; if a safety check fails, the edit is dropped and a warning is shown.

Every align option has an align_adaptive companion: when true, each line computes its own column widths instead of sharing the widest in the group.


Top-level options ​

indent_size ​

Number of spaces per indentation level.

toml
[format]
indent_size = 4
systemverilog
// indent_size = 2
module m_top;
  logic a;
endmodule

// indent_size = 4
module m_top;
    logic a;
endmodule

blank_lines_between_items ​

Number of blank lines kept wherever the source has at least one. 0 removes them. A gap that has no blank line is never given one. Blank lines inside parentheses or braces (a port list, a concatenation) are always removed, whatever this value is. Range 0 to 100.

toml
[format]
blank_lines_between_items = 1
systemverilog
// source: three blank lines between the assigns
// blank_lines_between_items = 1
assign a = b;

assign c = d;

// blank_lines_between_items = 0
assign a = b;
assign c = d;

default_indent_level_inside_outmost_block ​

Indent levels to add inside the outermost design unit, 0 or 1 (other values are rejected with a warning and the default 1 is used): module, macromodule, interface, package, program, class, checker, primitive, or config. Set to 0 to keep its body at column 0. A unit nested inside another (a class in a package) always indents its body.

toml
[format]
default_indent_level_inside_outmost_block = 1
systemverilog
// default_indent_level_inside_outmost_block = 1
module m_top;
  logic a;
endmodule

// default_indent_level_inside_outmost_block = 0
module m_top;
logic a;
endmodule

tab_align ​

When true, alignment column widths are rounded up to the next multiple of indent_size. Produces cleaner tab-stop-aligned columns across port declarations, variable declarations, instances, enums, and modports.

toml
[format]
tab_align = true
indent_size = 4

# the example below also uses
[format.port_declaration]
align = true
align_adaptive = false
section1_min_width = 1
section2_min_width = 1
section3_min_width = 1
section4_min_width = 1
section5_min_width = 0
systemverilog
// tab_align = false, indent_size = 4
    input  logic [7:0] data,
    output logic       valid

// tab_align = true, indent_size = 4  (each column width rounded up to a multiple of 4)
    input   logic   [7:0]   data,
    output  logic           valid

With the default port widths (12, already a multiple of 4) the two settings give the same output.


log_path ​

A directory for the formatter's per-pass debug logs, for reporting a formatter bug. Empty (the default) writes nothing. A relative path is relative to the working directory of the server or lazyverilog-fmt process, not to lazyverilog.toml. The directory is created when needed, and every format, including format-on-save, writes to it, so leave it empty in normal use.

toml
[format]
log_path = "/tmp/lazyverilog-fmt-log"

enable_format_on_save ​

When true, the server formats the whole document on save. It does not stop other save-time generators such as [autoarg].autoarg_on_save.

Saving goes through LSP textDocument/willSaveWaitUntil, which the Neovim plugin and the VS Code extension both send on every save, so no editor-side setting such as editor.formatOnSave is needed. This option only controls saving: an explicit "Format Document" (:Format, vim.lsp.buf.format(), Shift+Alt+F) always formats, whatever it is set to.

toml
[format]
enable_format_on_save = true

format_off_comment_pattern / format_on_comment_pattern ​

Regex patterns used to detect line comments that disable and re-enable formatting. The regex is matched against the comment token text, for example // verilog_format: off.

toml
[format]
format_off_comment_pattern = '//\s*verilog[-_]format\s*:\s*off\b'
format_on_comment_pattern = '//\s*verilog[-_]format\s*:\s*on\b'
systemverilog
// verilog_format: off
assign   a=b;      // preserved verbatim
// verilog_format: on
assign a = b;      // formatted normally

[format.spacing] ​

Controls whitespace around operators, keywords, and delimiters.

control_keyword_space ​

Insert a space between control keywords (if, for, while, etc.) and the opening parenthesis.

toml
[format.spacing]
control_keyword_space = true
systemverilog
// control_keyword_space = true
if (a) begin

// control_keyword_space = false
if(a) begin

space_inside_parens ​

Insert spaces inside ordinary parentheses. Empty parentheses stay ().

toml
[format.spacing]
space_inside_parens = false
systemverilog
// space_inside_parens = false
assign a = foo(bar);

// space_inside_parens = true
assign a = foo( bar );

space_inside_dimension_brackets ​

Insert spaces inside dimension brackets [ ].

toml
[format.spacing]
space_inside_dimension_brackets = false
systemverilog
// space_inside_dimension_brackets = false
logic [7:0] data;

// space_inside_dimension_brackets = true
logic [ 7:0 ] data;

binary_operator_spacing ​

Controls spaces around binary operators (+, -, *, ==, etc.) outside dimension brackets.

Values: "none" | "before" | "after" | "both"

toml
[format.spacing]
binary_operator_spacing = "both"
systemverilog
// "both"
assign c = a + b;
// "none"
assign c = a+b;
// "before"
assign c = a +b;
// "after"
assign c = a+ b;

dimension_binary_operator_spacing ​

Controls spaces around binary operators inside dimension brackets [...].

Values: "none" | "before" | "after" | "both"

toml
[format.spacing]
dimension_binary_operator_spacing = "none"
systemverilog
// "none"
logic [WIDTH-1:0] data;
// "both"
logic [WIDTH - 1:0] data;

semicolon_spacing ​

Controls spaces around semicolons in for-loop headers.

Values: "none" | "before" | "after" | "both"

toml
[format.spacing]
semicolon_spacing = "after"
systemverilog
// "after"
for (int i = 0; i < 8; i++)
// "both"
for (int i = 0 ; i < 8 ; i++)
// "none"
for (int i = 0;i < 8;i++)

range_colon_spacing ​

Controls spaces around the colon in range expressions inside [...].

Values: "none" | "before" | "after" | "both"

toml
[format.spacing]
range_colon_spacing = "none"
systemverilog
// "none"
logic [7:0] data;
// "both"
logic [7 : 0] data;

It also spaces the colons of a min:typ:max triple (#(1:2:3), a specify path delay = (1:2:3)), which is one value rather than a ternary.

This option only affects ranges. A case item's colon is not configurable: it is always written label: statement, whether the label is a literal, an identifier, a macro, or default.

systemverilog
case (op)
    `NOP: y = 0;
    4'hc4: y = 1;
    ST_IDLE: y = 2;
    default: y = 3;
endcase

indexed_part_select_spacing ​

Controls spaces around indexed part-select operators +: and -:.

Values: "none" | "before" | "after" | "both"

toml
[format.spacing]
indexed_part_select_spacing = "both"
systemverilog
// "both"
data[offset +: WIDTH]
// "none"
data[offset+:WIDTH]

procedural_event_control_at_spacing ​

Controls spaces around @ in procedural event control (always @(...)).

The space before @ follows this option only after a keyword. An intra-assignment event takes the assignment operator's spacing (q <= @(posedge clk) d;), and an @ after a control's ) or a delay (wait (a) @(e), #5 @(e)) is always separated from it. So is an @ after the name a clocking block or covergroup declares (clocking cb @(posedge clk);, covergroup cg @(posedge clk);).

Values: "none" | "before" | "after" | "both"

toml
[format.spacing]
procedural_event_control_at_spacing = "before"
systemverilog
// "before"
always @(posedge clk)
// "after"
always@ (posedge clk)
// "both"
always @ (posedge clk)
// "none"
always@(posedge clk)

space_inside_event_control_parens ​

Insert spaces inside event control parentheses @(...).

toml
[format.spacing]
space_inside_event_control_parens = false
systemverilog
// false
always @(posedge clk)
// true
always @( posedge clk )

assignment_operator_spacing ​

Controls spaces around assignment operators = and <=.

Values: "none" | "before" | "after" | "both"

toml
[format.spacing]
assignment_operator_spacing = "both"
systemverilog
// "both"
assign a = b;
q <= d;
// "none"
assign a=b;
q<=d;

[format.statement] ​

Controls formatting of consecutive assignment statements.

align ​

Align = and <= operators across consecutive assignment lines.

toml
[format.statement]
align = true
systemverilog
// align = true
a      = 1;
data   = 2;
result = 3;

// align = false
a = 1;
data = 2;
result = 3;

align_adaptive ​

When true, the operators line up at lhs_min_width and a longer left-hand side widens only its own line, which keeps one space before its operator. When false, all consecutive lines in a group share the column of the widest left-hand side.

toml
[format.statement]
align_adaptive = false
systemverilog
// align = true
// align_adaptive = false
a              = 1;
data           = 2;
result         = 3;
very_long_text = 4;

// align = true
// align_adaptive = true
// lhs_min_width = 6
a      = 1;
data   = 2;
result = 3;
very_long_text = 4;

lhs_min_width ​

Minimum character width of the left-hand side field when align is true.

toml
[format.statement]
lhs_min_width = 6
systemverilog
// lhs_min_width = 6
a      = 1;
data   = 2;

// lhs_min_width = 1
a    = 1;
data = 2;

begin_newline ​

When true, block openers are placed on a new line. When false, they stay on the line that introduces them. This applies to begin, fork, and every brace that opens a block: constraint and coverage braces, and the body brace of a struct or union.

An enum brace is not moved: it holds a list of names, not a block of declarations.

toml
[format.statement]
begin_newline = false
systemverilog
// begin_newline = false
if (a) begin
  ...
end

constraint c {
  if (a) {
    x == 1;
  }
}

// begin_newline = true
if (a)
begin
  ...
end

constraint c
{
  if (a)
  {
    x == 1;
  }
}

typedef struct packed
{
  logic a;
} s_t;

typedef enum logic {
  A,
  B
} e_t;

wrap_end_else_clauses ​

When true (the default), else after end or } is placed on a new line. When false, end else or } else stays on the same line.

An else that follows a labelled end : name, or a comment after end, starts a new line under either value.

toml
[format.statement]
wrap_end_else_clauses = true
systemverilog
// wrap_end_else_clauses = true
end
else begin
  ...
end

}
else {
  ...
}

// wrap_end_else_clauses = false
end else begin
  ...
end

} else {
  ...
}

[format.port_declaration] ​

Controls alignment of

  • ANSI port declarations inside module header.
  • non-ANSI port declarations inside module body.

Port declarations are split into 5 sections:

  1. Direction (input, output, inout)
  2. Type + qualifier (logic, wire signed, etc.)
  3. Packed dimension ([7:0])
  4. Port name
  5. Trailing (unpacked dimensions, = default, etc.)

align ​

Enable column alignment of the 5 sections across consecutive port declarations. Default: false.

toml
[format.port_declaration]
align = true
systemverilog
// align = true, default widths (align_adaptive = true, every section 12)
input       logic       [7:0]       data                    ,
output      logic                   valid

// align = true, align_adaptive = false,
// section1..4_min_width = 1, section5_min_width = 0
input  logic [7:0] data,
output logic       valid

// align = false
input logic [7:0] data,
output logic valid

align_adaptive ​

When true (default), a section wider than its minimum widens only its own line instead of pushing every port in the group to the same column.

toml
[format.port_declaration]
align_adaptive = true

section1_min_width .. section5_min_width ​

Minimum character width for each alignment section. When tab_align is true, these are snapped to indent grid. Section 5 pads the trailing column, so a port's , or ; lines up after it. Default: 12 for each section.

toml
[format.port_declaration]
section1_min_width = 12   # direction column
section2_min_width = 12   # type column
section3_min_width = 12   # dimension column
section4_min_width = 12   # port name column
section5_min_width = 12   # trailing column
systemverilog
// align = true
// align_adaptive = true
// section1_min_width = 10
// section2_min_width = 11
// section3_min_width = 12
// section4_min_width = 13
// section5_min_width = 14
// tab_align = false
input                            i_clk                      ;
input                            i_rst_n                    ;
input     logic      [1:0]       i_data       [7:0]         ;
input     var byte               i_data2                    ;
|        |           |           |            |             |
 section1   section2    section3   section4       section5

[format.var_declaration] ​

Controls alignment of variable/signal declarations (logic, wire, reg, etc.) in module body.

Declarations are split into 4 sections:

  1. Type + qualifier (logic, wire signed, etc.)
  2. Packed dimension ([7:0])
  3. Signal name
  4. Trailing (unpacked dimensions, initializers, etc.)

align ​

Enable column alignment across consecutive variable declarations.

toml
[format.var_declaration]
align = true
systemverilog
// align = true, default widths (section1 0, section2 30, section3 30, section4 0)
logic [7:0]                         data                          ;
logic                               valid                         ;

// align = true, section1..3_min_width = 1, section4_min_width = 0
logic [7:0] data  ;
logic       valid ;

// align = false
logic [7:0] data;
logic valid;

section1_min_width .. section4_min_width ​

Minimum character width for each section.

section1_min_width = 0 (the default) selects a simpler mode. Only the type column is lined up across the group. The dimension and name sections are each padded to their own minimum width, line by line, so names and = line up only when every dimension and name fits in that width. A section whose width is 0 gets no padding at all, and the ; is not aligned. Set section1_min_width to 1 or more to line up every section, the = and the ; across the group.

systemverilog
// align = true, section1_min_width = 0, section2_min_width = 8, section3_min_width = 8
logic    [7:0]   data    = 1;
logic            valid   ;
int      [15:0]  a_very_long_name_x = 0;
packet_t         p       ;

// align = true, section1_min_width = 1, section2_min_width = 8, section3_min_width = 8
logic    [7:0]   data               = 1;
logic            valid                 ;
int      [15:0]  a_very_long_name_x = 0;
packet_t         p                     ;
toml
[format.var_declaration]
section1_min_width = 16    # type column
section2_min_width = 12   # dimension column
section3_min_width = 20   # signal name column
section4_min_width = 16    # trailing column (minimum width; 0 = no minimum)
systemverilog
logic           [7:0]       dout                = 8'hFF         ;
logic           [8:0]       din                 = 8'hFF         ;
packet_t        [1:0]       test_init           = 8'hFF         ;
packet_t                    test_init2          = 8'hFF         ;
|               |           |                   |               |
    section1      section2          section3        section4

[format.instance] ​

Controls formatting of module instantiation port connections.

align ​

Align port connections across lines in an instance. With align = true, one space also separates the instance name from (; with align = false, the ( follows the name directly.

toml
[format.instance]
align = true
systemverilog
// align = true
m_fifo u_fifo (
  .clk   (clk  ),
  .data  (data ),
  .valid (valid)
);

// align = false
m_fifo u_fifo(
  .clk(clk),
  .data(data),
  .valid(valid)
);

port_indent_level ​

Number of indent levels for port lines relative to the instantiation line.

toml
[format.instance]
port_indent_level = 1
systemverilog
// port_indent_level = 1, indent_size = 4
m_fifo u_fifo(
    .clk(clk)
);

// port_indent_level = 2, indent_size = 4
m_fifo u_fifo(
        .clk(clk)
);

instance_port_name_width ​

Total field width from . to ( — controls spacing between the port name and the opening parenthesis.

toml
[format.instance]
instance_port_name_width = 10
systemverilog
// instance_port_name_width = 10
m_fifo u_fifo (
    .clk       (clk  ),
    .data      (data ),
);

instance_port_between_paren_width ​

Total field width from ( to ) — controls spacing between the signal name and the closing parenthesis.

toml
[format.instance]
instance_port_between_paren_width = 10
systemverilog
// instance_port_between_paren_width = 10
m_fifo u_fifo (
    .clk  (clk       ),
    .data (data      ),
);

align_adaptive ​

When true, each port line computes its own gap. When false, all ports in the instance share common alignment columns.

toml
[format.instance]
align_adaptive = false
systemverilog
// align = true, align_adaptive = false
m_fifo u_fifo (
  .clk            (clk           ),
  .data           (data          ),
  .very_long_text (              ),
  .din            (very_long_text)
);

// align = true, align_adaptive = true,
// instance_port_name_width = 6, instance_port_between_paren_width = 10
m_fifo u_fifo (
  .clk  (clk       ),
  .data (data      ),
  .very_long_text (          ),
  .din  (very_long_text)
);

[format.function_call] ​

Controls formatting of function/task calls.

break_policy ​

When to break function call arguments onto separate lines.

  • "never" — always single-line
  • "always" — always break (if args exist)
  • "auto" — break when line exceeds line_length or argument count exceeds arg_count
toml
[format.function_call]
break_policy = "auto"

line_length ​

When break_policy = "auto", break if the single-line rendering exceeds this character width. The width is the whole line as it will be written, indentation included, so the limit is a column and a call nested four levels deep breaks at the same column as one at the top level.

toml
[format.function_call]
line_length = 100

The width is measured up to the call's closing ); a ; or , after it is not counted. The single-line call below ends at column 30.

systemverilog
// break_policy = auto
// line_length = 40
    sum(.i_a(i_a2), .i_b(i_b));

// break_policy = auto
// line_length = 20
    sum(
      .i_a(i_a2),
      .i_b(i_b)
    );

A call is not broken when that would not help: when the arguments would still start past the limit after the break (after the ( for layout = "hanging", one indent past the call's name for "block").


arg_count ​

When break_policy = "auto", break if the number of arguments is >= this value. Set to -1 to disable arg-count breaking.

toml
[format.function_call]
arg_count = 3
systemverilog
// arg_count = 3, 2 args → stays single-line
foo(a, b);

// arg_count = 3, 3 args → breaks
foo(
    a,
    b,
    c
);

layout ​

How to indent broken arguments.

  • "block" — arguments indented one level from the call
  • "hanging" — arguments aligned to the opening parenthesis
toml
[format.function_call]
layout = "block"
systemverilog
// layout = "block"
foo(
  a,
  b,
  c
);

// layout = "hanging"
foo(a,
    b,
    c);

space_before_paren ​

Insert a space between the function name and the opening (.

toml
[format.function_call]
space_before_paren = false
systemverilog
// false
foo(a, b);
// true
foo (a, b);

space_inside_paren ​

Insert spaces inside function call parentheses. An empty argument list stays ().

toml
[format.function_call]
space_inside_paren = false
systemverilog
// false
foo(a, b);
// true
foo( a, b );

[format.function_declaration] ​

Controls formatting of function and task declaration port lists.

Declaration spacing is intentionally limited to the gap before the opening parenthesis. Unlike [format.function_call], declarations do not currently expose space_inside_paren; declaration port-list interior spacing is normalized by the formatter's declaration layout rules.

layout ​

How to indent broken port arguments.

  • "block" — ports indented one level from the declaration
  • "hanging" — ports aligned to the opening parenthesis
toml
[format.function_declaration]
layout = "block"
systemverilog
// layout = "block"
function void foo(
  input logic a,
  input logic b
);

// layout = "hanging"
function void foo(input logic a,
                  input logic b);

line_length ​

Declarations shorter than this stay single-line. Declarations exceeding this are broken according to layout. The width includes the declaration's indentation, as it does for function_call.line_length.

toml
[format.function_declaration]
line_length = 100
systemverilog
// line_length = 100, short declaration stays single-line
function void foo(input logic a, input logic b);

// line_length = 40, same declaration breaks
function void foo(
  input logic a,
  input logic b
);

space_before_paren ​

Insert a space between the declared function/task name and the opening (.

toml
[format.function_declaration]
space_before_paren = false
systemverilog
// space_before_paren = false
function int add_number(
  input int a,
  input int b,
  output int result
);

// space_before_paren = true
function int add_number (
  input int a,
  input int b,
  output int result
);

[format.module] ​

Controls module header formatting.

parameter_layout ​

  • "block" — parameters indented one level
  • "hanging" — parameters aligned to #(
toml
[format.module]
parameter_layout = "block"
systemverilog
// parameter_layout = "block"
module m_top #(
  parameter WIDTH = 8,
  parameter DEPTH = 16
)(
  ...
);

// parameter_layout = "hanging"
module m_top #(parameter WIDTH = 8,
               parameter DEPTH = 16)(
  ...
);

non_ansi_port_per_line_enabled / non_ansi_port_per_line ​

When enabled, non-ANSI port lists are wrapped with a fixed number of ports per line.

toml
[format.module]
non_ansi_port_per_line_enabled = true
non_ansi_port_per_line = 3
systemverilog
// non_ansi_port_per_line = 3
module m_top(
  a, b, c,
  d, e, f,
  g
);

non_ansi_port_max_line_length_enabled / non_ansi_port_max_line_length ​

When enabled, non-ANSI port lists are wrapped based on maximum line length. If both non_ansi_port_per_line_enabled and non_ansi_port_max_line_length_enabled are enabled, both constraints are applied: a line break is inserted when either the fixed port count is reached or adding the next port would exceed the maximum line length.

toml
[format.module]
non_ansi_port_max_line_length_enabled = true
non_ansi_port_max_line_length = 80

[format.enum_declaration] ​

Controls alignment of enum member declarations.

align ​

Align enum names and values across members.

toml
[format.enum_declaration]
align = true
systemverilog
// align = true
typedef enum logic [1:0] {
  IDLE    = 2'b00,
  ACTIVE  = 2'b01,
  DONE    = 2'b10
} state_t;

// align = false
typedef enum logic [1:0] {
  IDLE = 2'b00,
  ACTIVE = 2'b01,
  DONE = 2'b10
} state_t;

align_adaptive ​

Per-member adaptive alignment instead of block-wide alignment.

toml
[format.enum_declaration]
align_adaptive = false
systemverilog
// align = true
// align_adaptive = true
typedef enum logic [1:0] {
    IDLE            = 2'b00,
    ACTIVE          = 2'b01,
    DONE            = 2'b10,
    VERY_LONG_TEXT  = 2'b11
} state_t;

// align = true
// align_adaptive = false
typedef enum logic [1:0] {
    IDLE           = 2'b00,
    ACTIVE         = 2'b01,
    DONE           = 2'b10,
    VERY_LONG_TEXT = 2'b11
} state_t;

enum_name_min_width ​

Minimum character width for the enum member name column.

toml
[format.enum_declaration]
enum_name_min_width = 1

enum_value_min_width ​

Minimum character width for the enum value column. Set to 0 to disable value-column alignment.

toml
[format.enum_declaration]
enum_value_min_width = 0

[format.modport] ​

Controls alignment of modport declarations inside interfaces.

align ​

Align direction and signal columns across modport members.

toml
[format.modport]
align = true
systemverilog
// align = true (align_adaptive = false: the `,` lines up after the widest signal)
modport master (
  input  clk  ,
  input  rst_n,
  output valid
);

// align = true, align_adaptive = true
modport master (
  input  clk,
  input  rst_n,
  output valid
);

// align = false
modport master (
  input clk,
  input rst_n,
  output valid
);

direction_min_width ​

Minimum character width for the direction column (input, output).

toml
[format.modport]
direction_min_width = 1

signal_min_width ​

Minimum character width for the signal name column.

toml
[format.modport]
signal_min_width = 0

[format.macros] ​

Controls how user-defined macros are classified for formatting purposes. Macro classification affects wrapping, indentation, and spacing decisions. See macros.md for the full option reference, available role lists, and examples.

The lists you set extend the built-in UVM defaults; they do not replace them. A built-in macro cannot be removed or moved to another role. See Built-in defaults for the list.

No macro is whitespace_sensitive by default. To keep a macro's arguments exactly as written, list it, for example OpenTitan's DV_CHECK_FATAL:

toml
[format.macros]
whitespace_sensitive = ["DV_CHECK_FATAL"]

Released under the MIT License. Themed with Catppuccin.