A Cargo-style CLI for SystemVerilog
kiln itself only needs a Rust toolchain. The runtime tools
(Slang, Verilator, etc.) are installed separately via kiln install-tools.
# macOS and Linux (no Rust required)
curl -fsSL https://raw.githubusercontent.com/tejasprabhune/kiln/main/install.sh | sh
# or via cargo
cargo install kiln-sv
# install the runtime tools (slang, verilator, verible, surfer, bender)
kiln install-tools
# or build slang and verilator from source (needs cmake + C++17)
kiln install-tools --build-from-source
kiln new counter
cd counter
kiln check # elaboration via slang
kiln build # compile via verilator
kiln test # run testbenches under tests/
Run kiln init in the project root. It creates a Kiln.toml
and a .gitignore entry for build artifacts. Then point [design]
at your existing source tree:
cd my_existing_project
kiln init
# edit Kiln.toml: set top module and adjust sources glob
[package]
name = "my_design"
version = "0.1.0"
[design]
top = "my_top"
sources = ["rtl/**/*.sv", "rtl/**/*.v"]
If you have existing bender or git dependencies, add them under
[dependencies] — see the Dependencies section.
kiln lsp wraps slang-server,
giving you diagnostics, hover, go-to-definition (including into dependencies),
completions, references, and inlay hints. Install it first:
kiln install-tools --tools slang-server
The binary lands at ~/.local/share/kiln/bin/. Make sure that's on your
PATH, or set KILN_SLANG_SERVER_PATH to override discovery.
-- ~/.config/nvim/lsp/kiln.lua
return {
cmd = { 'kiln', 'lsp' },
filetypes = { 'systemverilog', 'verilog' },
root_markers = { 'Kiln.toml' },
}
-- ~/.config/nvim/init.lua
vim.lsp.enable('kiln')
Open any .sv file inside a project. Neovim launches kiln lsp
from the project root and diagnostics appear within a second. To restart after
editing Kiln.toml: :LspRestart.
require('lspconfig.configs').kiln = {
default_config = {
cmd = { 'kiln', 'lsp' },
filetypes = { 'systemverilog', 'verilog' },
root_dir = require('lspconfig.util').root_pattern('Kiln.toml'),
},
}
require('lspconfig').kiln.setup {}
kiln fmt wraps Verible.
Wire it as a format command so your editor calls it on save:
-- format .sv files with kiln fmt on save
vim.api.nvim_create_autocmd('BufWritePost', {
pattern = { '*.sv', '*.svh', '*.v' },
callback = function()
local file = vim.fn.expand('%:p')
vim.fn.jobstart({ 'kiln', 'fmt', file }, {
on_exit = function() vim.cmd('edit') end,
})
end,
})
Or use kiln fmt --check in CI to fail on unformatted files
without modifying anything.
kiln check # fast: slang elaboration only, no simulation
kiln build # compile with verilator (debug profile)
kiln build --release
kiln run # build + execute the simulator binary
kiln clean # remove target/kiln/
Builds are content-hash cached. A recompile only happens when source files, defines, or the build profile change.
Place testbenches under tests/. Each .sv file is a test;
its filename stem is the top module name. A test passes when it prints
PASS to stdout and exits 0.
kiln test # run all tests in parallel
kiln test smoke # substring filter
kiln test --jobs 1 # serial
kiln test --fail-fast # stop on first failure
kiln test --list # print test names and exit
kiln test --trace # dump FST files to target/kiln/waves/
kiln wave # open the most recent FST in surfer
kiln wave smoke # open a specific test's FST
kiln wave --print-path # print the path without opening surfer
kiln manages dependencies via Bender.
Resolved versions are locked in Kiln.lock, which should be committed.
# add a git dependency
kiln add axi --git https://github.com/pulp-platform/axi.git --version 0.39
# add a path dependency
kiln add local_ip --path ../local_ip
# remove a dependency
kiln remove axi
# update all deps to the latest matching versions
kiln update
# print the dependency graph
kiln tree
Dependency sources are picked up automatically by kiln build,
kiln check, and kiln lsp — no manual include path management.
A minimal manifest. The only required fields are name,
version, and top.
[package]
name = "counter"
version = "0.1.0"
description = "A simple counter"
[design]
top = "counter"
sources = ["src/**/*.sv"] # default: src/**/*.sv + .v + .svh
include_dirs = ["include"] # passed as -I to slang and verilator
defines = { SIMULATION = "" } # +define+ flags
[dependencies]
axi = { git = "https://github.com/pulp-platform/axi.git", version = "0.39" }
[lint]
width-trunc = "error" # promote to error
unused-net = "warn" # emit as warning
implicit-net = "allow" # suppress entirely
Lint rule keys are slang's optionName strings. Unknown keys anywhere
in the file are rejected to catch typos early.