Skip to content
VLSI Mentor

DDR · Module 19

PHY Calibration

Reset release is not readiness. A PHY becomes usable only after clocks settle, initialisation completes and calibration establishes settings that cannot be computed — some of which stop being correct while the system runs.

Four chapters have consumed signals that nothing has produced. Chapter 19.1's command stage refused traffic until phy_operational. 19.3 launched write data against a trained_offset and reported when trained_valid was low. 19.4 opened a gate at a position given by gate_offset and flagged an untrained gate_trained.

Every one of those was an opaque input. This chapter is where they come from, and the reason they exist at all:

A DDR PHY is not usable when reset is released. It becomes usable after a sequence of steps that establish values which cannot be calculated — and some of those values stop being correct while the system is running.

Both clauses matter. The first explains why bring-up is a sequence. The second explains why calibration is not a bring-up activity that finishes.

1. Five Events, Not One

The habit this chapter exists to break is treating “the PHY came out of reset” as a single event. It is at least five, they happen in order, and skipping the distinction is the direct cause of a failure class that only appears on cold boot.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  1. RESET RELEASED       rst_n goes high.
                          Logic state is defined. Nothing else is.

  2. CLOCKS STABLE        the PHY's clock resources have settled.
                          Before this, nothing clocked is meaningful.

  3. INITIALISED          the PHY's own configuration is applied and
                          the device has been brought through its
                          required power-up sequence.

  4. CALIBRATED           the settings that cannot be computed have
                          been established by measurement.

  5. OPERATIONAL          and only now may the controller issue
                          memory traffic.

Each step depends on the one before it, and each takes a non-trivial and largely unpredictable amount of time. Clock resources take time to lock. Device power-up has device-specified requirements. Calibration takes as long as the search takes (Module 21).

2. What Calibration Actually Establishes

Chapter 19.3 §2 decomposed a launch offset into a programmed term and a measured one, and 19.4 §3 found the same decomposition on the receive side. Calibration is the process that produces every instance of the second term.

ValueConsumed byWhy it cannot be computed
Write launch offset19.3's alignerdepends on the difference between two board paths
Receive gate position19.4's gatedepends on a round trip through the board
Per-lane skew compensationboth, per lanelanes are routed differently (19.3 §5)
Sampling position within the dataModule 20's capturedepends on the received signal's shape
Reference level for the receiverModule 20's capturedepends on electrical conditions (Module 22)

The common property is the last column. Not one of these is a property of the design; every one is a property of this manufactured system — this silicon, this package, this board, at this temperature and voltage. A designer cannot know them, a datasheet cannot list them, and a simulation cannot produce them.

So they are found by trying. Something drives known patterns, observes what comes back, and selects settings that work. That is Module 21's subject in its entirety, and this chapter deliberately says nothing about how the search is conducted — only that it happens, that it takes time, and that until it finishes the consuming blocks have nothing meaningful to use.

3. Two Things Called Calibration

A terminology hazard flagged in 19.1 §7 and worth resolving fully here, because the two mechanisms are confused constantly and their failures look nothing alike.

ZQ calibrationPHY calibration
Which sidethe DRAM devicethe PHY, in the SoC
What it establishesthe device's own output-driver and termination characteristicsthe PHY's timing settings: offsets, gate positions, sampling points
Invoked bya command from the controller in DDR4; 7.7 §5 notes DDR5 changed thisthe bring-up sequence and periodic triggers
Result visible to the controller?no7.7 §3 is built on thisyes, as register state
Owned byChapter 7.7this chapter, plus Module 21

They can fail independently and the symptoms do not resemble each other. A device whose output driver is uncalibrated produces signals with the wrong electrical characteristics — a margin problem that worsens with rate and looks like Module 22's territory. A PHY whose timing settings are wrong misses beats or captures noise at specific positions — 19.4 §3's displacement and corruption signatures.

The practical rule: a failure that is electrical in character points at the device side; a failure that is positional in character points at the PHY side. Reaching for the wrong one sends a debug effort to the wrong die.

4. Once, and Then Continuously

The part that surprises people, and the reason the canonical description of this chapter says “at bring-up and continuously”.

Calibration is not a bring-up activity that completes. The physical quantities of §2 are not constants — they are functions of temperature and supply voltage, both of which move while a system runs. A setting that was optimal at cold idle can be marginal at sustained load.

So a real PHY has two calibration paths:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  BRING-UP path        runs once, from a known-nothing state
                       establishes every setting
                       takes as long as it takes
                       memory is UNUSABLE throughout

  PERIODIC path        runs repeatedly, from a known-good state
                       adjusts settings that have drifted
                       must be brief
                       memory is mostly usable around it

5. The Lifecycle

The PHY calibration lifecycle as six states. The machine starts held in reset, where nothing is established. When reset is released it moves to waiting for clocks, where it remains until the clock resources report stability. It then moves to initialising, where the PHY's own configuration is applied and the device is brought through its power-up requirements. From there it moves to calibrating, where the settings that cannot be computed are established by measurement; this state is where module twenty-one's algorithms run, and the machine has no visibility into how long it will take. When calibration reports success the machine becomes operational, and only in that state is memory traffic permitted. From operational a periodic trigger moves it to recalibrating, a brief state that adjusts drifted settings and returns to operational. A calibration failure from either path returns the machine to reset, because a PHY with unusable settings must not present itself as operational.IN RESETCLK WAITINITCALIBRATINGOPERATIONALRECALreset releasedresetreleasedclocks stableclocks stableinit sequence completeinit sequence completeinitsequence…settings establishedsettings establishedperiodic triggerperiodic triggersettings refreshedsettings refreshedcalibration failedcalibration failed

Three features of this machine are the design.

OPERATIONAL is the only state in which traffic is permitted. Chapter 19.1's command stage gates on exactly this, and §1's failure is what happens when something else gates instead.

CALIBRATING has no known duration. The machine cannot predict when it will finish, because Module 21's search takes as long as the search takes. A lifecycle that waits a fixed number of cycles and then declares success is asserting something it does not know.

Failure returns to IN RESET rather than proceeding. A PHY that cannot establish usable settings must not present itself as operational — and §9's corner-case table treats a “calibrated but failed” state as the one outcome that must be impossible.

6. Readiness Over Time

EDUCATIONAL — phase boundaries show ordering only. Real clock-lock, initialisation and calibration intervals are generation- and implementation-specific and are far longer than any ten-cycle drawing can represent (§7).

From reset release to operational, and a later recalibration

10 cycles
Ten sampling points across the PHY lifecycle, drawn on a clock grid purely so the ordering is legible; the real intervals between these steps are far longer than a clock period. Reset is released at the first point. Clocks become stable two points later, and initialisation completes two points after that. Calibration then runs and reports success, at which moment the trained valid and gate trained flags both assert and the PHY operational output goes high. Only from that point does the controller's command stage accept traffic, shown by a command accepted row that is low throughout the earlier phases and high once operational. Later a periodic recalibration trigger asserts: the operational output drops briefly while settings are refreshed, command acceptance pauses with it, and both resume. The trained flags remain asserted throughout the recalibration because the previous settings stay valid until new ones replace them.unusable — four distinct stepsunusable — four distinct stepsmemory traffic permittedmemory traffic permittedreset released — NOT readyreset released — NOT readyoperational at lastoperational at lastrecal: traffic pausesrecal: traffic pausesCKrst_nclocks_stableinit_donecalib_donetrained_validrecal_reqphy_operationalcmd_acceptedt0t1t2t3t4t5t6t7t8t9

The gap between points 1 and 4 is the chapter. Reset is released at point 1 and the interface is unusable for the whole of that span — and in a real system that span is orders of magnitude longer than the drawing suggests, because clock lock and calibration are not cycle-scale activities.

Point 7 is the recalibration. phy_operational drops, cmd_accepted follows it down, and both come back. Note what does not drop: trained_valid stays high throughout, because the previous settings remain valid until new ones replace them. Dropping validity during a refresh would tell the consuming blocks they have nothing to use, when in fact they have something slightly stale — which is a strictly better position.

7. Why There Are No Real Numbers Here

An omission worth defending explicitly, because its absence is conspicuous.

Real initialisation sequences have specified timing. Devices require minimum intervals between power-supply stability, clock stability, reset deassertion and the first command; those intervals are device parameters and they are not small. Clock resources have lock times. Calibration takes as long as its search.

None of those numbers appears in this chapter, for three reasons.

They are generation-specific — the sequence and its constraints differ between DDR generations, and a number quoted without its generation is worse than no number.

They are device-specific — they come from a particular datasheet for a particular part.

And they are implementation-specific on the PHY side — clock lock time is a property of the PLL, and calibration duration is a property of Module 21's algorithm and the number of lanes it must sweep.

What transfers between systems is the ordering, not the magnitudes, and the ordering is what this chapter teaches. A reader who wants the magnitudes for a specific system will find them in that system's device datasheet and PHY documentation — which is exactly the discipline Chapter 18.4 established for address mapping, applied to a different question.

8. The Lifecycle Block

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────
// phy_calib_lifecycle
//
// CLASSIFICATION
//   Synthesizable educational RTL. Sequential. One responsibility:
//   sequence a PHY from reset to operational through its required
//   steps, publish readiness, and manage periodic recalibration.
//
//   It models ORDERING AND GATING. It does not perform calibration.
//
// WHAT IT DOES NOT MODEL
//   - NO CALIBRATION ALGORITHM. calib_done and calib_failed are INPUTS
//     from whatever runs the search -- firmware, a hardware engine, or
//     the controller, and Chapter 19.1 §3 established that which one
//     is implementation-dependent. Module 21 owns the algorithms
//     entirely; this block never inspects a setting's value.
//   - NO CLOCK GENERATION. clocks_stable is an input from a PLL or DLL
//     resource; such structures are not expressible in portable RTL
//     (Chapter 19.1 §5).
//   - NO DEVICE INITIALISATION SEQUENCE. init_done is an input. The
//     required order and intervals are generation- and device-specific
//     (§7) and belong to the device documentation, not to this model.
//   - NO ZQ CALIBRATION. That is device-side and Chapter 7.7 owns it
//     (§3); nothing here is about it.
//   - No real durations. Every wait here is "until the input says so",
//     which is the only honest model of an unpredictable interval.
// ─────────────────────────────────────────────────────────────────────
module phy_calib_lifecycle #(
  // Periodic recalibration interval, in cycles. A POLICY value: the
  // right number depends on how fast settings drift in this system,
  // which is a thermal and electrical property, not a logic one.
  parameter int RECAL_INTERVAL = 4096,
  // How long a recalibration pass is permitted to hold traffic off.
  parameter int RECAL_CYCLES   = 16,
  parameter int IVL_W = (RECAL_INTERVAL <= 1) ? 1 : $clog2(RECAL_INTERVAL + 1),
  parameter int RCL_W = (RECAL_CYCLES   <= 1) ? 1 : $clog2(RECAL_CYCLES + 1)
) (
  input  logic       clk,
  input  logic       rst_n,

  // ── Progress reports from the resources this block sequences. Each
  //    is "it has happened", never "it will happen in N cycles" (§7).
  input  logic       clocks_stable,
  input  logic       init_done,
  input  logic       calib_done,
  input  logic       calib_failed,

  // ── Allows periodic recalibration to be disabled, which is useful
  //    in bring-up debug and is a legitimate configuration.
  input  logic       recal_enable,

  // ── THE output the rest of Module 19 gates on. Chapter 19.1's
  //    command stage consumes exactly this.
  output logic       phy_operational,

  // ── Settings validity. Deliberately NOT the same signal as
  //    phy_operational: settings stay valid across a recalibration
  //    pass, because the previous values remain usable until new ones
  //    replace them (§6). Chapters 19.3 and 19.4 consume these.
  output logic       trained_valid,

  // ── Observability.
  output logic [2:0] lifecycle_state,
  output logic       recal_active,
  output logic       err_traffic_while_not_operational,
  output logic       err_calib_done_and_failed,

  // ── From Chapter 19.1's command stage, for the error check only.
  input  logic       ctrl_traffic_accepted
);

  if (RECAL_INTERVAL < 1) $fatal(1, "phy_calib_lifecycle: RECAL_INTERVAL must be >= 1");
  if (RECAL_CYCLES   < 1) $fatal(1, "phy_calib_lifecycle: RECAL_CYCLES must be >= 1");

  typedef enum logic [2:0] {
    L_RESET = 3'd0,
    L_CLK   = 3'd1,
    L_INIT  = 3'd2,
    L_CAL   = 3'd3,
    L_OPER  = 3'd4,
    L_RECAL = 3'd5
  } life_e;

  life_e             state;
  logic [IVL_W-1:0]  ivl_cnt;
  logic [RCL_W-1:0]  rcl_cnt;
  // Sticky: once settings have ever been established they remain
  // usable until reset, including across a recalibration pass.
  logic              settings_established;

  assign lifecycle_state = state;
  assign phy_operational = (state == L_OPER);
  assign recal_active    = (state == L_RECAL);
  assign trained_valid   = settings_established;

  // ── Traffic accepted outside OPERATIONAL is the §1 failure, caught
  //    at the moment it happens rather than as corruption later.
  assign err_traffic_while_not_operational =
      ctrl_traffic_accepted && !phy_operational;

  // ── A calibrator reporting both outcomes is broken; proceeding on
  //    either interpretation would be a guess.
  assign err_calib_done_and_failed = calib_done && calib_failed;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      state                <= L_RESET;
      ivl_cnt              <= '0;
      rcl_cnt              <= '0;
      settings_established <= 1'b0;
    end else begin
      unique case (state)

        // Reset is RELEASED here, not asserted. Arriving in this state
        // with rst_n high means the machine is starting its sequence,
        // or has returned after a calibration failure.
        L_RESET: begin
          settings_established <= 1'b0;
          state                <= L_CLK;
        end

        L_CLK:
          if (clocks_stable) state <= L_INIT;

        L_INIT:
          if (init_done) state <= L_CAL;

        L_CAL: begin
          // Failure is checked FIRST. A calibrator asserting both is
          // already broken, and treating that as success would present
          // an unusable PHY as operational -- the one outcome §9 says
          // must be impossible.
          if (calib_failed)     state <= L_RESET;
          else if (calib_done) begin
            settings_established <= 1'b1;
            state                <= L_OPER;
            ivl_cnt              <= '0;
          end
        end

        L_OPER:
          if (recal_enable && ivl_cnt >= IVL_W'(RECAL_INTERVAL - 1)) begin
            state   <= L_RECAL;
            rcl_cnt <= '0;
          end else if (!(&ivl_cnt)) begin
            ivl_cnt <= ivl_cnt + IVL_W'(1);
          end

        L_RECAL: begin
          // settings_established is deliberately NOT cleared here: the
          // previous values stay usable while new ones are found (§6).
          if (calib_failed) begin
            state <= L_RESET;
          end else if (rcl_cnt >= RCL_W'(RECAL_CYCLES - 1)) begin
            state   <= L_OPER;
            ivl_cnt <= '0;
          end else begin
            rcl_cnt <= rcl_cnt + RCL_W'(1);
          end
        end

        default: state <= L_RESET;
      endcase
    end
  end

endmodule

The bounded L_RECAL and the unbounded L_CAL are different on purpose. Bring-up calibration waits for calib_done with no timeout, because it genuinely does not know how long the search will take and inventing a deadline would mean declaring success or failure without evidence. Periodic recalibration is bounded by RECAL_CYCLES, because it is interrupting real traffic and §4 established that it must be brief — a periodic pass that could run indefinitely is a hang, not a calibration.

9. Corner Cases

SituationCorrect behaviourFailure if mishandled
traffic offered before L_OPERrefused by 19.1's stage; error flagged§1's cold-boot failure, in hardware
calib_done and calib_failed togetherfailure wins; error flaggedan unusable PHY presented as operational
calib_failed during bring-upreturn to L_RESET, settings clearedproceeding with settings that do not work
calib_failed during recalibrationreturn to L_RESETcontinuing on values known to be bad
clocks_stable never assertsmachine waits in L_CLKa timeout that declares readiness it cannot verify
calib_done never assertsmachine waits in L_CALthe same, at the more damaging step
recalibration while a write is in flightsettings stay valid; in-flight offset already loadeda launch offset that shifts mid-transaction
recal_enable lowstays in L_OPER indefinitelydrift accumulating with no correction
RECAL_CYCLES = 1RCL_W guarded; one-cycle passzero-width counter
reset during L_OPERfull sequence repeats; settings clearedstale settings trusted after a reset
ivl_cnt saturation with recal_enable lowinterval counter saturates harmlesslya wrap that triggers recalibration at a wrong time

The two “never asserts” rows are deliberate design decisions, not oversights. A lifecycle that times out and proceeds is claiming knowledge it does not have: if calibration has not reported success, the settings are not established, and declaring operational anyway produces exactly the failure the machine exists to prevent. A hang in L_CAL is a visible, diagnosable condition; a false phy_operational is not. Where a timeout is genuinely wanted it belongs at system level, with a defined recovery, rather than as a silent promotion inside this block.

10. What the Assertions Prove

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ── P1. THE property of the chapter. Traffic is accepted only while
//    operational -- §1's failure, caught at the moment of acceptance
//    rather than as unexplained corruption several cycles later.
property p_no_traffic_before_operational;
  @(posedge clk) disable iff (!rst_n)
    ctrl_traffic_accepted |-> phy_operational;
endproperty
a_no_traffic_before_operational: assert property (p_no_traffic_before_operational);

// ── P2. Operational is reachable only through the full sequence. The
//    ordering property: catches a machine that skips a step, which is
//    the structural form of the same bug.
property p_operational_only_via_calibration;
  @(posedge clk) disable iff (!rst_n)
    $rose(phy_operational)
      |-> $past(lifecycle_state == 3'd3 || lifecycle_state == 3'd5, 1);
endproperty
a_operational_only_via_calibration: assert property (p_operational_only_via_calibration);

// ── P3. A calibration failure never yields an operational PHY on the
//    next cycle. The one outcome §9 says must be impossible.
property p_failure_never_operational;
  @(posedge clk) disable iff (!rst_n)
    (lifecycle_state == 3'd3 && calib_failed) |=> !phy_operational;
endproperty
a_failure_never_operational: assert property (p_failure_never_operational);

// ── P4. Settings survive a recalibration pass. §6: the previous
//    values stay usable while new ones are found, and clearing
//    validity here would tell 19.3 and 19.4 they have nothing to use
//    when in fact they have something slightly stale.
property p_settings_survive_recal;
  @(posedge clk) disable iff (!rst_n)
    (recal_active && trained_valid && !calib_failed) |=> trained_valid;
endproperty
a_settings_survive_recal: assert property (p_settings_survive_recal);

// ── P5. Recalibration is bounded. An unbounded periodic pass is a
//    hang that presents as a memory system which stops responding.
property p_recal_terminates;
  @(posedge clk) disable iff (!rst_n)
    $rose(recal_active) |-> ##[1:RECAL_CYCLES+1] !recal_active;
endproperty
a_recal_terminates: assert property (p_recal_terminates);

// ── Covers. Every one of these is a path a happy-path bring-up test
//    never reaches, and P3 through P5 check nothing without them.
c_calib_failure:  cover property (@(posedge clk) disable iff (!rst_n)
                    lifecycle_state == 3'd3 && calib_failed);
c_recal_pass:     cover property (@(posedge clk) disable iff (!rst_n)
                    $rose(recal_active) ##[1:$] $fell(recal_active));
c_traffic_early:  cover property (@(posedge clk) disable iff (!rst_n)
                    ctrl_traffic_accepted && !phy_operational);
c_full_sequence:  cover property (@(posedge clk) disable iff (!rst_n)
                    lifecycle_state == 3'd1 ##[1:$] lifecycle_state == 3'd2
                    ##[1:$] lifecycle_state == 3'd3 ##[1:$] lifecycle_state == 3'd4);

What they prove. That readiness has a cause: traffic is gated on it, it is reachable only through the full sequence, a calibration failure cannot produce it, settings survive a refresh, and a periodic pass terminates.

What they do not prove — and on this block the limitation is categorical. Nothing here establishes that the settings calibration produced are good. calib_done is an input; this block trusts it completely and has no means not to. A calibrator that reports success having selected settings at the very edge of the margin satisfies every property above, and the resulting system works in the lab and fails in the field at temperature.

That gap is not closable in RTL, and recognising it is the point of the chapter's placement. Whether a trained value is good — whether it sits in the centre of a working range rather than at its edge — is measured, not asserted, and Module 21 is where measuring it properly is the subject. Module 28 is where the consequences of doing it badly are diagnosed.

Vacuity. c_full_sequence is the cover that matters most: without it, a test that never completes bring-up satisfies P2 and P3 trivially. P5's bounded window makes it genuinely falsifiable, unlike an ##[1:$] formulation which would be satisfied by any eventual exit.

11. DV — Checking a Sequence, Not a Datapath

There is no data here, so the independent model is a shadow sequencer: an enumeration of the five events of §1, advanced independently from observed inputs rather than from the RTL's state register.

Maintain a reference position in the sequence. On each observed input assertion, advance it if and only if the sequence permits. Then check three things the RTL never states: that the observed lifecycle_state matches the reference position, that phy_operational is high only at the final position, and that every transition to operational was preceded by an observed calib_done — reconstructed from the input stream, not read from the state.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  LIFECYCLE ORDERING VIOLATION
    cycle                    : 3,204
    boot type                : COLD (settings_established was 0)

    observed input sequence  : rst_n released   @ 3,180
                               clocks_stable    @ 3,186
                               init_done        @ 3,191
                               calib_done       @ never

    RTL phy_operational      : asserted @ 3,204
    reference position       : INIT_DONE  (step 3 of 5)

    diagnosis : the PHY declared itself operational without a
                calibration completion. Every setting the aligner and
                the gate will consume is whatever the registers held.
    predicted symptom : first reads return displaced or corrupt data;
                first writes land where nothing is sampling.
    why it may look intermittent : on a WARM reset the registers
                retain the previous boot's settings, so the same bug
                produces a working interface. The fault is present in
                both cases and visible only in one.
    caught by : P1 if traffic is offered; P2 on the transition itself

The why it may look intermittent block is the reason this report is worth building. The same defect produces a passing system and a failing one depending on boot type, and a report that does not say so invites the conclusion that cold boot has a different bug.

Directed cases worth running: a cold boot with each input withheld in turn, confirming the machine waits rather than proceeding; calib_done and calib_failed asserted together; a failure during L_RECAL; a reset landing in each state; recal_enable low across the interval boundary; and RECAL_CYCLES = 1.

12. Synthesis and What Is Missing

Cost. Three state bits, an interval counter sized by RECAL_INTERVAL, a short recalibration counter, and one sticky flag. For a 4096-cycle interval that is thirteen bits of counter — trivial, and instantiated once per PHY rather than per lane, unlike 19.3's aligner and 19.4's gate.

What a production lifecycle has that this does not:

  • The calibration engine itself, or the interface to the firmware that is running it — and 19.1 §3 established that which of those it is varies by implementation.
  • Per-lane calibration status, because lanes are trained independently and one can fail while others succeed.
  • Retry and fallback. A real bring-up that fails calibration usually retries, often at a lower rate, before giving up. This block returns to reset and repeats, which is the simplest defensible behaviour and not the only one.
  • Coordination with the controller's own maintenance. Chapter 17.3's refresh manager and a periodic recalibration both need the device quiet, and a real system arbitrates between them rather than letting them collide.
  • Low-power state transitions, which interact with clock stability and can invalidate settings.
  • Reporting of margin, not just success — knowing how much margin a calibration achieved is what turns a pass/fail into a health indicator.

13. Debugging

Symptom: works after a warm reset, fails from cold. §1. Check phy_operational's derivation before anything else — this signature is produced by an ordering assumption far more often than by a power or device problem, and it is the cheapest thing in the list to rule out. err_traffic_while_not_operational names it directly.

Symptom: the interface hangs during bring-up and never becomes ready. Read lifecycle_state. It is three bits and it says exactly which step did not complete: L_CLK means the clock resource never reported lock, L_INIT means the initialisation sequence did not finish, L_CAL means calibration never reported. Each points at a different subsystem, and §9 explains why the machine waits rather than timing out.

Symptom: works at bring-up, degrades after sustained load. Drift (§4). Check whether recal_enable is asserted and whether recalibration is actually running — recal_active should pulse at the configured interval. A system with periodic calibration disabled shows exactly this and looks like a thermal problem, which in a sense it is.

Symptom: one lane fails calibration and the rest pass. Per-lane physics or per-lane state (19.3 §5). Not this block, which has no per-lane status — §12 lists that as a production omission precisely because it is the first thing a real bring-up needs.

Symptom: intermittent failures that correlate with nothing obvious. Consider whether calibration succeeded marginally. §10 is explicit that nothing in RTL distinguishes a setting at the centre of its working range from one at the edge, and a marginal pass behaves exactly like a good one until conditions move. This is Module 21's centring problem and Module 28's diagnostic territory.

Symptom: transactions corrupt around a recalibration. Check that in-flight state is unaffected: 19.3 §9's aligner loads its offset at the command and 19.4 §9's gate does the same. A design that applies a new setting immediately rather than at the next transaction boundary produces corruption that correlates with the recalibration interval — which is a very distinctive period once you think to look for it.

14. Misconceptions

“PHY ready means reset is deasserted.” §1 — five events, not one. Consequence: traffic issued into an uncalibrated interface. Clue: phy_operational wired to rst_n, and a cold-boot-only failure.

“Training is optional tuning.” The values are not computable (19.3 §2); without them there is no correct offset or gate position to use. It is a prerequisite, not an optimisation. Clue: a bring-up plan that lists training as a performance step.

“Training happens once.” §4 — the physical quantities move with temperature and voltage. Clue: a design with no periodic path, degrading under sustained load.

“Calibration and ZQ calibration are the same thing.” §3 — different die, different state, different symptoms. Clue: a debug effort on the wrong side of the interface.

“This chapter explains how training works.” It explains when it runs and what depends on it. The algorithms are Module 21's, and treating a lifecycle diagram as an understanding of training is the trap this chapter is placed before that module to avoid. Clue: an answer about training that describes states rather than searches.

“If calibration reports success the settings are good.” §10 — a marginal pass satisfies every property. Clue: sign-off with no margin measurement.

“A timeout is a safe way to handle a calibration that does not complete.” §9 — proceeding without evidence produces a false readiness, which is strictly worse than a visible hang. Clue: a lifecycle that declares operational after a fixed count.

“Settings must be invalidated during recalibration.” §6 — the old values stay usable until new ones replace them. Invalidating them makes a brief refresh into a full outage. Clue: traffic stalling far longer than the recalibration window.

15. Interview Reasoning

“Why can't the controller issue traffic as soon as reset is released?” Because four more things must happen first, and the last of them establishes values that cannot be computed. The strong answer names the cold-boot-versus-warm-reset signature unprompted.

“Why does a PHY need calibration at all?” Because the timing it must meet depends on this board and this part, which no datasheet can state. Then the consequence: the value must be found by measurement, which takes time and must happen before traffic.

“Why is calibration not a one-time bring-up activity?” Because the quantities drift with temperature and voltage. Then the structural analogy: periodic recalibration is a maintenance obligation on the controller's time, like refresh.

“What is the difference between ZQ calibration and PHY calibration?” Different sides of the interface, different state, different failure character — electrical versus positional.

“Your lifecycle hangs in the calibrating state. Is that a bug?” It is a report. It says calibration never completed, which is diagnosable; the alternative — timing out and declaring readiness — hides the same fault behind data corruption.

“What can simulation prove about calibration?” The ordering and the gating. Not that the settings are good, because goodness is a margin measured on hardware. Volunteering the second half is the discriminator.

“Why do settings stay valid during a recalibration pass?” Because slightly stale values are strictly better than none, and invalidating them would turn a brief refresh into an outage.

16. Exercises

1. List the five events of §1 and, for each, name one thing that would go wrong if the controller began issuing traffic immediately after it.

2. A design asserts phy_operational 64 cycles after reset release. Give the test that passes, the test that fails, and explain why the passing one is the misleading result.

3. With RECAL_INTERVAL = 4096 and RECAL_CYCLES = 16, what fraction of time is traffic held off by recalibration? State the assumption your answer depends on.

4. calib_done and calib_failed assert together. Trace the FSM and say which state results and why the order of the checks in L_CAL matters.

5. Write the property asserting that trained_valid never rises without a preceding calib_done. Why is that stronger than P2?

6. A colleague clears settings_established on entry to L_RECAL. Describe what 19.3's aligner and 19.4's gate report, and what the system does for the duration of the pass.

7. All ten properties pass on a calibrator that selects settings at the extreme edge of the working range. Describe the field behaviour, and name the module that owns preventing it.

8. Explain why L_CAL is unbounded and L_RECAL is bounded, in terms of what each is interrupting.

17. Module 19, Complete

Five chapters, one boundary.

The PHY exists because some functions cannot be written in portable RTL. Chapter 19.1 drew the controller/PHY/DRAM split, marked the six functions whose ownership genuinely varies between implementations, and named the structures — delay elements, capture circuitry, clock resources — that are technology-specific rather than logical.

The width-versus-rate conversion is genuinely digital. 19.2 built both gearboxes, established that the transmit side can be stalled and the receive side cannot, and stopped at named abstractions in both directions.

Command and data take different paths. 19.3 decomposed the launch offset into a programmed term anyone can compute and a measured term nobody can — a decomposition that reappeared on the receive side and explains why every failure in this module has a population signature.

The strobe is authored on transmit and estimated on receive. 19.4 built the gate, showed the two ways to misplace it, and established that its correctness is a containment relationship against a window the PHY cannot see.

And none of it works until the sequence completes. This chapter supplied phy_operational, trained_valid and gate_trained, and explained why reset release is not readiness and why calibration does not finish.

The discipline every chapter repeated, because it is the one thing most likely to be misunderstood: every block here is genuinely correct and genuinely insufficient. A gearbox that orders beats perfectly, an aligner that counts cycles exactly, a gate that opens and closes on cue — all of it can be right while the interface does not function, because the quantity that decides is sub-cycle and no portable RTL contains a representation of it.

What Module 19 did not build is the rest: no capture, no training algorithms, no electrical analysis, no PLL, no delay line, no production PHY. Each chapter's limits section names its own omissions.

Module 20 opens the box marked CAPTURE — how DQ is actually sampled on DQS edges, and what makes a sampling point correct. Module 21 opens the search that produces every opaque value this module consumed. Module 22 explains why the signals look the way they do when they arrive.

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.