AMBA APB · Module 7
PWDATA Timing
When PWDATA must be valid and who drives it — the manager's drive obligation to present it in setup and hold it byte-for-byte stable through access until the commit, the mirror of PRDATA's subordinate-owned validity.
Module 3 told you where PWDATA lives — manager-driven, captured at completion. This chapter pins the edges: the precise window during which PWDATA must be valid, who is obligated to keep it there, and the single instant the subordinate consumes it. PWDATA has one timing obligation that belongs entirely to the manager — present the value in SETUP and hold it byte-for-byte stable through every ACCESS cycle, wait states included, until the commit edge. The single idea to carry: the subordinate captures whatever is on PWDATA at the commit edge, so the value is correct only because the manager held it there. Drop it early, or change it mid-access, and the subordinate captures the wrong value — and nothing on the bus warns you.
1. Problem statement
The problem is guaranteeing that the value the subordinate samples on the commit edge is exactly the value the manager intended to write — across a bus where the manager cannot know in advance which cycle will commit.
A write has no data return leg, so there is no read-back inside the transfer to confirm what landed. The subordinate simply latches PWDATA on the one cycle the handshake completes. That creates a timing obligation: the value has to be valid and unchanging on that cycle — but the manager does not choose the cycle. A slow subordinate inserts wait states and completes later; a fast one completes on the first access cycle. The manager has no way to "aim" PWDATA at the right edge. So APB resolves it with a window, not a target:
- Present in SETUP.
PWDATAis driven from the setup cycle, so it is settled a full cycle before any capture can occur. - Hold through ACCESS.
PWDATAis held byte-for-byte stable through every access cycle — including each wait state wherePREADYis low — so the value is still valid on whichever cycle finally commits. - Capture once. The subordinate samples on exactly the completion edge —
PSEL,PENABLE,PWRITE, andPREADYall high — and never before.
The window absorbs the uncertainty. Because PWDATA is valid across the whole access phase, the same capture rule works whether the commit lands on cycle one or cycle five. The obligation to maintain that window is the manager's, and it is the entire subject of this chapter.
2. Why previous knowledge is insufficient
Module 3 — the PWDATA signal gave you the role and the half-sentence contract: "presented from setup, held through access, captured at completion." That is correct, and you should keep it. What it does not do is treat the hold as a timing obligation with an owner and a failure mode — and that is exactly what you need to drive a real manager or sign off a real write monitor. This chapter drills three things Module 3 stated but did not pin:
- The manager's drive obligation is a timing contract, not a convenience. Module 3 says the manager "holds"
PWDATA. This chapter makes that a duty with an edge: the manager must keepPWDATAvalid for every cycle from setup until the commit edge, because it cannot predict the commit cycle. Holding is not the manager being polite — it is the only way a single capture rule can be correct for every subordinate speed. - The exact valid window has a near edge and a far edge. Near edge: the setup cycle (driven, settled). Far edge: the commit edge (sampled). Between them, including every wait cycle,
PWDATAmust not move by a single bit. Module 3 named the endpoints; here we mark the band and the one capture edge on the waveform and reason about why each cycle in between must stay frozen. - The capture is "whatever is there now," so the failure mode is silent corruption. Module 3's bug was early capture (committing before completion). This chapter's bug is the mirror: correct-timed capture of a value the manager already corrupted — the manager released or changed
PWDATAbefore the commit, so the subordinate dutifully latches a wrong or partial value at the right edge. That is the deeper, write-specific hazard, and it is the mirror of a read, where the subordinate ownsPRDATAvalidity.
So the model to add is not "where the data lives" but the manager's hold-until-commit obligation and the silent corruption that follows when it breaks.
3. Mental model
The model: PWDATA is a number you write on a whiteboard and must keep your hand off until the clerk copies it down — and the clerk copies whatever the board says at the moment they look, not what you originally wrote.
You write the value the instant you start (presented in SETUP). The clerk is busy and may take a while — you do not know how long — so you must keep the board frozen, hand off, however many cycles it takes (held stable through ACCESS and every wait state). At one unpredictable instant the clerk glances up and copies the board verbatim (captured at the commit edge). If you smudged a digit, erased the top half, or started rewriting it the moment before they looked, the clerk copies that — a wrong number — and walks away satisfied. The board offered the value the whole time; the clerk consumed exactly one snapshot, and they trusted you to keep it true.
Three refinements make the timing precise:
- The far edge is unpredictable, so you hold across the whole window. You cannot aim
PWDATAat the commit cycle because the subordinate, viaPREADY, decides when that is. You guarantee the value by freezing it for every cycle it could possibly be sampled — setup through completion. - A wait state is not permission to touch the data. While
PREADYis low the access is held, not paused-for-you. The manager must holdPWDATAexactly as stable during a wait as during a ready cycle. The wait is the subordinate's, but the hold is still yours. - The capture is a verbatim snapshot. The subordinate does not validate
PWDATA, average it, or wait for it to settle — it latches the literal bus state on the commit edge. Stability is not requested; it is assumed. That is why the corruption is silent.
4. Real SoC implementation
In silicon the contract has two halves that meet at the commit edge. On the manager side, PWDATA is driven from a register loaded when the transfer is launched and held by the manager FSM — the same register output feeds the bus for setup and every access cycle, so the value physically cannot change until the FSM advances past completion. On the subordinate side, PWDATA flows combinationally to every register's data input, and a single gated write-enable clocks it on the commit edge. The correctness of the captured value is not enforced by the subordinate — it is inherited from the manager's hold.
// PWDATA timing — manager presents and HOLDS; subordinate captures the snapshot.
// The manager drives wdata_q from setup and holds it; the subordinate samples
// whatever is on PWDATA at the commit edge. Because the manager held it stable,
// the captured value EQUALS the presented value.
// --- manager side: drive from setup, hold until the FSM leaves ACCESS ---
always_ff @(posedge pclk or negedge presetn) begin
if (!presetn) wdata_q <= '0;
else if (start_transfer) wdata_q <= cpu_wdata; // load once, at launch
// NOTE: no other assignment. wdata_q is FROZEN across setup + every access
// cycle, so PWDATA cannot move while the subordinate is deciding when to commit.
end
assign pwdata = wdata_q; // held value drives the bus
// --- subordinate side: capture the snapshot on the one commit edge ---
wire write_commit = psel & penable & pwrite & pready; // the single capture edge
always_ff @(posedge pclk or negedge presetn) begin
if (!presetn) ctrl_q <= '0;
else if (write_commit && (paddr == ADDR_CTRL)) ctrl_q <= pwdata; // verbatim snapshot
end
// ctrl_q == cpu_wdata holds ONLY because pwdata was unchanged from load to commit.Two facts make the timing robust. First, the manager's wdata_q is assigned in exactly one place — at launch — so there is no RTL path that can change PWDATA mid-transfer; the hold is structural, not a discipline the FSM has to remember each cycle. Second, the subordinate's capture is a verbatim snapshot of the bus on the commit edge: ctrl_q <= pwdata. The equality "captured value equals presented value" is therefore not something the subordinate guarantees — it is a consequence of the manager holding PWDATA from load to commit. Break the hold and the same line silently latches a corrupted value. (The completion edge itself is the subject of the write completion contract; here we care only that PWDATA is valid on it.)
5. Engineering tradeoffs
Placing the entire PWDATA timing obligation on the manager — present early, hold across the whole window — is a deliberate split. Each property trades a capability APB does not need for the timing simplicity it does.
PWDATA timing property | What it gives up | What it buys | Why it is correct for APB |
|---|---|---|---|
| Presented in SETUP, a cycle before any capture | Just-in-time data delivery | A value settled well before the earliest possible commit | The subordinate never sees PWDATA mid-transition |
| Held stable through every wait cycle | Freedom to update data mid-access | A value valid on whichever cycle commits | One capture rule works at any subordinate speed |
| Hold owned by the manager (the producer) | A shared stability burden | A single, locatable owner of write-data timing | The producer of the data is the one that can hold it |
| Subordinate captures a verbatim snapshot | Subordinate-side data validation | A trivially simple capture: one gated flop | Validity is guaranteed upstream, so no checking is needed |
| Far edge (commit) chosen by the subordinate | A manager that can aim at a fixed cycle | A handshake that decouples data hold from completion timing | The manager holds a window, not a moment |
The throughline: APB pays for the manager holding PWDATA across a window it cannot predict, and in return the capture is a single unconditional snapshot that is correct at any subordinate speed. The cost lives entirely on the producer; the consumer just latches. That is the same bargain a read strikes in reverse — there the subordinate, as producer, owns PRDATA's validity, and the manager just samples.
6. Common RTL mistakes
7. Debugging scenario
A write where PWDATA was released or changed before the commit is the mirror of the "write doesn't stick" bug: here the write does stick — it just sticks the wrong value — and like all write bugs it is invisible on the bus.
8. Verification perspective
PWDATA timing is verified on two fronts: an assertion that the manager honored the hold, and a scoreboard that the captured value equals the presented value. Together they catch the corruption the bus cannot show.
- Assert the hold, edge for edge. The core property is
PWDATAstability across a held write access: while a write is in access and not yet complete,PWDATAmust not change. Written asassert property (@(posedge pclk) (psel & penable & pwrite & ~pready) |=> $stable(pwdata));, it fires the instant the manager movesPWDATAduring a wait — exactly the debug scenario, now caught automatically and at its source rather than via a downstream mismatch. A companion property can require$stable(pwdata)from the setup cycle through the commit for the whole window. - Scoreboard the snapshot against the presentation. The monitor records
PWDATAat the setup cycle aspresented_data; onwrite_commitit records the captured bus value and assertscaptured == presented. Because the reference model updatesmodel_reg[paddr] = pwdataon the commit and a later read comparesPRDATAto the model, a held-then-corrupted write surfaces as both a stability assertion failure and a read-back mismatch — two independent nets under the same bug. - Cover the timing corners. Functional coverage must hit a write with
PWDATAchanging value between back-to-back transfers (to prove the new value, not a stale one, is captured), a write whose commit lands after one wait and after several (to prove the hold survives long waits), and writes to every register (to prove the snapshot reaches the right flop). The cross of "number of wait states" with "register written" closes the gap where a long wait could letPWDATAdrift.
The point: a write monitor that checks only that PREADY rose has verified the handshake, not the data. The $stable(pwdata)-until-commit assertion is what verifies the manager's actual obligation, and the scoreboard is what proves the snapshot was the intended value.
9. Interview discussion
"When must PWDATA be valid, and whose job is it to keep it valid?" separates someone who memorized "held through access" from someone who understands the timing contract. A weak answer says "the manager drives it." A strong one names the window, the owner, and the failure mode.
Lead with the window and the owner: PWDATA is presented in SETUP and must be held byte-for-byte stable through every ACCESS cycle, wait states included, until the commit edge — and that hold is entirely the manager's obligation, because the manager cannot predict which cycle the subordinate will complete. Then give the consumer's side: the subordinate captures a verbatim snapshot on the commit edge (PSEL & PENABLE & PWRITE & PREADY), so the captured value equals the intended value only because the manager held it. Then deliver the two depth points that mark seniority: the failure mode is silent — releasing or changing PWDATA before the commit makes the subordinate latch a wrong or partial value at the correct edge, invisible on the bus and provable only by read-back or scoreboard — and it is the mirror of PRDATA, where the subordinate is the producer and owns the validity, so the same "producer owns the data's timing" rule explains both directions. Closing with "I'd bind a $stable(pwdata)-until-commit assertion to catch it at the source" signals you verify the obligation, not just the handshake.
10. Practice
- Mark the window. On a write waveform with two wait states, draw
PWDATAand shade the exact cycles it must be held stable. Mark the near edge, the far edge, and the single capture edge, and state who owns the hold on each cycle in between. - Trace the corruption. Given a waveform where
PWDATAchanges from0xA5C3to0x00C3during a wait state, state what the subordinate captures on the commit edge and why the bus shows nothing wrong. - Write the hold. From memory, write the manager-side RTL that drives
PWDATAfrom a value loaded once at launch and held until the FSM leaves access, and explain why a combinationalPWDATAsource is a latent bug. - Write the assertion. Write the
$stable(pwdata)-until-commit SVA property and explain each term, then explain why aPREADY-only check would pass on the corrupted write. - Mirror it to a read. State which side owns data-timing on a read, on which signal, and the analogous obligation — then explain in one sentence why "the producer owns the data's timing" covers both
PWDATAandPRDATA.
11. Q&A
12. Key takeaways
PWDATAhas one timing window — driven from SETUP (near edge), held byte-for-byte stable through every ACCESS cycle, and sampled on the commit edge (far edge). The whole window must stay valid because the far edge is chosen by the subordinate, not the manager.- The hold is the manager's obligation. The manager owns
PWDATA's stability from setup to commit; the subordinate only captures. A wait state holds the access but never relaxes the manager's hold. - The subordinate captures a verbatim snapshot. It latches whatever is on
PWDATAat the commit edge with no validation, so the captured value equals the intended value only because the manager held it stable. - The failure mode is silent corruption. Releasing or changing
PWDATAbefore the commit makes the subordinate latch a wrong or partial value at the correct edge — invisible on the bus, provable only by read-back or scoreboard. - Verify the hold at its source. Bind
assert property (@(posedge pclk) (psel & penable & pwrite & ~pready) |=> $stable(pwdata));and scoreboard the captured value against the value presented in setup; aPREADY-only check verifies the handshake, not the data. - It mirrors
PRDATA. The producer owns the data's timing — the manager holdsPWDATAuntil the subordinate samples it; the subordinate presentsPRDATAvalid at completion for the manager to sample. One rule covers write and read data integrity.