Phase 1: APB Spec & Environment Setup | APB on EDA Playground
Series AMBA 3 APB on EDA Playground

Phase 1 — Spec & Environment Setup

Week 1–2 (May 12–22) IHI 0024B §4 · §3 apb_pkg + apb_if + 6 SVA

Before writing a single line of RTL, we lock down the parameter package, define every APB signal exactly as the spec describes them, set up the SystemVerilog interface with modports, and wire in protocol-level assertions that will fire the moment something violates the spec — in every phase that follows.

01 · Setup
02 · RTL
03 · Verify
04 · Integrate
05 · Sign-off
1

What is APB and why does it matter?

The Advanced Peripheral Bus (APB) is the simplest bus in the AMBA family. Where AXI handles high-bandwidth pipelined transactions and AHB bridges the processor to memory, APB handles the last-mile job: talking to slow, low-bandwidth control registers — UARTs, GPIO banks, timer config registers, interrupt controllers.

The spec’s guiding design constraint is stated in §1.1:

SPEC §1.1

APB is optimized for minimal power consumption and reduced interface complexity. All signal transitions are related only to the rising edge of the clock. Every transfer takes at least two cycles.

Those two constraints — clock-edge alignment and 2-cycle minimum — are the root of every rule in this series. When something goes wrong in an APB design, tracing back to one of these two constraints almost always reveals the bug.

2

The 10 APB signals — Table 4-1

The entire APB interface is just 10 signals. Memorise the source of each — many bugs come from driving a signal from the wrong side.

SignalSourceDirectionDescription
PCLKClockINRising edge clocks all transfers
PRESETnSystem busINActive LOW reset — always connected to system reset
PADDRAPB bridgeOUTAddress bus, up to 32 bits
PSELxAPB bridgeOUTPer-slave select. One signal per peripheral
PENABLEAPB bridgeOUTHIGH in 2nd+ cycle (ACCESS phase)
PWRITEAPB bridgeOUTHIGH = write, LOW = read
PWDATAAPB bridgeOUTWrite data, driven when PWRITE=1
PREADYSlaveINLOW extends transfer (wait states)
PRDATASlaveINRead data, driven by slave when PWRITE=0
PSLVERRSlaveINError response. Optional — tie LOW if not used
COMMON MISTAKE

PRESETn is active LOW. Every designer wires it correctly on paper and then forgets to invert the polarity in simulation. The first thing our Phase 3 testbench checks is that the DUT is properly held in reset when PRESETn=0.

3

The 3-state machine — §3 Figure 3-1

APB has exactly three operating states. The entire bus protocol flows from this diagram. Every timing figure in Chapter 2 of the spec is just this state machine drawn on a clock grid.

IDLE
PSELx = 0
PENABLE = 0
cpu_req
SETUP
PSELx = 1
PENABLE = 0
always
ACCESS
PSELx = 1
PENABLE = 1

IDLE: default state. PSELx=0, PENABLE=0. The bus sits here until a master initiates a transfer.

SETUP: PSELx goes HIGH, PENABLE stays LOW. This is the first clock cycle of every transfer — address, write, and data signals are driven here and must be stable by the next rising edge. The bus stays in SETUP for exactly one cycle.

ACCESS: PENABLE goes HIGH. This is the second cycle. The slave can extend this by holding PREADY LOW (wait states). The transfer completes on the rising edge where PREADY=1.

KEY INSIGHT

SETUP is always exactly 1 cycle. There is no “SETUP with wait states”. Wait states only exist in the ACCESS phase, controlled by PREADY. This is why every transfer is at least 2 cycles.

4

Code walkthrough — apb_pkg.sv

The package defines all shared types, parameters, and the state encoding. It goes into the LEFT pane (design.sv) on EDA Playground.

State encoding

apb_pkg.sv — state typedef
SystemVerilog
typedef enum logic [1:0] {
  IDLE   = 2'b00,   // Default state — no transfer in progress
  SETUP  = 2'b01,   // PSELx=1, PENABLE=0  (exactly 1 cycle)
  ACCESS = 2'b10    // PSELx=1, PENABLE=1  (1+ cycles)
} apb_state_t;

Using a named enum instead of bare 2-bit logic gives you readable waveforms in EPWave — you will see SETUP and ACCESS instead of 01 and 10.

Why logic [1:0] instead of reg?

SystemVerilog’s logic type replaces both reg and wire. It can be driven by a single always_ff or assign block. Using reg in 2024 is legal but signals to the reader that you are writing Verilog, not SystemVerilog.

5

Code walkthrough — apb_if.sv

The interface bundles all 10 APB signals plus modports (which enforce direction rules at compile time) plus 6 SVA assertions that check the protocol throughout simulation.

Modport: master side

apb_if.sv — master modport
SystemVerilog
modport master_mp (
  output PADDR, PSELx, PENABLE, PWRITE, PWDATA,  // bridge drives
  input  PREADY, PRDATA, PSLVERR,                 // bridge reads
  input  PCLK, PRESETn
);

The modport makes it a compile-time error to accidentally read PADDR from the slave side or drive PREADY from the master side. This catches a whole class of wiring bugs before simulation.

The 6 SVA assertions — always-on protocol checkers

ap_penable_req_psel
PENABLE can only be HIGH when PSELx is also HIGH. PENABLE without select is meaningless.
Spec §3
ap_setup_before_access
ACCESS phase ($rose(PENABLE)) must follow a SETUP cycle: $past(PSELx)=1 and $past(PENABLE)=0.
Spec §3, Fig 3-1
ap_addr_stable
PADDR must not change while PENABLE=1 and PREADY=0 (wait states).
Spec §2.1.2
ap_pwdata_stable
PWDATA must remain stable during write wait states. Changing it mid-transfer corrupts the write.
Spec §2.1.2
ap_pslverr_window
PSLVERR is only meaningful when PSEL & PENABLE & PREADY = 1. The spec recommends driving it LOW otherwise.
Spec §2.3
ap_min_2_cycles
Every transfer must span at least 2 cycles. $rose(PSELx) must be followed by PENABLE one cycle later.
Spec §1.1
WHY ASSERTIONS FIRST

We add assertions in Phase 1, before any RTL exists, so they are active in every subsequent phase. When Phase 3 testbench accidentally creates a race condition, the assertion fires immediately with a time-stamp — no need to hunt through waveforms.

6

Running Phase 1 on EDA Playground

1

Open EDA Playground

Go to edaplayground.com and log in with Google or GitHub. Registration is free.

2

Select simulator

From the Tools & Simulators dropdown, choose Aldec Riviera-PRO. This gives full SystemVerilog + SVA support. Icarus Verilog 12 also works but won’t fire SVA assertions.

3

Paste design.sv → LEFT pane

Copy the entire phase1/design.sv file (package + interface with assertions) into the left editor panel.

4

Paste testbench.sv → RIGHT pane

Copy phase1/testbench.sv into the right panel. This drives the interface signals and exercises the SVA assertions.

5

Tick “Open EPWave after run”

Enable the checkbox at the bottom left. This opens the browser-based waveform viewer automatically when simulation finishes.

6

Click Run and check console

You should see Phase 1 PASSED - Interface & SVA OK. No [SVA FAIL] lines should appear.

7

Open EPWave — add signals

Click Get Signals → select all → Apply. Look for: PCLK, PSELx, PENABLE, PSLVERR, PRESETn. Verify PSELx goes HIGH before PENABLE.

Expected console output

EDA Playground Console
Output
SETUP phase: PSELx=1 PENABLE=0
ACCESS phase: PSELx=1 PENABLE=1 PREADY=1
Transfer complete - deasserting
Testing PSLVERR in valid window
Phase 1 PASSED - Interface & SVA OK
Open EPWave to verify signal timing
EDA PLAYGROUND NOTE

Use $dumpfile("dump.vcd") and $dumpvars(0, tb) for EPWave. Do not use $fsdbDumpfile — that is VCS/Verdi only and will cause a compile error on EDA Playground.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top