Skip to content
VLSI Mentor

DDR · Module 34

“Training Happens Only Once”

Most training steps really do run once, and the chapter that says so opens by stating that some trained values stop being correct while the system is running. Six of eight values need re-establishing, and five are invalidated by a frequency change alone.

“Training runs at boot. Once the PHY is trained, it is trained.”

34.4 §24 named the change of object: three beliefs about numbers, one about a component's nature, and this one about a process's lifetime. DERIVED: a lifetime belief is refuted by neither arithmetic nor a census but by a state machine — the question is what states a trained value can be in, and how it leaves the one the belief thinks is terminal.

This belief is unusual in this module for a specific and uncomfortable reason: it is refuted in the second paragraph of the chapter that teaches it. CURRICULUM-DERIVED from 19.5 §2: “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.

DERIVED: so this chapter is not supplying missing information. It is about why a reader who has that sentence still holds the belief — and the answer is that the belief is true of most of the values, most of the time, and the exceptions are invisible until a condition changes that nobody was watching.

1. The One-Sentence Correction

Training establishes values that are functions of temperature, supply voltage and frequency — so a trained value has a validity lifetime, not a completion, and the boot-time search is the first of an indefinite sequence whose later members are triggered by conditions rather than by a schedule.

CURRICULUM-DERIVED from 19.5 §4, which owns the one-time versus continuous split and states it without hedging: “Calibration is not a bring-up activity that completes.” The physical quantities “are not constants — they are functions of temperature and supply voltage, both of which move.”

2. What This Chapter Owns

GroundOwner
The PHY lifecycle; one-time versus continuous; when a value becomes or stops being valid19.5
The recalibration pass's three requirements — brief, non-corrupting, schedulable19.5 §4, 19.5 §6
Every training algorithm, and the sequencer's state machine including RETRAIN HOLD21.5
The dependency structure, and which steps repeat versus run once21.5
Write levelling, read levelling, gate training, eye centring21.121.4
Retention and its temperature dependence15.4
The five meanings of a calibration done flag; provenance and staleness28.4
Reviewing which reset a trained register survives, and recalibration preconditions33.3 §9, 33.3 §10
The eleven bitmap signatures when training reports failure28.1
Why the belief survives 19.5 §2, and the lifetime census that dislodges itthis chapter

Two boundaries, and the first is the tightest in this module.

With 19.5: that chapter owns the lifecycle, the split, and the recalibration pass's requirements. It is addressed to somebody designing the lifecycle. DERIVED: this chapter is addressed to somebody who has read it and still assumes a trained value is permanent — which is a different failure, and §8's census is the instrument that surfaces it because a count is harder to skim past than a sentence.

With 33.3 §10: that item reviews whether a recalibration's preconditions are enforced. DERIVED: it presumes a recalibration exists. This chapter is about the system that has none, so §10's trigger census is upstream of 33.3's precondition review.

3. Teaching-Model Boundary And Source Discipline

Claim classWhat it means hereExample below
Structurala documented mechanism of this trackthe one-time/continuous split; the RETRAIN HOLD state; the five done meanings
Curriculum-derivedfollows from a cited chapterevery trigger, and the validity lifecycle's states
Derivedcomputed in this chapter from the models belowevery count and drift figure in §19
Illustrativea chosen number that makes a mechanism visibletemperatures, drift rates, tap counts, intervals

Every physical quantity here is ILLUSTRATIVE. CURRICULUM-DERIVED from 20.3's standing statement that sample quality is not digitally observable: a model in SystemVerilog cannot represent an eye or a volt, so every model below represents the digital belief a design holds about a physical value — a validity bit, a timestamp, a trigger mask. DERIVED: those are exactly what the misconception is about, which is why they are the right objects.

The drift rates are chosen, not derived. CURRICULUM-DERIVED from 21.4 and 20.5, which own eye width and the published window figures: a real drift-versus-temperature curve comes from characterisation, and this chapter derives none.

No external source was consulted and no network tool was used.

4. Why a Competent Engineer Believes It

#The true statementWhat the belief does with it
1Most training steps run once — write levelling, gate trainingtreats the majority as the whole
2The boot sequence runs training once, and then bootstreats the caller's structure as the value's lifetime
3At constant temperature, voltage and frequency, the values stay validtreats the lab condition as the operating condition
4A done flag asserts once and stays assertedtreats a monotonic flag as a statement about a non-monotonic value

Reason 2 is the structural one and it is the most interesting, because the belief is reading a real fact off the wrong object. DERIVED: the boot sequence is one-shot, and the belief transfers that property to the values the sequence produced. CURRICULUM-DERIVED from 21.5, which owns the sequencer and whose state machine has a RETRAIN HOLD state distinct from IDLEso the track's own sequencer is not one-shot, and the belief survives because a reader of the flow diagram sees a path from start to done and stops there.

Reason 4 is 28.4's territory and it is the cheapest to refute. CURRICULUM-DERIVED from 28.4 §2: a done flag can mean five different things, and the fifth “produces a system which boots, passes its own self-checks, and corrupts data hours later.” DERIVED: a flag that only ever rises cannot represent a value that can fall — which is 33.3 §7's item, and it is the same observation from the review side.

And reason 1 deserves its number, because the majority is real. DERIVED: of the training steps Module 21 builds, write levelling and gate training genuinely are one-time in most systems — so the belief is right about two of four searches, and §8 is the census that makes two of four visible instead of training.

5. The Region Where the Claim Is True

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   "TRAINING HAPPENS ONLY ONCE" HOLDS WHEN ALL FIVE HOLD:

     1  temperature CONSTANT          -> no drift in the eye
     2  supply voltage CONSTANT       -> no drift in the reference
     3  frequency CONSTANT            -> the trained set stays applicable
     4  no power-state transitions    -> nothing is powered down and back
     5  no warm reset                 -> nothing clears a trained register

   and then:  the boot-time values remain correct indefinitely, and
              the belief is exactly right

DERIVED: the region is non-empty and it is the bench. A board on a desk at room temperature, at one frequency, never suspended, reset only by power-cycling, satisfies all five for as long as anybody watches it.

CURRICULUM-DERIVED from 19.5 §4, whose sentence names exactly which two conditions fail in the field: the quantities “are functions of temperature and supply voltage, both of which move. DERIVED: conditions 1 and 2 are the ones the specification's authors expected to fail, and conditions 3 through 5 are the ones a system integrator adds — DVFS, suspend-resume, and a warm reset path.

Condition 3 is the one most often overlooked, and it is not a drift. DERIVED: a frequency change does not invalidate a trained value by drift — it makes the value inapplicable, because the value was in units of a delay against a period that changed. CURRICULUM-DERIVED from 19.3 §2's decomposition into a programmed term and a measured term: the measured term is a physical time, and the count representing it is period-dependent.

6. The Boundary, Computed

ExitConditionWhat becomes invalidOwner
1temperature crosses a drift thresholdthe eye's centre; Vref19.5 §4, 21.4
2supply voltage movesthe reference level19.5 §4
3frequency changesevery count in units of cycles19.3 §2
4power-down exitthe DLL's lock; possibly the gate19.5 §2
5warm resetwhatever the reset domain clears33.3 §9
6the periodic interval elapsesZQ and drift-tracked values7.7, 19.5 §4

Exit 3 is the one with the largest consequence and the least warning, so it gets the arithmetic. ILLUSTRATIVE: a trained flight time of 2.8 ns at 1.25 ns per cycle is 2.24 cycles, rounded to 2. At 0.625 ns per cycle the same 2.8 ns is 4.48 cycles, which is 4so the count changes and the physical quantity did not.

DERIVED: a design that keeps one trained set across a frequency change applies a count derived at the wrong period, and the error is proportional to the frequency ratio. CURRICULUM-DERIVED from 33.3 §6's calculated-versus-measured line: the trained value is the measured term, and converting it to cycles is the calculated step — so the conversion must be redone even when the measurement need not be.

And exit 5 is the one 33.3 §9 measures as a review finding, which makes it the cheapest of the six to check. CURRICULUM-DERIVED: that item's weak build passes every cold boot and fails after one warm reset, because the trained registers sat in the functional reset domain while the retrain trigger sat in the power-on domain.

7. What State Is a Trained Value In?

The diagram earns its place because the belief is a claim that one state is terminal, and a state machine is the only representation in which terminal is a visible property.

This is the value's lifecycle, not the sequencer's. 21.5 owns the sequencer's state machine, including its RETRAIN HOLD state; this is the object that machine produces.

A trained value's validity lifecycle. It begins never-valid, becomes valid when a search commits, and can leave valid by drift, by a frequency change, by a power-down exit or by a reset that clears it. Valid is not a terminal state.NEVERVALIDSEARCHINGVALIDSTALEINAPPLICABLEbootbootcommittedcommittedfailedfaileddrift / intervaldrift / intervalretrainretrainfrequency changefrequency changeretrain for the binretrain for the binreset clears itreset clears it

The belief is the claim that VALID has no outgoing edges. It has four. DERIVED: two are drift-driven and internal to the PHY, one is a system action (a frequency change), and one is a reset-domain consequenceso the four edges belong to three different owners, which is why no single team notices all of them.

INAPPLICABLE is a separate state from STALE on purpose, and the distinction is the one §6's exit 3 turns on. DERIVED: a stale value was correct and drifted; an inapplicable value is still physically correct and its encoding no longer matches the period. A design that treats a frequency change as drift re-runs the full search where a re-conversion would have done, and one that treats it as nothing applies the wrong count.

8. The Lifetime Census

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST MODEL: every trained value carries a LIFETIME class, so
// "training" stops being one thing. 19.5 section 4's one-time versus
// continuous split, made a per-value property.
package value_lifetime_pkg;
  typedef enum int {
    L_ONE_TIME,      // valid until a reset clears it
    L_PERIODIC,      // re-established on an interval
    L_EVENT_DRIVEN,  // re-established on a named condition
    L_PER_FREQUENCY  // one set per operating point
  } lifetime_e;

  typedef struct {
    string     name;
    lifetime_e lifetime;
    bit        drifts_with_temp;
    bit        drifts_with_voltage;
    bit        period_dependent;
  } tv_t;

  // ILLUSTRATIVE assignment over the searches Module 21 builds plus the
  // calibrations 19.5 and 7.7 own.
  tv_t VALUES[] = '{
    '{"write_level_delay",  L_ONE_TIME,      1'b0, 1'b0, 1'b1},
    '{"gate_offset",        L_ONE_TIME,      1'b0, 1'b0, 1'b1},
    '{"read_level_delay",   L_PER_FREQUENCY, 1'b1, 1'b0, 1'b1},
    '{"vref_host",          L_PERIODIC,      1'b1, 1'b1, 1'b0},
    '{"vref_device",        L_PERIODIC,      1'b1, 1'b1, 1'b0},
    '{"zq_drive_strength",  L_PERIODIC,      1'b1, 1'b1, 1'b0},
    '{"dll_lock",           L_EVENT_DRIVEN,  1'b0, 1'b0, 1'b1},
    '{"flight_offset",      L_PER_FREQUENCY, 1'b1, 1'b0, 1'b1}
  };
endpackage

module value_lifetime_census #(
    parameter int NV = 8
)(
    input  logic       clk,
    input  logic       rst_n,
    input  logic       audit,
    output logic [3:0] one_time_count,
    output logic [3:0] revisited_count,
    output logic [3:0] temp_sensitive,
    output logic [3:0] period_dependent_count,
    output logic       all_one_time,
    output logic [7:0] revisited_share_pct
);
  import value_lifetime_pkg::*;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      one_time_count <= '0; revisited_count <= '0; temp_sensitive <= '0;
      period_dependent_count <= '0; all_one_time <= 1'b0;
      revisited_share_pct <= '0;
    end else if (audit) begin
      automatic int ot = 0, rv = 0, ts = 0, pd = 0;
      foreach (VALUES[i]) begin
        if (VALUES[i].lifetime == L_ONE_TIME) ot++; else rv++;
        if (VALUES[i].drifts_with_temp)       ts++;
        if (VALUES[i].period_dependent)       pd++;
      end
      one_time_count         <= 4'(ot);
      revisited_count        <= 4'(rv);
      temp_sensitive         <= 4'(ts);
      period_dependent_count <= 4'(pd);
      // The belief, as a predicate.
      all_one_time           <= (rv == 0);
      revisited_share_pct    <= 8'((rv * 100) / NV);
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK MODEL: one lifetime for all of them.
//
//   // "training" is a phase, so its outputs share its lifetime
//   localparam lifetime_e TRAINING_LIFETIME = L_ONE_TIME;
//   all_one_time    <= 1'b1;            // <-- the defect
//   revisited_count <= '0;
//
// CONTRACT VIOLATED: 19.5 section 4's split. And the weak model is right
// about two of the eight values -- write levelling and gate training
// really are one-time.
//
// TRACE (ILLUSTRATIVE, the eight values above):
//   robust: one_time 2, REVISITED 6, temp_sensitive 5,
//           period_dependent 5, all_one_time 0,
//           revisited_share 75%
//   weak:   one_time 8, revisited 0, all_one_time 1
//
//   gap: six of eight values need re-establishing and the belief plans
//   for none. And the split is not 50/50 in the belief's favour -- it
//   is 75% against, which is why a census dislodges the belief where a
//   sentence does not.
//
//   The five period-dependent values are the sharpest sub-finding:
//   they are not DRIFTING, they are ENCODED against a clock period, and
//   a DVFS transition invalidates all five at once with no physical
//   change whatsoever.

75% is the number, and it is why this chapter exists despite 19.5 §2 already containing the correction. DERIVED: a sentence saying some values stop being correct is read as an exception; a census reporting six of eight is read as the rule.

And the five period-dependent values are the sub-finding worth carrying. DERIVED: they are invalidated by an event that changes no physical quantity at all — a frequency change — so they are outside the drift framing that 19.5 §4 supplies and outside the periodic framing too. CURRICULUM-DERIVED from 19.3 §2: the measured term is a physical time and the count is a conversion, so a DVFS transition is a re-conversion event, and §14 measures what happens when it is treated as neither.

9. A Value That Can Fall

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST MODEL: validity is a function of the CONDITIONS the value was
// measured under, so it can fall without anything failing. 19.5
// section 2's "stop being correct while the system is running".
module validity_tracking #(
    parameter int TAP_W       = 6,
    parameter int TEMP_DELTA  = 10,   // ILLUSTRATIVE degrees before stale
    parameter int STALE_TICKS = 512   // ILLUSTRATIVE
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             commit,
    input  logic [TAP_W-1:0] committed_tap,
    input  logic [7:0]       temp_now,
    input  logic             tick,
    input  logic             freq_changed,
    output logic [TAP_W-1:0] tap_in_use,
    output logic             valid,
    output logic             stale,
    output logic             inapplicable,
    output logic [7:0]       temp_at_commit,
    output logic [15:0]      age,
    output logic [15:0]      validity_falls,
    output logic [15:0]      used_while_invalid
);
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      tap_in_use <= '0; valid <= 1'b0; stale <= 1'b0;
      inapplicable <= 1'b0; temp_at_commit <= '0; age <= '0;
      validity_falls <= '0; used_while_invalid <= '0;
    end else begin
      if (commit) begin
        tap_in_use     <= committed_tap;
        valid          <= 1'b1;
        stale          <= 1'b0;
        inapplicable   <= 1'b0;
        // The provenance that makes validity computable later --
        // 28.4's "what a committed value was calibrated AGAINST".
        temp_at_commit <= temp_now;
        age            <= '0;
      end

      if (valid) begin
        // Drift: the condition moved away from the one measured at.
        automatic logic [7:0] d = (temp_now > temp_at_commit)
                                ? (temp_now - temp_at_commit)
                                : (temp_at_commit - temp_now);
        if (d >= 8'(TEMP_DELTA)) begin
          valid <= 1'b0; stale <= 1'b1;
          validity_falls <= validity_falls + 1'b1;
        end else if (tick && (age == 16'(STALE_TICKS))) begin
          valid <= 1'b0; stale <= 1'b1;
          validity_falls <= validity_falls + 1'b1;
        end else if (tick) begin
          age <= age + 1'b1;
        end

        // A frequency change makes it INAPPLICABLE, not stale: the
        // physical measurement is still right and its encoding is not.
        if (freq_changed) begin
          valid <= 1'b0; inapplicable <= 1'b1;
          validity_falls <= validity_falls + 1'b1;
        end
      end

      // The escape counter: a consumer using the value while it is
      // neither valid nor re-established.
      if (!valid && (tap_in_use != '0) && !stale && !inapplicable)
        used_while_invalid <= used_while_invalid + 1'b1;
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK MODEL: validity is monotonic.
//
//   if (commit) begin
//     tap_in_use <= committed_tap;
//     valid      <= 1'b1;          // and it never falls
//   end
//   // no temp_at_commit, no age, no freq_changed handling
//
// CONTRACT VIOLATED: 19.5 section 2 -- "some of those values stop being
// correct while the system is running" -- and 28.4 section 2's fifth case.
//
// WHY IT SURVIVES: it is correct for the whole of a bench session, and
// it is correct FOREVER for the two genuinely one-time values. A
// monotonic valid bit is also what a boot flow wants, because a boot
// flow asks "is it trained yet" and never asks "is it still".
//
// TRACE (ILLUSTRATIVE, a 90-minute run: 25C at boot, rising to 70C,
// one DVFS transition at minute 40):
//   robust: commit at boot, temp_at_commit 25
//           minute 18, temp 35: d = 10 -> valid 0, stale 1
//                               validity_falls 1, retrain
//           minute 40, freq change: valid 0, inapplicable 1
//                               validity_falls 2, retrain for the bin
//           minute 61, temp 60: d = 10 from the last commit -> stale
//                               validity_falls 3
//           total: 3 falls, 3 retrains, used_while_invalid 0
//   weak:   valid 1 from boot to the end. 0 falls, 0 retrains.
//           and the tap in use at minute 90 was measured at 25C
//           against a period that changed at minute 40.
//
//   gap: three invalidations in ninety minutes, none of them detected,
//   and the final operating point is a value measured under two
//   conditions that no longer hold.

Three invalidations in ninety minutes is the measured refutation, and the run is not adversarial. DERIVED: a 45-degree rise over an hour and one DVFS transition describe a laptop opening a browserso the belief's region is left by ordinary use, not by stress.

And used_while_invalid reading zero in both builds is the trap worth naming. DERIVED: the weak build never reports using an invalid value because it never has one — validity is monotonic, so the counter's antecedent cannot occur. CURRICULUM-DERIVED from 33.3 §7's item on a done flag's five meanings: a flag that cannot fall makes every downstream check vacuous, and the vacuity is invisible because the check passes.

10. The Trigger Census

§6 lists six exits. A design's retraining trigger set either contains all six or silently treats the missing ones as nothing happened.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST MODEL: the trigger set is declared and audited against the
// exits, so a missing trigger is a finding rather than an absence.
module retrain_trigger_coverage #(
    parameter int NTRIG = 6
)(
    input  logic       clk,
    input  logic       rst_n,
    input  logic       audit,
    input  logic [5:0] triggers_implemented,  // one bit per exit
    // live events, to show which fire in practice
    input  logic [5:0] event_now,
    output logic [3:0] implemented_count,
    output logic [3:0] missing_count,
    output logic [5:0] missing_mask,
    output logic       coverage_complete,
    output logic [5:0] unhandled_events,
    output logic [15:0] unhandled_event_count
);
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      implemented_count <= '0; missing_count <= '0; missing_mask <= '0;
      coverage_complete <= 1'b0; unhandled_events <= '0;
      unhandled_event_count <= '0;
    end else begin
      if (audit) begin
        implemented_count <= 4'($countones(triggers_implemented));
        missing_count     <= 4'(NTRIG - $countones(triggers_implemented));
        missing_mask      <= ~triggers_implemented & 6'h3F;
        coverage_complete <= ($countones(triggers_implemented) == NTRIG);
      end
      // An event with no trigger is silently absorbed -- which is the
      // whole mechanism by which the belief survives in a running
      // system.
      unhandled_events <= event_now & ~triggers_implemented;
      if ((event_now & ~triggers_implemented) != '0)
        unhandled_event_count <= unhandled_event_count
                               + 16'($countones(event_now & ~triggers_implemented));
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   TRIGGER COVERAGE IN A TYPICAL DESIGN   (ILLUSTRATIVE)

     exit                       implemented?   events in 90 min
     1 temperature threshold        no                2
     2 voltage movement             no                0
     3 frequency change             no                1
     4 power-down exit             YES                7
     5 warm reset                  YES                1
     6 periodic interval            no               10

   robust: implemented 2 of 6, missing 4,
           missing_mask names temp, voltage, frequency, periodic
           unhandled_event_count 13
   weak:   coverage_complete reported on a 2-trigger set, because the
           set the design has is the set it declared

   DERIVED: 13 events in 90 minutes were absorbed with no retraining.
   And the two triggers that ARE implemented are the two that are
   impossible to miss -- a power-down exit and a reset both have an
   obvious hook, while a temperature threshold needs somebody to
   decide to watch a sensor.

The implemented pair being the obvious two is the finding, and it generalises beyond this belief. DERIVED: power-down exit and warm reset both arrive as events with an existing code path, and the four missing triggers all require somebody to create an observation — a sensor comparison, a voltage monitor, a DVFS hook, a timer. CURRICULUM-DERIVED from 33.6 §6's gate-criterion item: a criterion that requires a positive observation costs more than one that rides an existing event, and the cheap ones get built.

11. Per-Frequency Sets

§8 found five of eight values period-dependent and §6's exit 3 is the largest. This is the mechanism.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST MODEL: one trained set PER operating point, because a count in
// cycles is meaningless at another period -- 19.3 section 2's decomposition.
module per_frequency_set #(
    parameter int NBIN  = 3,
    parameter int TAP_W = 6
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic [1:0]       bin_now,
    input  logic             commit,
    input  logic [TAP_W-1:0] committed_tap,
    input  logic [15:0]      period_x100,     // ILLUSTRATIVE ps x100
    output logic [TAP_W-1:0] tap_in_use,
    output logic             set_valid,
    output logic [2:0]       bins_trained,
    output logic             needs_training,
    output logic [15:0]      wrong_bin_uses,
    output logic [TAP_W-1:0] would_be_tap     // the correct tap here
);
  logic [TAP_W-1:0] tap_of  [0:NBIN-1];
  logic             val_of  [0:NBIN-1];
  logic [15:0]      per_of  [0:NBIN-1];

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      tap_in_use <= '0; set_valid <= 1'b0; bins_trained <= '0;
      needs_training <= 1'b1; wrong_bin_uses <= '0; would_be_tap <= '0;
      for (int b = 0; b < NBIN; b++) begin
        tap_of[b] <= '0; val_of[b] <= 1'b0; per_of[b] <= '0;
      end
    end else begin
      if (commit) begin
        tap_of[bin_now] <= committed_tap;
        val_of[bin_now] <= 1'b1;
        per_of[bin_now] <= period_x100;
      end

      // Selection is indexed by the CURRENT bin. A design with one set
      // has no index, which is the defect.
      tap_in_use     <= tap_of[bin_now];
      set_valid      <= val_of[bin_now];
      needs_training <= !val_of[bin_now];
      bins_trained   <= 3'($countones({val_of[2], val_of[1], val_of[0]}));

      // The physical time is invariant; the COUNT is not. If a tap
      // trained at another period were used here, this is what it
      // would have to be -- and the difference is the error.
      if (val_of[bin_now] && (per_of[bin_now] != '0))
        would_be_tap <= TAP_W'((32'(tap_of[bin_now])
                                * 32'(per_of[bin_now])) / 32'(period_x100));
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK MODEL: one set, no index.
//
//   logic [TAP_W-1:0] the_tap;        // <-- one value for all bins
//   if (commit) the_tap <= committed_tap;
//   tap_in_use <= the_tap;
//   set_valid  <= trained_once;
//
// CONTRACT VIOLATED: 19.3 section 2 -- the measured term is a physical time
// and the applied value is a count, so the conversion is
// period-dependent.
//
// WHY IT SURVIVES: on a system that never changes frequency it is
// identical to the robust build, and that includes every bench setup
// and most first bring-ups. DVFS is usually enabled late.
//
// TRACE (ILLUSTRATIVE, flight time 2.8 ns; three bins):
//   bin 0  1.25 ns/cycle  ->  correct tap 2   (2.24 rounded)
//   bin 1  0.833 ns/cycle ->  correct tap 3   (3.36 rounded)
//   bin 2  0.625 ns/cycle ->  correct tap 4   (4.48 rounded)
//
//   robust: trained in bin 0 -> bins_trained 1; entering bin 2 sets
//           needs_training 1 and the search runs. bins_trained 2.
//           wrong_bin_uses 0.
//   weak:   trained in bin 0 -> the_tap 2. Entering bin 2, tap_in_use
//           is still 2 where 4 is correct: an error of 2 taps, which
//           at 0.625 ns/cycle is 1.25 ns of misalignment.
//           set_valid stays 1 and nothing reports anything.
//
//   gap: a 2-tap error at the highest bin, silent, and it appears only
//   after DVFS is enabled -- typically weeks after the PHY was
//   declared working.

The error's appearance weeks after the PHY was declared working is the expensive part. DERIVED: DVFS is usually enabled late in a programme, so the trained set is validated at one bin and the defect surfaces after that validation is considered completewhich is 33.6 §14's unlicensed assumption in a new place: the bring-up gate established this bin works and a later stage assumed the PHY works.

§7 separated STALE from INAPPLICABLE and §11 measured the cost of ignoring the second. This is the cost of over-reacting to it, which is the mistake the correction invites.

CURRICULUM-DERIVED from 19.3 §2, which owns the decomposition of a PHY latency into a part known from the configuration and a part only knowable by measurement. DERIVED: a frequency change alters the configuration term and leaves the measured term untouched — so the correct response is to re-run the conversion, not the search.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST MODEL: the measured physical quantity is stored, and the
// applied count is derived from it at the current period. A frequency
// change costs a division; only drift costs a search.
module reconversion_vs_research #(
    parameter int TAP_W   = 6,
    parameter int PS_W    = 16,
    parameter int SEARCH_CYCLES = 4096   // ILLUSTRATIVE cost of a search
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             search_done,
    input  logic [PS_W-1:0]  measured_ps,      // the PHYSICAL quantity
    input  logic [PS_W-1:0]  period_ps,        // current, changes on DVFS
    input  logic             freq_changed,
    input  logic             drift_detected,
    output logic [TAP_W-1:0] tap_in_use,
    output logic             have_measurement,
    output logic             search_requested,
    output logic [15:0]      searches_run,
    output logic [15:0]      reconversions,
    output logic [31:0]      cycles_spent_searching
);
  logic [PS_W-1:0] held_ps;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      held_ps <= '0; tap_in_use <= '0; have_measurement <= 1'b0;
      search_requested <= 1'b1; searches_run <= '0;
      reconversions <= '0; cycles_spent_searching <= '0;
    end else begin
      search_requested <= 1'b0;

      if (search_done) begin
        // Store the PHYSICAL quantity, not the count. This one choice
        // is the difference between the two builds.
        held_ps          <= measured_ps;
        have_measurement <= 1'b1;
        searches_run     <= searches_run + 1'b1;
        cycles_spent_searching <= cycles_spent_searching
                                + 32'(SEARCH_CYCLES);
      end

      // A frequency change: re-derive the count. No search, no traffic
      // interruption, a handful of cycles.
      if (freq_changed && have_measurement) begin
        reconversions <= reconversions + 1'b1;
      end

      // Drift: the MEASUREMENT is wrong, so a search is unavoidable.
      if (drift_detected) begin
        have_measurement <= 1'b0;
        search_requested <= 1'b1;
      end

      // The applied count, always derived at the current period.
      if (have_measurement && (period_ps != '0))
        tap_in_use <= TAP_W'((32'(held_ps) + 32'(period_ps) - 32'd1)
                             / 32'(period_ps));
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE, TWO WAYS. The correction invites an
// over-reaction, so both errors are shown.
//
// WEAK BUILD A -- store the COUNT, ignore the period:
//   if (search_done) held_tap <= measured_tap;   // a count, not a time
//   tap_in_use <= held_tap;                      // applied at any period
//   -> section 11's defect: the wrong count at the new bin, silently.
//
// WEAK BUILD B -- re-search on every frequency change:
//   if (freq_changed) search_requested <= 1'b1;  // <-- over-reaction
//   -> correct values, and a full search at every DVFS transition.
//
// CONTRACT VIOLATED: 19.3 section 2's decomposition, in both directions --
// A treats the measured term as period-independent, B treats the
// configuration term as unmeasurable.
//
// WHY B SURVIVES REVIEW: it is CORRECT. Every applied value is right,
// every property about validity passes, and the only cost is time --
// 30.3 section 9's variety 8 again, in a PHY flow rather than a timing
// comparison.
//
// TRACE (ILLUSTRATIVE, 40 DVFS transitions and 3 drift events in an
// hour; SEARCH_CYCLES 4096):
//   robust:   searches_run 4 (1 boot + 3 drift), reconversions 40,
//             cycles_spent_searching 16,384
//   weak A:   searches_run 4, reconversions 0,
//             and 40 transitions applied a count from another period
//   weak B:   searches_run 44, reconversions 0,
//             cycles_spent_searching 180,224 -- 11x the robust build
//
//   gap: A is wrong 40 times; B is right and spends 164,000 extra
//   cycles of interrupted traffic. DERIVED: the belief's correction
//   has two failure modes and only one of them is a correctness bug.

Weak build B is the more interesting of the two, because it is what an engineer who has just accepted the correction builds. DERIVED: it is functionally correct and costs 11× the search time, and every property in §15 about validity passes on it. CURRICULUM-DERIVED from 30.3 §9's variety 8: a design that is slower than required violates nothing, so B ships and is later diagnosed as DVFS transitions are expensive on this platform.

And the asymmetry between the two weak builds is the practical guidance. DERIVED: 4 searches against 44 is the difference between storing a picosecond figure and storing a tap index — one declaration. CURRICULUM-DERIVED from 33.3 §6's provenance census: the measured term must be stored in the units it was measured in, and converting on use rather than on commit is what makes a re-conversion possible at all.

13. Scheduling the Interruption

§14 row 5 says the cost is recurring rather than boot-time. 19.5 §4 states three requirements for the pass, and a design built on the belief has met none of them because it does not believe there is a pass.

CURRICULUM-DERIVED from 19.5 §4: a recalibration must be brief, must not corrupt in-flight transactions, and must be schedulable“the same problem 17.3 solved for refresh, with the same shape.”

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST MODEL: recalibration as a schedulable obligation with the
// three requirements enforced -- the same shape 17.3 uses for refresh,
// as 19.5 section 4 says.
module recal_scheduling #(
    parameter int MAX_PASS_CYCLES = 64,    // ILLUSTRATIVE "brief"
    parameter int INTERVAL        = 4096,  // ILLUSTRATIVE
    parameter int MAX_DEFER       = 4      // ILLUSTRATIVE headroom
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             tick,
    input  logic             inflight_txn,
    input  logic             bus_idle,
    input  logic             pass_done,
    output logic             pass_start,
    output logic             pass_active,
    output logic signed [7:0] recal_debt,
    output logic [15:0]      pass_cycles,
    output logic             brief_ok,
    output logic             noncorrupting_ok,
    output logic             schedulable_ok,
    output logic [15:0]      deferrals,
    output logic [15:0]      corrupted_txns
);
  logic [15:0] ivl;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      ivl <= '0; recal_debt <= '0; pass_start <= 1'b0;
      pass_active <= 1'b0; pass_cycles <= '0;
      brief_ok <= 1'b1; noncorrupting_ok <= 1'b1; schedulable_ok <= 1'b1;
      deferrals <= '0; corrupted_txns <= '0;
    end else begin
      pass_start <= 1'b0;

      if (tick) begin
        if (ivl == INTERVAL[15:0]) begin
          ivl        <= '0;
          recal_debt <= recal_debt + 8'sd1;
        end else begin
          ivl <= ivl + 1'b1;
        end
      end

      // REQUIREMENT 3, schedulable: the pass waits for a window, and
      // the wait is bounded so it cannot be deferred forever.
      if ((recal_debt > 8'sd0) && !pass_active) begin
        if (bus_idle && !inflight_txn) begin
          pass_start  <= 1'b1;
          pass_active <= 1'b1;
          pass_cycles <= '0;
        end else if (recal_debt >= 8'sd(MAX_DEFER)) begin
          // At the bound it goes regardless -- 17.3's
          // illegal-versus-deprioritised line, reused.
          pass_start  <= 1'b1;
          pass_active <= 1'b1;
          pass_cycles <= '0;
          // REQUIREMENT 2: starting with a transaction in flight is
          // the corruption case, counted rather than assumed away.
          if (inflight_txn) corrupted_txns <= corrupted_txns + 1'b1;
        end else if (tick) begin
          deferrals <= deferrals + 1'b1;
        end
      end

      if (pass_active) begin
        pass_cycles <= pass_cycles + 1'b1;
        // REQUIREMENT 1, brief: a pass that overruns is a finding.
        if (pass_cycles > 16'(MAX_PASS_CYCLES)) brief_ok <= 1'b0;
        if (pass_done) begin
          pass_active <= 1'b0;
          recal_debt  <= recal_debt - 8'sd1;
        end
      end

      noncorrupting_ok <= (corrupted_txns == '0);
      schedulable_ok   <= (recal_debt <= 8'sd(MAX_DEFER));
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   THE THREE REQUIREMENTS, MEASURED   (ILLUSTRATIVE, one hour,
                                       INTERVAL 4096, 14 passes due)

     design                  brief  non-corrupting  schedulable
     ------------------------------------------------------------
     no recalibration          --         --             --
       (the belief: nothing to schedule; 0 of 3 met)
     recalibrate immediately   yes        NO             yes
       (corrupted_txns 9 of 14 -- it starts mid-transaction)
     recalibrate when idle     yes        yes            NO
       (deferrals unbounded; on a busy hour, 0 of 14 passes ran)
     robust: idle, with a bound yes       yes            yes
       (11 passes at idle, 3 forced at the bound, 1 corrupted)

   DERIVED: the middle two designs each satisfy two requirements and
   fail one, and they are the two an engineer writes first. Only the
   bounded-deferral form satisfies all three, and it is exactly
   17.3's refresh structure.

The middle two rows are the finding: each is a natural first design and each fails one requirement. DERIVED: recalibrate immediately corrupts 9 of 14, and recalibrate when idle runs 0 of 14 on a busy hourand the resolution is the bounded-deferral ledger 17.3 already built for refresh, which is why 19.5 §4 says the same problem, with the same shape.

The 9-of-14 corruption figure deserves one line, because it is the requirement people assume is free. DERIVED: do not corrupt in-flight transactions sounds like a property of the pass and is actually a property of when the pass startsCURRICULUM-DERIVED from 19.5 §4, which cites 19.3 §9's aligner as the case that is unaffected by a later change because it loads its offset at the command. So some consumers are immune and some are not, and the pass has to know which — which is a per-consumer classification, exactly like 33.3 §10's precondition list.

And the first row is the belief. DERIVED: a design that believes training completes has nothing to schedule, so it satisfies zero of three requirements and reports no violation of any of themthere is no pass to be brief, nothing to corrupt, and no obligation to schedule. CURRICULUM-DERIVED from 34.4 §11's obligation-with-no-requester finding: this is the second such obligation in the curriculum, and a controller built on either belief has no type for it.

14. The Decision Built on the Belief

Where it is appliedWhat it producesMeasured consequence
A boot flowtrain, then boot6 of 8 values with no re-establishment path
A valid flagmonotonic, set onceevery downstream check vacuous (§9)
A trigger setthe two obvious events13 unhandled events in 90 minutes
A DVFS enablement planthe PHY is already trained2-tap error at the top bin
A power budgettraining costs boot time onlyrecalibration is recurring traffic interruption
A verification plantrain once, then test33.3 §10's precondition item unreachable

Row 2 is the most damaging and the least visible, and it deserves the emphasis. DERIVED: a monotonic valid makes every consumer's check pass forever, so the design has the guard 33.3 §8 demands and the guard can never fire. CURRICULUM-DERIVED from 33.3 §7: a flag that cannot fall cannot represent a value that can — so the belief does not remove the safety check, it neuters it, which is strictly worse because the check's presence is evidence.

And row 5 is the one that surprises system architects. DERIVED: if training is one-time, its cost is boot time; if six of eight values are re-established periodically, its cost is a recurring traffic interruptionCURRICULUM-DERIVED from 19.5 §4's three requirements for a recalibration pass: it must be brief, must not corrupt in-flight transactions, and must be schedulable“the same problem 17.3 solved for refresh, with the same shape.” A design built on the belief has no scheduler for it.

15. What the Assertions Prove

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  // ---- Section 8: the census. The belief is a predicate, and it is false.
  property p_not_all_values_are_one_time;
    @(posedge clk) disable iff (!rst_n)
      audit |=> !all_one_time;
  endproperty
  assert property (p_not_all_values_are_one_time)
    else $error("the census reports every trained value as one-time");

  property p_census_partitions_the_values;
    @(posedge clk) disable iff (!rst_n)
      audit |=> ((one_time_count + revisited_count) == 4'(NV));
  endproperty
  assert property (p_census_partitions_the_values)
    else $error("the lifetime classes do not partition the trained values");

  // ---- Section 9: validity must be able to FALL -- 19.5 section 2.
  property p_validity_falls_on_drift;
    @(posedge clk) disable iff (!rst_n)
      (valid && (temp_now > (temp_at_commit + 8'(TEMP_DELTA)))) |=> !valid;
  endproperty
  assert property (p_validity_falls_on_drift)
    else $error("a trained value stayed valid past its drift threshold");

  property p_frequency_change_makes_inapplicable;
    @(posedge clk) disable iff (!rst_n)
      (valid && freq_changed) |=> (inapplicable && !valid);
  endproperty
  assert property (p_frequency_change_makes_inapplicable)
    else $error("a frequency change left the value valid");

  // Stale and inapplicable are DIFFERENT states -- section 7's distinction.
  property p_stale_and_inapplicable_are_exclusive;
    @(posedge clk) disable iff (!rst_n) !(stale && inapplicable);
  endproperty
  assert property (p_stale_and_inapplicable_are_exclusive)
    else $error("a value was reported both stale and inapplicable");

  property p_never_used_while_invalid;
    @(posedge clk) disable iff (!rst_n) used_while_invalid == '0;
  endproperty
  assert property (p_never_used_while_invalid)
    else $error("a consumer used a value that was neither valid nor re-established");

  // Two-sided -- 30.3 section 9's variety 8: a design that invalidates
  // every cycle satisfies every property above and never operates.
  property p_validity_survives_within_threshold;
    @(posedge clk) disable iff (!rst_n)
      (commit && (temp_now == temp_at_commit)) |=> valid;
  endproperty
  assert property (p_validity_survives_within_threshold)
    else $error("a freshly committed value was invalidated at its own temperature");

  // ---- Section 10: the trigger set, against section 6's six exits.
  property p_trigger_coverage_is_complete;
    @(posedge clk) disable iff (!rst_n)
      (audit && coverage_complete) |=> (implemented_count == 4'(NTRIG));
  endproperty
  assert property (p_trigger_coverage_is_complete)
    else $error("trigger coverage was called complete with an exit unhandled");

  property p_no_event_is_absorbed;
    @(posedge clk) disable iff (!rst_n) unhandled_events == '0;
  endproperty
  assert property (p_no_event_is_absorbed)
    else $error("an invalidating event occurred with no retraining trigger");

  property p_missing_mask_matches_the_count;
    @(posedge clk) disable iff (!rst_n)
      audit |=> (missing_count == 4'($countones(missing_mask)));
  endproperty
  assert property (p_missing_mask_matches_the_count)
    else $error("the missing trigger count disagrees with the mask");

  // ---- Section 11: per-frequency sets.
  property p_set_is_indexed_by_bin;
    @(posedge clk) disable iff (!rst_n)
      set_valid |-> (tap_in_use == tap_of[bin_now]);
  endproperty
  assert property (p_set_is_indexed_by_bin)
    else $error("the applied tap did not come from the current bin's set");

  property p_untrained_bin_requests_training;
    @(posedge clk) disable iff (!rst_n)
      (!val_of[bin_now]) |=> needs_training;
  endproperty
  assert property (p_untrained_bin_requests_training)
    else $error("an untrained operating point did not request training");

  property p_no_wrong_bin_use;
    @(posedge clk) disable iff (!rst_n) wrong_bin_uses == '0;
  endproperty
  assert property (p_no_wrong_bin_use)
    else $error("a tap trained at another period was applied");

  // ---- Section 12: re-conversion. The measured term is stored in
  // physical units, so the count follows the period -- 19.3 section 2.
  property p_tap_tracks_the_period;
    @(posedge clk) disable iff (!rst_n)
      (have_measurement && (period_ps != '0))
        |=> (tap_in_use == TAP_W'((32'($past(held_ps))
                                   + 32'($past(period_ps)) - 32'd1)
                                  / 32'($past(period_ps))));
  endproperty
  assert property (p_tap_tracks_the_period)
    else $error("the applied tap did not follow the current period");

  property p_frequency_change_needs_no_search;
    @(posedge clk) disable iff (!rst_n)
      (freq_changed && have_measurement) |=> !search_requested;
  endproperty
  assert property (p_frequency_change_needs_no_search)
    else $error("a frequency change triggered a full search");

  property p_drift_does_need_a_search;
    @(posedge clk) disable iff (!rst_n)
      drift_detected |=> search_requested;
  endproperty
  assert property (p_drift_does_need_a_search)
    else $error("drift did not request a new search");

  // ---- Section 13: the three requirements -- 19.5 section 4.
  property p_pass_is_brief;
    @(posedge clk) disable iff (!rst_n) brief_ok;
  endproperty
  assert property (p_pass_is_brief)
    else $error("a recalibration pass exceeded its brevity budget");

  property p_pass_does_not_corrupt;
    @(posedge clk) disable iff (!rst_n)
      pass_start |-> (!inflight_txn || (recal_debt >= 8'sd(MAX_DEFER)));
  endproperty
  assert property (p_pass_does_not_corrupt)
    else $error("a pass started mid-transaction with headroom remaining");

  property p_pass_is_schedulable;
    @(posedge clk) disable iff (!rst_n) schedulable_ok;
  endproperty
  assert property (p_pass_is_schedulable)
    else $error("recalibration debt exceeded its deferral bound");

  // And the two-sided partner: it must actually RUN, not merely defer.
  property p_pass_runs_at_idle;
    @(posedge clk) disable iff (!rst_n)
      ((recal_debt > 8'sd0) && bus_idle && !inflight_txn && !pass_active)
        |=> pass_start;
  endproperty
  assert property (p_pass_runs_at_idle)
    else $error("a due pass did not start in an idle window");

  // ---- The CLAIM, as a conditional pair -- 34.1 section 1's required form.
  property p_claim_holds_in_its_region;
    @(posedge clk) disable iff (!rst_n)
      (valid && (temp_now == temp_at_commit) && !freq_changed && !tick)
        |=> valid;
  endproperty
  assert property (p_claim_holds_in_its_region)
    else $error("with every condition constant the value still went invalid");

  property p_claim_fails_outside_its_region;
    @(posedge clk) disable iff (!rst_n)
      (valid && freq_changed) |=> (validity_falls > $past(validity_falls));
  endproperty
  assert property (p_claim_fails_outside_its_region)
    else $error("a frequency change did not invalidate anything");

  // ---- COVERS. Each on the dimension the belief's failure scales with.
  // The REGION: conditions constant, so the claim pair is not vacuous.
  cover property (@(posedge clk) disable iff (!rst_n)
                  valid && (temp_now == temp_at_commit) && !freq_changed);
  // A TEMPERATURE excursion past the threshold. The dimension is the
  // ENVIRONMENT, and a bench at 25C never reaches it.
  cover property (@(posedge clk) disable iff (!rst_n)
                  valid && (temp_now > (temp_at_commit + 8'(TEMP_DELTA))));
  // A FREQUENCY change -- the dimension is the operating point, and a
  // single-bin system never reaches it however long it runs.
  cover property (@(posedge clk) disable iff (!rst_n) valid && freq_changed);
  // Validity actually FALLING, so the properties about falling are not
  // vacuous in a design where it never does.
  cover property (@(posedge clk) disable iff (!rst_n) validity_falls > 16'd0);
  // Both post-valid states, separately.
  cover property (@(posedge clk) disable iff (!rst_n) stale);
  cover property (@(posedge clk) disable iff (!rst_n) inapplicable);
  // Section 10: an event with NO trigger -- the absorption mechanism.
  cover property (@(posedge clk) disable iff (!rst_n) unhandled_events != '0);
  // And complete coverage, so p_trigger_coverage_is_complete has a
  // witness rather than being satisfied by never completing.
  cover property (@(posedge clk) disable iff (!rst_n)
                  audit && coverage_complete);
  // Section 11: a SECOND bin trained -- which requires a DVFS transition
  // to occur at all.
  cover property (@(posedge clk) disable iff (!rst_n) bins_trained >= 3'd2);
  // And an untrained bin entered, so the request path is exercised.
  cover property (@(posedge clk) disable iff (!rst_n)
                  needs_training && !set_valid);
  // A census reporting a REVISITED majority -- section 8's 75%.
  cover property (@(posedge clk) disable iff (!rst_n)
                  audit && (revisited_share_pct > 8'd50));
  // Section 12: a RE-CONVERSION without a search -- the cheap path, which
  // a design storing a tap index can never take.
  cover property (@(posedge clk) disable iff (!rst_n)
                  freq_changed && have_measurement && !search_requested);
  // And a search caused by DRIFT, so the two causes are separated.
  cover property (@(posedge clk) disable iff (!rst_n)
                  drift_detected && search_requested);
  // Section 13: a pass FORCED at the deferral bound -- the case the
  // idle-only design never reaches and the belief has no pass for.
  cover property (@(posedge clk) disable iff (!rst_n)
                  pass_start && (recal_debt >= 8'sd(MAX_DEFER)));
  // And a pass starting in a genuine idle window.
  cover property (@(posedge clk) disable iff (!rst_n)
                  pass_start && bus_idle && !inflight_txn);

Two notes, and the first is this chapter's central property design.

p_not_all_values_are_one_time asserts the belief false as a property of the census, which is unusual and deliberate. DERIVED: every other chapter in this module asserts the claim true in its region and false outside it. Here the belief's predicate — every value is one-time — is false in every region, because two of eight being one-time is a fact about the value set rather than about conditions. CURRICULUM-DERIVED from 19.5 §4's split: the split is a property of the quantities, so no operating condition makes all eight one-time. The region in §5 makes the consequences invisible, not the classification wrong.

And p_never_used_while_invalid is the property the weak build satisfies vacuously, which §9 already measured. DERIVED: it reads zero in both builds and for opposite reasons — the robust build retrains before use, the weak build has no invalid state. CURRICULUM-DERIVED from 27.2: the cover on validity_falls > 0 is what separates the two, and without it the property is 33.4 §7's unprovable-but-passing case.

16. Mutation Testing

Baseline first: all twenty-three assertions pass and all fifteen covers are non-zero.

#MutationKilled bySurvived?
M1§8: every value set to L_ONE_TIMEp_not_all_values_are_one_timekilled
M2§8: revisited_count tied to zerop_census_partitions_the_valueskilled
M3§9: valid made monotonicp_validity_falls_on_drift, by one coverkilled
M4§9: drop temp_at_commitp_validity_falls_on_driftkilled
M5§9: treat freq_changed as driftp_frequency_change_makes_inapplicablekilled
M6§9: set both stale and inapplicablep_stale_and_inapplicable_are_exclusivekilled
M7§9: invalidate every cyclep_validity_survives_within_thresholdkilled
M8§10: coverage_complete tied highp_trigger_coverage_is_completekilled
M9§10: absorb events silentlyp_no_event_is_absorbed, by one coverkilled
M10§10: missing_mask tied to zerop_missing_mask_matches_the_countkilled
M11§11: one tap, no bin indexp_set_is_indexed_by_bin, by one coverkilled
M12§11: needs_training tied lowp_untrained_bin_requests_trainingkilled
M13§11: apply the nearest trained bin's tapp_no_wrong_bin_usekilled
M14TEMP_DELTA raised to 200nothingSURVIVES
M15STALE_TICKS raised to its maximumnothingSURVIVES
M16NBIN set to 1nothingSURVIVES
M17the stimulus fixed at one temperaturenothingSURVIVES
M18NTRIG reduced to 2nothingSURVIVES
M19§12: store the tap index, not the picosecondsp_tap_tracks_the_period, by one coverkilled
M20§12: re-search on every frequency changep_frequency_change_needs_no_searchkilled
M21§12: drift does not request a searchp_drift_does_need_a_searchkilled
M22§13: start the pass regardless of in-flightp_pass_does_not_corruptkilled
M23§13: defer while busy, unboundedp_pass_is_schedulable, by one coverkilled
M24§13: never start the passp_pass_runs_at_idlekilled
M25§13: MAX_PASS_CYCLES raised to its maximumnothingSURVIVES

DERIVED: nineteen of twenty-five killed, six survived — and M18 is the one that is new to this module.

M25 is the sixth survivor and it is the brevity requirement's quantity. Raising MAX_PASS_CYCLES to its maximum makes brief_ok permanently true, so a pass of any length satisfies 19.5 §4's first requirement. DERIVED: and a long pass is exactly what brief was protecting against — the interruption whose whole cost is its duration. CURRICULUM-DERIVED from 33.4 §15's variety 12: the mechanism checks that brevity is tested and says nothing about the budget, and the budget's honest source is the deadline of whatever the pass interrupts — which is 33.5's per-class deadline, not a PHY parameter.

Reducing NTRIG to 2 makes coverage_complete true on a two-trigger design, and every property passes because each is written against NTRIG. DERIVED: that is §10's weak build reached by changing the denominator rather than the numerator — and it is the same shape as 34.4 §16's census defect, where the belief supplied its own denominator. CURRICULUM-DERIVED from 33.1 §5: a census's denominator must come from outside the design, and §6's six exits are this chapter's, derived from 19.5 §4 and 33.3 §9 rather than from the trigger set.

M14, M15, M16 and M17 reconstruct §5's region — the fifth consecutive chapter in this module with that result, and now unremarkable. A 200-degree drift threshold, an unreachable staleness age, one frequency bin, one temperature. DERIVED: each makes the belief true and kills nothing.

Three mutations are killed only by a cover, and M11's is the one with a schedule consequence. A single tap with no bin index is indistinguishable from the robust build until a second bin is entered, so the cover on bins_trained >= 2 is the only thing that reaches it. CURRICULUM-DERIVED from 31.2 §14: the dimension is the operating point, and DVFS being enabled late in a programme is precisely why this defect ships.

17. Baseline Defects Found Before Mutation

Belief applied toCaught byAt what cost
a lifetime assumptionp_not_all_values_are_one_timenothing — classify the eight values
a valid flagp_validity_falls_on_driftnothing — read the assignment
a trigger setp_no_event_is_absorbednothing — count against six
a DVFS planp_set_is_indexed_by_binnothing — is the set an array?
a running systemp_never_used_while_invalida temperature excursion
a recalibration budgetnothing: §8's 75% is the budget

DERIVED: five of six are found without running anything, and four of the five are structural — a classification, an assignment, a count, and whether a declaration is an array. That is the cheapest detection profile in this module, and it is because a lifetime belief leaves a structural fingerprint: a value with no invalidation path has no code to invalidate it.

One needs a stimulus, and the dimension belongs to the environment.

ApplicationThe stimulusWhy the usual test misses it
a running systema temperature excursion or a DVFS transitiona bench runs at one temperature and one bin

DERIVED: and both are cheap to add to a test plan and absent from most of themCURRICULUM-DERIVED from 33.4 §6's configuration-reach item: the environment must be able to vary temperature and frequency, which is a testbench capability rather than a stimulus, and no amount of traffic substitutes for it.

18. Silicon Observability

What silicon showsWhat it says about the belief
errors appearing after a warm-up period, gone after a power cycle§9 — drift, with no retraining
errors that start when DVFS is enabled§11 — one set, several bins
a trained flag that has never been observed low§14 row 2 — monotonic validity
failures correlated with chassis temperature, not with load§6 exit 1, and not a thermal throttling issue
a training-time counter that reads 1 for the part's lifetimethe belief, implemented
errors after suspend-resume only§6 exit 4 — power-down exit

Row 1 is the signature and it is nearly diagnostic on its own. DERIVED: errors that appear after a warm-up and vanish on a power cycle describe a value that drifted and was re-established by the rebootand the power cycle's only relevant effect is that it re-runs training. CURRICULUM-DERIVED from 28.4 §2's fifth case: a system that “boots, passes its own self-checks, and corrupts data hours later”this is that case's field signature.

Row 3 is the cheapest check in the chapter and it needs no equipment. DERIVED: ask whether anybody has ever seen the trained flag low after boot. If the answer is no, either the design is in §5's region or the flag cannot fall — and the two are distinguished by reading one assignment. CURRICULUM-DERIVED from 33.4 §10's positive-control matrix: a signal with no observed transition is either protecting something that never happens or is incapable of the transition, and only an injection separates them.

Row 4 is the one most often misattributed. DERIVED: temperature-correlated failures that are not load-correlated point at drift rather than at power — and the discriminator is one experiment: hold the load constant and change the chassis temperature. CURRICULUM-DERIVED from 33.7 §9's rate-consistency item: the hypothesis set for temperature-correlated corruption includes retention, drift, and thermal throttling, and a load-held temperature sweep partitions them.

19. Quantitative Reasoning

QuantityTruthUnder the beliefGapProvenance
trained values needing re-establishment6 of 80 of 875%DERIVED, ILLUSTRATIVE set
genuinely one-time values2 of 88 of 8DERIVED
period-dependent values5 of 80all five silentDERIVED
retraining triggers implemented2 of 62 of 64 missingDERIVED
invalidating events in 90 min130 detected13 absorbedDERIVED, ILLUSTRATIVE run
validity falls in 90 min303DERIVED
tap error at the top DVFS bin2 taps0 reported1.25 nsDERIVED
used_while_invalid00none — vacuouslyDERIVED
recalibration costrecurringboot-time onlya schedulerCURRICULUM-DERIVED, 19.5 §4

The eighth row is the one to dwell on, because it is the only row in this module where the belief and the truth agree and the agreement is worthless. DERIVED: used_while_invalid is zero in both builds — in one because the design retrains, in the other because there is no invalid state to be in. CURRICULUM-DERIVED from 33.4 §7: a property that passes with an unreached antecedent is unproven rather than proven, and this is the module's clearest instance of a belief producing one.

Sort by what kind of thing the belief gets wrong and this chapter adds a fourth kind to the module's collection.

KindRowsWhat the belief does
Classificationone-time count, period-dependentassigns one lifetime to a set with four
Completenesstriggers, absorbed eventshas 2 of 6 and reports complete
Vacuityused_while_invalidmakes a correct check unfalsifiable
Categoryrecalibration costprices a recurring cost as a one-off

DERIVED: the third row is new. 34.1 was wrong about magnitude, 34.2 silent, 34.3 an identification, 34.4 an expressibility gap. Here the belief leaves a correct guard in place and makes it unable to fire, which is the only one of the five that damages a design's verification rather than its function.

20. The Beliefs This One Generates

Downstream beliefWhy it followsWhere it is refuted
trained high means the PHY is good”if training completes§14 row 2; 28.4 §2
“training costs boot time”if it happens once§14 row 5; 19.5 §4
“DVFS is a clock-tree problem”if trained values are frequency-independent§11; 19.3 §2
“a reboot fixing it means it was software”if training is not a reboot effect§18 row 1
“temperature failures mean throttling”if the PHY is temperature-independent§18 row 4

The fourth row is the most expensive misdirection in this table. DERIVED: a power cycle re-runs training, so a reboot fixes it is evidence about training and is routinely read as evidence about software state. CURRICULUM-DERIVED from 33.7 §7's discriminating-power item: a reboot perturbs software state, hardware state and the trained set simultaneously, so it eliminates nothing — and it is the single most-performed experiment in computing.

And the third row reaches a different team entirely. DERIVED: DVFS enablement is usually owned by power management, and a trained-value dependency on frequency is invisible from therewhich is 34.3 §9's compounding in a new form: two teams each correct about their own layer, and a dependency crossing between them that neither's specification mentions.

21. Common Wrong Answers

  1. “Training runs once at boot.” The boot sequence runs once; the values have four lifetimes. CURRICULUM-DERIVED from 19.5 §4: “Calibration is not a bring-up activity that completes.”

  2. “So nothing is one-time.” Inverted — §8: two of eight are. Write levelling and gate training genuinely complete. DERIVED: the correction is a census, not an inversion.

  3. trained is high, so the PHY is configured.” CURRICULUM-DERIVED from 28.4 §2: a done flag means one of five things, and the worst “boots, passes its own self-checks, and corrupts data hours later.”

  4. “We have a valid gate on every consumer.” Can it fall? §9: a monotonic valid makes every such gate vacuous — the guard is present and unfalsifiable, which §19 calls the vacuity error.

  5. “Periodic recalibration is a ZQ thing.” §8: five of eight values drift with temperature and three are periodic. CURRICULUM-DERIVED from 19.5 §4: the quantities are functions of temperature and supply voltage, both of which move.

  6. “We do not change frequency.” Then condition 3 holds and the belief is right about that exit. DERIVED: and §11's defect is invisible until DVFS is enabled, which happens late — so we do not change frequency is often we do not change frequency yet.

  7. “A frequency change needs retraining, so we retrain on it.” Sometimes it needs only a re-conversion. DERIVED: §7 separates STALE from INAPPLICABLE because the physical measurement may still be right while its cycle count is not — and a full search where a division would do costs boot time at every transition.

  8. “The trained value is a physical time, so it is frequency-independent.” The value is; the register is not. CURRICULUM-DERIVED from 19.3 §2: a latency decomposes into a programmed term and a measured term, and the applied value is a count.

  9. “We retrain on power-down exit and reset, which covers it.” §10: those are the two obvious exits, and four remain — temperature, voltage, frequency and the periodic interval. 13 unhandled events in 90 minutes.

  10. “Our trigger coverage is complete.” Against what denominator? §16's M18: reducing NTRIG to 2 makes a two-trigger design completeCURRICULUM-DERIVED from 33.1 §5: the denominator must come from outside the design.

  11. “A reboot fixes it, so it is software.” A reboot re-runs training. CURRICULUM-DERIVED from 33.7 §7: it perturbs three things at once and therefore eliminates none of them.

  12. “Temperature-correlated failures mean thermal throttling.” §18 row 4: hold the load constant and sweep the temperature. DERIVED: throttling is load-correlated and drift is not, and one experiment separates them.

  13. “Recalibration would interrupt traffic, so we do not do it.” CURRICULUM-DERIVED from 19.5 §4: a recalibration pass must be brief, non-corrupting and schedulable“the same problem 17.3 solved for refresh.” DERIVED: the requirement is a scheduling problem with a known shape, not a reason to skip it.

  14. “Training cost is a boot-time number.” §14 row 5: with six of eight values re-established, it is recurring — and a design built on the belief has no scheduler for the recurrence.

  15. “Our bench has run for a week without an error.” At one temperature, one voltage, one frequency, with no suspend and no warm reset. DERIVED: §5's five conditions, all satisfied, for a week.

  16. “19.5 says some values stop being correct — I know that.” And §8 says six of eight. DERIVED: this chapter exists because some reads as an exception and 75% reads as the rule — the sentence and the census differ in effect, not in content.

  17. “Then we should retrain continuously.” §15's p_validity_survives_within_threshold rejects that — a design that invalidates every cycle satisfies every falling-validity property and never operates. CURRICULUM-DERIVED from 30.3 §9's variety 8: the two-sided pair exists for exactly this over-correction.

  18. used_while_invalid reads zero, so we are safe.” It reads zero in the broken build too, and for the opposite reason. §19's eighth row — the only place in this module where the belief and the truth agree on a number and the agreement means nothing.

  19. “The five period-dependent values drift, so periodic retraining covers them.” They do not drift on a frequency change — they become inapplicable instantly. DERIVED: a periodic timer may not fire before the wrong count is applied, so the trigger has to be the transition rather than an interval.

  20. “This is a PHY team problem.” §20 row 3: DVFS enablement is owned by power management, and the dependency crosses between the two teamsCURRICULUM-DERIVED from 34.3 §9's compounding: two correct specifications with an unmentioned dependency between them.

  21. “Four mutations survived, so the property set is weak.” All five survivors move a quantity — a drift threshold, a staleness age, a bin count, a trigger count, a stimulus temperature. CURRICULUM-DERIVED from 33.4 §15's variety 12, for the fifth consecutive chapter.

  22. “I would never assume a trained value is permanent.” The test is structural: does your valid bit have a falling assignment? DERIVED: §17 finds four of six applications of this belief by reading a declaration, and the fingerprint is an absence of code rather than a wrong value.

22. Self-Check

  1. Name the four lifetime classes a trained value can have, and give the split across §8's eight values.
  2. Which chapter's second paragraph refutes this belief, and what does it say?
  3. State the five conditions under which training happens only once is true, and say which two the specification's authors expected to fail.
  4. Why is INAPPLICABLE a different state from STALE, and what does treating a frequency change as drift cost?
  5. A valid bit is assigned only in a commit branch. State the finding in one sentence, and say what it does to every downstream guard.
  6. Six exits invalidate a trained value. Name them, and say which two a typical design implements and why those two.
  7. Flight time is 2.8 ns. Give the correct tap at 1.25 and at 0.625 ns per cycle, and the error a single-set design applies at the faster bin.
  8. used_while_invalid reads zero. Give the two reasons that can be true, and the cover that distinguishes them.
  9. A system fails after a warm-up and works after a power cycle. State the mechanism, and say why a reboot is a poor experiment.
  10. M18 reduced NTRIG from 6 to 2. What did that make the instrument report, and which chapter's rule does the fix come from?
  11. §19's table has a row the four preceding chapters do not. Name it, and say why it is the only error kind that damages verification rather than function.
  12. A colleague proposes retraining continuously. Give the property that rejects it and the variety it invokes.

23. The Residual Risk

What this chapter cannot settle.

It cannot supply the drift thresholds. §9's TEMP_DELTA is ILLUSTRATIVE and M14 raised it to 200 with nothing firing. CURRICULUM-DERIVED from 21.4 and 20.5: a real threshold comes from an eye-width-versus-temperature characterisation, and this chapter derives none — the fifth consecutive chapter whose survivor needs a measurement rather than a property.

It cannot tell you which values your PHY treats how. §8's assignment of eight values to four classes is ILLUSTRATIVE. CURRICULUM-DERIVED from 19.1 §3, whose ownership table has six implementation-dependent rows: DERIVED: a vendor PHY may handle drift internally and expose none of it, in which case several of §8's rows move to the IP's problem — and §10's trigger census then needs the IP's documentation rather than the design's code.

It cannot schedule the recalibration. §14 row 5 establishes that the cost is recurring and 19.5 §4 states the three requirements. DERIVED: how to make room for a brief, non-corrupting, schedulable interruption is 17.3's problem shape and 33.3 §10's review item, and this chapter only establishes that the problem exists.

It cannot tell you which consumers are immune to an interruption. §13's non-corruption requirement needs a per-consumer classification, and 19.5 §4 cites 19.3 §9's aligner as one immune case. DERIVED: the classification is a property of each consumer's own latching discipline, so it is design-specific and this chapter models the requirement rather than the list — the same shape as 33.3 §10's precondition item, one level down.

And it cannot distinguish a value the PHY re-establishes silently from one nobody re-establishes. DERIVED: a design with no retraining trigger and no failures may have a PHY doing it internally, or may be inside §5's region — and §10's census cannot tell those apart from the outside. CURRICULUM-DERIVED from 33.4 §13's VIP-observability item: what a supplied component does not report has to be established by experiment, and the experiment here is a temperature sweep.

24. Where This Goes

Five beliefs down: three about numbers, one about a component's nature, one about a process's lifetime.

Chapter 34.6 closes the module, and it changes the object once more. DERIVED: DDR5 is just faster DDR4 is a claim about a generation's relationship to its predecessor — which is neither a quantity, a structure nor a lifetime, but a claim about what changed.

And it inherits this chapter's sharpest sub-finding. DERIVED: §8 found five of eight trained values period-dependent — invalidated by a frequency change with no physical change at all. A generation change is a frequency change with everything else changed too, so every dependency this chapter found crossing a DVFS boundary crosses a generation boundary as well.

CURRICULUM-DERIVED from 4.6, whose framing the last chapter is built on: DDR5 transfers sixteen beats per burst and keeps granularity identical to DDR4's by halving the width the burst crossesDERIVED: that is not a speed change, it is a structural change chosen to hold one quantity constant while a rate doubled, and a belief that reads it as a speed bump misses the reason the structure moved.

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.