Skip to content
VLSI Mentor

DDR · Module 12

Sequential Burst

A burst does not increment an address. It visits positions inside a burst-local window and wraps within it — which is why a burst starting partway through ends by visiting columns before its own starting point.

Chapter 12.1 established the contract: how many transfers a column command moves. It said nothing about which positions those transfers visit.

This chapter answers that, and the answer is less obvious than "count upward":

Given a starting column, which column positions does a sequential burst visit, and in what order?

A burst does not increment an address. It moves through a burst-local window and wraps inside it — so a burst that starts partway through its window finishes by visiting positions before its own starting point. That wrapping is not a convenience. It is the mechanism that makes a burst structurally incapable of reaching another row.

1. The Question the Contract Left Open

A column command carries one column operand. The contract says the command will move, say, eight transfers.

Eight transfers need eight positions, and the command named one.

So something must generate the other seven, and it must generate them identically at both ends — the device produces or consumes them in some order, and the controller must agree, with nothing on the interface stating the order any more than it states the count.

That is the same structural arrangement as Chapter 12.1 §6's: two ends deriving the same thing from shared configuration, with no handshake. And it fails the same way — if the two derive different orders, every transfer after the first lands somewhere unintended, and nothing objects.

2. The Burst-Local Window

The ordering does not operate on the whole column address. It operates on a small low-order field.

This is the fact that makes everything else in the chapter follow, and it is the one most often skipped.

For a burst of N transfers, the order varies only the low log₂N bits of the column address. Every bit above that field is fixed for the entire burst — it takes the value the command's column operand supplied, and it does not change.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   column operand:   [ high column bits ][ burst-local field ]
                      └── fixed ────────┘└── varies ────────┘

   for N = 8:  the low 3 bits vary
   for N = 4:  the low 2 bits vary
   for N = 16: the low 4 bits vary

So a burst visits exactly the N positions that share those high bits — a naturally aligned block of N columns — and it visits every one of them exactly once.

This is consistent with what the device documentation describes. For a DDR4 device, vendor documentation states that the ordering of accesses within a burst is determined by the burst length, the burst type and the starting column address, with the low column address bits — CA[2:0] for an eight-transfer burst — determining which position is accessed first.

3. The Sequential Rule

The rule: add the transfer index to the starting column, discarding any carry out of the burst-local field.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   position(i)  =  ( start + i )  mod  N        ← within the low field
                   with the high column bits unchanged

Equivalently, and closer to how it is described in device material: a counter is added to the column address and carries past the burst length are ignored, so the sequence wraps back to the beginning of the block when it reaches the end.

Worked, for N = 8 — a block of eight columns, tables generated from the rule above:

StartTransfer order
00 → 1 → 2 → 3 → 4 → 5 → 6 → 7
33 → 4 → 5 → 6 → 7 → 0 → 1 → 2
66 → 7 → 0 → 1 → 2 → 3 → 4 → 5

Read the row starting at 3. The burst runs 3, 4, 5, 6, 7 — and then wraps to 0 and finishes at 2. It visits column 0 after column 7, which is a lower column than it started at, and it does so without any address decrementing.

And for N = 4, where only the low two bits vary and the third bit is fixed:

StartTransfer orderFixed bits
11 → 2 → 3 → 0block {0,1,2,3}
55 → 6 → 7 → 4block {4,5,6,7}

The second row is worth pausing on. Starting at 5 with a four-transfer burst never touches columns 0 to 3 at all — because bit 2 is above the burst-local field and stays at 1. A shorter burst does not mean a smaller step; it means a smaller window.

4. Why the Window Has a Boundary

The wrapping is usually presented as a detail. It is the opposite — it is a structural guarantee, and it connects directly to Module 9.

A column command carries no row address. Chapter 8.2 §2 derived why: the row lives in the bank's state, deposited by an earlier activate, and there is nowhere on a column command for a second row number to go.

So if a burst could carry out of its field, it would eventually carry past the column field entirely — and the positions it produced would correspond to a row the command never named and the bank may not be holding. There is no mechanism for a burst to open a row, and Chapter 9.1 established that only an activate does.

The wrap removes the question. By discarding the carry, the rule guarantees:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   every position a burst visits shares the command's high column bits
   → every position is inside the row the bank already holds
   → a burst cannot reach a row that was not activated

5. RTL — Generating the Order

The engineering problem

Given a starting column and a transfer index, produce the column that transfer visits — as a pure function, so that any consumer can ask about any transfer without replaying the ones before it.

Why hardware needs it

A controller must know which position each transfer carries, to associate data with addresses. A monitor needs the same answer in a different access pattern: it observes transfer 5 and must know what column that was, without having watched 0 through 4.

Classification

SYNTHESIZABLE EDUCATIONAL CONTROLLER RTL. Address generation, not a datapath.

What it models

The sequential burst-order mapping from a transfer index to a column position, with the burst-local field isolated structurally and the index range checked.

What it does NOT model

The transfer count's origin (Chapter 12.1, consumed as a parameter). Beat generation or timing (Modules 10, 11, 13, 14). Data. The alternative ordering ruleChapter 12.3 owns it. Address mapping (Module 8). Row state (Module 9) — the block cannot reach another row by construction, which is §4's point, but it does not model rows at all.

Interface and parameter contract

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// sequential_burst_address_gen
//
// Classification: SYNTHESIZABLE EDUCATIONAL CONTROLLER RTL (address
// generation).
//
// MODELS: the SEQUENTIAL burst-order mapping from a transfer index to a
// column position -- as a PURE FUNCTION of (start_col, xfer_index), so any
// consumer can ask about any transfer without replaying earlier ones.
//
// COMBINATIONAL BY DESIGN, NOT A SEQUENCER. Chapter 4.1's sdr_burst_engine,
// Chapter 11.3's write_beat_sequencer and Chapter 10.4's
// read_beat_collector already advance beat indices; none of them produces
// a COLUMN. A stateful advancer here would duplicate all three, and would
// force a monitor to keep a second stateful copy of the order -- which is
// Chapter 9.2's divergence hazard.
//
// IS NOT Chapter 8.2's col_operand_resolve, which extracts a column FROM A
// SYSTEM ADDRESS under an address map. This takes a column as given and
// orders positions within a burst.
//
// THE WRAP IS STRUCTURAL. Carries out of the burst-local field are
// discarded, so every generated position shares the command's high column
// bits and a burst CANNOT reach a row the command never named (Section 4).
//
// MODELS NO PHYSICAL OR ANALOG BEHAVIOUR.
// ─────────────────────────────────────────────────────────────────────────
module sequential_burst_address_gen #(
  parameter int COL_W = 10,

  // Transfers in this burst, from Chapter 12.1's contract. MUST be a power
  // of two -- see the elaboration guard for why that is a real constraint
  // rather than a convenience.
  parameter int BURST_TRANSFERS = 8,

  // DERIVED. Width of the burst-local field: the number of low column bits
  // the order varies. Every bit above this is fixed for the whole burst.
  parameter int WRAP_W = (BURST_TRANSFERS <= 1) ? 1 : $clog2(BURST_TRANSFERS),
  // Width of a transfer index, spanning 0..BURST_TRANSFERS-1.
  parameter int IDX_W  = WRAP_W
) (
  // The column the command carried. Its low WRAP_W bits are the starting
  // position within the window; its high bits fix which window.
  input  logic [COL_W-1:0] start_col,
  input  logic [IDX_W-1:0] xfer_index,

  output logic [COL_W-1:0] xfer_col,
  output logic             is_last,

  // The index names a transfer this burst does not have. Only reachable
  // when BURST_TRANSFERS is not a power of two -- which does not
  // elaborate -- so this is permanently low in every legal configuration
  // and exists so a consumer's contract is explicit.
  output logic             index_out_of_range
);

  if (COL_W < 1) begin : g_cw
    initial $fatal(1, "sequential_burst_address_gen: COL_W must be >= 1");
  end
  if (BURST_TRANSFERS < 1) begin : g_bt
    initial $fatal(1, "sequential_burst_address_gen: BURST_TRANSFERS must be >= 1");
  end
  // ── THE POWER-OF-TWO REQUIREMENT, and why it is fatal.
  //    The wrap is implemented by discarding carries out of a FIELD. A
  //    field of WRAP_W bits holds exactly 2**WRAP_W values, so a burst of
  //    some other length would either revisit positions or skip them --
  //    and the rule "ignore carries past the burst length" is only a clean
  //    modulo when the length is the field's full range. Neither outcome
  //    is repairable at runtime, so neither may elaborate.
  if (BURST_TRANSFERS != (1 << WRAP_W)) begin : g_pow
    initial $fatal(1, "sequential_burst_address_gen: BURST_TRANSFERS must be a power of two");
  end
  // The window must fit inside the column field, or the burst would need
  // bits the column does not have.
  if (WRAP_W > COL_W) begin : g_fit
    initial $fatal(1, "sequential_burst_address_gen: burst window wider than COL_W");
  end

  // ── The two halves of the column, separated structurally.
  logic [WRAP_W-1:0] start_local;
  logic [WRAP_W-1:0] next_local;

  assign start_local = start_col[WRAP_W-1:0];

  // THE RULE. Addition inside a WRAP_W-bit field: the carry out of the
  // top of this field has nowhere to go, so it is discarded by the width
  // of the expression itself rather than by an explicit mask. That is why
  // the wrap is structural -- there is no line of code that could be
  // removed to make a burst escape its window.
  assign next_local = start_local + xfer_index;

  // ── Reassembly. The high bits come from the command, unchanged.
  if (WRAP_W == COL_W) begin : g_all_local
    // The window is the whole column field: no high bits exist.
    assign xfer_col = next_local;
  end else begin : g_with_high
    assign xfer_col = {start_col[COL_W-1:WRAP_W], next_local};
  end

  assign is_last = (xfer_index == IDX_W'(BURST_TRANSFERS - 1));

  // Permanently low given the power-of-two guard above. Present so that a
  // consumer reading this port has a stated contract rather than an
  // assumption, and so the port survives if the guard is ever relaxed.
  assign index_out_of_range = 1'b0;

endmodule

State, combinational and sequential behaviour

No state, no clock, no reset. One addition inside a narrow field, one concatenation, one comparison.

The absence of a mask is the design. next_local is WRAP_W bits wide, so the carry out of the field is discarded by the expression's width. There is no masking line that could be deleted, no modulo that could be mis-parameterised — the wrap is a property of the declaration.

Bit-level derivation

At COL_W = 10, BURST_TRANSFERS = 8, so WRAP_W = 3:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   start_col = 10'b0110101_011      (high 7 bits = 0110101, local = 011 = 3)

   index 0 →  011 + 000 = 011 = 3   → 0110101_011
   index 1 →  011 + 001 = 100 = 4   → 0110101_100
   index 4 →  011 + 100 = 111 = 7   → 0110101_111
   index 5 →  011 + 101 = 000 = 0   → 0110101_000   ← carry discarded
   index 7 →  011 + 111 = 010 = 2   → 0110101_010

   The high 7 bits are identical in every row. That is Section 4.

Index 5 is the wrap. 011 + 101 is 1000 in four bits; in three it is 000. The carry is not masked away — it never existed, because the sum was computed in a three-bit field.

How to simulate, and expected output

Sweep xfer_index from 0 to BURST_TRANSFERS-1 for several starting columns and check the sequence against §3's tables. Then:

Start at a block boundary — local bits all zero. The order is 0 through 7 and no wrap occurs, which is precisely the case where a naive addr + i model also happens to be right. Testing only this configuration will not catch the bug §9 describes.

Start at the top of the window — local bits all ones. The first transfer is the last position and every subsequent transfer wraps.

Confirm the high bits are invariant across the whole sweep for every starting column. This is the property that matters most and it is one comparison.

BURST_TRANSFERS = 1 gives WRAP_W = 1 through the guard — a degenerate single-transfer burst where index 0 is also the last. Note the guard makes this a two-position window with only one transfer used, which is a stated consequence of keeping widths legal.

WRAP_W == COL_W exercises the g_all_local branch, where no high bits exist at all.

Non-power-of-two BURST_TRANSFERS must not elaborate.

Expected waveform

§6, which shows the order and the invariant high bits together.

Synthesis implications

A WRAP_W-bit adder and a concatenation — at eight transfers, a three-bit adder. The whole of burst ordering costs less than any beat counter in the curriculum, which is worth noticing: the expensive part of a burst is moving the data, not deciding where it goes.

Corner cases

BURST_TRANSFERS == 1 is legal and degenerate. Non-power-of-two does not elaborate, for the reason in the guard's comment. WRAP_W == COL_W is legal and removes the high-bit concatenation. start_col values differing only in high bits produce identical local sequences, which is correct and is the invariance the assertions check.

Failure modes and debugging clues

High bits changing across a burst means the wrap has been implemented as a full-width addition — §9's central bug. The first transfer correct and later ones wrong is the same thing seen from the data side. An order that is correct only for block-aligned starting columns is the diagnostic signature, because that is exactly when a full-width add and a field add agree.

Extension ideas

Parameterising the rule rather than fixing it turns this into Chapter 12.3's reference model — and that chapter builds it, deliberately as a verification model rather than by extending this one.

Limitations

One ordering rule. Power-of-two burst lengths only. It knows nothing about rows, banks or timing. And it produces positions, not data — whether the right data appeared at the right position is a scoreboard question that Modules 10 and 11 own.

6. The Order, in Cycles

sequential_burst_address_gen — wrapping inside the window

10 cycles
Ten cycles showing two eight-transfer bursts. The first burst starts at local column position three and visits positions three, four, five, six, seven, then wraps to zero, one and two. The high column bits shown above remain identical at every transfer, demonstrating that the burst never leaves its window. The transfer index counts zero through seven and the is-last output asserts only on index seven. A second burst then begins at local position six, and its first two transfers are six and seven before it wraps to zero.one window, eight positionsone window, eight positionswraps to 0wraps to 0last transferlast transfernew start: 6new start: 6CKxfer_index0123456701start local3333333366col local3456701267col high0x350x350x350x350x350x350x350x350x350x35is_lastt0t1t2t3t4t5t6t7t8t9
Figure 1 — Two bursts in the same window, starting at different positions. EDUCATIONAL — the ordering is the subject, the spacing implies no timing.

The col high row never changes. Not at the wrap, not between bursts, not anywhere. That invariance is §4 made visible, and it is the single most important thing on this waveform: a burst cannot leave its window, so it cannot reach a row the command never named.

Cycle 5 is the wrap. The previous transfer was position 7 — the top of the window — and the next is position 0. No address decremented and no carry propagated; the three-bit field simply rolled over.

And cycles 0 to 7 visit all eight positions exactly once. A sequential burst is a permutation of its window, not a walk through memory — which is the framing Chapter 12.3 needs in order to compare two rules that produce the same set in different orders.

EDUCATIONAL. One transfer per cycle is a drawing convenience — Chapter 12.1 §2 established that DDR moves two transfers per clock period — and no spacing here corresponds to any timing parameter.

7. Four Assertions Worth Writing

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// P1 -- THE STRUCTURAL GUARANTEE. The high column bits are never altered
// by the ordering. This is what makes a burst incapable of reaching
// another row, and it is the property a full-width adder breaks -- which
// is Section 9's bug and the one that produces plausible wrong columns.
property p_high_bits_never_change;
  @(posedge clk)
    (WRAP_W < COL_W)
      |-> (xfer_col[COL_W-1:WRAP_W] == start_col[COL_W-1:WRAP_W]);
endproperty
assert property (p_high_bits_never_change);

// P2 -- the first transfer is the starting column. Trivial to state, and
// it is the anchor every other position is relative to: an order that is
// correct in shape but starts at the wrong place is wrong everywhere.
property p_first_transfer_is_start;
  @(posedge clk)
    (xfer_index == '0) |-> (xfer_col == start_col);
endproperty
assert property (p_first_transfer_is_start);

// P3 -- the rule itself, stated over the local field. Written as modular
// arithmetic rather than by re-implementing the adder, so the property
// and the design are not the same expression twice.
property p_local_position_follows_the_rule;
  @(posedge clk)
    xfer_col[WRAP_W-1:0]
      == WRAP_W'((start_col[WRAP_W-1:0] + xfer_index) % BURST_TRANSFERS);
endproperty
assert property (p_local_position_follows_the_rule);

// P4 -- consecutive transfers advance by exactly one position, modulo the
// window. This catches an order that visits the right SET of positions in
// the wrong sequence -- which P1 to P3 would not, and which is exactly
// what Chapter 12.3's alternative rule produces.
property p_consecutive_transfers_advance_by_one;
  @(posedge clk)
    ((xfer_index == $past(xfer_index) + IDX_W'(1))
      && (start_col == $past(start_col)))
      |-> (xfer_col[WRAP_W-1:0]
             == WRAP_W'(($past(xfer_col[WRAP_W-1:0]) + 1) % BURST_TRANSFERS));
endproperty
assert property (p_consecutive_transfers_advance_by_one);

What these prove. P1 is the most valuable — it is the structural safety guarantee, and its failure is the bug that produces columns in rows the command never named. P2 anchors the sequence. P3 states the rule without re-implementing it. P4 is the one that distinguishes sequential from any other permutation of the same window, and it is the property Chapter 12.3's rule deliberately fails.

What these do not prove. Nothing here says the right data appeared at these positions — the block produces addresses and holds no data, and that comparison needs a scoreboard against a reference memory. Nothing says the transfers occurred at all, or on time; Modules 10, 11, 13 and 14 own those. Nothing says this is the rule the device is using — the block implements the sequential rule, and whether the device is configured for it is a mode-register question, which is Chapter 12.3's central verification point. And nothing proves anything physical.

8. DV — Checking Order Independently of Data

Burst order is unusually well suited to being checked on its own, and separating it from data checking is worth doing deliberately.

The reason is that order and data fail independently. A burst can visit exactly the right positions and carry wrong values; it can carry perfectly correct values in the wrong sequence. A scoreboard that compares data against expected addresses conflates them — a wrong order presents as a data mismatch, and the investigation goes to the data path.

So check the order as a set-and-sequence property:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   given a command's starting column and the contract's count:
     1. the generated positions are a PERMUTATION of the window
        → no position visited twice
        → no position skipped
     2. the FIRST position is the starting column
     3. the sequence matches the configured rule

Point 1 is the strongest and the cheapest. It does not depend on knowing which rule is in force — any legal burst order is a permutation of its window — so it catches duplicated and skipped positions even during bring-up when the configured burst type has not been established. Chapter 12.3 §8 builds on exactly this.

Two further requirements:

Check the window invariance separately. P1's property — the high column bits unchanged — is a different check from the permutation, and it catches the specific failure where a burst produces well-ordered positions that drift out of the window.

Do not derive the monitor's order from the design's generator. The same argument as Chapter 10.2 §8: a monitor sharing the design's implementation agrees with it by construction. Derive the monitor's order from the rule as specified, so a design that implements the rule incorrectly is detectable.

9. Debugging — First Word Correct, Later Words From Wrong Columns

Symptom. The first transfer of every burst carries the expected data. Later transfers carry data belonging to other columns — sometimes adjacent, sometimes far away. Bursts that happen to start at a block boundary are fine.

That last sentence is the whole diagnosis if you notice it, and it is worth checking first because it costs nothing: a fault that disappears for block-aligned starting columns is a wrap fault, because block-aligned is precisely when a wrapping add and a non-wrapping add agree.

Candidate mechanisms.

  1. The order is generated by a full-width addition rather than an addition inside the burst-local field, so the carry propagates into the high column bits — and, at the top of a row, further.
  2. WRAP_W is derived from the wrong burst length, so the window is the wrong size: too small and the burst revisits positions; too large and it skips them.
  3. The starting column is taken from the wrong place — the address map's output rather than the command's operand, or vice versa. Chapter 8.2.
  4. The monitor is applying the sequential rule while the device is configured for a different burst type. The positions are a permutation of the right window and the sequence differsChapter 12.3.
  5. The order is right and the data association is wrong — an off-by-one between positions and transfers, which is Module 10's or 11's.

Evidence to collect. The generated column for every transfer of a failing burst, not just the failing ones. The high column bits at each transfer. The starting column's local bits. The configured burst length and the derived WRAP_W. And whether the set of visited positions is a permutation of the window — that single computation separates mechanism 4 from everything else.

Discriminator.

  • Do the high column bits change across the burst? Mechanism 1, immediately. P1 catches it and its absence from the assertion set is the finding.
  • Are block-aligned starting columns correct and others wrong? Mechanism 1 again, from the other direction — and this is usually noticed first because it looks like a data-dependent fault.
  • Is any position visited twice, or skipped? Mechanism 2 — the window is the wrong size. The ratio of duplicates to the burst length tells you by how much.
  • Is the visited set correct but the sequence different? Mechanism 4, and this is the important one: the positions are right, so the window and the length are right, and only the rule differs. Nothing is broken in the address generator — the monitor and the device disagree about the configured burst type.
  • Is the order correct and the data still wrong? Mechanism 5, and the fault is in association rather than ordering. The order check has done its job by exonerating itself.

Responsible layer. Mechanisms 1 and 2 are this chapter's generator. Mechanism 3 is Module 8's. Mechanism 4 is configuration and Chapter 12.3's. Mechanism 5 is the transaction modules'. None is a device fault — the device produces its configured order, and every failure here is a disagreement about what that order is.

Fix. For mechanism 1, compute the sum in a field of WRAP_W bits so the carry cannot exist, and add P1. Do not fix it with a mask — a mask is a line that can be deleted, and the width cannot.

10. Common Misconceptions

"Sequential means increment the memory address."

Why it is tempting: "sequential" is the ordinary English word, and incrementing is what sequences do.

Concrete failure: a full-width addition that carries into the high column bits. Correct for block-aligned starting columns and wrong for every other, which makes it look like a data-dependent bug rather than an arithmetic one.

Correct model: addition inside the burst-local field, carries discarded. §3.

Prevention: P1 — the high bits never change — and computing the sum in a narrow field so no carry exists.

"A burst can naturally cross into another open row."

Why it is tempting: if it wraps at the end of a window, it feels like it should be able to continue past it.

Concrete failure: a model that produces positions in a row the command never named. Since a column command carries no row, those positions correspond to nothing the device would produce, and a checker built on the model reports the device as broken.

Correct model: the wrap is the boundary. Every position shares the command's high column bits. §4.

Prevention: P1 again, and remembering that Chapter 9.1 gives only an activate the power to open a row.

"A shorter burst takes smaller steps."

Why it is tempting: shorter and smaller feel related.

Concrete failure: a model where a four-transfer burst starting at column 5 visits 5, 6 — and then something in the 0–3 range. It does not touch those columns at all, because the bit above the two-bit window is fixed.

Correct model: a shorter burst has a smaller window, not a smaller step. §3's four-transfer table.

Prevention: compute WRAP_W from the burst length and check the fixed bits.

"Burst order is about the address map."

Why it is tempting: both concern which column an access reaches.

Concrete failure: an engineer debugging wrong columns inspects Module 8's field extraction and finds nothing, because the map correctly produced the starting column and the ordering corrupted the rest.

Correct model: the map produces the starting column from a system address; the burst order produces the remaining positions from that column. Two layers, two different bugs.

Prevention: check whether the first transfer is correct. If it is, the map is exonerated.

"A correct transfer count proves the order is correct."

Why it is tempting: the count is the obvious thing to check and the easy thing to check.

Concrete failure: eight transfers arrive, the count checker passes, and they visited five distinct positions with three duplicated. Data lands in the wrong places and nothing about the count noticed.

Correct model: count and order are independent. §8's permutation check is the one that catches this.

Prevention: check that the positions are a permutation of the window — it is cheap and rule-independent.

11. Interview Reasoning

"What does sequential burst ordering actually mean?"

Adding the transfer index to the starting column inside a burst-local field, discarding any carry out of that field. So the positions wrap within a naturally aligned block of N columns, and every bit of the column above log₂N stays exactly as the command supplied it. The important part is what it is not: it is not an increment of the memory address. A burst starting partway through its window finishes by visiting positions below where it started — and a model that uses a full-width addition is correct only for block-aligned starting columns, which makes the bug look data-dependent.

"Can a burst cross a row boundary?"

No, and the reason is structural rather than a rule being enforced. A column command carries no row address — the row lives in bank state from an earlier activate — so there is no way for a burst to name a different row. The wrap is what guarantees it: by discarding the carry out of the burst-local field, every position the burst generates shares the command's high column bits, which means every position is inside the row the bank already holds. A model that lets a burst run past its window is not a simplification; it produces positions the device would never produce.

"How would you verify burst order?"

As a set-and-sequence property, separately from data. First, and most valuable: are the visited positions a permutation of the window — nothing duplicated, nothing skipped? That check is independent of which ordering rule is in force, so it works during bring-up before the configured burst type has been established. Then: is the first position the starting column, and does the sequence match the configured rule? And check the window invariance separately — the high column bits unchanged — because that catches a well-ordered sequence that drifts out of its window, which the permutation check alone would not.

"A burst visits the right set of columns in the wrong order. What is broken?"

Very possibly nothing in the address generator. If the set is right, the window size and the starting column are both right — so the generator is producing a valid permutation of the correct window. What differs is the rule, which means the monitor and the device disagree about the configured burst type. That is a configuration or mode-register question rather than an arithmetic one, and it is why the permutation check and the sequence check should be separate: one exonerates the generator while the other localises the disagreement.

"Why is a combinational order generator preferable to a stateful one?"

Because a monitor needs random access. A monitor observes transfer 5 and must know which column that was, without having watched transfers 0 through 4 — a sequencer would have to be replayed from the start, so the monitor would need its own stateful copy, and two stateful models of one order can drift apart. A pure function of (start, index) can be queried by anyone about anything. There is also a duplication argument: the curriculum already has three blocks that advance beat indices, and none of them produces a column — adding a fourth advancer would duplicate all three while still not answering the question.

12. Engineering Exercise

COL_W = 10, BURST_TRANSFERS = 8.

1. Give WRAP_W. Which column bits vary and which are fixed?

2. Generate the full order for starting local positions 0, 2 and 7.

3. For BURST_TRANSFERS = 4 starting at local position 6, give the order and say which columns are never visited.

4. A design computes xfer_col = start_col + xfer_index at full width. For which starting columns is it correct, and what does it produce for local start 6 at index 3?

5. A monitor reports that a burst visited positions {3,4,5,6,7,0,1,2} but flagged a sequence mismatch. What is the likely cause, and what is not broken?

6. Write the property that catches a burst leaving its window, and explain why a mask is a worse fix than a narrow adder.

13. Summary

A burst does not increment an address. It adds the transfer index to the starting column inside a burst-local field, discarding the carry — so the order wraps within a naturally aligned block of N columns.

Only the low log₂N column bits vary. Every bit above them is fixed for the whole burst at the value the command supplied, which means a burst visits exactly the N positions sharing those high bits, each once.

The wrap is the boundary, and the boundary is a safety guarantee. A column command carries no row address, so a burst that could carry out of its field would produce positions in a row nobody activated. The discarded carry is what makes that impossible.

A shorter burst has a smaller window, not a smaller step. A four-transfer burst starting at position 6 visits 6, 7, 4, 5 and never touches the other block.

The set of positions is fixed by the starting column; only the order depends on the rule. A burst is a permutation of its window — which is the framing that makes the next chapter's comparison possible, and which gives verification its cheapest and most rule-independent check.

And a full-width addition is correct exactly when it does not matter. Block-aligned starts work; everything else drifts out of the window — which is why the fix is a narrow adder rather than a mask, and why the symptom looks data-dependent.

14. What Comes Next

The sequential rule produces one permutation of the window. Chapter 12.3 — Interleaved Burst is about a different one.

The same N positions, the same window, the same starting column — visited in a different sequence, produced by a different arithmetic rule. That chapter derives the rule, generates its order tables from first principles, and compares the two side by side.

And it takes seriously a question this chapter did not have to ask: which generations actually let you choose? A burst-order rule is only meaningful if something selects it, and the selection mechanism — and its availability — is generation-specific in a way that has changed. That chapter is as much about how technical assumptions age as it is about arithmetic, which is why it treats its own factual limits explicitly rather than asserting past them.


Return to Burst Length for the contract this chapter orders, Column Address for where a starting column comes from, Row Opening for why a burst must not leave its row, Burst Reads and Burst Writes for the transactions that carry these positions, and SDR SDRAM for the beat engine that counts transfers without knowing their columns.

Continue learning

Standards & specifications

Governing standard
JEDEC JESD79 (DDR SDRAM)(opens JEDEC Solid State Technology Association in a new tab)

Defines the DDR SDRAM device itself — signals, command encoding, mode registers, timing parameters and the initialisation sequence — one document per generation. Memory-controller microarchitecture, address-mapping policy, PHY training algorithms and board-level design are not specified by it.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the DDR curriculum.