An industry-standard SystemVerilog and Universal Verification Methodology (UVM 1.2) testbench environment for verifying a synthesizable AXI4 Full Protocol Memory Controller.
🌐 Live Demo on EDA Playground: You can execute and inspect this complete UVM verification suite directly in your browser at edaplayground.com/x/CPAQ.
This repository contains a synthesizable AXI4 Full (Advanced eXtensible Interface 4) slave memory controller design and a complete UVM 1.2 verification testbench architecture designed according to the ARM AMBA AXI4 Specification (ARM IHI 0022E).
- 5-Channel Full-Duplex Bus Architecture: Independent Write Address (
AW), Write Data (W), Write Response (B), Read Address (AR), and Read Data (R) channels. - Complete Burst Support: Supports
FIXED(2'b00),INCR(2 me'b01), andWRAP(2'b10) burst types. - Variable Lengths & Byte Sizes: Variable burst lengths (1 to 256 beats) and byte sizes (1, 2, or 4 bytes per beat for a 32-bit data bus).
- Byte Strobe Masking (
WSTRB): Full byte-level write strobe masking supporting narrow and unaligned memory accesses. - Backpressure & Handshake Handling: Protocol-compliant
VALID/READYhandshake logic with configurable driver delay cycles. - Verification Suite: Modular UVM 1.2 environment with constrained-random sequences, active byte lane scoreboard predictor, functional coverage collector, and SVA protocol assertions.
- Write Address Channel (
AW):awid,awaddr,awlen,awsize,awburst,awvalid,awready - Write Data Channel (
W):wdata,wstrb,wlast,wvalid,wready - Write Response Channel (
B):bid,bresp,bvalid,bready - Read Address Channel (
AR):arid,araddr,arlen,arsize,arburst,arvalid,arready - Read Data Channel (
R):rid,rdata,rresp,rlast,rvalid,rready
The ASCII diagram below illustrates the modular UVM verification environment topology:
+-----------------------------------------------------------------------------------+
| axi4_tb_top |
| |
| +-----------------------------------------------------------------------------+ |
| | axi4_env | |
| | | |
| | +-----------------------------------------------------------------------+ | |
| | | axi4_agent | | |
| | | | | |
| | | +------------------+ +-----------------+ +--------------------+ | | |
| | | | axi4_sequencer |-->| axi4_driver | | axi4_monitor | | | |
| | | +------------------+ +-----------------+ +--------------------+ | | |
| | +---------------------------------------------------------|-------------+ | |
| | | | |
| | +-----------------------+ | | |
| | | axi4_scoreboard |<------------------------+ | |
| | +-----------------------+ | | |
| | | axi4_coverage |<------------------------+ | |
| | +-----------------------+ | |
| +-----------------------------------------------------------------------------+ |
| | (axi4_if) |
| +----------------------------------v------------------------------------------+ |
| | axi4_slave_memory (RTL DUT) | |
| +-----------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------------+
Here is the functional coverage and beat matching results achieved by each testcase on Siemens QuestaSim (EDA Playground):
| Test Name | Primary Objective | Burst Modes | Beats Verified | Functional Coverage | Scoreboard Result | Status |
|---|---|---|---|---|---|---|
axi4_smoke_test |
Basic single Write & Read check | INCR |
1 Beat | 43.06% | PASSED (0 Errors) | ✅ PASS |
axi4_corner_case_test |
Narrow 1-byte bursts & backpressure delays | INCR |
4 Beats | 43.06% | PASSED (0 Errors) | ✅ PASS |
axi4_burst_test |
Comprehensive Burst verification | INCR, FIXED, WRAP |
12 Beats | 64.58% | PASSED (0 Errors) | ✅ PASS |
axi4_random_test |
20 Constrained-Random stress test | INCR, FIXED, WRAP |
168 Beats | 89.24% | PASSED (0 Errors) | ✅ PASS |
💡 Merged Suite Functional Coverage: Combining all testcases across the regression suite yields 95.83% Total Merged Functional Coverage.
# UVM_INFO @ 0: reporter [RNTST] Running test axi4_random_test...
# UVM_INFO axi4_random_test.sv(15) @ 0: uvm_test_top [RAND_TEST] ===========================================
# UVM_INFO axi4_random_test.sv(16) @ 0: uvm_test_top [RAND_TEST] RUNNING AXI4 CONSTRAINED RANDOM TEST
# UVM_INFO axi4_random_test.sv(17) @ 0: uvm_test_top [RAND_TEST] ===========================================
# UVM_INFO axi4_random_sequence.sv(25) @ 0: uvm_test_top.env.agent.sequencer@@rand_seq [RAND_SEQ] Executing 20 random write-read transactions
# UVM_INFO uvm_objection.svh(1270) @ 4395000: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
# UVM_INFO axi4_coverage.sv(65) @ 4395000: uvm_test_top.env.coverage [COV_REPORT] AXI4 Functional Coverage achieved: 89.24%
# UVM_INFO axi4_scoreboard.sv(133) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] --------------------------------------------------------
# UVM_INFO axi4_scoreboard.sv(134) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] AXI4 SCOREBOARD SUMMARY
# UVM_INFO axi4_scoreboard.sv(135) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] --------------------------------------------------------
# UVM_INFO axi4_scoreboard.sv(136) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] Total Write Transactions Processed: 20
# UVM_INFO axi4_scoreboard.sv(137) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] Total Read Transactions Processed : 20
# UVM_INFO axi4_scoreboard.sv(138) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] Total Successful Beat Matches : 168
# UVM_INFO axi4_scoreboard.sv(139) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] Total Data Mismatch Errors : 0
# UVM_INFO axi4_scoreboard.sv(140) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] --------------------------------------------------------
# UVM_INFO axi4_scoreboard.sv(143) @ 4395000: uvm_test_top.env.scoreboard [SCOREBOARD_REPORT] STATUS: SCOREBOARD PASSED (0 ERRORS)
# --- UVM Report Summary ---
# ** Report counts by severity
# UVM_INFO : 20 | UVM_WARNING : 0 | UVM_ERROR : 0 | UVM_FATAL : 0
| File / Folder Path | Description |
|---|---|
| rtl/axi4_slave_memory.sv | Synthesizable AXI4 Slave RAM design supporting 5 channels, byte strobes, and burst modes. |
| tb/interfaces/axi4_if.sv | SystemVerilog Interface defining signals, clocking blocks, and modports. |
| tb/transactions/axi4_transaction.sv | UVM sequence item with constrained-random generation and spec-correct strobe alignment. |
| tb/drivers/axi4_driver.sv | UVM Driver driving AW, W, B, AR, and R channels with handshake delay handling. |
| tb/monitors/axi4_monitor.sv | Passive UVM Monitor capturing transaction packets for analysis ports. |
| tb/scoreboard/axi4_scoreboard.sv | Golden reference memory model verifying read data with active byte-lane masking. |
| tb/coverage/axi4_coverage.sv | Functional coverage collector tracking burst types, sizes, lengths, and cross coverage. |
| tb/assertions/axi4_assertions.sv | Concurrent SVA checkers enforcing VALID/READY stability rules. |
| tb/sequences/ | UVM sequences including base, write, read, burst, random, and virtual sequences. |
| tb/tests/ | UVM test library (axi4_smoke_test, axi4_burst_test, axi4_random_test, axi4_corner_case_test). |
| tb/packages/axi4_pkg.sv | Package compiling all UVM components into axi4_pkg. |
| tb/top/tb_top.sv | Top-level verification module instantiating DUT, interface, and running run_test(). |
| results/ | Raw saved simulation log output files (.log) for all 4 UVM tests. |
Direct Access Link: edaplayground.com/x/CPAQ
- Simulator:
Siemens QuestaSim 2025.2orAldec Riviera-PRO - UVM Version:
UVM 1.2 - Run Options:
+UVM_TESTNAME=axi4_random_test(oraxi4_burst_test,axi4_smoke_test,axi4_corner_case_test)
To execute tests locally via command line:
cd sim
vsim -c -do "do run_questasim.do axi4_smoke_test"
vsim -c -do "do run_questasim.do axi4_burst_test"
vsim -c -do "do run_questasim.do axi4_random_test"
vsim -c -do "do run_questasim.do axi4_corner_case_test"- The Issue: During multi-beat burst reads, read data returned for Beat 1 matched Beat 0, Beat 2 matched Beat 1, and Beat 3 matched Beat 2—resulting in a 1-beat read address pipeline lag.
- The Resolution: In
axi4_slave_memory.sv,reg_araddrwas updated via non-blocking assignment (<=) upon handshake completion. The memory fetch logic was modified to evaluate the next beat address (next_read_addr) combinationally during the handshake edge and immediately pre-fetchmem[next_read_addr], ensuring zero-latency pipeline reads matching the AXI4 spec.
- The Issue: On narrow transfers (
size = 0orsize = 1), the scoreboard checked all 4 byte lanes (i = 0..3). If an inactive byte lane contained old data inref_memfrom a prior test, the scoreboard compared it against uninitialized DUT bus bytes and raised false mismatch errors. - The Resolution: Updated
process_read_transactioninaxi4_scoreboard.svto calculatelane_offset = curr_addr % 4andbytes_in_beat = 1 << size, restricting verification loops strictly to active byte lanes for each beat.
- The Issue: When injecting
driver_rready_delay > 0backpressure delays, the driver assertedrready <= 1and then slept for delay cycles, during which the slave assertedrvalid, completed the handshake, and de-assertedrvalid. When the driver woke up to samplervalid, it saw0, causing simulation hangs. - The Resolution: Restructured
drive_read_transactioninaxi4_driver.svto holdrready <= 0during the backpressure delay, assertrready <= 1, and usedo @(vif.driver_cb); while (!vif.driver_cb.rvalid)to guarantee atomic sampling on exact handshake clock edges.
Distributed under the MIT License. See LICENSE for details.