Skip to content

AMBA AXI · Module 7

Burst Length, Size & Beats

The foundation of AXI data transfer — what a beat is, how burst length is AxLEN+1, how transfer size is 2^AxSIZE bytes per beat, the total-bytes formula, and the AXI3 vs AXI4 length limits.

AXI is a burst-based protocol: a single address transaction can move many data items. Module 6 introduced AxLEN and AxSIZE as signals; this module treats bursts as first-class, and it starts here with the three quantities every burst is built from — the beat, the burst length, and the transfer size. Getting these exactly right is foundational: every burst type, every per-beat address, the 4 KB rule, and narrow/unaligned handling in the rest of Module 7 are arithmetic on top of these definitions. This chapter pins down each term, the formulas that connect them, and the AXI3↔AXI4 limits.

1. The Beat — One Data Transfer

A beat is a single data transfer on a data channel — one successful VALID/READY handshake that moves up to one bus-width of data. On the write-data channel a beat is one WVALID&WREADY cycle carrying one WDATA word (with its WSTRB); on the read-data channel a beat is one RVALID&RREADY cycle carrying one RDATA word (with its RRESP). "Beat" is AXI's unit of data; a burst is just an ordered sequence of beats sharing one address transaction.

The width of a beat — how many bytes it can carry — is set by AxSIZE (Section 3), and is at most the data bus width. The number of beats is set by AxLEN (Section 2).

One address transaction maps to multiple data beats: address handshake then beat 0, beat 1, up to beat AxLEN.1 addressAW / AR handshakeBeat 02^AxSIZE bytesBeat 12^AxSIZE bytesup toBeat AxLENfinal beat (LAST)12
Figure 1 — one address transaction expands into a burst of beats. A single AW/AR address handshake is followed by AxLEN+1 data beats on the W or R channel, each beat one VALID/READY transfer of up to 2^AxSIZE bytes. The beat is AXI's unit of data; the burst is the sequence sharing one address.

2. Burst Length — AxLEN + 1

The burst length is the number of beats in the burst, and it is AxLEN + 1. AxLEN is the encoded value, offset by one so that the minimum legal burst (one beat) is encoded as AxLEN = 0:

AxLENBeats in burst
01
12
34
1516
255256 (AXI4 INCR only)

The "+1" is the single most common off-by-one in AXI: a burst of 4 beats is AxLEN = 3, not 4. The field width — and therefore the maximum length — differs by version and burst type (Section 5).

3. Transfer Size — 2^AxSIZE Bytes per Beat

AxSIZE sets the number of bytes transferred per beat, as a power of two: bytes/beat = 2^AxSIZE. It must not exceed the data bus width.

AxSIZEBytes per beat
01
12
24
38
416
532
664
7128

A beat whose AxSIZE equals the full bus width is a full-width transfer (all byte lanes usable); a smaller AxSIZE is a narrow transfer that uses only some lanes each beat (Chapter 7.7). AxSIZE is fixed for the whole burst — every beat is the same size.

burst-beats — 4-beat burst (AxLEN=3), 4 bytes/beat (AxSIZE=2)

6 cycles
A burst of four data beats D0 to D3 each transferred on a VALID/READY handshake, with LAST asserted on the fourth beat.4 beats = AxLEN(3)+1, 4 bytes each4 beats = AxLEN(3)+1, 4 byteseachbeat 0 (D0)beat 0 (D0)beat 3 (D3) — RLASTbeat 3 (D3) — RLASTaclkrvalidrreadyrdataXD0D1D2D3D3rlastt0t1t2t3t4t5
Figure 2 — burst-beats: a 4-beat INCR read burst with AxLEN=3 and AxSIZE=2 (4 bytes/beat). One address handshake yields four R beats (D0–D3), each a VALID/READY transfer; RLAST marks the fourth. Burst length = AxLEN+1 = 4; each beat carries 2^AxSIZE = 4 bytes.

4. Total Data and Why Bursts Exist

The total data a burst moves follows directly:

bytes transferred ≈ (AxLEN + 1) × 2^AxSIZE

i.e., beats × bytes-per-beat. (For INCR/WRAP the address advances across those bytes; for FIXED the same address is rewritten each beat — same byte count, different addressing, Chapter 7.2.) A full-width 64-bit bus (AxSIZE = 3, 8 bytes) doing a 16-beat burst (AxLEN = 15) moves 16 × 8 = 128 bytes from one address transaction.

That "one address transaction" is the whole point. Bursts amortize the address-phase and arbitration overhead across many beats: the manager arbitrates and issues an address once, then streams AxLEN+1 beats. This is what makes AXI efficient for memory and DMA traffic — without bursts, every data word would pay a full address handshake and arbitration round.

One arbitration and one address handshake amortize over many beats, giving high efficiency versus one address per word.thenyieldsArbitrate +address — onceStream AxLEN+1 beats× 2^AxSIZE bytesOverheadamortized → highthroughput
Figure 3 — why AXI is burst-based. A single address transaction (one arbitration, one address handshake) amortizes over AxLEN+1 beats of 2^AxSIZE bytes each. The per-transfer overhead is paid once, not per word — the basis of AXI's memory/DMA efficiency.

5. AXI3 vs AXI4 Length Limits

The maximum burst length depends on the version and the burst type:

AxLEN widthINCR maxFIXED / WRAP max
AXI34 bits16 beats16 beats
AXI48 bits256 beats16 beats

AXI4 widened AxLEN to 8 bits and raised the INCR ceiling to 256 beats, while FIXED and WRAP remain capped at 16 beats (a WRAP length must also be 2, 4, 8, or 16 — Chapter 7.4). AXI3's uniform limit was 16 beats for all types. This matters at AXI3↔AXI4 bridges: a 256-beat AXI4 INCR burst cannot pass through to an AXI3 side unchanged — it must be split into ≤16-beat bursts. (And independently of length, no burst may cross a 4 KB address boundary — Chapter 7.6.)

AXI3 all types 16 beats; AXI4 INCR 256 beats, FIXED and WRAP 16 beats.AXI3 (4-bit)all types ≤ 16 beatsAXI4 INCR≤ 256 beats (8-bit AxLEN)AXI4 FIXED / WRAP≤ 16 (WRAP ∈ 2/4/8/16)AXI4→AXI3 bridgesplit 256-beat INCR to≤1612
Figure 4 — burst-length limits by version and type. AXI3 caps all types at 16 beats (4-bit AxLEN). AXI4 widens AxLEN to 8 bits, raising INCR to 256 beats while FIXED and WRAP stay at 16 (WRAP restricted to 2/4/8/16). A long AXI4 INCR burst therefore must be split when bridged down to AXI3.

6. The Arithmetic in Code

The three quantities are worth writing down as functions, because every burst bug in §7 is one of these expressions computed wrongly. This is the address progression AMBA defines, for all three burst types.

axi_burst_math.svh — beats, bytes, and the per-beat address
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// One place for the burst arithmetic. DATA_BYTES is the data bus width in bytes.
 
function automatic int beats_in_burst(input logic [7:0] axlen);
  return int'(axlen) + 1;                       // the +1 encoding (§2)
endfunction
 
function automatic int bytes_per_beat(input logic [2:0] axsize);
  return 1 << axsize;                           // 2^AxSIZE (§3)
endfunction
 
// Per-beat address. `beat` is 0-based: beat 0 is the first transfer.
//   FIXED : every beat reuses the start address.
//   INCR  : beat 0 uses the (possibly unaligned) start address; every later
//           beat is aligned to the transfer size, per the AMBA definition.
//   WRAP  : like INCR, but the address wraps back to the container's lower
//           boundary once it reaches the upper one.
function automatic longint unsigned beat_address(
    input longint unsigned start_addr,
    input logic [7:0]     axlen,
    input logic [2:0]     axsize,
    input logic [1:0]     axburst,              // 00=FIXED 01=INCR 10=WRAP
    input int             beat
);
  int  nbytes  = bytes_per_beat(axsize);
  int  nbeats  = beats_in_burst(axlen);
  longint unsigned aligned = (start_addr / nbytes) * nbytes;
 
  case (axburst)
    2'b00: beat_address = start_addr;                      // FIXED
    2'b01: beat_address = (beat == 0) ? start_addr         // INCR
                                      : aligned + longint'(beat) * nbytes;
    2'b10: begin                                            // WRAP
      longint unsigned container = longint'(nbeats) * nbytes;
      longint unsigned lower     = (start_addr / container) * container;
      longint unsigned next      = aligned + longint'(beat) * nbytes;
      beat_address = lower + ((next - lower) % container);
    end
    default: beat_address = start_addr;                     // 2'b11 reserved
  endcase
endfunction

Two details in there are the ones people get wrong. INCR's first beat is not aligned — it uses the address the master drove, which may sit mid-word; only the subsequent beats step from the aligned base. And WRAP's container is beats × bytes_per_beat, not the bus width or the total transfer — which is exactly why WRAP lengths are restricted to 2, 4, 8 or 16 (§5): any other count would make the container a non-power-of-two and the wrap boundary would stop being a simple address mask. Where a burst may sit relative to a 4 KB page is a separate constraint entirely, developed in the 4 KB boundary rule.

The rules stated in §2–§5 are all mechanically checkable. This is a passive checker — it observes an address channel and its data channel, and never drives anything.

axi_burst_legality.sv — bind to a read or write address/data channel pair
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Passive. `DATA_BYTES` is this interface's data-bus width in bytes.
module axi_burst_legality #(parameter int DATA_BYTES = 8) (
  input logic       aclk, aresetn,
  // address channel
  input logic       axvalid, axready,
  input logic [7:0] axlen,
  input logic [2:0] axsize,
  input logic [1:0] axburst,
  // data channel (R or W)
  input logic       dvalid, dready, dlast
);
  // ---- NORMATIVE: a beat may not be wider than the bus ----
  property p_size_fits_bus;
    @(posedge aclk) disable iff (!aresetn)
      (axvalid && axready) |-> ((1 << axsize) <= DATA_BYTES);
  endproperty
 
  // ---- NORMATIVE: WRAP length must be 2, 4, 8 or 16 beats ----
  property p_wrap_length_legal;
    @(posedge aclk) disable iff (!aresetn)
      (axvalid && axready && axburst == 2'b10) |-> (axlen inside {1, 3, 7, 15});
  endproperty
 
  // ---- NORMATIVE: FIXED and WRAP are capped at 16 beats ----
  property p_fixed_wrap_max16;
    @(posedge aclk) disable iff (!aresetn)
      (axvalid && axready && axburst != 2'b01) |-> (axlen <= 15);
  endproperty
 
  // ---- NORMATIVE: AxBURST 2'b11 is reserved ----
  property p_burst_type_legal;
    @(posedge aclk) disable iff (!aresetn)
      (axvalid && axready) |-> (axburst != 2'b11);
  endproperty
 
  a_size_fits   : assert property (p_size_fits_bus)
    else $error("AxSIZE=%0d asks for %0d bytes/beat on a %0d-byte bus", axsize, 1<<axsize, DATA_BYTES);
  a_wrap_len    : assert property (p_wrap_length_legal)
    else $error("WRAP burst with AxLEN=%0d (%0d beats) - must be 2/4/8/16", axlen, axlen+1);
  a_fixed_wrap  : assert property (p_fixed_wrap_max16)
    else $error("Non-INCR burst longer than 16 beats (AxLEN=%0d)", axlen);
  a_burst_type  : assert property (p_burst_type_legal)
    else $error("AxBURST = 2'b11 is reserved");
 
  // ---- NORMATIVE: exactly AxLEN+1 beats, with LAST on the final one ----
  // A counter is needed because the property spans the whole burst.
  int expected, seen;
  always_ff @(posedge aclk or negedge aresetn) begin
    if (!aresetn) begin
      expected <= 0;
      seen     <= 0;
    end
    else begin
      if (axvalid && axready) begin
        expected <= int'(axlen) + 1;             // latch the promised beat count
        seen     <= 0;
      end
      if (dvalid && dready) begin
        if (dlast) begin
          // LAST must land on exactly the promised beat.
          a_beat_count: assert (seen + 1 == expected)
            else $error("burst ended on beat %0d but AxLEN promised %0d", seen + 1, expected);
          seen <= 0;
        end
        else begin
          // A non-LAST beat must not exceed the promised count.
          a_no_overrun: assert (seen + 1 < expected)
            else $error("beat %0d with no LAST - burst overran AxLEN+1 = %0d", seen + 1, expected);
          seen <= seen + 1;
        end
      end
    end
  end
endmodule

What each property is for, and what its failure looks like. a_size_fits catches a master that confuses AxSIZE with a byte count — driving AxSIZE=4 on a 32-bit bus asks for 16 bytes per beat from a 4-byte interface, and the message prints both numbers so the confusion is obvious on sight. a_wrap_len catches the illegal WRAP length, which otherwise produces silently wrong addresses because the wrap container is no longer a power of two. a_beat_count and a_no_overrun are the pair that catch the +1 error, and they fail in opposite directions: a master encoding "4 beats" as AxLEN=4 sends five beats, so a_no_overrun fires on the fifth; a slave that asserts LAST a beat early trips a_beat_count instead. Which one fires tells you which side made the mistake.

A caution on scope: these are the checks that follow from this chapter's quantities. They do not constitute an AXI protocol checker — handshake stability lives with the VALID/READY handshake, boundary legality with the 4 KB rule, and lane-level behaviour with narrow and unaligned transfers.

8. Proving the Arithmetic

A short self-checking bench pins the three burst types against hand-computed addresses, and confirms the checker rejects the two classic illegal cases.

tb_burst_math.sv — expected vs actual, explicit PASS/FAIL
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_burst_math;
  `include "axi_burst_math.svh"
 
  int errors = 0;
 
  task automatic chk(input longint unsigned got, exp, input string what);
    if (got !== exp) begin
      errors++;
      $error("[FAIL] %s: got 0x%0h expected 0x%0h", what, got, exp);
    end
  endtask
 
  initial begin
    // ---- INCR: 4 beats x 4 bytes from an ALIGNED start 0x1000 ----
    chk(beat_address(64'h1000, 8'd3, 3'd2, 2'b01, 0), 64'h1000, "INCR beat0");
    chk(beat_address(64'h1000, 8'd3, 3'd2, 2'b01, 3), 64'h100C, "INCR beat3");
 
    // ---- INCR from an UNALIGNED start: beat 0 keeps the odd address,
    //      later beats step from the aligned base 0x1000.
    chk(beat_address(64'h1002, 8'd3, 3'd2, 2'b01, 0), 64'h1002, "INCR unaligned beat0");
    chk(beat_address(64'h1002, 8'd3, 3'd2, 2'b01, 1), 64'h1004, "INCR unaligned beat1");
 
    // ---- FIXED: every beat reuses the start address ----
    chk(beat_address(64'h2000, 8'd3, 3'd2, 2'b00, 2), 64'h2000, "FIXED beat2");
 
    // ---- WRAP: 4 beats x 4 bytes = 16-byte container based at 0x1000.
    //      Starting at 0x1008, beats run 1008, 100C, then WRAP to 1000, 1004.
    chk(beat_address(64'h1008, 8'd3, 3'd2, 2'b10, 0), 64'h1008, "WRAP beat0");
    chk(beat_address(64'h1008, 8'd3, 3'd2, 2'b10, 1), 64'h100C, "WRAP beat1");
    chk(beat_address(64'h1008, 8'd3, 3'd2, 2'b10, 2), 64'h1000, "WRAP beat2 (wrapped)");
    chk(beat_address(64'h1008, 8'd3, 3'd2, 2'b10, 3), 64'h1004, "WRAP beat3");
 
    // ---- the quantities themselves ----
    chk(beats_in_burst(8'd0),   1,  "AxLEN=0 is ONE beat");
    chk(beats_in_burst(8'd255), 256,"AxLEN=255 is 256 beats");
    chk(bytes_per_beat(3'd3),   8,  "AxSIZE=3 is 8 bytes");
 
    if (errors == 0) $display("PASS - burst arithmetic matches the AMBA definition");
    else             $display("FAIL - %0d check(s) failed", errors);
    $finish;
  end
endmodule

The WRAP case is the one worth reading twice. A 4-beat, 4-byte WRAP burst starting at 0x1008 does not run 1008, 100C, 1010, 1014 — it runs 1008, 100C, 1000, 1004, because the 16-byte container based at 0x1000 is the whole address space this burst may touch. That is the entire point of WRAP: a cache line fills starting at the critical word and wraps to collect the rest, never leaving the line. Get the container wrong and the burst silently reads the wrong memory, which no handshake check would ever notice.

9. Common Misconceptions

10. Debugging Insight

11. Verification Insight

12. Interview Questions

13. Summary

Every AXI burst is built from three quantities. A beat is a single VALID/READY data transfer — AXI's unit of data. The burst length is AxLEN + 1 beats (the +1 offset so 1 beat = AxLEN 0; mind the off-by-one). The transfer size is 2^AxSIZE bytes per beat, constant across the burst and never exceeding the bus width. Together they move (AxLEN+1) × 2^AxSIZE bytes from a single address transaction — and that amortization of address/arbitration overhead over many beats is the entire reason AXI is burst-based and efficient for memory and DMA. The limits differ by version: AXI3 caps every type at 16 beats; AXI4 raises INCR to 256 while FIXED/WRAP stay at 16 (WRAP16).

These definitions are the arithmetic foundation for the rest of Module 7: the burst types (FIXED/INCR/WRAP), per-beat address calculation, the 4 KB boundary rule, and narrow/unaligned transfers are all computations on beats, length, and size. Debug and verify them by converting any symptom back to (AxLEN+1) beats and 2^AxSIZE bytes. Next: the first burst type, FIXED — where every beat reuses the same address.

14. What Comes Next

You've got the burst foundation; next, the three burst types, starting with FIXED:

  • 7.2 — FIXED Bursts (coming next) — the burst where every beat reuses the same address, and its FIFO/peripheral use case.
  • 7.3 — INCR Bursts (coming soon) — the incrementing workhorse for memory access.

Where these are specified. The burst quantities, the AxLEN+1 encoding, the per-beat address definitions for FIXED/INCR/WRAP and the version-dependent length limits are all defined in Arm's AMBA AXI Protocol Specification (IHI 0022). The address-progression definition in §6 is worth checking against the original once, because it is stated there more compactly than any tutorial can afford.

Previous: 6.8 — RESP & LAST Signals. Related: 6.1 — AxADDR, AxLEN & AxSIZE for the signals, and 6.2 — AxBURST for the burst-type selector. For the broader protocol catalog, see the AMBA family overview doc.