An AXI bus in TxHDL: links, routers and bridges
Complex designs in TxHDL communicate over AXI4 interfaces. The Vreteno RISC-V processor, the Razboj rasteriser, DDR3 memory controllers, Ethernet MACs, and HDMI video controllers all use AXI interconnects. This post describes the AXI components in the TxHDL standard library. The library provides high-level channel abstractions, hardware protocol trackers, address routers, and bridges to AXI-Lite and Wishbone. All components lower to synthesizable Verilog and VHDL, verified against randomized bus fuzzing on every build.
Five channels, one link
The AXI4 protocol specifies five independent signaling channels: write address,
write data, write response, read address, and read data.
Managing these channels directly requires tracking address-data correlations,
burst beat counts, last boundary flags, and transaction identifiers.
Manual management introduces frequent protocol errors.
TxHDL encapsulates this complexity through the axi() constructor.
Like standard message-passing channels, axi() initializes all five channels
and returns connected host and peripheral endpoints:
- The host endpoint exposes two primary methods.
readaccepts an address and beat count.writeaccepts an address and a slice of payload beats. Both operations return transaction handles that the client awaits for completion. Clients can hold multiple outstanding handles and await them in arbitrary order. - The peripheral endpoint exposes an
acceptmethod. It waits for complete transactions, returning decoded requests with payload buffers already assembled. Transactions respond directly withok,err, ordataresults.
A serve helper allows multiple concurrent processes to share a peripheral
endpoint.
Worker processes claim incoming transactions as they become idle, returning
responses as computation completes.
Protocol trackers
Two synthesizable hardware units manage protocol sequencing between endpoints:
AxiHostconverts client requests into valid address phases. It allocates transaction identifiers, streams write data beats, and routes completed responses back to client handles.AxiPerarbitrates read and write address channels into a unified request stream. It forwards write data beats to peripheral logic and formats responses into valid AXI beats.
Both trackers compile into clean synthesizable netlists. The standard five-channel bus exposed between them connects directly to AXI4 interconnect routers.
Identifiers remain reserved until the client collects the completed response. Reclaiming identifiers immediately upon response arrival can cause race conditions: if an identifier is reallocated before the client reads the previous response, both transactions risk colliding.
The address router
Parameterized routers (Router2 through Router8) connect a single host to
multiple peripheral slaves.
Each peripheral’s address range is configured via base and mask parameters
encoded directly into the router type.
The address map is part of the static type signature, producing optimized
decode logic during lowering.
The router implements three critical protocol rules:
- Strict write-beat ordering: because write data beats contain no
transaction identifiers, they follow the oldest uncompleted write address
phase.
The router tracks active write targets, queuing secondary writes until the
preceding transaction asserts
last. - Atomic read bursts: the router selects a target peripheral at the first
read beat and locks the route until the
lastflag asserts. - Unmapped address handling: access to unmapped addresses returns a
DecErrresponse. For unmapped writes, the router drains payload beats before returningDecErr. For unmapped reads, it generatesDecErrresponses across the requested burst length.
Protocol bridges
Simpler peripherals do not require burst capability or concurrent transaction
identifiers.
The LiteBridge series translates full AXI4 bursts into sequential AXI-Lite
single-beat transactions.
A single burst can push an entire Ethernet packet to an AXI-Lite transmit FIFO
register.
For existing open-source IP blocks, TxHDL provides AxiWb.
AxiWb bridges AXI4 transactions to pipelined Wishbone host interfaces.
Our board infrastructure uses this bridge to communicate with open-source DDR3
controllers.
Randomized bus fuzzing
Directed unit tests verify individual protocol scenarios under predefined timings. Randomized fuzz testing verifies protocol compliance across arbitrary edge cases and concurrent stalls.
The test harness places configurable delay relays across all fifteen internal channels. Each relay inserts pseudo-random stalls ranging from single-cycle delays to 47-cycle pauses. A randomized host issues mixed read and write bursts of one to sixteen beats, tracking up to four concurrent operations. A mock peripheral processes four requests concurrently with randomized response latencies, returning simulated errors across selected address ranges.
The test harness asserts several formal invariants:
- Every issued burst receives exactly one response.
- Read operations return the data most recently written to that address.
- The
lastflag asserts on the final burst beat and nowhere else. - No transaction identifier is reissued while its response remains uncollected.
- Execution completes within a bounded cycle limit.
Continuous integration runs 24 random seeds per commit, and nightly builds evaluate 1,024 seeds. Fuzz testing uncovered two critical concurrency bugs during initial bringup: channel contention between multi-worker peripheral processes, and head-of-line blocking in host identifier allocation. Both issues passed directed testing but failed under randomized bus contention.
Complete implementation code and testbenches are available in the AXI chapter of the TxHDL documentation, with sources in the repository.