SystemVerilog/UVM testbench for an AMBA APB Subsystem with UART, SPI, I2C, GPIO, and RAM peripherals.
This project is a complete System-on-Chip (SoC) verification environment built using SystemVerilog and UVM.
Instead of verifying protocols in isolation, this project verifies a Peripheral Subsystem. It simulates how a CPU interacts with low-speed peripherals (UART, SPI, I2C) through a standard bus interface (AMBA APB).
The goal is to validate that the APB Bridge correctly routes data to the specific controllers, and that the controllers correctly translate that data onto their respective physical interfaces.
Here is a simple analogy used to design this testbench:
Imagine a busy Pizza Restaurant:
- The Boss (The CPU/APB Master): The Boss sits in the office. He is too busy to run to the door. When he wants to talk to a customer, he writes a note and drops it in the Hallway.
- The Hallway (The AMBA APB Bus): This is the path the notes travel. It connects the office to the front counter.
- The Helpers (The Peripherals): There are three specialists at the counter:
- Mr. UART: Talks to customers one-on-one (Serial).
- Mrs. SPI: Fast and efficient, moving boxes out and money in simultaneously.
- Mr. I2C: Polite and checks addresses before delivering.
- The Health Inspector (The UVM Testbench):
- You don't make the pizza. You create chaos to see if the restaurant breaks.
- Test: "What happens if the Boss sends 100 notes really fast?" (FIFO Overflow).
- Test: "What happens if the Hallway lights turn off?" (Bus Error).
If the restaurant survives the chaos and delivers the right pizza, the design passes.
├── design/ # RTL Design
│ ├── apb_subsystem_top.sv # Top-level subsystem with address decoder
│ ├── apb_uart.sv # UART controller (TX only, 115200 baud)
│ ├── apb_spi.sv # SPI master (CPOL=0, CPHA=0)
│ ├── apb_i2c.sv # I2C master controller
│ ├── apb_gpio.sv # 8-bit GPIO with direction control
│ └── apb_ram.sv # 1KB RAM
│
├── tb/ # UVM Testbench
│ ├── agents/ # APB agent (driver, monitor, sequencer)
│ ├── env/ # Environment and scoreboard
│ ├── interfaces/ # APB interface definitions
│ ├── sequences/ # Test sequences for each peripheral
│ ├── tests/ # Test cases
│ ├── top/ # Top-level testbench
│ ├── apb_pkg.sv # Package for RAM-only tests
│ └── apb_subsystem_pkg.sv # Package for subsystem tests
│
├── sim/ # Simulation
│ ├── file_list.f # RAM-only file list
│ ├── run.f # RAM-only run script
│ ├── subsystem_file_list.f # Subsystem file list
│ └── run_subsystem.f # Subsystem run script
│
└── doc/ # Documentation
| Peripheral | Base Address | Registers |
|---|---|---|
| UART | 0x000 | 0x00: TX_DATA, 0x04: STATUS |
| SPI | 0x100 | 0x00: DATA/STATUS |
| GPIO | 0x200 | 0x00: DIR, 0x04: OUT, 0x08: IN |
| I2C | 0x300 | 0x00: CSR, 0x04: ADDR, 0x08: DATA |
| RAM | 0x400 | 1KB memory space |
| Test | Description |
|---|---|
subsystem_all_periph_test |
Tests all peripherals |
subsystem_rand_test |
Random peripheral access |
uart_test |
UART transmission test |
spi_test |
SPI transfer test |
gpio_test |
GPIO walking ones test |
i2c_test |
I2C write test |
ram_test |
RAM read/write test |
# Setup
source setupX.bash
# Run subsystem tests
cd sim
xrun -f run_subsystem.f +UVM_TESTNAME=subsystem_all_periph_test
# Run specific test
xrun -f run_subsystem.f +UVM_TESTNAME=ram_test
# Run original RAM-only tests
xrun -f run.f +UVM_TESTNAME=apb_rand_test