verilaxi is a lightweight, Verilator-friendly AXI verification library written in SystemVerilog.
It provides simple, task-based AXI, AXI-Lite, and AXI-Stream drivers, monitors, and test environments designed for fast RTL bring-up — without UVM.
For a deeper walkthrough of the architecture, module inventory, register maps, and verification flow, see the Developer Guide.
- ✅ AXI4, AXI-Lite, and AXI-Stream support
- ✅ UART core, AXI-Lite GPIO, and UART↔AXI-Lite control-plane blocks
- ✅ AXI-Stream packet, beat, and weighted round-robin arbitration
- ✅ AXI-Stream width converters — integer-ratio (k:1 up, 1:k down) and rational-ratio (e.g. 16↔24)
- ✅ Synchronous and asynchronous AXI-Stream FIFOs
- ✅ Verilator-first (tested with FST + Surfer)
- ✅ No UVM, no factory, no phases
- ✅ Task-based drivers (
write,read,write_burst,read_burst) - ✅ Parameterized widths (ADDR, DATA, ID)
- ✅ AXI stream backpressure (SRC_BP / SINK_BP) and AXI slave ready backpressure (READY_PROB)
- ✅ Selectable test scenarios via TESTTYPE plusarg
- ✅ Clean Makefile-driven test selection with interactive menu
- ✅ SVA protocol checkers for AXI4-Full, AXI-Lite, and AXI-Stream, plus 4KB AXI burst-boundary checks (Verilator
--assert)
These sistenix posts are the narrative layer for the repository. The intent is that a reader can understand the design choices in the blog, then inspect the exact RTL, VIP, and testbench code here in verilaxi.
- Synchronous and Asynchronous FIFOs — sync FIFO flags, async FIFO Gray pointers, CDC headroom, and AXI-Stream async FIFO framing
- AXI-Stream Arbitration in SystemVerilog — packet, beat, and weighted round-robin AXI-Stream arbitration, with RTL and testbench examples
- Building AXI-Stream Width Converters — integer up/down sizing, rational byte repacking, TKEEP handling, and byte-accurate verification
- AXI DMA: Moving Data Without the CPU — S2MM/MM2S and CDMA architecture, 4KB boundary handling, partial strobes, circular mode, and throughput
- Writing a CSR Block Using AXI-Lite — self-clearing control bits, sticky status, and AXI-Lite software control patterns
- Building SystemVerilog AXI VIP for Fast Bring-Up — the task-based VIP style used for fast bring-up in this repo
- Checking AXI Protocol with SystemVerilog Assertions — the assertion layer used to check AXI, AXI-Lite, AXI-Stream, and 4KB burst rules
- Building a Verilator Testbench for AXI Designs — how
sim_main.cpp,testbench.sv, plusargs, and--timingfit together - Reproducible RTL Simulation with Docker and GitHub Actions — containerized simulation, sweeps, and CI flow
verilaxi/
├── rtl/
│ ├── axi/ snix_axi_dma, snix_axi_cdma, snix_axi_mm2mm, mm2s, s2mm
│ ├── axil/ snix_axil_register, snix_axil_gpio, snix_uart_axil_slave, snix_uart_axil_master
│ │ snix_axi_dma_csr, snix_axi_cdma_csr
│ ├── axis/ snix_axis_arbiter, snix_axis_fifo, snix_axis_afifo, snix_axis_register
│ │ snix_axis_upsizer, snix_axis_downsizer
│ │ snix_axis_rr_converter, snix_axis_rr_upsizer, snix_axis_rr_downsizer
│ ├── uart/ snix_uart_lite
│ └── common/ snix_sync_fifo, snix_async_fifo, snix_register_slice
├── tb/
│ ├── classes/ axi_master, axi_slave, axil_master, axis_source, axis_sink …
│ ├── interfaces/ axi4_if, axil_if, axis_if
│ ├── packages/ axi_pkg, axi_dma_pkg, axi_cdma_pkg
│ ├── assertions/ axis_checker, axil_checker, axi_mm_checker, axi_4k_checker
│ └── tests/ test_dma, test_cdma, test_axil_register, test_axil_gpio, test_axis_*
├── filelists/ common.f, tb_top.f
├── mk/ config.mk, build.mk, menu.mk, help.mk
└── Makefile
git clone https://github.com/nelsoncsc/verilaxi.git
cd verilaxi- Verilator 5.046
- Yosys 0.63
- SystemVerilog support enabled
- Surfer (recommended) or GTKWave for FST viewing
This repository is validated against Verilator 5.046 and Yosys 0.63. Older packaged 5.x Verilator releases may fail to parse or build parts of the testbench and should not be assumed to work. Older Yosys releases such as 0.33 may also fail on some of the newer SystemVerilog syntax used by modules like snix_axis_arbiter.
logic [31:0] wr_data[];
logic [31:0] rd_data[];
wr_data = new[4];
rd_data = new[4];
wr_data[0] = 32'h1111_0001;
wr_data[1] = 32'h2222_0002;
wr_data[2] = 32'h3333_0003;
wr_data[3] = 32'h4444_0004;
driver.write_read_check(32'h100, wr_data, rd_data, 4);Interactive menu (prompts for test scenario and backpressure settings):
makemake run TESTNAME=dma # AXI4 DMA (stream → memory, memory → stream)
make run TESTNAME=cdma # AXI4 CDMA (memory-to-memory copy)
make run TESTNAME=axil_register # AXI-Lite register
make run TESTNAME=axil_gpio # AXI-Lite GPIO with user LEDs, RGB LEDs, and debounced buttons
make run TESTNAME=uart_lite # UART core loopback test
make run TESTNAME=uart_axil_slave # AXI-Lite UART peripheral
make run TESTNAME=uart_axil_master # UART-to-AXI-Lite bridge
make run TESTNAME=axis_register # AXI-Stream register slice
make run TESTNAME=axis_arbiter # AXI-Stream round-robin arbiter (packet mode)
make run TESTNAME=axis_arbiter_beat # AXI-Stream beat-mode arbiter
make run TESTNAME=axis_arbiter_weighted # AXI-Stream weighted packet arbiter
make run TESTNAME=axis_fifo # AXI-Stream FIFO
make run TESTNAME=axis_afifo # AXI-Stream async FIFO / CDC FIFO
make run TESTNAME=axis_upsizer # AXI-Stream integer upsizer (IN=8 → OUT=32)
make run TESTNAME=axis_downsizer # AXI-Stream integer downsizer (IN=32 → OUT=8)
make run TESTNAME=axis_rr_converter # AXI-Stream rational-ratio converter (IN=32 → OUT=48)
make run TESTNAME=axis_rr_upsizer # AXI-Stream rational-ratio upsizer (IN=16 → OUT=24)
make run TESTNAME=axis_rr_downsizer # AXI-Stream rational-ratio downsizer (IN=24 → OUT=16)# AXI-Stream arbiter with sink and source backpressure
make run TESTNAME=axis_arbiter SRC_BP=1 SINK_BP=1
# Beat-mode arbiter
make run TESTNAME=axis_arbiter_beat SRC_BP=1 SINK_BP=1
# Weighted packet arbiter
make run TESTNAME=axis_arbiter_weighted SRC_BP=1 SINK_BP=1
# AXI-Stream async FIFO in streaming mode
make run TESTNAME=axis_afifo FRAME_FIFO=0 TESTTYPE=1 SRC_BP=1 SINK_BP=1
# AXI-Stream async FIFO in frame-store-and-forward mode
make run TESTNAME=axis_afifo FRAME_FIFO=1 TESTTYPE=1 SRC_BP=1 SINK_BP=1Select a test scenario and stress with AXI slave backpressure:
# CDMA: 4KB boundary test with 80% AXI ready probability
make run TESTNAME=cdma TESTTYPE=1 READY_PROB=80# DMA: 4KB boundary test
make run TESTNAME=dma TESTTYPE=3 READY_PROB=80make synth SYNTH_NAME=axis_arbiter SYNTH_TARGET=generic
make synth SYNTH_NAME=uart_lite SYNTH_TARGET=generic
make synth SYNTH_NAME=axil_gpio SYNTH_TARGET=generic
make synth SYNTH_NAME=uart_axil_slave SYNTH_TARGET=generic
make synth SYNTH_NAME=uart_axil_master SYNTH_TARGET=generic
make synth SYNTH_NAME=axis_fifo SYNTH_TARGET=generic
make synth SYNTH_NAME=axis_afifo SYNTH_TARGET=artix7
make synth SYNTH_NAME=axis_upsizer SYNTH_TARGET=artix7
make synth SYNTH_NAME=axis_downsizer SYNTH_TARGET=artix7
make synth SYNTH_NAME=axis_rr_converter SYNTH_TARGET=artix7
make synth SYNTH_NAME=axis_rr_upsizer SYNTH_TARGET=artix7
make synth SYNTH_NAME=axis_rr_downsizer SYNTH_TARGET=artix7
make synth SYNTH_NAME=dma SYNTH_TARGET=artix7
make synth SYNTH_NAME=cdma SYNTH_TARGET=genericSimulation logs and FST waveforms are written with parameter-aware filenames so sweep runs do not overwrite each other. For example, make run TESTNAME=axis_afifo FRAME_FIFO=1 TESTTYPE=1 SRC_BP=1 SINK_BP=1 produces work/logs/axis_afifo_ff1_tt1_src1_sink1.log and work/waves/axis_afifo_ff1_tt1_src1_sink1.fst.
A minimal Docker environment is included for reproducible Linux runs with Verilator 5.046, Yosys 0.63, and make.
docker build -t verilaxi .
docker run --rm -it -v "$PWD":/workspace -w /workspace verilaxi \
make run OBJ_DIR=work/obj_dir_linux TESTNAME=axis_afifo FRAME_FIFO=1 TESTTYPE=1 SRC_BP=1 SINK_BP=1This is also the recommended cross-platform path for macOS, Linux, and Windows via WSL2 when you want a consistent tool environment. Using a container-specific OBJ_DIR avoids collisions between host-built binaries and Linux container builds.
Useful Docker examples:
# Tool versions
docker run --rm -it -v "$PWD":/workspace -w /workspace verilaxi \
bash -lc "verilator --version && yosys -V"
# Synthesis
docker run --rm -it -v "$PWD":/workspace -w /workspace verilaxi \
make synth SYNTH_NAME=axis_afifo SYNTH_TARGET=generic
# Sweep wrapper
docker run --rm -it -v "$PWD":/workspace -w /workspace verilaxi \
./scripts/sweep.sh synth genericA convenience regression script is included for broader simulation and synthesis sweeps:
scripts/sweep.sh sim
scripts/sweep.sh synth both
scripts/sweep.sh all bothThe simulation sweep covers the AXIS register, UART core, AXI-Lite GPIO, UART/AXI-Lite control-plane blocks, arbiter (packet/beat/weighted), FIFO, AFIFO, upsizer, downsizer, rr_converter, rr_upsizer, rr_downsizer matrices, axil_register, and DMA/CDMA runs with READY_PROB=70. The synthesis sweep covers all supported designs for generic, artix7, or both.
This project was developed independently. Credit is due to the wider open-source AXI community for helping shape good engineering practice around AXI design and verification. In particular, ZipCPU's AXI articles and examples, together with Alex Forencich's AXI and AXI-Stream component work, were useful sources of inspiration and reference.
This repository does not use code from my current or previous employers; rather, it is a summary of my learnings during my spare time. AI tools were used as auxiliary tools for debugging, scripting, and documentation support.


