Skip to content
VLSI Mentor

DDR · Module 28

DDR Silicon Bring-Up

Every investigation in this module was expensive because many variables had changed before anyone looked. Staging is the discipline that makes the suspect list short by construction.

Every chapter in this module began the same way: a system already running, a failure already present, and a suspect list containing everything.

Chapter 28.1 needed five experiments to establish that a bitmap meant anything. Chapter 28.2 reconstructed a violated contract from history that might have been recorded from the wrong signal. Chapter 28.5 had sixteen axes because one wrong byte is consistent with all of them.

Those investigations were expensive largely because many variables had changed at once before anyone looked.

Bring-up is the discipline that prevents it, and the central question is not how do I make it work. It is:

HOW DO YOU MOVE A DDR SYSTEM FROM UNKNOWN BEHAVIOUR TO LOCALIZED, REPRODUCIBLE, EXPLAINABLE BEHAVIOUR?

The answer is staging: establish each layer, believe it for a stated reason, and only then let the next layer depend on it. When a failure appears at stage seven, the suspect list is stage seven plus whatever stage six's gate failed to establishshort by construction rather than by investigation.

1. Why Order Is the Whole Method

State the argument once, precisely.

A DDR subsystem is a stack of dependencies. Training depends on calibration; a meaningful transaction depends on training; address expansion depends on the map being right; refresh interaction depends on traffic working at all.

So a failure at any layer has a suspect list that includes every layer beneath it — unless those layers were established and believed first.

ApproachSuspect list when a failure appears at stress traffic
Configure everything, run random trafficclocks, reset, configuration, PHY, calibration, training, map, bursts, banks, refresh, frequency, channel
Staged, each gate satisfiedstress traffic, plus whatever the previous gate failed to establish

That difference is worth days per failure, and it compounds: every failure found during bring-up is found with a short list, so each is cheaper than the last would have been.

And the second column's caveat is the honest part. A stage gate establishes something for a stated reason, and the reason is always partial. §3 is about what each gate actually establishes, because a gate believed to prove more than it does reintroduces the long suspect list silently.

2. The Stages

The order, with the DDR-specific gate at each. CURRICULUM-DERIVED from the owners named in each row.

#StageGate — what must be true to proceedOwner
0Clocks, reset, register accessa known register reads its known reset value, and a written value reads back6.8
1Controller configurationevery timing and geometry register reads back what provenance says it should — §6Module 17
2PHY initialisation and calibration19.5's five events completed; 28.4's four fields clean19.5
3Trainingevery step started, converged, committed, and its window is not one tap wideModule 21, 28.1
4One deterministic transactionone write, one read, one address, one pattern — and it matchesModule 27
5Address expansiona walking-bit address sweep, checked against the map's inversion8.6
6Lane, burst and pattern variationevery lane, every beat position, several transition densitiesModule 12, 28.6 §4
7Bank and rank expansionmulti-bank interleaving, then multiple ranksModule 16, 5.4
8Refresh, idle and power interactionrefresh running with traffic; idle and power transitions exercisedModule 15, 28.3
9Frequency expansioneach supported frequency, retrained, with provenance re-verified28.4 §5
10Stress trafficrandomised, concurrent, long-durationModule 23

Stage 4 is the pivot and deserves its own emphasis. Everything before it establishes that the machinery exists; stage 4 is the first moment anything is known to work. A bring-up that reaches stage 10 without ever having done stage 4 in isolation has no baseline at all.

And stage 10 is last for a reason that is often reversed in practice. Random stress traffic finds failures efficiently — and it finds them with the longest possible suspect list, which is the opposite of what bring-up is for. Its place is to find what the staged sequence missed, not to be the sequence.

3. What a Gate Actually Establishes

The most dangerous thing in a staged bring-up is a gate believed to prove more than it does.

GateEstablishesDoes not establish
Register reads backthe access path worksthe value is correct — §6
Calibration donea flag is setthat it started, converged or committed — 28.4 §1
Training passeda setting was committedthat the window is wide — 28.1 §5
One transaction matchedone address, one pattern, one lane set worksanything about other addresses
Address sweep cleanthe map is self-consistent over that sweepthat the map matches the device's geometry
All lanes exercisedeach lane carried datathat each has margin
Refresh runningcommands are issuingthat deadlines are met — 28.3 §3
A frequency passesthat frequency works nowthat its settings are not stale — 28.4 §5

Row two is the one that costs the most. Chapter 28.4 showed that done implemented as !busy reads true from reset — so a stage-2 gate that checks only done lets an entire uncalibrated PHY through, and the failure surfaces at stage 3 or 4 with training or the first transaction blamed.

Row three is the second most expensive. A committed setting at the centre of a one-tap window passes every digital check and fails under real traffic. Chapter 28.1 §5 is explicit that a one-tap window means the window is at or below the step size, and the gate must therefore check the width, not merely that a setting was chosen.

So a gate is a statement with a stated limit, and §15's ledger records both — because a bring-up that reaches stage 10 needs to know, when something fails, exactly what each earlier gate did and did not establish.

4. The One-Variable Rule

The rule that makes every stage transition interpretable.

Change exactly one controlled variable between runs. The difficulty is that one variable is not obvious, and several bring-up actions change more than one.

ActionVariables actually changed
Raise the frequencyperiod, every derived timing count, calibration validity, channel behaviour, accesses per second
Enable a second rankloading, termination configuration, address space, arbitration
Retrainevery committed setting, and the state the device is left in
Enable refreshtraffic interruptions, bus occupancy, thermal profile
Switch the address mapwhich bank each address hits, row-hit rate, bank parallelism
Enable a wider burstdata phases per command, bus occupancy, some spacing feasibility

Not one of those is a single variable, and that is the point: "change one thing" is a goal that requires decomposition rather than discipline alone.

The practical technique is to change the compound variable and then, if the result is surprising, decompose it. Raising the frequency is one bring-up step; if it fails, the decomposition is: re-derive the timing counts by hand (28.2 §11), retrain at the new frequency (28.4 §5), and re-measure per access (28.6 §2) — three sub-experiments that isolate three of the five things the one step changed.

And the rule has a corollary that is easy to violate under pressure: do not change a variable and a stage at the same time. Moving from stage 7 to stage 8 while also raising the frequency produces a failure whose suspect list is both, and the whole method collapses for that failure.

5. Configuration Provenance as a Bring-Up Artefact

Chapter 28.2 §11 walks the chain from a device figure to an applied count, and treats it as a debugging procedure. During bring-up it is cheaper and more valuable: build the chain once, as a record, before stage 1's gate.

LinkWhat the record must contain
Device specification figurethe figure, its units, and its condition — including whether it is a max(nCK, ns) form
Frequency binwhich bin this run uses
Conversionthe arithmetic, and the rounding direction used
Register encodingthe encoded value and the decode back to a count
Readbackthe value read from the register after configuration
Interpretationcommand clocks or controller clocks

Stage 1's gate is that every row's readback matches its conversion, which turns 28.2's most tedious investigation into a one-time table.

CURRICULUM-DERIVED from 28.2 §10: a minimum time requirement must round up, and a floor is invisible wherever the division is exact. So the provenance record must state the rounding direction explicitly — because a run that happens to use a frequency where every division is exact will pass a readback gate with a rounding bug present.

The bring-up payoff is specific and large. Every later chapter's investigation asks is the applied value right? A provenance table answers it in seconds and, more importantly, answers it the same way every time — which is what makes 28.6 §1's exclusion recordable rather than re-argued.

6. Stage 4 — The First Transaction

The most important stage, and the one most often skipped because it looks trivial.

One write, one read, one address, one pattern, one burst, one bank. Everything else disabled or minimised.

What makes it valuable is not that it passes. It is that it is the only configuration in which a failure has almost no suspect list — and that it establishes a baseline every later stage is compared against.

ChooseWhy
An address whose map decomposition you can stateso a failure names a bank, row and column — 8.6
A pattern with a known transition countso 28.6 §4's axis has a defined value
The shortest legal burstso a beat-position failure has fewer positions — 12.1
One bank, kept openso no activate/precharge timing is exercised yet
Refresh disabled if legal for the durationso 28.3's axis is out of the picture

And run it enough times to establish a rate, not once. Chapter 28.5 §3's argument applies here first: a single passing transaction and a transaction that fails one time in ten thousand are indistinguishable in one attempt. The gate is a rate over a stated count, and that number becomes the baseline every later stage's rate is compared against.

7. Stages 5 to 7 — Expanding Along One Axis at a Time

Each expansion adds one dimension of 28.5 §2's axis table, deliberately.

Stage 5 — address expansion. A walking-bit sweep exercises each address bit independently. CURRICULUM-DERIVED from 8.6, which owns the map and its inversion: the gate is that every accessed address decomposes to the bank, row and column you predicted, verified by the inversion rather than by the data matching.

That distinction matters. Data matching proves the round trip worked; the inversion proves the map is what you think it is — and a map that is wrong in a self-consistent way passes a data check and fails at stage 7 when banks start interleaving.

Stage 6 — lane, burst and pattern. Three sub-axes, and the order within them matters: lanes first (each lane must carry data at all), then beat positions (via burst length variation — 12.1), then transition density (28.6 §4's profile at several levels).

Stage 7 — banks and ranks. Multi-bank interleaving first, because it exercises Module 16's parallelism and every cross-bank timing rule (14.7, 14.8) without adding electrical load. Ranks last within the stage, because adding a rank changes loading and termination as well as address space — §4's second row.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   what each expansion ADDS to the suspect list, and what it
   therefore tests

   stage 5  address bits, the map, its inversion
   stage 6  per-lane paths, beat positions, transition density
   stage 7  cross-bank timing, bank-group rules, then rank loading

   a failure appearing at stage 6 and not stage 5 implicates the
   axis stage 6 added -- which is three sub-axes, and the sub-order
   within the stage narrows it to one.

   this is the entire value of staging, in three lines.

8. Stages 8 and 9 — Interactions and Frequency

The two stages where previously-established things stop being true.

Stage 8 — refresh, idle and power. Refresh introduces traffic interruptions (28.3 §6's drain), idle introduces the long-gap cases (28.2 §12's stale history and counter wrap), and power transitions introduce the restore-versus-re-establish question (28.4 §5).

Sub-stageGateWhat it catches
Refresh with trafficzero deadline misses and a clean error histogram by window position28.3 §9's restart bug
Long idle, then trafficno violation on the first command after the gap28.2 §12's stale history
Power-state entry and exitsettings re-established, provenance tag matching28.4 §5

Stage 9 — frequency expansion, and this is the stage that invalidates the most. Every timing count changes, calibration validity changes, and the channel behaves differently.

So the gate has three parts and skipping any of them is how a frequency bug reaches production: the provenance table re-derived for the new bin (§5), a full retrain with its own window-width check, and a re-run of stages 4 through 8 at the new frequency.

That last requirement is the expensive one and it is not negotiable. A frequency that passes stage 10 without having passed stage 4 at that frequency has no baseline at that frequency, and every failure found there inherits the long suspect list the whole method exists to avoid.

9. A Stage Gate Failing

The moment the method earns its cost. ILLUSTRATIVE stage indices.

A gate fails, evidence is captured, and the system does not advance

10 cycles
A ten-cycle bring-up sequence trace. The clock runs throughout. The stage index lane shows the system progressing through stages zero, one and two, then arriving at stage three and remaining there. The gate evaluation signal pulses at each stage boundary. The gate pass signal is high for the evaluations at stages zero, one and two, and low for the evaluation at stage three, which is the failing gate. The advance signal follows gate pass exactly, so the system advances after each of the first three gates and does not advance after the fourth. The evidence captured signal rises at the cycle of the failing gate and stays high, because evidence must be captured before any recovery action. The recovery signal rises only at the final cycle, strictly after evidence capture, which is the ordering the chapter argues is the most commonly violated rule under time pressure. The blocked output rises with the failing gate and remains high for the rest of the trace. The first marker at cycle one notes stage zero's gate passing. The second marker at cycle seven notes stage three's gate failing. The third marker at cycle nine notes recovery occurring only after evidence capture. The first phase spans cycles zero to five and covers the stages that advanced. The second phase spans cycles seven to nine and covers the blocked interval during which evidence is captured before any recovery.stages advancingstages advancingblocked: capture firstblocked: capturefirststage 0 gate passedstage 0 gate passedstage 3 gate FAILED: blockedstage 3 gate FAILED:blockedrecovery only after capturerecovery only after captureCKstage0011223333gate_evalgate_passadvanceevidencerecoveryblockedt0t1t2t3t4t5t6t7t8t9

advance tracks gate_pass exactly, and that is the structural commitment. A bring-up in which advancing is a human decision rather than a gate result will advance past a marginal gate at four in the afternoon, and the cost lands three stages later.

evidence rises before recovery, and the ordering is the rule this chapter cares most about. §14 is about why.

And blocked staying high is what preserves the finding. A system that retried automatically and succeeded would leave no record that stage 3 ever failed — which is the module's fourth law in hardware form.

10. Evidence Capture Before Recovery

The rule most often broken, and the one with the highest cost when it is.

When something fails in a lab, the instinct is to recover: reset, reboot, retrain, power-cycle. Every one of those destroys the state that would explain the failure.

Recovery actionDestroys
Resetevery debug register, all captured state, the failing configuration
Rebootthe above, plus the software state that produced the stimulus
Retrainthe committed settings that were in use when it failed — 28.1
Power-cycleall of the above, plus the thermal state

So the rule is: capture first, recover second, and the capture list is short enough to be a checklist:

The first-error snapshots. Chapter 28.2 §15's violation snapshot, 28.5 §13's first-error capture, 28.1 §14's ledger. All three are designed to survive until an explicit clear, and that design exists for this moment.

The full configuration. Not the intended configuration — the configuration as read back, per §5.

The stage and the gate results. Which stage, which gate, and what every earlier gate established.

The rate and the duration. Chapter 28.5 §3's arithmetic requires both, and neither is recoverable after a reboot.

And the reason this is hard is worth naming. The pressure to recover is highest exactly when the failure is most interesting — a rare failure after eleven hours. A written capture checklist is what survives that pressure, and §15's ledger exists so that most of the list is captured automatically rather than remembered.

11. Minimal Reproducer Reduction, During Bring-Up

Chapter 28.5 §15 owns reduction as a post-failure technique. During bring-up it is cheaper, because the staged sequence has already done most of the work.

A failure at stage N is already minimal in every axis stage N had not yet added. That is the staging dividend: a stage-6 failure needs no address-range reduction, because stage 5's sweep is the range and stage 6 added lanes, beats and patterns.

Failure appears atAlready minimal inReduce within
Stage 4everythingpattern, then burst length
Stage 5lanes, beats, banks, refresh, frequencythe address range
Stage 6banks, refresh, frequencylane, then beat, then transition density
Stage 7refresh, frequencybanks, then ranks
Stage 8frequencywhich interaction — refresh, idle, or power
Stage 10nothingeverything — which is why stage 10 is last

The bottom row is the argument for the whole method in one line. A failure found by random stress traffic is minimal in nothing, and reducing it is the expensive investigation every earlier chapter described. A failure found at stage 6 arrives pre-reduced in five axes.

12. The Bring-Up Ledger

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// bringup_ledger -- CLASSIFICATION: synthesisable, BINDABLE.
//
// WHAT IT DOES: records the staged sequence -- stage, gate verdicts,
// evidence-before-recovery ordering, and the number of variables
// changed per stage transition.
//
// WHY advance IS GATED BY gate_pass (§9): a bring-up in which
// advancing is a human decision will advance past a marginal gate at
// four in the afternoon, and the cost lands three stages later. The
// ledger records any advance that happened WITHOUT a passing gate, so
// the violation is a number rather than a memory.
//
// WHY THE FIRST FAILING STAGE IS LATCHED: Module 28's second law. A
// later stage's failure is usually a consequence of an earlier gate
// that was not really satisfied, so the FIRST failing stage is the
// evidence.
//
// WHY recovery_without_evidence IS COUNTED (§14): reset, reboot,
// retrain and power-cycle each destroy the state that explains the
// failure. The pressure to recover is highest exactly when the
// failure is most interesting, and a counter survives that pressure
// better than a checklist.
//
// WHY vars_changed (§4): "change one thing" requires decomposition,
// and a transition that changed several variables makes the next
// failure's suspect list long again. Recording it makes the method's
// own violations visible.
//
// WHAT IT CANNOT TELL YOU: whether a gate's CRITERION was strong
// enough (§3). No register detects a gate that proves too little.
//
// SYNTHESIS: a stage register, counters, and a small per-stage array.
// ---------------------------------------------------------------------
module bringup_ledger #(
  parameter int STAGES = 11,   // §2's table, 0..10
  parameter int VAR_W  = 8
)(
  input  logic                        clk,
  input  logic                        rst_n,

  input  logic                        gate_eval,
  input  logic                        gate_pass,
  input  logic                        advance,
  input  logic [$clog2(STAGES)-1:0]   stage,
  input  logic [VAR_W-1:0]            vars_changed,  // §4
  input  logic                        evidence_captured,
  input  logic                        recovery,
  input  logic                        clear,

  output logic                        blocked,
  output logic [15:0]                 gates_evaluated,
  output logic [15:0]                 gates_passed,
  output logic [15:0]                 gates_failed,
  output logic [$clog2(STAGES)-1:0]   first_fail_stage,
  output logic                        first_fail_valid,
  output logic [15:0]                 advance_without_pass,
  output logic [15:0]                 recovery_without_evidence,
  output logic [15:0]                 multi_var_transitions,
  output logic [$clog2(STAGES)-1:0]   max_stage_reached,
  output logic [15:0]                 gate_result [STAGES]
);
  // $clog2(1) is 0, making the stage vector illegal as [-1:0]. A
  // single-stage bring-up is also not a staged bring-up.
  initial begin
    if (STAGES < 2) $fatal(1, "bringup_ledger: STAGES must be >= 2 (got %0d)", STAGES);
    if (VAR_W  < 1) $fatal(1, "bringup_ledger: VAR_W must be >= 1");
  end

  logic ev_seen_this_failure;

  always_ff @(posedge clk) begin
    if (!rst_n || clear) begin
      blocked                   <= 1'b0;
      gates_evaluated           <= '0;
      gates_passed              <= '0;
      gates_failed              <= '0;
      first_fail_stage          <= '0;
      first_fail_valid          <= 1'b0;
      advance_without_pass      <= '0;
      recovery_without_evidence <= '0;
      multi_var_transitions     <= '0;
      max_stage_reached         <= '0;
      ev_seen_this_failure      <= 1'b0;
      for (int s = 0; s < STAGES; s++) gate_result[s] <= '0;
    end else begin
      if (gate_eval) begin
        if (gates_evaluated != 16'hFFFF) gates_evaluated <= gates_evaluated + 1'b1;
        if (gate_pass) begin
          if (gates_passed != 16'hFFFF) gates_passed <= gates_passed + 1'b1;
          // Per-stage tally: a stage whose gate was evaluated many
          // times before passing is a stage that was nearly failed,
          // which §3 says is worth knowing later.
          if (gate_result[stage] != 16'hFFFF)
            gate_result[stage] <= gate_result[stage] + 1'b1;
        end else begin
          if (gates_failed != 16'hFFFF) gates_failed <= gates_failed + 1'b1;
          blocked <= 1'b1;
          // §9, and the module's second law: the FIRST failing stage
          // is the evidence. A later failure is usually a consequence.
          if (!first_fail_valid) begin
            first_fail_valid <= 1'b1;
            first_fail_stage <= stage;
          end
          ev_seen_this_failure <= 1'b0;
        end
      end

      // §9: advancing without a passing gate is the method's own
      // violation, recorded rather than prevented -- this block
      // observes a controller, it does not drive one.
      if (advance && !(gate_eval && gate_pass)
          && advance_without_pass != 16'hFFFF)
        advance_without_pass <= advance_without_pass + 1'b1;

      if (advance) begin
        if (stage > max_stage_reached) max_stage_reached <= stage;
        // §4: a transition that changed more than one variable makes
        // the next failure's suspect list long again.
        if (vars_changed > 1 && multi_var_transitions != 16'hFFFF)
          multi_var_transitions <= multi_var_transitions + 1'b1;
      end

      if (evidence_captured) ev_seen_this_failure <= 1'b1;

      // §14: recovery before capture destroys the explanation. Counted
      // per recovery event, and only while blocked -- a recovery
      // during normal operation is not a violation of this rule.
      if (recovery && blocked && !ev_seen_this_failure
          && recovery_without_evidence != 16'hFFFF)
        recovery_without_evidence <= recovery_without_evidence + 1'b1;

      // A recovery while blocked clears the block so the sequence can
      // be retried -- but first_fail_stage and every counter survive,
      // which is what makes the retry interpretable afterwards.
      if (recovery && blocked) blocked <= 1'b0;
    end
  end
endmodule

first_fail_stage latches and survives every recovery, which is the module's second law in one register. A bring-up that failed at stage 3, was recovered, and then reached stage 10 has a different meaning from one that reached stage 10 first time — and after the recovery nothing else in the system remembers the difference.

advance_without_pass records the method's own violation rather than preventing it. This block observes a controller; it does not drive one. Making the violation a number is what allows a post-mortem to ask whether the method was actually followed, which is otherwise a matter of recollection.

And recovery_without_evidence is counted only while blocked. A recovery during normal operation is not a violation of §14's rule, and counting it would make the number meaningless through noise.

13. What the Assertions Prove

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bound to §15's ledger. Every property carries `disable iff`, and
// every antecedent is covered below -- 27.2 measured this curriculum
// at 78.53% implications, so a silent pass is otherwise
// indistinguishable from an unbound block.
module bringup_ledger_sva #(
  parameter int STAGES = 11
)(
  input logic clk, rst_n, clear,
  input logic gate_eval, gate_pass, advance, evidence_captured, recovery, blocked,
  input logic [$clog2(STAGES)-1:0] stage, first_fail_stage, max_stage_reached,
  input logic first_fail_valid,
  input logic [15:0] gates_evaluated, gates_passed, gates_failed,
  input logic [15:0] advance_without_pass, recovery_without_evidence
);
  // ---- P1. FORBIDDEN. A failing gate always blocks. §9: advancing
  // past a marginal gate is how a cost lands three stages later.
  property p_fail_blocks;
    @(posedge clk) disable iff (!rst_n)
      (gate_eval && !gate_pass) |=> blocked;
  endproperty
  assert property (p_fail_blocks)
    else $error("ledger: a failing gate did not block");

  // ---- P2. The first failing stage is latched and never changes
  // without a clear. Module 28's second law.
  property p_first_fail_sticky;
    @(posedge clk) disable iff (!rst_n)
      (first_fail_valid && !clear) |=> (first_fail_stage == $past(first_fail_stage));
  endproperty
  assert property (p_first_fail_sticky)
    else $error("ledger: first_fail_stage changed after being latched");

  // ---- P3. FORBIDDEN. A recovery does not clear the first-failure
  // record. §14: recovery destroys everything else, and this must
  // survive it.
  property p_recovery_preserves_first_fail;
    @(posedge clk) disable iff (!rst_n)
      (first_fail_valid && recovery && !clear) |=> first_fail_valid;
  endproperty
  assert property (p_recovery_preserves_first_fail)
    else $error("ledger: a recovery cleared the first-failure record");

  // ---- P4. PARTITION. Passes plus failures equal evaluations. A gate
  // that was evaluated and produced neither is a verdict nobody
  // recorded.
  property p_gate_partition;
    @(posedge clk) disable iff (!rst_n)
      (gates_passed + gates_failed == gates_evaluated);
  endproperty
  assert property (p_gate_partition)
    else $error("ledger: %0d passed + %0d failed != %0d evaluated",
                gates_passed, gates_failed, gates_evaluated);

  // ---- P5. INVARIANT. Evaluations only advance on an evaluation.
  property p_eval_only_on_eval;
    @(posedge clk) disable iff (!rst_n)
      (!gate_eval) |=> (gates_evaluated == $past(gates_evaluated));
  endproperty
  assert property (p_eval_only_on_eval)
    else $error("ledger: gates_evaluated advanced with no evaluation");

  // ---- P6. FORBIDDEN. An advance with no passing gate in the same
  // cycle is recorded. §9 -- the method's own violation, made a number.
  property p_advance_without_pass_counted;
    @(posedge clk) disable iff (!rst_n)
      (advance && !(gate_eval && gate_pass) && advance_without_pass != 16'hFFFF)
        |=> (advance_without_pass == $past(advance_without_pass) + 1);
  endproperty
  assert property (p_advance_without_pass_counted)
    else $error("ledger: an ungated advance was not recorded");

  // ---- P7. FORBIDDEN. A recovery while blocked with no evidence
  // captured is recorded. §14's rule, as a counter.
  property p_recovery_without_evidence_counted;
    @(posedge clk) disable iff (!rst_n)
      (recovery && blocked && !evidence_captured && !$past(evidence_captured)
       && recovery_without_evidence != 16'hFFFF)
        |=> (recovery_without_evidence >= $past(recovery_without_evidence));
  endproperty
  assert property (p_recovery_without_evidence_counted)
    else $error("ledger: a recovery before capture was not recorded");

  // ---- P8. INVARIANT. max_stage_reached is monotone. A high-water
  // mark that fell would erase how far the bring-up actually got.
  property p_max_stage_monotone;
    @(posedge clk) disable iff (!rst_n)
      (!clear) |=> (max_stage_reached >= $past(max_stage_reached));
  endproperty
  assert property (p_max_stage_monotone)
    else $error("ledger: max_stage_reached decreased");

  // ---- P9. INVARIANT. The stage index stays in range.
  property p_stage_in_range;
    @(posedge clk) disable iff (!rst_n)
      (stage < STAGES);
  endproperty
  assert property (p_stage_in_range)
    else $error("ledger: stage %0d outside STAGES", stage);

  // ---- P10. INVARIANT. max_stage_reached bounds the current stage
  // whenever an advance has occurred.
  property p_max_bounds_stage;
    @(posedge clk) disable iff (!rst_n)
      (max_stage_reached >= stage) || (max_stage_reached == 0);
  endproperty
  assert property (p_max_bounds_stage)
    else $error("ledger: stage exceeds max_stage_reached");

  // ---- P11. A recovery while blocked releases the block, so the
  // sequence can be retried. A block with no release would make the
  // ledger a one-shot.
  property p_recovery_releases_block;
    @(posedge clk) disable iff (!rst_n)
      (recovery && blocked) |=> !blocked;
  endproperty
  assert property (p_recovery_releases_block)
    else $error("ledger: a recovery did not release the block");

  // ---- P12. FORBIDDEN. Clear releases everything including the
  // first-failure record -- and clear is the ONLY thing that does.
  property p_clear_releases_all;
    @(posedge clk) disable iff (!rst_n)
      clear |=> (!first_fail_valid && !blocked && gates_evaluated == 16'd0);
  endproperty
  assert property (p_clear_releases_all)
    else $error("ledger: clear did not release the record");

  // ---- 27.2 §7: publish every antecedent.
  cover property (@(posedge clk) disable iff (!rst_n) gate_eval);
  cover property (@(posedge clk) disable iff (!rst_n) gate_eval &&  gate_pass);
  cover property (@(posedge clk) disable iff (!rst_n) gate_eval && !gate_pass);
  cover property (@(posedge clk) disable iff (!rst_n) advance);
  cover property (@(posedge clk) disable iff (!rst_n) blocked);
  cover property (@(posedge clk) disable iff (!rst_n) evidence_captured);
  cover property (@(posedge clk) disable iff (!rst_n) recovery);
  cover property (@(posedge clk) disable iff (!rst_n) recovery && blocked);
  cover property (@(posedge clk) disable iff (!rst_n) clear);
  cover property (@(posedge clk) disable iff (!rst_n) first_fail_valid);
  cover property (@(posedge clk) disable iff (!rst_n) advance_without_pass != 16'd0);
  cover property (@(posedge clk) disable iff (!rst_n) recovery_without_evidence != 16'd0);
  cover property (@(posedge clk) disable iff (!rst_n) stage == STAGES - 1);
  cover property (@(posedge clk) disable iff (!rst_n) max_stage_reached == STAGES - 1);
endmodule

14. DV — Testing the Ledger

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// SIMULATION-ONLY. Independent reference: it replays the event stream
// into a QUEUE and derives every count by rescanning, rather than
// accumulating incrementally. A different algorithm, so agreement is
// evidence -- 27.4 §15's argument.
class bringup_reference;
  typedef struct {
    int  stage; bit eval; bit pass; bit adv;
    bit  evid;  bit rec;  int vars;
  } ev_t;
  ev_t log[$];

  function void push(int stage, bit eval, bit pass, bit adv,
                     bit evid, bit rec, int vars);
    ev_t e;
    e.stage = stage; e.eval = eval; e.pass = pass; e.adv = adv;
    e.evid = evid;   e.rec = rec;   e.vars = vars;
    log.push_back(e);
  endfunction

  function int gates_evaluated();
    int n = 0; foreach (log[i]) if (log[i].eval) n++; return n;
  endfunction

  function int gates_failed();
    int n = 0; foreach (log[i]) if (log[i].eval && !log[i].pass) n++; return n;
  endfunction

  // Module 28's second law: the FIRST failing stage. Returns -1 when
  // none failed, so "never failed" is distinct from "failed at 0".
  function int first_fail_stage();
    foreach (log[i]) if (log[i].eval && !log[i].pass) return log[i].stage;
    return -1;
  endfunction

  function int advance_without_pass();
    int n = 0;
    foreach (log[i]) if (log[i].adv && !(log[i].eval && log[i].pass)) n++;
    return n;
  endfunction

  function int multi_var_transitions();
    int n = 0; foreach (log[i]) if (log[i].adv && log[i].vars > 1) n++; return n;
  endfunction

  // §14: a recovery is a violation only if it happens while blocked
  // and no evidence was captured since the failure that blocked it.
  function int recovery_without_evidence();
    int n = 0; bit blocked = 0, evid = 0;
    foreach (log[i]) begin
      if (log[i].eval && !log[i].pass) begin blocked = 1; evid = 0; end
      if (log[i].evid) evid = 1;
      if (log[i].rec && blocked) begin
        if (!evid) n++;
        blocked = 0;
      end
    end
    return n;
  endfunction

  function int max_stage_reached();
    int m = 0; foreach (log[i]) if (log[i].adv && log[i].stage > m) m = log[i].stage;
    return m;
  endfunction
endclass
CheckWhat it establishes
Replay §9's trace through both; compare every outputIncremental ledger and rescanning reference agree
30,000 random event streams through bothTwo algorithms agree on all seven counts
No gate ever failsReference first_fail_stage() returns −1; ledger's first_fail_valid is 0
Fail at stage 3, recover, reach stage 10first_fail_stage stays 3 — P2, P3
Fail at stage 3, then at stage 7First record stays 3 — the module's second law
Advance with no passing gateadvance_without_pass rises — P6
Advance with vars_changed = 3multi_var_transitions rises — §4
Recover while blocked, no evidencerecovery_without_evidence rises — P7
Recover while blocked, evidence firstCounter unchanged — §14's rule satisfied
Recover while not blockedCounter unchanged — not a violation of this rule
Assert clearEverything releases, including first_fail_valid — P12
STAGES = 1Elaboration fails — a single stage is not a staged bring-up
Drive stage = STAGESP9 fires
70,000 gate evaluationsCounters saturate; partition still holds — P4
Run with the bring-up controller disconnectedAll 12 properties pass; all 14 covers empty

Two reports close the module, and they are the two ways a bring-up looks finished and is not:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  TWO PASSING BRING-UP REPORTS

  (A) the ledger was never connected
        all 12 properties            PASS
        gates_evaluated              0
        gates_passed                 0
        gates_failed                 0
        first_fail_valid             0
        max_stage_reached            0
        ------------------------------------------------
        cover gate_eval              0 hits
        ... all 14 covers            0 hits

        seven of the twelve properties are implications and never
        armed. The five INVARIANTS -- the gate partition, the
        monotone high-water mark, the stage range, the bound, and the
        evaluation counter -- all pass on zeros.

        "bring-up completed with no gate failures" is produced by this
        run AND by a flawless one. gates_evaluated is the field that
        separates them, and it is the first one to read.

  (B) every gate passed and the method was never followed
        gates_evaluated              11
        gates_passed                 11
        gates_failed                 0
        first_fail_valid             0
        max_stage_reached            10
        ------------------------------------------------
        advance_without_pass         0
        multi_var_transitions        7      <-- seven of ten transitions
        recovery_without_evidence    0

        every gate passed, nothing was ever blocked, and the system
        reached stage 10. By the headline numbers this is a textbook
        bring-up.

        and SEVEN of the ten stage transitions changed more than one
        variable. §4 says that makes each subsequent failure's suspect
        list long again -- so the staging dividend §11 describes was
        never actually earned, and a stage-6 failure here would NOT
        arrive pre-reduced in five axes.

        the gates also each passed first time, which §3 says is
        exactly when a gate's criterion deserves scrutiny: a gate that
        never nearly failed may be one that could not fail.

    diagnosis : (A) is the vacuity case, and it is the module's last
      appearance of a pattern that has appeared in all seven
      chapters. (B) is subtler and more common: the ceremony of
      staging without its substance. Both report success.

    the fix : (A) read gates_evaluated. (B) read
      multi_var_transitions -- and treat a gate that has never once
      failed across a programme as a gate to review rather than a
      gate to trust.

Report (B) is the honest closing note for this module. A bring-up can satisfy every property, pass every gate, reach the final stage, and still have produced none of the localization the method exists to produce — because the value was never in the stages. It was in changing one variable at a time so that each failure's suspect list stayed short.

15. Proving a Repair

The last step, and the one the module's third law exists for.

A configuration change that makes a failure disappear is an experiment. Turning it into a repair requires three things, and the third is the one usually skipped.

A mechanism. Not what I changed, but why that change addresses the cause — stated in terms of the contract that was violated. Chapter 28.2's six fields, 28.3's three questions, 28.4's five failures: each gives a form the mechanism can be stated in.

A demonstration that the mechanism was present. Ideally: reintroduce the defect and show the failure returns. A repair whose defect cannot be reintroduced is a correlation, and it is worth saying so in the report rather than claiming more.

A regression at the right duration and scope. Chapter 28.5 §3's arithmetic sets the duration: long enough that the baseline rate would have produced enough failures for zero to be surprising. And the scope must be expanded, not the reproducer — because the reproducer was minimised, and a repair verified only on the minimal case has been verified on the case least likely to expose a side effect.

Regression scopeWhy
The minimal reproducerproves the specific failure is gone
Every stage from 4 onwardproves the change did not break an earlier gate
Every frequency§8 — a change may be right at one bin and wrong at another
The stress stage, at durationproves it survives the case with no suspect list

Row two is the one that catches a repair which fixed one stage and broke another, and it is cheap precisely because the staged sequence already exists as a runnable artefact. That is the final dividend of the method: the bring-up sequence is also the regression suite.

16. Corner Cases

CaseBehaviourWhy
STAGES = 1Elaboration fails$clog2(1) is 0, and one stage is not a staged bring-up
Gate failsblocked rises, advance stopsP1 — §9's structural commitment
Second failure after the firstFirst stage retainedP2 — the module's second law
Recovery while blockedBlock releases, record survivesP3, P11
Recovery while not blockedNot counted as a violation§12 — otherwise the number is noise
Recovery before evidence captureCountedP7 — §14's rule
Advance with no passing gateCounted, not prevented§12 — the block observes, it does not drive
Transition changing 3 variablesmulti_var_transitions rises§4
Every gate passes first timeWorth reviewing§3, report (B) — a gate that never nearly failed
Stage 10 reached, 7 multi-variable transitionsStaging dividend not earnedreport (B)
Frequency raised without re-running stage 4No baseline at that frequency§8
gates_evaluated zeroThe ledger was never connectedreport (A)
70,000 evaluationsCounters saturate; partition holdsP4
clear assertedEverything releasesP12

Rows nine and ten are the two findings that only a ledger produces. Neither is a failure, and both mean the method delivered less than its report suggests.

17. Misconceptions

“Bring-up is a checklist.” §1. It is a dependency order with a gate at each step, and the gates are what make a later failure cheap to localize.

“Start with stress traffic to find bugs fast.” §2. It finds them with the longest possible suspect list. Its place is last, to find what the staged sequence missed.

“The gate passed, so that layer is established.” §3. A gate establishes something for a stated reason, and every reason is partial. Calibration done is the expensive example.

“I only changed one thing.” §4. Raising the frequency changes five things; enabling a rank changes four. One action is not one variable.

“Provenance is a debugging activity.” §5. Built once before stage 1, it answers every later chapter's is the applied value right? in seconds.

“One passing transaction means stage 4 is done.” §6. A single pass and a one-in-ten-thousand failure are indistinguishable in one attempt. The gate is a rate over a stated count.

“Reset it and try again.” §10. Reset destroys every debug register, the captured state and the failing configuration. Capture first.

“It passed on the retry, so we are fine.” The module's fourth law, and §12's first_fail_stage exists so the retry does not erase the record.

“The frequency passed stress traffic, so it is good.” §8. Without stage 4 at that frequency there is no baseline, and every failure there inherits the long list.

“The fix works — the failure is gone.” §15. A mechanism, a demonstration that the mechanism was present, and a regression at the right duration and expanded scope. Absence of the symptom is the weakest of the three.

“Verify the repair on the minimal reproducer.” §15. That is the case least likely to expose a side effect. Expand the scope, do not minimise it.

18. Interview Reasoning

Why stage a bring-up at all? Because a failure's suspect list is every layer beneath it. Staging makes the list short by construction rather than by investigation.

What is the first stage and its gate? Clocks, reset and register access — a known register reads its reset value and a written value reads back. Without it nothing else is observable.

Why is one deterministic transaction its own stage? It is the first moment anything is known to work, and it is the only configuration where a failure has almost no suspect list. It is also the baseline every later stage is compared against.

Why is stress traffic last? It finds failures efficiently and with the longest possible suspect list. Its job is to find what the staged sequence missed.

Give an example of a gate that proves less than it appears to. Calibration done. Implemented as !busy it reads true from reset, so a stage gate checking only that lets an entirely uncalibrated PHY through.

What counts as one variable? Less than one action. Raising the frequency changes the period, every derived timing count, calibration validity, channel behaviour and the access rate — five things.

How do you handle a compound step like a frequency change? Take it as one bring-up step, and if it fails, decompose: re-derive the timing counts, retrain at the new frequency, and re-measure per access.

Something fails after eleven hours. What do you do first? Capture. The first-error snapshots, the configuration as read back, the stage and gate results, and the rate with its duration. Every recovery action destroys some of that.

Why is the reproducer already minimal when a staged bring-up finds a failure? Because the stage that found it is minimal in every axis the earlier stages had not yet added. A stage-6 failure needs no address reduction.

How do you prove a repair? State the mechanism in terms of the violated contract, show the failure returns when the defect is reintroduced, and regress at the duration the baseline rate demands — across expanded scope, not the minimal reproducer.

19. Exercises

  1. §2 gives eleven stages. Choose two adjacent ones and argue for swapping them, then say what the swap costs when a failure appears at the later of the two.

  2. §3 lists eight gates and what each fails to establish. For the address-sweep gate, construct the map error that passes it and fails at stage 7.

  3. §4 decomposes a frequency change into five variables. Design the smallest set of sub-experiments that isolates each, and state the total cost.

  4. §5 requires the rounding direction in the provenance record. Construct the frequency at which a floor bug is invisible for a given parameter, and say how you would choose a bin to expose it.

  5. §6's gate is a rate over a stated count. Derive the count needed to distinguish a working path from one failing at 10⁻⁶ with reasonable confidence, and state your assumption.

  6. §12 counts advance_without_pass rather than preventing it. Argue for making the ledger drive the controller instead, then decide.

  7. Report (B) has seven multi-variable transitions and no failures. Write the paragraph you would put in the bring-up report, and say what you would do differently next time.

  8. §15 requires reintroducing the defect. Construct the repair for which that is impossible, and say what the report should claim instead.

20. Where This Goes

Bring-up is the discipline that makes every other chapter in this module cheap. Stage the system so each layer is established and believed before the next depends on it; know what each gate does and does not establish; change one controlled variable at a time, remembering that one action is rarely one variable; build configuration provenance before the first transaction rather than during the first investigation; and capture evidence before recovering, because every recovery action destroys the state that would explain the failure.

Four results carry forward. Stage 4 is the pivot — one transaction, one address, one pattern, run enough times to establish a rate — and a bring-up that never did it in isolation has no baseline. A gate believed to prove more than it does reintroduces the long suspect list silently, and calibration done is the standing example. A failure found at stage N arrives pre-reduced in every axis stage N had not yet added, which is the staging dividend. And the bring-up sequence is also the regression suite, which is what makes §15's expanded-scope requirement affordable.

Module 28 as a whole has one result. Every chapter took a signature that looked like a verdict and turned it into evidence: a pass bitmap that is not an eye, a timing violation whose rule may be the wrong rule, a refresh correlation with four mechanisms, a done flag covering five failures, a corruption structure that correction can rewrite, and an escalation criterion with two clauses rather than one. In every case the instrument's most valuable output was a statement about its own limits — an unknown, a refusal, a count of what it did not check.

And the through-line from Module 27 is now complete. That module built instruments that report what they did not check. This module showed why: because the thing they did not check is where the next hypothesis lives, and an investigation that cannot see its own blind spots spends its time in them.

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.