Skip to content

Configuration

Everything is set in lazyverilog.toml. The server uses the nearest one above each file you open, so two projects open side by side each use their own.

Minimal example

toml
[design]
vcode = "demo/vcode.f"
define = ["RTL_SIM"]

[format]
enable_format_on_save = true
indent_size = 4

[lint]
enable = true

Complete example

The lazyverilog.toml from the repository root, imported here so it cannot drift from the file the project tests against.

toml
[design]
vcode = "demo/vcode.f"
define = ["RTL_SIM"]   # preprocessor defines passed to slang for parsing

[compilation]
background_compilation = false # run semantic compilation in background workers (slower, richer diagnostics)

[lint]
enable = true                  # global kill-switch; false disables all lint rules


[lint.naming]
enable = true
severity = "hint"          # "warning" | "error" | "hint"
module_pattern = "^m_.*$" # regex; empty = skip
input_port_pattern = "^i_.*$"  # regex; empty = skip
output_port_pattern = "^o_.*$" # regex; empty = skip
signal_pattern = "^(?!q_).*"           # regex for internal logic/wire/var; empty = skip
interface_pattern = ".*_intf$"        # regex for interface names; empty = skip
struct_pattern = ".*_t$"           # regex for struct names; empty = skip
union_pattern = ".*_u$"            # regex for union names; empty = skip
enum_pattern = ""             # regex for enum names; empty = skip
parameter_pattern = "^W_.*$"        # regex for parameter names; empty = skip
localparam_pattern = "^LP_.*$"       # regex for localparam names; empty = skip
register_pattern = "^r_.*$"
check_module_filename = true # check that module name matches filename
check_package_filename = true # check that package name matches filename

[lint.module]
enable = true
severity = "warning"          # "warning" | "error" | "hint"
one_module_per_file = true   # check that at most one module is declared per file

[lint.instance]
enable = true
severity = "warning"          # "warning" | "error" | "hint"
module_instantiation_style = "named"  # "positional", "named", or "both"
stale_instance_diagnostic = true

[lint.statement]
enable = true
severity = "warning"          # "warning" | "error" | "hint"
no_raw_always = true         # check that there are no occurrences of raw always
blocking_nonblocking_assignments = true  # check blocking vs non-blocking assignments
latch_inference_detection = true # check for latch inference
case_missing_default = true              # check that default case-item is always defined
explicit_begin = true # check that Verilog begin directive follows all applicable statements

[lint.function]
enable = true
severity = "warning"          # "warning" | "error" | "hint"
functions_automatic = false   # functions should be automatic type
function_call_style = "both"      # "positional", "named", or "both"
explicit_function_lifetime = true  # check that functions have explicit lifetime (static/automatic)
explicit_task_lifetime = true    # check that tasks have explicit lifetime (static/automatic)

[lint.style]
trailing_whitespace = true

[rtltree]
show_instance_name = true   # show "cpu (u_cpu)" instead of just "cpu"
show_file = true             # show "[rtl/cpu.sv]" after module name

[format]
indent_size = 4
blank_lines_between_items = 1
default_indent_level_inside_outmost_block = 0
tab_align = false
enable_format_on_save = true
format_off_comment_pattern = '//\s*verilog[-_]format\s*:\s*off\b'
format_on_comment_pattern = '//\s*verilog[-_]format\s*:\s*on\b'
log_path = "" # optional directory for formatter per-pass debug logs

[format.spacing]
control_keyword_space = true
space_inside_parens = false
space_inside_dimension_brackets = false
binary_operator_spacing = "both"                    # none | before | after | both
dimension_binary_operator_spacing = "none"          # none | before | after | both
semicolon_spacing = "both"                         # none | before | after | both; for-loop headers
range_colon_spacing = "none"                        # none | before | after | both; ranges inside []
indexed_part_select_spacing = "none"                # none | before | after | both; +: and -:
procedural_event_control_at_spacing = "both"      # none | before | after | both; always @(...)
space_inside_event_control_parens = true
assignment_operator_spacing = "both"                  # none | before | after | both; = and <= operators

[format.statement]
align = true              # align = and <= operators in consecutive assignments
align_adaptive = true
lhs_min_width = 10           # minimum width of the LHS column before the operator
begin_newline = false       # true: place begin / constraint { on the next line
wrap_end_else_clauses = true

[format.port_declaration]
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

[format.var_declaration]
align = true
align_adaptive = true
section1_min_width = 20
section2_min_width = 20
section3_min_width = 20
section4_min_width = 16

[format.function_call]
break_policy = "auto"      # never | always | auto
line_length = 100
arg_count = 3 # when auto: break if arg count >= this value; -1 disables arg-count breaking
layout = "hanging"           # hanging | block
space_before_paren = false
space_inside_paren = false

[format.function_declaration]
layout = "block"           # hanging | block — applies to function and task declarations
line_length = 13          # declarations shorter than this stay single-line
space_before_paren = false # insert a space between function/task name and '('

[format.macros]
object_like_expr = []      # expression token, for example: `MY_WIDTH
function_like_expr = [
    "dv_fatal"
]    # expression-valued call, for example: `CLAMP(a, b)
statement_like = []        # complete procedural statement, for example: `DV_CHECK_EQ(a, b)
declaration_like = [
    "DV_ALERT_IF_CONNECT", # module/class item helper; often used without a trailing semicolon
]
control_flow_like = []     # control-like macro, for example: `ASSERT_IF(en)
block_begin_like = []      # opens logical indent scope, for example: `MY_BLOCK_BEGIN()
block_end_like = []        # closes logical indent scope, for example: `MY_BLOCK_END
whitespace_sensitive = []  # preserve invocation argument spelling/line breaks

[format.module]
parameter_layout = "block" # block | hanging
non_ansi_port_per_line_enabled = true
non_ansi_port_per_line = 3
non_ansi_port_max_line_length_enabled = false
non_ansi_port_max_line_length = 18

[format.enum_declaration]
align = true
align_adaptive = true
enum_name_min_width = 10
enum_value_min_width = 12

[format.modport]
align = true
align_adaptive = true
direction_min_width = 15
signal_min_width = 10

[format.instance]
align = true
port_indent_level = 1                   # indent levels for port lines relative to instantiation
instance_port_name_width = 20           # total field width from '.' to '(' (port name + gap)
instance_port_between_paren_width = 30  # total field width from '(' to ')' (signal + trailing gap)
align_adaptive = true                  # if true, per-line gap; if false, all ports in instance align to common column


[inlay_hint]
enable = true  # set false to disable all inlay hints

[folding]
enable = true  # set false to stop the editor requesting folds on every edit

[autoff]
register_pattern = "^r_"  # regex — signal matching this is the register (dst); the other is the source

[autofunc]
indent_size = 4
use_named_arguments = true

[autoarg]
autoarg_on_save = true

[autowire]
group_by_instance = false
sort_by_name = true

Option reference

TopicPage
Filelist and definesDesign & filelist
FormatterOptions, macro policy
LinterLinter options
Semantic diagnosticsBackground compilation
Folding and inlay hintsLSP features
RTL treeRTL tree
Code generationAutoInst, AutoWire, AutoArg, AutoFunc, AutoFF

Released under the MIT License. Themed with Catppuccin.