|
CocoTB Framework · Verification Infrastructure for RTL Testing GitHub · Documentation Index · MIT License |
APB Components Overview¶
APB is the simplest bus in the AMBA family — a two-phase, non-pipelined interface that exists to move register reads and writes, not to win bandwidth contests. This directory has everything you need to verify an APB block: a master, a memory-backed slave, a monitor, and the packet/sequence machinery that feeds them.
Architecture Overview¶
The layering matches the rest of the framework: tests and sequences on top, the three protocol BFMs in the middle, packets underneath, shared services at the bottom.
graph TB
subgraph TestEnv["Test Environment"]
Seq[Sequences]
Fact[Factories]
Tests[Tests]
end
subgraph APBLayer["APB Protocol Layer"]
Master["APB Master<br/>(Driver)"]
Monitor["APB Monitor<br/>(Observer)"]
Slave["APB Slave<br/>(Responder)"]
end
subgraph PacketLayer["Packet & Sequence Layer"]
Packet["APB Packet<br/>(Protocol)"]
SeqGen["APB Sequence<br/>(Test Gen)"]
Factory["APB Factory<br/>(Creation)"]
end
subgraph Shared["Shared Components"]
MemModel[Memory Model]
Random[Randomization]
FieldCfg[Field Config]
end
TestEnv --> APBLayer
APBLayer --> PacketLayer
PacketLayer --> Shared
Component Categories¶
Protocol Implementation¶
The three signal-level components, one per role on the bus:
- APBMaster: drives transactions, with randomized PSEL/PENABLE timing
- APBSlave: memory-backed responder with tunable ready and error behavior
- APBMonitor: passive observer that turns bus activity into
APBPacketobjects
What matters here: - Full APB signal support, with APB4's additions (PSTRB, PSLVERR, PPROT) bound as optional so APB3 DUTs still attach - Configurable data and address widths - A real memory model behind the slave, not a hard-coded response - Error injection and timing randomization built in, not bolted on
Packet & Transaction Management¶
The layer above the pins:
- APBPacket: one object per transfer, with the APB field set baked in
- APBTransaction: constrained-random packet generator
- APBSequence: list-driven pattern generation with packet assembly
What matters here: - Direction-aware comparison and compact one-line formatting - Constrained randomization with a sane default profile - Ready-made patterns for bursts, alternating traffic, and stress runs - Read-modify-write flows via sequences
Factory Functions & Utilities¶
Boilerplate removers — the fastest route to a working testbench:
- Component factories: one-call creation of masters, slaves, and monitors
- Sequence factories: pre-built patterns for the common cases
- Register testing helpers: systematic register-file verification
- System integration: full testbench setup in a few lines
What matters here: - Sensible defaults on everything - Pre-configured sequences for common scenarios - Register-map-aware testing utilities - Automatic component interconnection
APB Protocol Support¶
Protocol Features¶
- APB3/APB4 Compatibility: the optional-signal binding (see
apb_components.py) is what makes an APB3 DUT and an APB4 DUT equally happy - Signal Coverage: every standard and optional APB signal
- Error Handling: PSLVERR generated by the slave, captured by master and monitor
- Protection: PPROT driven and observable, for security-sensitive tests
- Strobes: PSTRB support for partial-word writes
Supported Operations¶
- Basic Read/Write: single-register access
- Burst-Style Patterns: sequential address sweeps, as fast as APB allows — one transfer at a time
- Error Injection: slave errors and out-of-range decode errors
- Timing Stress: randomized PREADY delays and PSEL/PENABLE spacing
- Register Testing: walking patterns, field access, reset checks
Signal Mapping¶
The two ends of the bus, for reference:
| APB Master Signals | Direction | APB Slave Signals | Direction |
|---|---|---|---|
| PSEL | out | PSEL | in |
| PENABLE | out | PENABLE | in |
| PWRITE | out | PWRITE | in |
| PADDR | out | PADDR | in |
| PWDATA | out | PWDATA | in |
| PSTRB | out | PSTRB | in |
| PPROT | out | PPROT | in |
| PRDATA | in | PRDATA | out |
| PREADY | in | PREADY | out |
| PSLVERR | in | PSLVERR | out |
Design Principles¶
1. Ease of Use¶
- Factory functions get you from zero to a running testbench in a few lines
- Defaults are chosen so the common case needs no configuration
- Signal mapping and widths follow the DUT
2. Flexibility¶
- Data and address widths from 8 bits upward
- Randomization is pluggable — bring your own FlexRandomizer profiles
- Directed and constrained-random styles coexist in the same test
3. Realism¶
- The slave is memory-backed, so reads reflect actual prior writes
- Ready delays, wait states, and error rates are all configurable
- Partial writes and protection attributes behave the way the spec says they should
4. Performance¶
- Queued transactions keep the bus busy without testbench babysitting
- Low per-transaction overhead — APB's two-phase handshake will limit you long before the BFM does
- Fast packet generation for long stress runs
Usage Patterns¶
Basic Testbench Setup¶
Four factory calls and a loop — a complete APB smoke test:
import cocotb
from CocoTBFramework.components.apb.apb_factories import (
create_apb4_master, create_apb4_slave, create_apb4_monitor, create_apb4_sequence
)
@cocotb.test()
async def basic_apb_test(dut):
# Create components
master = create_apb4_master(dut, "APB_Master", "apb_", dut.clk)
slave = create_apb4_slave(dut, "APB_Slave", "apb_", dut.clk, registers=1024)
monitor = create_apb4_monitor(dut, "APB_Monitor", "apb_", dut.clk)
# Create test sequence
sequence = create_apb4_sequence(pattern="alternating", num_regs=10)
# Run test
while sequence.has_more_transactions():
packet = sequence.next()
await master.send(packet)
Directed Register Testing¶
When you know exactly which registers and which values:
from CocoTBFramework.components.apb.apb_sequence import APBSequence
# Build a directed register test sequence
register_sequence = APBSequence(
name="register_test",
pwrite_seq=[True, False] * 4, # Write, then read back
addr_seq=[0x1000 + i * 4 for i in range(4)],
data_seq=[0xA0000000 + i for i in range(4)],
strb_seq=[0xF] * 4,
)
Stress Testing¶
When you've learned to trust the block and want to stop:
# Create stress test with randomization
stress_sequence = create_apb4_sequence(
pattern="stress",
num_regs=100,
randomize_delays=True
)
# Configure timing randomization (bin ranges must be tuples, not lists)
master.set_randomizer(FlexRandomizer({
'psel': ([(0, 0), (1, 10)], [7, 1]),
'penable': ([(0, 0), (1, 5)], [8, 1])
}))
Integration with Framework¶
Shared Components Integration¶
- Memory Model: backs the slave's storage — NumPy-backed, with byte-level access
- FlexRandomizer: supplies every timing and error distribution
- Field Configuration: defines packet layouts
- Statistics & Scoreboards: plug in the same way they do in every other protocol family
Protocol Independence¶
- Built on the shared packet infrastructure, so tooling that works on one protocol works here
- Shares randomization and memory components with the rest of the framework
- Comfortable in mixed-protocol testbenches — APB for config, something faster for data, the usual arrangement
Key Features¶
Transaction Management¶
- Automatic Queuing:
send()and move on; the driver drains the queue - Timing Control: from zero-delay to randomized wait states
- Error Injection: random PSLVERR, or deterministic errors on address overflow
- Data Patterns: walking, alternating, and stress sequences
Memory Integration¶
- Memory Model: NumPy-backed storage with strobe-mask support
- Register Maps: hook your register specification in for systematic sweeps
- Access Tracking: the memory model records reads and writes for coverage
- Boundary Behavior: grow-on-overflow or error-on-overflow, your choice
Verification Support¶
- Protocol Observation: the monitor sees every completed transfer
- Error Detection: PSLVERR lands in the packet, where scoreboards can check it
- Performance Analysis: timing stamps on packets make latency math easy
Testing Capabilities¶
Functional Testing¶
- Basic read/write verification
- Register field access and modification
- Error-condition handling
- Reset and initialization flows
Stress Testing¶
- Back-to-back transactions at zero delay
- Randomized timing injection
- Throughput measurement (within APB's one-transfer-at-a-time world)
- Corner-case hunting with constrained randomization
Register Testing¶
- Walking ones/zeros patterns
- Field-level access checks
- Read-modify-write sequences
- Reset-value validation
Protocol Testing¶
- Signal timing checks via the monitor
- Error response validation
- Protection attribute coverage
- Strobe pattern coverage
Getting Started¶
Quick Setup¶
- Import the factories:
from CocoTBFramework.components.apb.apb_factories import create_apb4_master, create_apb4_slave, create_apb4_monitor - Create master and slave against the DUT's signals
- Pick a sequence — built-in pattern or your own lists
- Run it: send packets, watch the monitor, check the scoreboard
Advanced Usage¶
- Custom Randomization: build FlexRandomizer profiles for the corners you care about
- Register Integration: bring your register map and let the helpers sweep it
- Error Injection: configure the slave's error behavior deliberately, not accidentally
- Performance Analysis: use the statistics and monitoring components for numbers, not vibes
The per-module pages linked from the index carry the full API detail and worked examples. This page is the map.