AXI-Lite in Verilator - An Educational Experiment

Krishna KarthikKrishna Karthik
6 min read

Introduction

Coming from a digital verification background at a large semiconductor firm, I regularly use constrained random verification methodology and UVM. However, sometimes going back to the basics often reveals new perspectives. This post is a reflection on trying open-source tools such as Verilator, GTKWave and building a C++ testbench without the complex abstraction layers of UVM. Whether you are learning AXI-lite or trying Verilator for the first time, I hope this post provides some practical insights.

Contents

  • Why AXI-lite and Verilator

  • AXI-lite basics

  • Building C++ TB in Verilator

  • Debugging using GTKwave

  • Learnings

Why AXI-lite and Verilator

AXI is one of the most commonly used AMBA protocols throughout industry, making it ideal for benchmarking open-source tools. I chose the AXI-lite version to focus more on the tooling and verification strategies rather than design complexity.

Verilator stood out to me because of its approach: It takes traditional SystemVerilog code and translates to C++ code, allowing for a more native execution. This results in significant speed and performance enhancements in simulation. Verilator also has a large open source community and native support for waveform debugging through VCD(Value Change Dump) files - viewable in GTKWave. Lastly, I wanted to experiment with cycle-accurate simulators since I am more accustomed to traditional event-driven simulators like Synopsys VCS.

AXI-lite Basics

Advanced Michroarchitecture Bus Protocol(AMBA) is a family of communication protocols developed by ARM. Advanced Extensible Interface(AXI) is one revision of the AMBA architecture that is designed for high speed and performance communication. It does this through the use of separate read/write channels, allowing for independent and out of order execution. In this project, I focus on a simplified version of AXI known as AXI-lite. Because it omits complex features such as burst transactions, it is perfect for my Verilator experiment.

AXI-lite interface involves a manager to initiate transactions and a subordinate to execute the instructions. In this project, the subordinate is written in RTL while the testbench mimics the manager. The protocol has five distinct channels that adhere to the valid/ready protocol. Ready is used by the receiver to indicate that it is ready to accept data. Valid is used by sender to indicate data is ready. A transaction is only complete when the valid/ready handshake is complete.

The five channels to be implemented are:

  • Address Read(AR)

  • Read Data(RD)

  • Address Write(AW)

  • Write Data(WD)

  • Response(RE)

hi

The memory resides within the subordinate and is a word addressable array that can be indexed through the address signals. As per the AXI spec, addresses are byte-based, so the subordinate must adjust(shift) accordingly to index the memory. More details on the design can be found at the github link.

Building C++ TB in Verilator

Testcases

The overall testplan is below. Highlighted in yellow are future testing enhancements.

1) Simple write followed by read.

2) Write followed by simultaneous read and write.

3) Backpressure scenarios - randomly toggling ready signals.

4) Skew scenarios - address & data arrive asynchronously.

5) Error scenarios - Reading or writing to invalid addresses.

Generating the clock

Since Verilator is a cycle accurate simulator, a global variable called main_time tracks simulation time. A helper function “clock_cycle” advances the simulation by toggling the clock and evaluating the DUT at every half clock cycle.

Write Operation

A write operation involves selecting a write address(awaddr) and data(wdata). AXI-lite does not enforce an order so the bench asserts both awvalid and wvalid simultaneously. A successful write transaction is complete when awready and wready are also asserted high - meaning subordinate is ready to accept transactions. As soon as this condition is met, awvalid and wvalid are de-asserted to disengage the handshake:

Response Operation

A response operation immediately follows a write operation. Since the manager(testbench) constantly asserts bready, the handshake is complete as soon as bvalid is returned from the subordinate. At this point, bresp should contain any error codes from the write operation.

Read Operation

A read operation involves selecting a read address(araddr) and waiting for read data(rdata). Arvalid and rready are asserted to initiate the transaction. Once both arready and rvalid are returned from the subordinate, the handshake is complete and arvalid is de-asserted. rready is left high as the testbench is always ready to accept read transactions.

Notes on Verilator

  • Fully open source — No licensing headache!

  • Very fast simulations — Completes within seconds for this project.

  • Helpful linting feedback — Unused signals, unused bits, illegal non-blocking constructs etc.

  • Many run options — For signal tracing, warnings, etc.

  • Seamless C++ integration — it will be easily compatible with other C++ or systemC models.

    Limitations

  • Two state logic only - does not model don’t cares(X) or high impedance states(Z).

  • Timing verification — clock domain crossings, async resets, metastability.

  • Non synthesizable constructs — Delay statements, initial blocks, forever blocks.

  • UVM support — still under development along with SV assertions.

  • Coverage metrics — Unsupported at the moment.

  • latch inference — Missed some possible latch inferences in my code

Debugging using GTKWave

GTKWave is a open source graphical tool used for viewing simulation outputs. This is very useful to view state transitions, valid/ready handshake and internal signal behavior - all commonly used in hardware design. In Verilator, a VCD file can be generated using the trace utility, enabling cycle accurate debug(see above).

Test 1: Write and Read from Address 8

In test 1, incremental data is written to byte address 8 in memory, which translates to bit address 64. Because each data transaction is 32 bit(1 word), mem[2][31:0] is populated with this data. Following the write, data is read back from the same address to ensure data can correctly be retrieved from memory. GTKWave confirms that rdata is correctly populated and the rvalid/rready handshake is complete.

Test 2

The following sequence is run in this test:

  1. All 1 data written to byte address 4.

  2. Alternating 1s and 0s written to byte address 0 while data is read from byte address 4.

GTKWave confirms the independent port behavior - an important aspect of the AXI-lite protocol.

Notes on GTKWave

  • Easy to see FSM and valid/ready handshakes

  • The group feature is useful to gather related signals for better clarity.

  • Markers are useful to indicate any important events.

    Limitations

  • Advanced features like logic expressions or conditional breakpoints

  • Can be challenging to navigate hierarchy for large complex designs.

Learnings

I was impressed with Verilator’s performance, speed and flexibility. It can be particularly useful for smaller designs, or applications where simulation speed is critical. I can definitely see its appeal in FPGA prototyping and embedded systems, which would greatly benefit from Verilator’s speed and open source ecosystem.

That said, limited UVM support, lack of four state logic, and cycle accurate nature are worth noting. In complex subsystems or SOCs, asynchronous resets and timing checks are essential and need to be accounted for. Because of this, large semiconductor firms may be hesitant to switch away from the “big 3” vendors - Synopsys, Cadence and Mentor Graphics.

Regardless, Verilator offers the chance to build, prototype and debug quickly. More importantly, it lowers the traditionally high barrier to hardware design and simulation. Overall, I definitely plan to use Verilator more frequently - maybe even integrate Cocotb to write testbenches in python and make small open-source contributions to the ecosystem as I go. I am excited to see how the tool continues to evolve.

0
Subscribe to my newsletter

Read articles from Krishna Karthik directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Krishna Karthik
Krishna Karthik