AMBA AHB · Module 18
Burst Wrap Error
Diagnosing a WRAP burst computing the wrong address — a wrapping burst must wrap within an aligned region of size burst_len x beat_size; the bug is the address incrementing past the boundary instead of wrapping (e.g. a WRAP4 word from 12 producing 12,16,20,24 instead of 12,0,4,8). Diagnose by computing the correct wrapped sequence from the burst type/size/start (per the spec) and comparing against the actual bus addresses. The causes — wrong wrap mask, increment without the wrap, region size not scaled by beat size, wrap at the wrong bit position — are all in the address generator. It only shows when the burst starts near the top of its region (a bottom-start hides it). The correct computation holds the region base fixed and increments only the offset modulo the region size.
The burst-testing chapter (17.8) warned about the wrong-wrap bug and how to catch it; this chapter debugs one from a waveform. A burst wrap error is a wrapping burst computing the wrong address sequence — escaping its wrap region. A WRAP burst must wrap within an aligned region whose size is burst_len × beat_size (chapter 8.4–8.8); when the incrementing address reaches the region boundary, it must wrap back to the region base. The bug is the address incrementing past the boundary instead of wrapping. The diagnosis is spec-referenced: take the burst's type, size, and start address, compute the correct wrapped sequence (per the spec), and compare it against the actual addresses on the bus. The classic example: a WRAP4 of words wraps within 16 bytes; starting at 12 it should visit 12, 0, 4, 8, but a buggy generator produces 12, 16, 20, 24 — leaving the region. The common root causes — a wrong wrap-boundary mask (region size computed wrong), increment logic without the wrap, the region size not scaled by the beat size, or the wrap applied at the wrong bit position — are all in the address generator (the master's, or a slave's burst-address logic). And crucially: this only shows when the burst starts near the top of its region (a bottom-start increments normally and hides it — 17.8). This chapter builds the diagnosis.
1. What Is It?
Burst wrap error is a wrapping burst escaping its region; debugging it means computing the spec's wrapped sequence and comparing. Its parts:
- The wrap rule — a
WRAPburst wraps within an aligned region of sizeburst_len × beat_size; at the boundary, the address wraps to the region base. - The bug — the address increments past the boundary instead of wrapping (escaping the region).
- The diagnosis — compute the correct wrapped sequence from (type, size, start) per the spec; compare against the actual bus addresses.
- The causes — wrong wrap mask, increment-without-wrap, region size not scaled by beat size, wrap at the wrong bit position — all in the address generator. Only shows on a top-of-region start.
So burst wrap error is a modular-arithmetic bug in the address generator — the wrap (a bounded increment) computed as an unbounded increment. The key to debugging it is the spec's wrap definition: the wrap region is aligned and sized burst_len × beat_size, and the address wraps within it (the high bits — the region base — stay fixed, only the low bits — the offset — increment and wrap). So you compute the correct sequence (per this definition) for the given burst (type, size, start) and compare against the actual addresses. A deviation — the address leaving the region (e.g. 12 → 16 instead of 12 → 0) — is the bug. The causes are all forms of getting the modular arithmetic wrong (the mask, the region size, the bit position). And — the key debugging insight (shared with 17.8) — the bug only manifests when the burst exercises the wrap, i.e. starts near the top of its region; a bottom-start increments normally (never reaching the boundary) and hides the bug. So burst wrap error is the modular-arithmetic bug debugged by spec-comparison, visible only at top-of-region starts. So it's a wrong-address burst bug.
2. Why Does It Exist?
Burst wrap error exists because the wrap is modular arithmetic (a bounded increment within an aligned, beat-scaled region) that's easy to get wrong (the mask, the region size, the bit position), the wrong result (escaping the region) corrupts the burst's addressing, and it hides in bottom-start traffic (only surfacing at top-of-region starts) — so it must be debugged by computing the spec's sequence.
The the wrap is error-prone modular arithmetic is the root: the wrap isn't a simple increment — it's a modular increment: the address increments by the beat size, but wraps within an aligned region whose size is burst_len × beat_size. This involves several error-prone pieces: the region size (must be burst_len × beat_size — scaled by the beat size), the alignment/mask (the region is aligned, so the base is the start with the right low bits masked), and the bit position (the wrap happens at the right boundary). Each is easy to get wrong. So burst wrap error exists because the wrap is error-prone modular arithmetic. So it's an arithmetic bug. So the math can err.
The escaping corrupts the addressing is the consequence: if the wrap is wrong — the address escapes the region (increments past the boundary) — then the burst accesses the wrong addresses: instead of wrapping back into the region, it writes/reads outside it (corrupting neighboring data, or accessing wrong locations). So the consequence is wrong-address accesses — data corruption (especially for the common use of WRAP bursts: critical-word-first cache line fills, where the wrap fetches the rest of the line — a wrong wrap fetches the wrong data). So burst wrap error matters because escaping corrupts the addressing. So it's consequential. So wrong wraps corrupt.
The it hides in bottom-start traffic is the debug subtlety: the bug only manifests when the burst exercises the wrap — i.e., the address reaches the boundary within the burst, which requires starting near the top of the region. A bottom-start burst increments through the region without ever reaching the boundary (it finishes before wrapping), so the correct and buggy generators produce the same sequence — the bug is invisible. So finding/debugging it requires top-of-region starts (or a spec-comparison that checks the wrap). So burst wrap error exists because: the wrap is error-prone modular arithmetic (region size, mask, bit position — the why); escaping the region corrupts the addressing (wrong-address accesses — data corruption, e.g. cache fills — the consequence); and it hides in bottom-start traffic (only surfacing at top-of-region starts — the subtlety). So burst wrap error is the modular-arithmetic bug in the address generator — escaping the wrap region, corrupting the addressing, hidden in bottom-starts — debugged by computing the spec's wrapped sequence and comparing (and exercised by top-of-region starts). So this chapter teaches the spec-comparison diagnosis. So compute the spec's wrap and compare.
3. Mental Model
Model debugging a burst wrap error as finding why a clock hand skips past 12 instead of wrapping to 1 — the hand should cycle within the dial (the region), but a broken mechanism lets it run off the top. A clock face is a wrapping region: after 12 comes 1, not 13. If the hand keeps incrementing past 12 (13, 14, 15...) instead of wrapping to 1, the mechanism is broken. And you only see the break if the hand is near 12 when it advances — if it's at 3 and advances to 4, everything looks fine; the break only shows at the top of the dial. To debug, you compute where the hand should be (mod 12) and compare against where it actually went.
A clock face (the wrap region) where the hand cycles within the dial: after 12 comes 1, not 13 — the hand wraps at the top of the dial back to the bottom. The dial size (12 hours) is the region size; the hand position is the address; advancing the hand is incrementing by the beat. Now, wrapping is what makes a clock a clock: the hand stays on the dial, cycling. A burst wrap error is a broken mechanism where the hand, instead of wrapping at 12 to 1, keeps incrementing past 12 — 13, 14, 15... — running off the top of the dial (escaping the region). The hand is now pointing at numbers that don't exist on the dial (addresses outside the region). Here's the debug subtlety: you only see the break if the hand is near 12 when it advances. If the hand is at 3 and advances to 4, 5, 6 — everything looks fine (it's mid-dial, far from the wrap point — like a bottom-start burst that increments without reaching the boundary). The break only shows when the hand is near the top — at 11, advancing to 12, then (correctly) to 1, or (buggily) to 13. So to catch the bug, you must watch the hand near 12 (start the burst near the top of its region). To debug it, you compute where the hand should be — (position + advance) mod 12 — and compare against where it actually went: if it should be at 1 but is at 13, the wrap mechanism is broken. And the fix is in the mechanism that advances the hand (the address generator): it must take the modulo (wrap at 12), holding the dial fixed and only cycling the position.
This captures burst-wrap-error debug: the clock face = the wrap region; the hand cycling within the dial = the address wrapping within the region; the dial size (12) = the region size (burst_len × beat_size); after 12 comes 1 = the address wrapping to the region base; the hand running past 12 to 13, 14 = the address escaping the region (the bug); only seeing the break near 12 = the bug only showing at top-of-region starts; mid-dial looking fine = a bottom-start incrementing normally (hiding it); computing (position + advance) mod 12 and comparing = computing the spec's wrapped sequence and comparing; the mechanism that advances the hand = the address generator; taking the modulo = the correct wrap arithmetic (hold the region base, wrap the offset). Compute where the hand should be mod the dial, compare, and watch it near 12.
Watch a burst wrap error on the waveform — the WRAP4 escaping its region:
Burst wrap error: WRAP4 escaping its region
4 cyclesThe model's lesson: compute where the hand should be mod the dial, compare, and watch it near 12. In the waveform, the WRAP4 burst starting at 12 (the top of its region) exercises the wrap — beat 1 should wrap to 0 but increments to 16, escaping the region. Comparing the spec's 12, 0, 4, 8 against the actual 12, 16, 20, 24 reveals the bug. The fix: the address generator must hold the region base fixed and wrap the offset.
4. Real Hardware Perspective
In debug, you identify the burst (type, size, start), compute the spec's wrapped sequence, compare against the actual addresses, and trace the deviation to the address generator's wrap arithmetic (mask/region-size/bit-position).
The identify the burst and compute the spec sequence: from the waveform, identify the burst — its type (HBURST), size (HSIZE), and start address (the NONSEQ beat's address). Compute the correct wrapped sequence per the spec: region_size = burst_len × beat_size; region_base = start & ~(region_size - 1) (aligned); each beat addr = region_base | ((offset + beat) & (region_size - 1)). This is the golden sequence. So in debug, compute the spec's wrapped sequence. So it's the reference. So that's step one.
The compare and locate the deviation: compare the actual bus addresses (each beat's HADDR) against the spec sequence. The first beat that deviates — the address escaping the region (e.g. 16 where 0 is expected) — localizes the bug. The pattern of the deviation often reveals the cause: incrementing past the boundary (region base not held) → the generator increments the full address; a wrong-sized region (wrapping at the wrong boundary) → the region size (mask) is wrong (often not scaled by the beat size — e.g. wrapping at 4 bytes instead of 16 for a WRAP4 word); the wrap at the wrong bit → the mask bit position is off. So in debug, compare and read the deviation pattern. So it's localization. So that points to the cause.
The trace to the address generator: the address generator (the master's burst-address logic, or a slave's if it computes burst addresses — e.g. a memory predicting the next beat) is the cause. Trace its wrap logic: is the region base (high bits) held fixed? Is the region size burst_len × beat_size (scaled by the beat size)? Is the wrap mask at the right bit position? The fix is the modular arithmetic (hold the base, wrap the offset, scale by the beat). And — for finding it — drive the burst from a top-of-region start (17.8). An assertion/scoreboard helps: a burst checker (17.8) computing the expected wrapped sequence and comparing catches it. So in debug, burst wrap error is a spec-comparison (identify the burst → compute the spec sequence → compare against actual → locate the deviation → trace to the generator's wrap arithmetic → fix). So in debug, compute the spec's wrap and compare. So that's the method.
5. System Architecture Perspective
At the system level, a burst wrap error is a cache-line/critical-word-first corruption (WRAP bursts' primary use), making it high-consequence (whole cache lines fetched wrong); it's the same bug as the burst-testing wrap corner (17.8) — prevented by correct wrap RTL, caught by the burst checker, and surfaced by top-of-region starts — a through-line of burst correctness.
The cache-line corruption: WRAP bursts are primarily used for critical-word-first cache line fills — the CPU requests the critical word (the one it needs) first, and the burst wraps to fetch the rest of the line. So a wrap error fetches the wrong addresses for the rest of the line — corrupting the cache line (the line contains wrong data). So at the system level, a burst wrap error is a cache-line corruption — high-consequence (the CPU executes/uses wrong data). So it's a serious bug. So wrap correctness is critical.
The same bug as the burst-testing corner: a burst wrap error is exactly the bug the burst-testing wrap corner (17.8) targets — the wrong-wrap that only shows at top-of-region starts. So it's prevented by correct wrap RTL (the modular arithmetic), caught by the burst checker (17.8 — computing the expected wrapped sequence), and surfaced by top-of-region stimulus. So the whole burst story (RTL + verification + debug) centers on this one arithmetic. So at the system level, it's a through-line of burst correctness. So it ties the burst story together.
The prevention is the verification: because it hides in bottom-starts and corrupts cache lines, the verification (top-of-region burst testing + the burst checker — 17.8) is exactly what prevents it reaching silicon. So debugging it (when it escapes) and verifying it (to prevent escape) are the same arithmetic. So at the system level, a burst wrap error is a cache-line/critical-word-first corruption (WRAP bursts' primary use — high-consequence), the same bug as the burst-testing wrap corner (17.8 — prevented by correct wrap RTL, caught by the burst checker, surfaced by top-of-region starts), and a through-line of burst correctness (the modular wrap arithmetic connects the RTL, the verification, and the debug). So a burst wrap error is where one piece of modular arithmetic — get it right or corrupt cache lines — is prevented, verified, and debugged, making the wrap computation a concentrated point of burst mastery. So get the wrap arithmetic right (and test it from the top). So the wrap is the burst's crux.
6. Engineering Tradeoffs
Debugging a burst wrap error embodies the spec-compute, compare, trace-the-arithmetic approach.
- Spec-compute vs eyeball. Computing the spec's wrapped sequence (per the definition) gives the exact golden reference; eyeballing the addresses misses subtle wrap errors. Compute the spec sequence.
- Top-of-region start vs bottom-start. Starting the burst near the top exercises the wrap (exposes the bug); a bottom-start increments (hides it). Drive (and reproduce with) top-of-region starts.
- Trace the arithmetic vs guess. Reading the deviation pattern (escaped region / wrong boundary / wrong bit) points to the specific arithmetic error (base-not-held / region-size / bit-position); guessing is slow. Read the pattern.
- Fix the modular arithmetic vs patch. Fixing the wrap arithmetic (hold the base, wrap the offset, scale by beat) is correct; patching a specific case risks other burst types/sizes. Fix the general arithmetic.
The throughline: a burst wrap error is a wrapping burst computing the wrong address — incrementing past its region boundary instead of wrapping back to the region base (escaping the aligned region of size burst_len × beat_size). Diagnose by computing the correct wrapped sequence from (type, size, start) per the spec and comparing against the actual bus addresses — the deviation (escaping the region) localizes the bug. The causes — wrong wrap mask, increment-without-wrap, region size not scaled by beat size, wrap at the wrong bit position — are all in the address generator's modular arithmetic (the fix: hold the region base fixed, increment only the offset modulo the region size). It only shows on a top-of-region start (a bottom-start hides it — 17.8). It's a cache-line/critical-word-first corruption (high-consequence), the same bug as the burst-testing wrap corner — prevented, caught, and debugged by the same wrap arithmetic.
7. Industry Example
Debug a burst wrap error corrupting cache line fills.
A CPU's cache occasionally holds wrong data — a cache line with the critical word correct but the rest of the line wrong. The cache fills use critical-word-first WRAP bursts.
- The symptom. A cache line has its critical word (the first, requested word) correct, but the other words are wrong — they're data from the wrong addresses. No hang; the scoreboard (or a memory comparison) flags the line mismatch.
- Identify the burst. The cache fill is a
WRAP4burst of words (a 16-byte line), with the critical word at the requested address — say0x...C(offset12in the line's 16-byte region0x...0–0x...F). So the burst starts at offset 12 (the top of its region) — the wrap is exercised. - Compute the spec sequence. Per the spec: region size
= 4 × 4 = 16; region base= start & ~15; the sequence is...C, ...0, ...4, ...8(wrapping from...Cback to...0— fetching the whole line). - Compare — the bug. The actual bus addresses are
...C, ...10, ...14, ...18— escaping the line's region (incrementing past...F). So beats 1–3 fetch the wrong addresses (the next line's data), corrupting the cache line. - Trace to the generator. The cache's burst-address generator increments the full address (
addr += 4) without the modular wrap — so the region base isn't held, and the address escapes. The fix: hold the region base (high bits) and wrap the offset (low bits) modulo16. - Why it escaped testing. The unit tests used bottom-start WRAP bursts (starting at the region base
...0), which increment...0, ...4, ...8, ...Cwithout reaching the boundary — hiding the bug. The real cache fills start at the critical word (often not the base), exercising the wrap. The fix to testing: top-of-region burst starts (17.8).
The example shows the cache-line consequence and the method: the WRAP4 critical-word-first fill (starting at offset 12 — exercising the wrap) escaped its region (the burst-address generator incrementing the full address), corrupting the line; the spec-comparison (...C,0,4,8 vs ...C,10,14,18) found it; the fix was the modular arithmetic; and the test gap (bottom-start only) explained the escape. This is how you debug a wrap error. This is the cache line fetched correctly.
8. Common Mistakes
9. Interview Insight
Burst wrap error is a solid debug interview topic — the spec-compute-and-compare method, the modular-arithmetic cause, and the top-of-region-start insight are the signals.
The answer that lands gives the spec-compute method and the top-of-region insight: "A burst wrap error is a wrapping burst computing the wrong address sequence — escaping its wrap region. A WRAP burst has to wrap within an aligned region whose size is the burst length times the beat size — a WRAP4 of words wraps in sixteen bytes — and when the incrementing address reaches the region boundary, it wraps back to the region base. The bug is the address incrementing past the boundary instead of wrapping, so it escapes the region. To debug it, I compute the correct wrapped sequence from the burst's type, size, and start address, per the spec, and compare it against the actual addresses on the bus. The classic example is a WRAP4 of words starting at twelve: it should visit twelve, zero, four, eight, wrapping from twelve back to zero, but a buggy generator produces twelve, sixteen, twenty, twenty-four, escaping the region. The first beat where the actual address deviates from the spec localizes the bug, and the deviation pattern points to the cause — escaping the region means the generator incremented the full address instead of holding the region base fixed; wrapping at the wrong boundary means the region size is wrong, often because it wasn't scaled by the beat size. All of these are in the address generator's wrap arithmetic — usually the master's burst-address logic. The fix is the modular arithmetic: hold the region base, the high bits, fixed, and increment only the offset, the low bits, modulo the region size. The critical debugging insight is that this only shows when the burst starts near the top of its region — a bottom-start increments through without ever reaching the boundary, so the correct and buggy sequences are identical and the bug is invisible. That's why a wrap error can pass unit tests that use bottom-start bursts but corrupt cache lines in the real system, where the critical-word-first fill starts at the requested word, which is often not the region base. So to reproduce or test it, you drive the burst from a top-of-region start." The spec-compute-and-compare method, the modular-arithmetic cause, and the top-of-region-start insight are the senior signals.
10. Practice Challenge
Build and reason from debugging a burst wrap error.
- The wrap rule. State the correct wrap behavior (aligned region of size
burst_len × beat_size, address wraps to the region base at the boundary). - Spec-compare. Explain how to diagnose by computing the spec's wrapped sequence and comparing against the actual addresses.
- Read the waveform. From Figure 2, explain how the
WRAP4from 12 escapes its region (12,16,20,24 vs 12,0,4,8) and where the check fires. - The arithmetic. Explain the correct wrap arithmetic (region base fixed, offset wraps mod region size) and the common errors (full-address increment, region size not scaled, wrong bit).
- Top-of-region. Explain why the bug only shows on a top-of-region start and the cache-line consequence.
11. Key Takeaways
- A burst wrap error = a WRAP burst escaping its region — incrementing past the boundary instead of wrapping to the region base (the aligned region of size
burst_len × beat_size). - Diagnose by computing the spec's wrapped sequence from (type, size, start) and comparing against the actual bus addresses — don't eyeball. The deviation localizes the bug.
- The cause is the address generator's wrap arithmetic — usually incrementing the full address (region base not held → escapes); or the region size not scaled by beat size, or the wrap at the wrong bit. Fix: hold the region base fixed, wrap the offset mod the region size.
- It only shows on a top-of-region start — a bottom-start increments without reaching the boundary, hiding it. Reproduce/test from the top (17.8).
- High-consequence (cache-line corruption) — WRAP bursts' primary use is critical-word-first cache line fills; a wrap error fetches the wrong addresses for the rest of the line.
- It's a through-line of burst correctness — the same modular arithmetic is in the RTL, the verification (the burst checker — 17.8), and the debug. Get the wrap right; test it from the top.
12. What Comes Next
You now can debug a wrap error. The next chapters cover the hardest failure modes (multi-master and bridge):
- Arbitration Bug (next) — diagnose lost grants, starvation, or bad handover.
- Bridge Deadlock, and the Waveform-Based Debug Methodology — the module's hardest debug and the general method.
To revisit the wrap rules, see Boundary Wrapping, Burst Address Calculation, and WRAP4 & INCR4 Bursts; for catching it in verification, see Burst Testing.