Skip to content
VLSI Mentor

DDR · Module 14

tRRD — Row-to-Row Delay

Two different banks does not mean unconstrained parallelism. tRRD spaces activates across banks, published as the greater of a cycle floor and an absolute time — with a verified value that depends on page size.

Chapter 14.6 moved column commands from bank-local to shared scope. This chapter does the same for activates, and it removes an assumption that has survived six chapters:

Two different banks does not mean unconstrained parallelism.

Activating bank 0 and activating bank 9 are operations on banks that are independent in state, whose own bank-local obligations have nothing to say about each other. And they still contend — because activating a row draws on resources the banks share.

tRRD is also the one parameter in this module where I have a fully verified real value with its complete context, including a dependence nobody expects: it varies with the device's page size.

1. The Obligation, in Five Parts

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  PARAMETER          tRRD   (DDR4: tRRD_S and tRRD_L — see §4)

  1 triggering event   ACTIVATE accepted on any bank
  2 constrained event  the NEXT ACTIVATE, to a DIFFERENT bank
  3 resource           SHARED activation resources;
                       DDR4 refines by bank group.  See §3.
  4 magnitude          the GREATER of a cycle floor and an
                       absolute time.  VERIFIED — see §4.
  5 sense              MINIMUM SEPARATION
  ─────────────────────────────────────────────────────────────────
  consequence        next ACTIVATE not before
                     prev_act_cycle + max(nCK_floor,
                                          ceil(abs_min / tCK))

Part 4 is new. Every parameter so far has had a magnitude in one unit — nanoseconds for tRCD, tRP, tRAS and tRC; cycles for tCCD. tRRD is the first in this module published both ways at once, with the greater required. Chapter 13.2 §5 introduced that form using this exact parameter; §4 completes the story.

The follow-up questions:

What re-arms it? Every accepted ACTIVATE, to any bank. Same shared-scope statement as tCCD's.

What can dominate it? tRP, for an activate following a precharge to that bank. tRC, for an activate to the same bank. And tFAW, which is a rolling window rather than a pairwise spacing and can dominate both. Chapter 14.4 §5's trace had tRRD in the applicable set and satisfied — it was never the controlling one there, which is typical for a short trace and misleading.

Cycle or absolute-time component? Both, which is the chapter.

Does generation matter? Yes — §4 labels everything DDR4 and §5 is explicit about DDR5.

2. Same Bank Against Different Bank

The fastest way to see what tRRD is for is to put it beside tRC.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  ACT bank 0  ──── tRC  ────▶  next ACT bank 0     BANK-LOCAL   (14.4)
  ACT bank 0  ──── tRRD ────▶  next ACT bank 9     SHARED       (this)

Two obligations, both ACTIVATE-to-ACTIVATE, distinguished entirely by whether the target is the same bank. And they have very different magnitudes: Chapter 14.4 §3 verified tRC at 45.75 ns for a DDR4-3200 grade, while §4 below verifies tRRD_S at a few nanoseconds. Activating a different bank is far cheaper than recycling the same one — which is the entire architectural argument for having many banks.

But cheaper is not free, and the reason is worth getting right.

The scope consequence is Chapter 14.6's, repeated for activates. A per-bank countdown cannot express this obligation: bank 9's counter has never been told about bank 0. It is the same category error, with the same fast and wrong failure and the same signature — single-bank tests pass, and the violation rate rises with bank parallelism.

3. The Bank-Group Refinement

Chapter 14.6 §3 established the one topology fact this module asserts: DDR4 organises banks into groups, and accesses in different groups can be spaced more closely than accesses in the same group.

That refinement applies to activates exactly as it applies to column commands, giving two requirements:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  different bank group  →  the SHORTER requirement   (tRRD_S)
  same bank group       →  the LONGER  requirement   (tRRD_L)

So a candidate ACTIVATE to a different bank is subject to one of two magnitudes, selected by a property of the pair — the same pair-dependent shape Chapter 14.6 §4 introduced.

And the same architectural lever follows: steering consecutive activates into different bank groups pays the shorter spacing. For a workload that activates rows frequently — a miss-heavy one — that is a direct throughput difference arising purely from how addresses map onto banks, which is Module 18's subject.

How a dual-term activate-spacing specification is resolved and enforced. The device's table supplies two terms for each bank-group class: a cycle floor that is fixed in clock cycles and an absolute minimum fixed in picoseconds. The resolver divides the absolute term by the clock period, rounding up, and takes the greater of that result and the cycle floor, producing one integer magnitude per class and reporting which term governed. Those two magnitudes are handed to the bank-group spacer, which holds the countdowns and enforces them. A candidate activate to a different bank selects the shorter magnitude when the two commands fall in different bank groups and the longer magnitude when they fall in the same group, and the spacer returns the verdict.Device tableResolverGroup spacerVerdict4 nCK floor + absps, per classcycles_S, cycles_Lwhich term governseachsame group -> longerdiff group ->shorter

4. The Verified Value, With Its Full Context

This is the chapter's centrepiece, because it is the one place in this module where I can give a real number with everything needed to make it meaningful.

5. DDR5 — Not Established Here

6. The Crossover — Where the Two Terms Trade Places

Now the arithmetic that makes §4's dual-term form interesting rather than merely unusual.

Resolve the DDR4-2400, 1KB figure — the greater of 4 nCK or 3.3 ns — at several clock periods. Hold the absolute term fixed to isolate the conversion, exactly as Chapter 13.2 §8 did, and note as that chapter did that a real speed-grade table adjusts the absolute term too:

Data ratetCKceil(3.3 / tCK)cycle floormaxGoverned by
DDR4-16001.250 ns344cycle floor
DDR4-24000.8333 ns444tie
DDR4-29330.6819 ns545absolute
DDR4-32000.625 ns646absolute

The crossover sits at DDR4-2400, where the two terms tie at 4 cycles — which is almost certainly not a coincidence, given that 3.3 ns is the DDR4-2400 figure.

That is a genuinely useful thing to have learned from verified data: the dual-term form plus a per-grade absolute value is how a specification keeps a physical requirement at a roughly constant cycle cost across a device family.

7. RTL — Resolving Two Group Classes, and Reusing What Exists

Collision check. Chapter 4.5's bank_group_spacer implements group-scoped activate spacing with per-group countdowns and distinct stall reasons. Chapter 13.2's timing_spec_resolver resolves one max(nCK, ns) specification and reports which term governs. Chapter 14.6's column_turnaround_matrix selects a magnitude from a pair-dependent table.

Between them, the enforcement is already built. bank_group_spacer is the right block for holding the spacing, and this chapter reuses it rather than building a third group-scoped countdown.

What is not built is the thing §6 just did by hand: resolving two dual-term specifications and comparing their crossovers. timing_spec_resolver handles one specification. tRRD needs two — same-group and different-group — and the interesting output is not either resolved value but the pair, plus which term governs each.

The engineering problem. Resolve both group classes' dual-term specifications at the current clock period, report both magnitudes for bank_group_spacer to consume, and report which term governs each so an architect can answer the faster-bin question.

Classification: configuration-time arithmetic, expressed as combinational RTL. The same honest classification Chapter 13.2 §7 gave its resolver, and for the same reason: in a real controller this runs once per frequency change, in firmware.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────
//  activate_spacing_resolver
//
//  CLASSIFICATION
//    Configuration-time arithmetic, expressed as combinational RTL.
//    Pure function of tck_ps. No clock, no state, no timekeeping.
//
//  WHAT IT MODELS
//    §6's resolution, for BOTH DDR4 bank-group classes at once:
//      cycles_S = max(FLOOR_S_NCK, ceil(ABS_S_PS / tCK))
//      cycles_L = max(FLOOR_L_NCK, ceil(ABS_L_PS / tCK))
//    plus, for each, WHICH term governs -- which is the output an
//    architect actually wants, because it predicts whether the
//    constraint worsens in a faster speed bin.
//
//  WHAT IT DOES NOT MODEL
//    Any physical process. ABS_*_PS are numbers from a vendor table;
//    this block has no idea what circuitry they describe. It also does
//    NOT enforce anything -- Chapter 4.5's bank_group_spacer holds the
//    countdowns and this block only supplies its magnitudes.
//
//  RELATIONSHIP TO EXISTING RTL
//    This is a FEEDER for bank_group_spacer, not a replacement. It is
//    also two instances' worth of Chapter 13.2's timing_spec_resolver
//    logic brought together so the two classes can be COMPARED -- the
//    comparison is the new part, and a design could equally
//    instantiate that resolver twice and compare outside. Doing it in
//    one block makes the ORDERING invariant checkable; see §8's P3.
//
//  UNITS -- stated once, obeyed everywhere
//    ABS_*_PS and tck_ps are PICOSECONDS.
//    FLOOR_*_NCK and the outputs are CK CYCLES.
//    tck_ps is the CK PERIOD, not a data-rate interval. Chapter 13.2
//    §12 covers the cost of that confusion: every obligation wrong by
//    a factor of two.
//
//  PAGE SIZE
//    §4 verified that the absolute term depends on the device's page
//    size -- 3.3 ns at 1KB versus 5.3 ns at 2KB for DDR4-2400. That is
//    why ABS_*_PS are PARAMETERS to be programmed from the specific
//    device's table and not constants baked in here.
// ─────────────────────────────────────────────────────────────────────
module activate_spacing_resolver #(
  // DIFFERENT bank group -- DDR4's "_S". Verified form: greater of a
  // cycle floor and an absolute time (§4).
  parameter int FLOOR_S_NCK = 4,
  parameter int ABS_S_PS    = 3300,
  // SAME bank group -- DDR4's "_L". Longer by construction.
  parameter int FLOOR_L_NCK = 4,
  parameter int ABS_L_PS    = 6000,
  parameter int TCK_PS_W    = 16,
  parameter int CYC_W       = 8
) (
  input  logic [TCK_PS_W-1:0] tck_ps,

  // ── Magnitudes for bank_group_spacer to enforce.
  output logic [CYC_W-1:0]    cycles_diff_group,
  output logic [CYC_W-1:0]    cycles_same_group,

  // ── Which term governs each class. High = the absolute term won, so
  //    that class is PHYSICS-LIMITED at this frequency and its cycle
  //    count RISES if the clock rises. §6's architect question.
  output logic                diff_abs_governs,
  output logic                same_abs_governs,

  // ── Invariant check, published rather than assumed: the same-group
  //    requirement must not resolve shorter than the different-group
  //    one. A violation here means the programmed table is wrong.
  output logic                ordering_violation,

  output logic                tck_invalid,
  output logic                overflow
);

  // ── Elaboration guards.
  if ((FLOOR_S_NCK < 0) || (FLOOR_L_NCK < 0)) begin : g_floor
    initial $fatal(1, "activate_spacing_resolver: floors must be >= 0");
  end
  if ((ABS_S_PS < 0) || (ABS_L_PS < 0)) begin : g_abs
    initial $fatal(1, "activate_spacing_resolver: abs terms must be >= 0");
  end
  // A class with neither term constrains nothing -- almost certainly a
  // wiring mistake, so refused loudly rather than resolving to zero.
  if ((FLOOR_S_NCK == 0) && (ABS_S_PS == 0)) begin : g_empty_s
    initial $fatal(1, "activate_spacing_resolver: _S has no terms");
  end
  if ((FLOOR_L_NCK == 0) && (ABS_L_PS == 0)) begin : g_empty_l
    initial $fatal(1, "activate_spacing_resolver: _L has no terms");
  end
  // CYC_W bounded so the overflow detector cannot itself overflow --
  // the same structural guard Chapter 13.2 §7 used.
  if ((CYC_W < 1) || (CYC_W > 30)) begin : g_cyc
    initial $fatal(1, "activate_spacing_resolver: CYC_W must be 1..30");
  end
  if (TCK_PS_W < 1) begin : g_tck
    initial $fatal(1, "activate_spacing_resolver: TCK_PS_W must be >= 1");
  end

  localparam int MAX_CYCLES = (1 << CYC_W) - 1;

  int unsigned tck_u;
  int unsigned abs_s_cyc, abs_l_cyc;
  int unsigned req_s, req_l;

  always_comb begin
    tck_u       = 32'(tck_ps);
    tck_invalid = (tck_u == 32'd0);

    // ── §6's integer ceiling, twice. ceil(a/b) == (a + b - 1) / b,
    //    guarded against the zero divisor. An ABS term of 0 yields 0
    //    for any b >= 1, which is correct: no absolute component
    //    contributes no absolute-derived cycles.
    if (tck_invalid) begin
      abs_s_cyc = 32'd0;
      abs_l_cyc = 32'd0;
    end else begin
      abs_s_cyc = (32'(ABS_S_PS) + tck_u - 32'd1) / tck_u;
      abs_l_cyc = (32'(ABS_L_PS) + tck_u - 32'd1) / tck_u;
    end

    // ── The max, per class, and which term won. STRICT comparison, so
    //    a tie reports the floor as governing -- which is the
    //    conservative reading of §6's crossover and matches Chapter
    //    13.2 §7's convention exactly.
    req_s            = (abs_s_cyc > 32'(FLOOR_S_NCK)) ? abs_s_cyc
                                                      : 32'(FLOOR_S_NCK);
    diff_abs_governs = (abs_s_cyc > 32'(FLOOR_S_NCK));

    req_l            = (abs_l_cyc > 32'(FLOOR_L_NCK)) ? abs_l_cyc
                                                      : 32'(FLOOR_L_NCK);
    same_abs_governs = (abs_l_cyc > 32'(FLOOR_L_NCK));

    // ── Range check then saturate. Saturation is the safe failure:
    //    too long is slow, too short violates the contract.
    overflow = (req_s > 32'(MAX_CYCLES)) || (req_l > 32'(MAX_CYCLES));

    cycles_diff_group = (req_s > 32'(MAX_CYCLES)) ? CYC_W'(MAX_CYCLES)
                                                  : CYC_W'(req_s);
    cycles_same_group = (req_l > 32'(MAX_CYCLES)) ? CYC_W'(MAX_CYCLES)
                                                  : CYC_W'(req_l);

    // ── The invariant. Reported, not enforced: silently clamping a
    //    bad table would hide a configuration error.
    ordering_violation = !tck_invalid
                       && (cycles_same_group < cycles_diff_group);
  end

endmodule

Interface contract. Two magnitudes out, for Chapter 4.5's bank_group_spacer to consume as its DIFF_GAP and SAME_GAP. This block enforces nothing and holds no obligation; naming the outputs cycles_* rather than *_ok says so.

Parameter contract. ABS_S_PS and ABS_L_PS are parameters because §4 verified they depend on page size — 3.3 ns at 1KB against 5.3 ns at 2KB for the same speed grade. A block with these baked in would be wrong on half the parts in a family. CYC_W is bounded at 30 so 1 << CYC_W stays inside a signed 32-bit int.

Why the casts are safe. CYC_W'(MAX_CYCLES) is exact by construction. CYC_W'(req_s) and CYC_W'(req_l) are each reached only on the false branch of their own range test — the comparison guards the cast immediately above it, which is the pattern Chapter 13.2 §7 established.

Corner cases. tck_ps == 0: refused via tck_invalid, and both absolute terms contribute nothing, so the outputs degenerate to the floors — which a consumer must not trust, hence the flag. An absolute term of 0: that class is always floor-governed at every frequency. A floor of 0: always absolute-governed whenever the absolute term yields anything. Exact tie: reports floor-governed, per the strict comparison — and §6 showed the real DDR4-3200 figure sits exactly there, so this is not a rare case. ABS_L_PS < ABS_S_PS: a bad table, reported on ordering_violation rather than clamped.

Synthesis implications. Two integer divisions by a runtime value, which is the whole cost and the reason this is configuration-time arithmetic. Chapter 13.2 §7 covered the options: firmware, a lookup table over supported periods, or a pipelined divider. The comparisons and saturation are trivial.

Failure modes. Truncating division instead of the ceiling: under-waits by one cycle at every frequency where the division is inexact, which is most but not all of them — so a single-frequency test cannot find it. Using >= for the governs flags: misreports the tie, which §6 showed is exactly where the real DDR4-3200 value sits, so this error would be visible in practice rather than theoretical. Baking the absolute terms in as localparams: wrong on a different page size. Passing a data-rate interval as tck_ps: every magnitude wrong by a factor of two, and undetectable from inside the block.

8. Four Assertions Worth Writing

Where these live. This block is combinational with no clk port, so the properties belong in a testbench or bind unit sampled on the environment's clock — Chapter 13.2 §9 developed what that costs and why it is acceptable for configuration-time arithmetic.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ── Sampled on the ENVIRONMENT's clock: this block has none.
//
// ── P1. Each resolved magnitude covers its own cycle floor. The
//    safety property: a resolver that under-reports produces a design
//    that violates the contract everywhere at once.
property p_covers_floors;
  @(posedge clk) disable iff (!rst_n)
    !tck_invalid |-> ( ( (cycles_diff_group >= CYC_W'(FLOOR_S_NCK))
                      && (cycles_same_group >= CYC_W'(FLOOR_L_NCK)) )
                    or overflow );
endproperty
a_covers_floors: assert property (p_covers_floors);

// ── P2. Each conversion is a genuine ceiling, checked against the
//    DEFINITION rather than against the implementation's own formula.
//    ceil(a/b) = c means c*b >= a and (c-1)*b < a. Re-deriving the
//    RTL's expression would prove only that it equals itself.
//    Catches truncation, round-to-nearest, and an off-by-one in the
//    +b-1 term. Written for the _S class; the _L twin is identical.
property p_ceiling_is_a_ceiling_s;
  @(posedge clk) disable iff (!rst_n)
    (!tck_invalid && !overflow && (ABS_S_PS > 0) && diff_abs_governs) |->
      (  (32'(cycles_diff_group) * 32'(tck_ps) >= 32'(ABS_S_PS))
      && ((32'(cycles_diff_group) - 32'd1) * 32'(tck_ps) < 32'(ABS_S_PS)) );
endproperty
a_ceiling_is_a_ceiling_s: assert property (p_ceiling_is_a_ceiling_s);

// ── P3. The governs flags agree with the arithmetic, including the
//    TIE. §6 showed the real DDR4-3200 figure lands exactly on the
//    tie, so a >= / > confusion here is a bug that shows up on a real
//    part rather than only in theory.
property p_governs_flags_consistent;
  @(posedge clk) disable iff (!rst_n)
    (!tck_invalid && !overflow) |->
      ( ( diff_abs_governs
            ? (cycles_diff_group >  CYC_W'(FLOOR_S_NCK))
            : (cycles_diff_group == CYC_W'(FLOOR_S_NCK)) )
     && ( same_abs_governs
            ? (cycles_same_group >  CYC_W'(FLOOR_L_NCK))
            : (cycles_same_group == CYC_W'(FLOOR_L_NCK)) ) );
endproperty
a_governs_flags_consistent: assert property (p_governs_flags_consistent);

// ── P4. The CONFIGURATION invariant: same-group must not resolve
//    shorter than different-group, at any frequency. Not a property of
//    the logic -- the logic works for any table -- but a mis-programmed
//    table produces violations that look like logic bugs, and catching
//    it where the configuration arrives is far cheaper. Chapters 14.3
//    §7 and 14.6 §9 made the same argument.
property p_same_group_not_shorter;
  @(posedge clk) disable iff (!rst_n)
    !tck_invalid |-> !ordering_violation;
endproperty
a_same_group_not_shorter: assert property (p_same_group_not_shorter);

What these prove. That both magnitudes cover their floors; that the conversions are genuine ceilings, checked against the mathematical definition; that the governing-term flags agree with the arithmetic including at the tie; and that the programmed table respects _L >= _S.

What these do not prove. That the programmed values are the right ones for the device — §4's figures are speed-grade and page-size specific, and no property can see that the table entry matches the part. That tck_ps is a CK period rather than a data-rate interval: the block cannot see what the number means, and Chapter 13.2 §9 established that no block-level property can catch a units error at its own boundary. And nothing about enforcement — these magnitudes feed bank_group_spacer, whose own properties cover whether the countdowns honour them.

Vacuity. P2 requires ABS_S_PS > 0 and diff_abs_governs, so it says nothing at frequencies below the crossover — which is most of the interesting range for a floor-governed parameter. Sweep tck_ps across the crossover and cover both sides, or P2 passes having checked nothing.

9. The Two Classes, Across Frequency

activate_spacing_resolver — two classes, two crossovers

10 cycles
Ten observation points sweeping the clock period from twelve hundred and fifty picoseconds down to six hundred and twenty-five picoseconds, with both bank-group classes resolved at each point. The different-group class has a cycle floor of four and an absolute term of thirty-three hundred picoseconds, so it resolves to four cycles while the floor governs and rises to five and then six as the absolute term takes over above the crossover. The same-group class has the same floor of four but a longer absolute term of six thousand picoseconds, so its absolute term governs from the very first point and its resolved value rises from five through ten across the sweep. The two classes therefore cross over at different frequencies, and the same-group requirement is always at least the different-group one._S floor-governed_S floor-governed_S physics-governed_S physics-governed_S tie at DDR4-2400 — floor wins_S tie at DDR4-2400 — floorwins_S crossover: absolute takes over_S crossover: absolutetakes over_S = 6, _L = 10 cycles_S = 6, _L = 10 cyclesCKtck_ps12501250833833750750682682625625data rate1600160024002400266626662933293332003200_S abs cyc3344555566_S result4444555566_S abs gov_L abs cyc558888991010_L result558888991010_L abs govt0t1t2t3t4t5t6t7t8t9

Three observations.

The _S class crosses over and the _L class never does. With a 6.0 ns absolute term against a 4 nCK floor, the absolute term governs at every frequency in the sweep. The two classes are on opposite sides of the structure-versus-physics question at DDR4-1600 and the same side at DDR4-3200 — which is why the block resolves and reports them separately rather than assuming they behave alike.

The tie at DDR4-2400 reports floor-governed, per §7's strict comparison. §6 showed the real DDR4-3200 figure of 2.5 ns also lands on a tie, so this is a configuration a real part actually occupies.

The gap between the classes widens with frequency — 1 cycle at DDR4-1600, 4 cycles at DDR4-3200. So the throughput cost of concentrating activates into one bank group grows on faster parts, which makes Module 18's address mapping more important rather than less as speeds rise.

10. DV — Independent Reconstruction

Sweep, do not sample. The block is combinational, so a sweep costs nothing but loop iterations. The likeliest bug — a truncating division — is invisible at every frequency where the division happens to be exact, and §6's table contains two such points.

Search rather than recompute. A checker computing (abs + tck - 1) / tck proves the RTL contains that expression. A checker finding the smallest c with c * tck >= abs by counting upward proves it computes a ceiling. The second is slower and correct, and in a combinational sweep slowness is free — Chapter 13.2 §10's representation-inversion principle in miniature.

Hunt both crossovers deliberately. Each class has its own, at a different frequency. Test the two periods either side of each and the exact tie.

Resolve from the device's table, per page size. §4's page-size dependence is the tRRD-specific verification obligation: a checker programmed with the 1KB absolute term while the design is configured for a 2KB part agrees with nothing useful. The page size must come from the device configuration, not from a default.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  TIMING VIOLATION
    command        : ACTIVATE, bank 9  (bank group 2)
    issued at      : cycle 204
    resource       : SHARED activation path
    previous       : ACTIVATE bank 1 (bank group 2), cycle 201
    relationship   : SAME bank group
    selected       : tRRD_L                    CONTROLLING
    requirement    : max(4 nCK, 6.0 ns / 0.625 ns = 10) = 10 cycles
      governed by  : absolute term
    legal from     : cycle 211
    short by       : 7 cycles
    note           : different bank group would have selected tRRD_S
                     = max(4, ceil(2.5/0.625) = 4) = 4 cycles, legal
                     at cycle 205

Two lines earn their place here. The requirement line shows both terms and which governed, so a reader can check the resolution without leaving the report — and can see immediately whether a faster part would make it worse. The note gives Chapter 14.6 §10's counterfactual, which for activates is the difference between 10 cycles and 4.

11. Debugging

Symptom. Activates violate spacing, or activate throughput is below model.

Candidate mechanismEvidenceDiscriminator
Per-bank state for a shared obligationSingle-bank passes; violations rise with bank parallelismOne-bank against all-bank traffic. Chapter 14.6 §11's discriminator, unchanged.
_S selected where _L belongsViolations only on same-bank-group activate pairsThe violating pairs' groups. §10's report names the selection.
Only the cycle floor enforcedCorrect at low data rates; violations at high ones§6's crossover. A design enforcing 4 nCK and ignoring the absolute term is right below the crossover and wrong above it — which means it passes on the slow part it was brought up on.
Only the absolute term enforcedViolations at low data ratesThe mirror, and the counter-intuitive one: below the crossover the floor is the larger term, so ignoring it under-waits.
Wrong page size in the tableRequirement short by the 1KB-versus-2KB difference§4. Check the configured page size against the part.
Truncating divisionOff by one at frequencies where the division is inexact§10's search-based check.
ns-for-nCK confusionEvery magnitude wrong by roughly 1/tCKCompare the resolved value against §6's table by hand.
tFAW ignoredViolations only in bursts of four or more activatesChapter 14.8. A different constraint class entirely.

The discriminator unique to this chapter is which side of the crossover the failure appears on. A design enforcing only the cycle floor is correct below the crossover and wrong above; one enforcing only the absolute term is wrong below and correct above. So “it worked on the slower part” is diagnostic information rather than a puzzle — it says the floor was enforced and the absolute term was not, which is by far the more common omission because the floor is the simpler number to find.

Responsible layer. If both terms are resolved correctly and activate throughput is still short, look at whether activates are concentrating into one bank group — §9 showed that costs 4 cycles against 10 at DDR4-3200 — or at whether tFAW is the actual limiter, which the next chapter shows is common for activate-heavy traffic.

12. Common Misconceptions

“tRRD only matters when activating the same bank.” Tempting because the name pairs “row” with “row” and same-bank activation is the obvious conflict. Why it is wrong: the same-bank case is tRC's. tRRD is specifically the cross-bank obligation. Consequence: a controller that applies it per bank leaves cross-bank activates unconstrained — which is the traffic tRRD exists for. Replacement model: tRC for same bank, tRRD for different banks, at different scopes with very different magnitudes. Debugging clue: violations on activates to banks that had never been activated.

“If two banks are different, activating both is unconstrained.” Tempting because bank independence is DDR's selling point and six chapters of bank-local obligations reinforced it. Why it is wrong: §2 — activating a row engages shared resources, and the verified absolute-time component is the evidence. Consequence: back-to-back cross-bank activates violating spacing, with a rate that rises with parallelism. Replacement model: independent in state, contending in activation resources. Debugging clue: single-bank tests pass.

“If the nCK term passes, the absolute-time term can be ignored.” Tempting because the cycle floor is the easier number to find and enforce, and below the crossover it genuinely is the binding one. Why it is wrong: §6 — above the crossover the absolute term is larger, and it is larger on exactly the fast parts people care about. Consequence: a design correct at DDR4-2400 and violating at DDR4-3200, which is the worst possible distribution because bring-up often happens on the slower bin. Replacement model: resolve both terms and take the greater, every time. Debugging clue: “it worked on the slower part.”

“A timing table for one speed bin is universal.” Tempting because the parameter names and the cycle floors really are stable across a family. Why it is wrong: §4 verified the absolute term shrinking across grades — 3.3, 3.0, 2.5 ns — and varying with page size, 3.3 against 5.3 ns at one grade. Consequence: a controller configured from the wrong row of the table, short by the difference. Replacement model: a value needs its generation, speed grade and page size attached before it is a fact. Debugging clue: correct on one part number and wrong on another with identical nominal speed.

_S and _L exist in every DDR generation.” Tempting because the naming is everywhere in DDR4 material. Why it is wrong: §5 — DDR4-era naming for a DDR4 mechanism, and I could not confirm DDR5's. Consequence: a port assuming identical semantics. Replacement model: verify per generation. Debugging clue: a port that works except on one class of pattern.

“tFAW is just a longer tRRD.” Tempting because both constrain activates and tFAW's magnitude is larger. Why it is wrong: tRRD is pairwise — it relates a candidate to one prior activate. tFAW is a rolling window relating it to a history of several. Chapter 13.3 §2's class D against class A. Consequence: implementing tFAW as a single countdown, which cannot express a density limit — Chapter 14.8 is entirely about this. Replacement model: different constraint classes needing different state. Debugging clue: violations only in bursts of four or more activates, never in pairs.

13. Interview Reasoning

“What does tRRD constrain, and how is it different from tRC?” Both are activate-to-activate minimums, distinguished by scope: tRC is bank-local and governs recycling the same bank, while tRRD is shared and governs activating a different one. The magnitudes reflect that — tRC verified at 45.75 ns for a DDR4-3200 grade against tRRD_S at a few nanoseconds — which is the quantitative form of the argument for having many banks. The trap is applying tRRD per bank, which leaves the cross-bank traffic it exists for unconstrained.

“Why do activates to different banks contend at all?” Because an activate drives a wordline and starts sensing across a whole row, which engages circuitry the banks share. The strongest evidence is in the specification rather than in speculation about internals: the requirement has an absolute-time component, which is the signature of a physical cause, and it depends on page size — 3.3 ns at 1KB against 5.3 ns at 2KB for DDR4-2400. A purely structural requirement would not vary with how much array a row spans.

“tRRD_S is the greater of 4 nCK or 3.3 ns. Why both terms?” Because the two scale oppositely with frequency. The cycle floor is a structural requirement that stays 4 cycles at any clock; the absolute term is physical and costs more cycles as the clock rises. Specifying both and requiring the greater covers the whole operating range. And the verified figures show what the form is for: the absolute term shrinks across grades — 3.3 at DDR4-2400, 2.5 at DDR4-3200 — which keeps the resolved requirement near 4 cycles across the family instead of letting it grow.

“A design enforces only the 4 nCK floor. When does it fail?” Above the crossover, where the absolute term resolves larger than 4. At DDR4-2400 with 3.3 ns the two tie at 4, so the design is correct; at a grade where the absolute term resolves to 5 or 6 it under-waits. The uncomfortable part is the distribution: it passes on the slower bin, which is often where bring-up happens, and fails on the faster one. So “it worked on the slower part” is a diagnosis rather than a mystery.

“How does bank-group mapping affect activate throughput?” Same-group activate pairs pay the longer requirement and different-group pairs the shorter, so steering consecutive activates across groups issues them more often. With the educational same-group term in §9, the gap is 4 cycles against 10 at DDR4-3200 — and it widens with frequency, so address mapping matters more on faster parts, not less. That makes it a performance lever rather than a decoding detail.

“Why is tFAW not just a longer tRRD?” Different constraint classes. tRRD is pairwise: it relates the candidate to one prior activate, so one countdown expresses it. tFAW is a rolling window: it relates the candidate to a history of recent activates, and no single countdown can answer “how many happened in the last window.” The implementation consequence is that tFAW needs storage proportional to the event count, which is the next chapter.

14. Engineering Exercises

1. Resolve both terms. Using the verified DDR4-2400 1KB figure — the greater of 4 nCK or 3.3 ns — resolve tRRD_S at DDR4-1600, DDR4-2400 and DDR4-3200, and say which term governs at each.

Worked: at DDR4-1600, tCK is 1.25 ns, ceil(2.64) = 3, max(4, 3) = 4floor governs. At DDR4-2400, tCK is 0.8333, ceil(3.96) = 4, max(4, 4) = 4tie, reported as floor-governed. At DDR4-3200, tCK is 0.625, ceil(5.28) = 6, max(4, 6) = 6absolute governs. The crossover is at DDR4-2400.

2. Use the real per-grade value. Now redo DDR4-3200 with its actual verified absolute term of 2.5 ns instead of 3.3. What changes, and what does that tell you about how the table is constructed?

Worked: ceil(2.5 / 0.625) = 4, so max(4, 4) = 4back to the tie, and 2 cycles shorter than the fixed-3.3 sweep predicted. The table is constructed so the resolved requirement stays near the 4-cycle floor across the family. The fixed-term sweep of exercise 1 therefore over-estimates the real requirement at high speed, which is exactly why §6 labels it a teaching device.

3. Price the page size. At DDR4-2400, resolve tRRD_S for a 1KB part and a 2KB part. Express the difference as a percentage of activate spacing.

Worked: 1KB: max(4, ceil(3.3/0.8333) = 4) = 4 cycles. 2KB: max(4, ceil(5.3/0.8333) = 7) = 7 cycles. 75 percent longer, from a device property that appears nowhere in the parameter's name. A controller configured for the wrong page size is short by 3 cycles on every cross-group activate pair.

4. Find the one-sided design. A colleague enforces only the absolute term, ignoring the cycle floor. At which of exercise 1's three grades does that violate, and why is this error rarer in practice than the opposite one?

Worked: it violates at DDR4-1600, where the absolute term resolves to 3 and the floor requires 4. At the other two it is correct or conservative. It is rarer because the cycle floor is the more visible number in most documentation and tuning interfaces, so engineers are more likely to find the floor and miss the absolute term than the reverse — which is why §11 flags “worked on the slower part” as the common signature.

5. Compare the scopes. Construct the shortest activate sequence that violates tRRD but satisfies tRC, and one that violates tRC but satisfies tRRD.

Worked: tRRD only: ACTIVATE bank 0 at cycle 0, ACTIVATE bank 9 (different group) at cycle 1 — tRC does not apply since it is a different bank, and tRRD_S of 4 is violated. tRC only: ACTIVATE bank 0 at cycle 0, then PRECHARGE and ACTIVATE bank 0 again at cycle 20 with tRC of 74 — tRRD's 4 cycles are long satisfied and tRC is violated by 54. The pair makes the scope distinction concrete: neither obligation subsumes the other.

6. Sweep for the crossover. Write the loop that finds, for a given dual-term specification, the exact tck_ps at which the governing term changes. Then explain why §8's P2 proves nothing below that point.

7. Argue the reuse. §7 builds a resolver and reuses Chapter 4.5's bank_group_spacer for enforcement. Argue instead for one block doing both, then say what that costs in testability given that the resolver is combinational and the spacer is sequential.

15. Summary

tRRD constrains the next ACTIVATE to a different bank from any accepted ACTIVATEshared scope, refined by bank group in DDR4, a minimum separation. It is the activate counterpart to Chapter 14.6's column spacing, and it removes the assumption that survived six chapters: two different banks does not mean unconstrained parallelism.

It is also the one parameter in this module with a fully verified value in full context: Micron's TN-40-03 specifies tRRD_S for DDR4-2400 as the greater of 4 nCK or 3.3 ns at 1KB page size, and 5.3 ns at 2KB — with corroborating figures of 3.0 ns at DDR4-2933 and 2.5 ns at DDR4-3200. Four things follow, and each is load-bearing: the max(nCK, ns) dual-term form is real; the cycle floor stays 4 across grades while the absolute term shrinks; the absolute term depends on page size, which is a device property and the best available evidence that the cause is physical; and a value quoted without its grade and page size is not a fact.

The dual-term form creates a crossover. Below it the obligation is structure-limited and the floor governs; above it the obligation is physics-limited and every clock increase costs cycles. The verified per-grade figures reveal what the form is for: the shrinking absolute term keeps the resolved requirement near 4 cycles across the family, which the fixed-term sweep of §6 deliberately does not show — and which makes the fixed-term sweep a teaching device rather than a description of a real part.

The crossover also gives this chapter a diagnostic no other chapter has: a design enforcing only the cycle floor is correct below the crossover and violating above, so “it worked on the slower part” identifies the bug rather than deepening the mystery. The mirror error, enforcing only the absolute term, fails at low data rates — the counter-intuitive direction.

Enforcement is reused: Chapter 4.5's bank_group_spacer holds the group-scoped countdowns. activate_spacing_resolver supplies its two magnitudes, resolves both dual-term specifications, reports which term governs each, and checks the _L >= _S configuration invariant. Its absolute terms are parameters precisely because §4 verified they depend on page size.

And _S / _L are labelled DDR4 throughout. §5 states that I could not confirm DDR5's naming or semantics — the fourth such gap in this curriculum, and by now a pattern worth trusting.

16. What Comes Next

tRRD relates a candidate ACTIVATE to one prior activate. Chapter 14.8 relates it to several.

tFAW is the module's only rolling-window constraint — Chapter 13.3 §2's class D, the one that is different in kind because legality depends on a history rather than on a single prior event. No countdown can express it, because no countdown can answer “how many activates happened in the last window.” It needs storage proportional to the event count, it is the one place in this module where a timestamp queue is the right structure, and it is where §12's last misconception — that tFAW is just a longer tRRD — gets taken apart properly.

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.