Skip to content
VLSI Mentor

DDR · Module 33

PHY Review Checklist

A PHY's correctness lives in registers whose contents were measured rather than written, so every item is a question about provenance: what measured this, against what, when, and what happens when that measurement stops being true.

Chapter 33.2 asked what each line does. This gate asks about a value that no line contains.

A controller's correctness is in its code. A PHY's correctness is in its registers — and the contents of those registers were measured, not written. Chapter 19.5 §2 states the consequence in one sentence, and it is the reason this gate exists 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.”

What measured this value, against what, when — and what happens to the part when that measurement stops being true?

Every item below is a review question whose answer is not in the RTL. The code that applies a trained delay is trivial and correct in every build in this chapter. What is wrong is the value, its provenance, its lifetime, or the design's belief about it — and none of those is visible in the line that uses it.

This changes what a review can conclude. At 33.2's gate, five of nine items were decided by reading source text. Here, one is — and the rest require the reviewer to demand an artifact the design does not contain: a provenance table, a reset-domain map, a measured window width, a drift budget.

1. How To Use This Chapter

Each of the nine review items answers the same eight questions.

FacetWhat it settles
Under reviewthe value, flag or search being examined
Invariant at riskthe property that breaks if it is wrong
Where it livesthe register, and the step that wrote it
Evidence to demandthe artifact the reviewer asks for by name
What escapesthe bug that reaches silicon
How DV proves itthe stimulus that would falsify it
Telemetrywhat exposes it after tapeout
Misleading evidencewhat makes the broken value look correct

The misleading evidence at this gate has a shape all its own, and it is the most dangerous of the eight. At the architecture gate it is a reassuring document; at the RTL gate a reassuring waveform. Here it is a part that boots.

CURRICULUM-DERIVED from 28.4 §2, which names it precisely: a calibration done flag can mean five different things, and the worst of the five “produces a system which boots, passes its own self-checks, and corrupts data hours later.” Every item below has a build that boots. Seven of the nine have a build that boots, trains, reports success, and passes a functional test.

2. The One-Sentence Model

A PHY review is sound when every quantity in the timing path is classified as calculated or measured with no third category, when every completion flag's five possible meanings are distinguishable, when every trained value gates its own consumer closed by default, when each trained register's surviving reset matches the retraining that reset triggers, when every periodic recalibration's preconditions are enforced rather than assumed, when every search can tell an exhausted range from an absent margin, when every selection rule matches the shape of its pass region, when every margin names the measurement it came from, and when every level and delay is assigned to a direction and a side — and “training passed” is bit 0.

3. What This Chapter Owns

GroundOwner
The controller / PHY / DRAM ownership split, and the placement rule19.1 §3, 30.7
The PHY lifecycle, and one-time versus continuous19.5
Every training algorithm and the sequencerModule 21
Published window figures and the setup/hold trade20.5
What a training failure signature does and does not support28.1
The five meanings of one done flag, and the unverifiable result28.4
Why an eye is the shape it isModule 22
Reviewing the code that applies a trained value33.2
Reviewing the provenance, lifetime and belief attached to a measured valuethis chapter

Two boundaries need stating precisely, because this gate shares vocabulary with chapters on both sides of it.

With 33.2 §12: that item asks does any parameter name something outside the design — a question about source text, answered by grepping a parameter list, and its verdict is flag it. This chapter's §6 asks a different question about the same line: for every quantity in the timing path, which side of the calculated/measured line is it on, and who is authoritative? That is a census, its pass criterion is completeness, and it cannot be answered by grep because the entries the census is looking for are the ones that are missing.

With 28.1 and 28.4: those chapters own the interpretation of a failure that has already happened — eleven bitmap signatures, five done meanings, and the discriminating experiments. This chapter asks whether the design was built so that the discrimination is possible at all. 28.1's finding is “five causes, one signature.” This gate's item 6 is the review question that would have produced five signatures.

4. Teaching-Model Boundary And Source Discipline

Every SystemVerilog block below is an educational model. None is a PHY, none contains a delay line, and none should be taken as an implementation.

CURRICULUM-DERIVED from 20.3's standing statement that sample quality is not digitally observable: a model written in SystemVerilog cannot represent an eye, a phase, or a volt. What these models do represent is the digital belief the design holds about a physical quantity — a register, a validity flag, a reset domain, a selection rule, a range bound. Those are exactly the things a review can inspect, and exactly the things that go wrong.

Claim classWhat it means hereExample below
Structurala real, documented mechanismmode registers, done flags, reset domains, sweep ranges
Curriculum-derivedfollows from a cited chapter of this trackevery item's pass criterion, each cited by section
Derivedcomputed in this chapter from the models belowevery gap figure in §16
Illustrativea chosen number that makes a mechanism visiblewindow widths, tap counts, drift rates, tick intervals

Every number that stands for a physical quantity in this chapter is ILLUSTRATIVE, and labelled. Window widths, delay-tap resolutions, drift-per-degree figures and recalibration intervals are chosen to make an argument legible in simulation. CURRICULUM-DERIVED from 20.5, which owns the published figures: a real window comes from a device datasheet at a stated speed bin, and this chapter derives none.

No external source was consulted. Every structural claim traces to a chapter of this track, cited inline. Where this chapter needs a physical fact it does not own, it names the chapter that owns it and takes the fact as given — the discipline 19.3 §3 uses for CL and CWL, and the reason its models are about relationships rather than magnitudes.

5. The Line This Whole Gate Is About

One distinction organises all nine items, and 19.3 §2 owns it: a PHY latency decomposes into a part that is known from the configuration and a part that is only knowable by measurement.

Every defect in this chapter is a value on the wrong side of that line, or a belief about a value that outlived its measurement.

SidePropertyWhat goes wrong
Calculatedreproducible from programmed state; identical on every parta measured quantity is computed instead — works on one part
Measureddiscovered by search; differs per part, per board, per temperaturea calculated quantity is trained — wastes boot time, hides a config error
The line itselfwho is authoritative for each quantitythe census is incomplete, and nobody notices the missing row

The third row is the one this gate exists for. CURRICULUM-DERIVED from 30.7 §2's placement rule and its recorded consequence: six rows of 19.1's ownership table are implementation-dependent and one is strongly so, so “an architecture diagram claiming one boundary is describing a particular product, not DDR.” A review that checks the rows that are present, against a table that is incomplete by construction, has checked nothing about the rows that are absent.

And there is a second organising fact, from 19.5 §4: the measured side splits again into one-time and continuous. A value established once at boot and a value re-established every few milliseconds fail in completely different ways — the first fails at the next reset, the second fails between two updates — and items 4, 8 and 9 below are the three review questions that follow from that split.

6. Review Item 1 — Which Side of the Calculated / Measured Line Is This Quantity On?

FacetContent
Under reviewevery quantity that contributes to a PHY timing decision
Invariant at riska measured quantity is never recomputed from configuration
Where it livesthe expression that produces the launch or capture offset
Evidence to demanda provenance census: one row per quantity, with its side of the line and its authority
What escapesa part that works at the frequency and on the board the constant was derived at
How DV proves ittwo configurations whose calculated terms agree and whose measured terms differ
Telemetrya read-back of the offset actually in use, beside the offset training produced
Misleading evidencethe expression is dimensionally correct and its result is right on the bench

The pass criterion is completeness, not correctness. Every quantity feeding a timing decision must appear in the census with a side and an authority. A census with nine correct rows and one missing row fails this item, and the missing row is the finding.

That criterion is 33.1 §12's, reused deliberately. That item's commitment ledger passes only when every decision committed in silicon is listed, and its weak build failed on one undocumented commitment out of a correct set. DERIVED: a census judged on completeness has the same failure mode at both gates — the row that is absent is the row nobody argued about — and this is the second of the two places in this module where a review's verdict turns on an omission rather than on an error.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ILLUSTRATIVE quantities. ROBUST BUILD: provenance is a declared
// property of each quantity, and the launch offset is the sum of a
// calculated term and a measured term -- 19.3 section 2's decomposition,
// made structural so a review can audit it.
module quantity_provenance #(
    parameter int OFF_W        = 8,
    // CALCULATED side: reproducible from programmed state.
    parameter int CWL_CYCLES   = 9,      // 14.10's programmed value
    parameter int SER_CYCLES   = 2,      // 19.2's serialiser depth
    // MEASURED side: MUST arrive as an input. There is no default,
    // because a default is a calculated value wearing a measured name.
    parameter bit ALLOW_CALC_FLIGHT = 1'b0
)(
    input  logic                 clk,
    input  logic                 rst_n,
    // programmed configuration
    input  logic [3:0]           cfg_cwl,
    input  logic [1:0]           cfg_ser_depth,
    // measured, from training
    input  logic [OFF_W-1:0]     trained_flight,
    input  logic                 trained_flight_valid,
    // a quantity the reviewer must classify: does it belong to either side?
    input  logic [OFF_W-1:0]     board_trace_delay,   // never used: see below
    output logic [OFF_W-1:0]     launch_offset,
    output logic                 launch_offset_valid,
    // the census, exposed so a review can read it rather than infer it
    output logic [2:0]           calc_terms,
    output logic [2:0]           meas_terms,
    output logic [2:0]           unclassified_terms
);
  // Provenance enum, structural: 0 = calculated, 1 = measured.
  localparam int NQ = 3;
  localparam bit [NQ-1:0] PROVENANCE = 3'b100;  // {flight, ser, cwl}

  logic [OFF_W-1:0] calc_part, meas_part;

  always_comb begin
    // CALCULATED: from programmed registers, not from parameters. A
    // parameter here would make the term un-reprogrammable, which is
    // 33.2 section 12's finding in a different costume.
    calc_part = OFF_W'(cfg_cwl) + OFF_W'(cfg_ser_depth);

    // MEASURED: from the training input, and ONLY from it.
    meas_part = trained_flight;
  end

  // The census. Counted from PROVENANCE so it cannot drift from the
  // declaration, and unclassified is computed as a residue -- the whole
  // point of section 5's third row.
  always_comb begin
    calc_terms         = 3'(NQ - $countones(PROVENANCE));
    meas_terms         = 3'($countones(PROVENANCE));
    // board_trace_delay contributes to a timing decision and appears on
    // neither side. In the robust build it is REFUSED rather than used.
    unclassified_terms = (board_trace_delay != '0) ? 3'd1 : 3'd0;
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      launch_offset       <= '0;
      launch_offset_valid <= 1'b0;
    end else begin
      launch_offset       <= calc_part + meas_part;
      // Refuses while the measured term has no provenance.
      launch_offset_valid <= trained_flight_valid && !ALLOW_CALC_FLIGHT;
    end
  end
endmodule

The weak build is the one that exists in real code, and it does not look like a shortcut.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: the measured term is computed.
// Set ALLOW_CALC_FLIGHT = 1 and the module derives flight time from the
// clock period and a trace length -- dimensionally correct, reproducible,
// and wrong on every board but the one it was characterised on.
//
//   FLIGHT_NS  = TRACE_MM * PROP_NS_PER_MM      // ILLUSTRATIVE
//   flight_cyc = FLIGHT_NS / CLK_PERIOD_NS
//
// The expression is defensible on a whiteboard. That is the problem:
// it makes `trained_flight` redundant, so nobody notices it is unread.
//
// CONTRACT VIOLATED: 19.3 section 2 -- the measured term is the part that
// is "only knowable by measurement". A formula is not a measurement.
//
// WHY IT SURVIVES: on the characterisation board the two agree to within
// one tap, the census reports three classified terms and zero
// unclassified, and `launch_offset_valid` asserts without training.
// The part boots FASTER than the robust build.
//
// TRACE (ILLUSTRATIVE, PROP_NS_PER_MM = 6.5e-3, CLK_PERIOD_NS = 0.625):
//   board A: TRACE_MM = 48 -> flight_cyc = 0.499 -> 0  trained = 0  SAME
//   board B: TRACE_MM = 48 (assumed) but actual 96
//                          -> flight_cyc = 0       trained = 1  DIFFER
//   -> launch_offset low by 1 cycle on every write on board B.

The escape is specific and it is not “the formula is wrong.” The formula is right. What escapes is that the formula's inputs are assumptions about a board, and the design has no way to notice that the board changed. CURRICULUM-DERIVED from 22.3 §3: board and package design are separate disciplines “with their own tools, their own measurement methods and their own literature”so a trace length in RTL is a number transcribed across a discipline boundary, and nothing in the RTL domain can revalidate it.

Misleading evidence, precisely. The weak build's census reports three classified terms, zero unclassified — a clean audit. It reports that because the census counts the declaration, and the declaration was edited to match the code. DERIVED: a self-reported provenance census is evidence about the declaration, not about the code, which is why this item's evidence to demand is the census plus the read-back of §6's telemetry row — two artifacts that disagree when the formula path is active.

And the unread input is the tell, again. trained_flight is declared and never read in the weak build. CURRICULUM-DERIVED from 33.2 §8: eight of the track's eighteen documented defects present this way. This item is the PHY-side reason the tell is so common — a formula that reproduces a measurement makes the measurement look redundant.

7. Review Item 2 — Which of Five Things Does This done Flag Mean?

FacetContent
Under reviewevery completion, convergence or readiness flag in the PHY
Invariant at riska flag that gates consumption means the value is usable, not the step returned
Where it livesthe assignment that raises the flag, and every consumer that reads it
Evidence to demandfor each flag, what it would report in each of 28.4's five cases
What escapesa system that boots, self-checks clean, and corrupts data hours later
How DV proves itfive stimuli, one per case, each checked for a distinct flag pattern
Telemetrya separate bit per case, not one flag
Misleading evidencethe flag is high, and it is high for the correct reason on the bench

CURRICULUM-DERIVED from 28.4 §2, which owns the five-way split and states the consequence: five failures, one flag. This item does not re-derive the five. It demands that the design distinguish them.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: completion is FOUR separate facts, because collapsing
// them is 28.4's finding. The names are chosen to be un-aliasable.
module completion_semantics #(
    parameter int VAL_W    = 8,
    parameter int TIMEOUT  = 64,     // ILLUSTRATIVE
    parameter int STALE_AT = 512     // ILLUSTRATIVE ticks
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             start,
    // from the search engine
    input  logic             engine_returned,   // the step finished running
    input  logic             engine_converged,  // it found a point
    input  logic [VAL_W-1:0] engine_value,
    input  logic             engine_in_range,   // the point was inside the sweep
    input  logic             tick,              // ILLUSTRATIVE staleness clock
    input  logic             env_changed,       // e.g. a thermal event
    // four distinct outputs, deliberately not one
    output logic             ran,        // case 1 vs 2: did it even run?
    output logic             converged,  // case 3: did it find a point?
    output logic             in_range,   // case 4: was the point reachable?
    output logic             trusted,    // case 5: is it still true?
    output logic [VAL_W-1:0] value,
    output logic [2:0]       fail_case   // 0 = none; 1..5 = 28.4's cases
);
  logic [$clog2(TIMEOUT+1)-1:0]  busy_cnt;
  logic [$clog2(STALE_AT+1)-1:0] age;
  logic                          running;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      ran <= 1'b0; converged <= 1'b0; in_range <= 1'b0; trusted <= 1'b0;
      value <= '0; fail_case <= 3'd0; busy_cnt <= '0; age <= '0;
      running <= 1'b0;
    end else begin
      if (start) begin
        running   <= 1'b1;
        busy_cnt  <= '0;
        ran       <= 1'b0; converged <= 1'b0;
        in_range  <= 1'b0; trusted   <= 1'b0;
        fail_case <= 3'd0;
      end

      if (running) begin
        busy_cnt <= busy_cnt + 1'b1;

        if (engine_returned) begin
          running   <= 1'b0;
          ran       <= 1'b1;
          converged <= engine_converged;
          in_range  <= engine_in_range;
          value     <= engine_value;
          age       <= '0;
          // trusted requires ALL of the preceding facts, and nothing else
          // may raise it.
          trusted   <= engine_converged && engine_in_range;

          if      (!engine_converged && !engine_in_range) fail_case <= 3'd4;
          else if (!engine_converged)                     fail_case <= 3'd3;
          else                                            fail_case <= 3'd0;
        end else if (busy_cnt == TIMEOUT[$clog2(TIMEOUT+1)-1:0]) begin
          // Case 2: the step never completed. Distinguished from case 1
          // (never started) by `ran` staying low with `busy_cnt` high.
          running   <= 1'b0;
          ran       <= 1'b1;
          fail_case <= 3'd2;
        end
      end

      // Case 5: it converged, it was in range, and it STOPPED being true.
      // 19.5 section 4's continuous side: a value can become invalid without
      // anything failing.
      if (trusted) begin
        if (env_changed) begin
          trusted   <= 1'b0;
          fail_case <= 3'd5;
        end else if (tick) begin
          if (age == STALE_AT[$clog2(STALE_AT+1)-1:0]) begin
            trusted   <= 1'b0;
            fail_case <= 3'd5;
          end else begin
            age <= age + 1'b1;
          end
        end
      end
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: one flag, raised on return.
//
//   always_ff @(posedge clk or negedge rst_n)
//     if (!rst_n)              calib_done <= 1'b0;
//     else if (engine_returned) calib_done <= 1'b1;   // <-- the defect
//
// CONTRACT VIOLATED: 28.4 section 2 -- `done` must not mean "returned".
//
// WHY IT SURVIVES: on the bench the engine converges, in range, and
// nothing changes thermally during the test. `calib_done` is high for
// the correct reason, so every consumer behaves correctly. The flag is
// not wrong; it is UNDERDETERMINED.
//
// TRACE, five stimuli (ILLUSTRATIVE):
//   case 1 never started      robust: ran=0            weak: done=0  SAME
//   case 2 hung, timed out    robust: ran=1 fc=2       weak: done=1  DIFFER
//   case 3 returned, no point robust: converged=0 fc=3 weak: done=1  DIFFER
//   case 4 point out of range robust: in_range=0 fc=4  weak: done=1  DIFFER
//   case 5 converged, drifted robust: trusted=0 fc=5   weak: done=1  DIFFER
//
//   distinguishable cases: robust 5 of 5, weak 1 of 5.

The measured gap is 5 versus 1, and the shape of the error matters more than the count. Four of the five cases are indistinguishable from success in the weak build, and case 5 is indistinguishable from success forever — because nothing in the weak build ever lowers the flag. CURRICULUM-DERIVED from 19.5 §2: “some of those values stop being correct while the system is running”a flag that is monotonic cannot represent a value that is not.

Note what this item does not claim. It does not claim the weak build's calib_done is a bug in the sense of a wrong assignment. The assignment is exactly what its name says. The defect is that a consumer reads it as a statement about the value's usability, and the flag was never that. DERIVED: the review question is not is the flag correct but what does a consumer believe when it is high, and is that belief warranted by the assignment.

8. Review Item 3 — Does This Consumer Refuse to Operate Untrained?

FacetContent
Under reviewevery consumer of a trained value
Invariant at riskthe default state of a trained-value gate is closed
Where it livesthe reset branch of the gate, and the polarity of its enable
Evidence to demandthe value the gate takes at reset, read out of the RTL, not asserted in review
What escapesa window of traffic driven with reset-value delays, before training runs
How DV proves itdrive traffic between reset release and training start, and check it is refused
Telemetrya counter of operations attempted while untrained — must read exactly zero
Misleading evidencethe boot sequence never drives traffic early, so the window is never entered

The pass criterion is a polarity, and it is the cheapest item in this chapter. CURRICULUM-DERIVED from 19.5 §2: a PHY is not usable when reset is released. So the correct reset value of every trained-value consumer's enable is the one that refuses, and a reviewer reads the reset branch.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: refusal is the reset state, and the gate is closed by
// a value that cannot be produced by a stuck-at-zero fault on the
// validity input.
module untrained_refusal #(
    parameter int OFF_W = 8
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic [OFF_W-1:0] trained_offset,
    input  logic             trained_valid,
    input  logic             op_request,
    output logic             op_grant,
    output logic [OFF_W-1:0] offset_in_use,
    output logic             gate_open,
    // telemetry: 19.5's lifecycle, made countable
    output logic [15:0]      untrained_attempts,
    output logic [15:0]      granted_ops
);
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      // The whole item is these three lines.
      gate_open          <= 1'b0;
      offset_in_use      <= '0;
      untrained_attempts <= '0;
      granted_ops        <= '0;
      op_grant           <= 1'b0;
    end else begin
      // The gate tracks validity in BOTH directions -- 28.4's case 5
      // means a trained value can stop being trusted, so the gate must
      // be able to reclose.
      gate_open <= trained_valid;

      if (trained_valid) offset_in_use <= trained_offset;

      op_grant <= op_request && gate_open;

      if (op_request && !gate_open) untrained_attempts <= untrained_attempts + 1'b1;
      if (op_request &&  gate_open) granted_ops        <= granted_ops + 1'b1;
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: the gate opens at reset and
// closes on invalidity.
//
//   if (!rst_n)  gate_open <= 1'b1;            // <-- the defect
//   else         gate_open <= trained_valid;
//
// CONTRACT VIOLATED: 19.5 section 2 -- a PHY is not usable at reset release.
//
// WHY IT SURVIVES: `gate_open` is corrected on the first clock after
// reset, so the window is ONE CYCLE WIDE, and the boot ROM does not
// issue a transaction in it. The defect is invisible unless something
// changes the boot sequence -- a faster ROM, a warm reset that does not
// re-run the ROM, or a debug flow that drives traffic early.
//
// TRACE (ILLUSTRATIVE, 4 requests at t = 0, 1, 40, 41; training at t = 20):
//   robust: untrained_attempts = 2  granted_ops = 2  -> refused both early
//   weak:   untrained_attempts = 1  granted_ops = 3  -> ONE early op granted
//                                                       with offset_in_use = 0
//   gap: one operation, executed with a reset-value delay, no error raised.

One operation is the whole finding, and the reason it matters is not the operation. DERIVED: the weak build's untrained_attempts reads 1 rather than 2, so its own telemetry under-reports by exactly the number of escapes. A reviewer who checks the counter and finds a non-zero value has found a problem; a reviewer who checks the counter and finds it lower than the number of early requests has found this one.

And the misleading evidence is a property of the environment, not the design. CURRICULUM-DERIVED from 30.7 §10's finding that an environment sharing the design's wrong constant cannot detect it — here the environment shares the design's schedule: a testbench that models the boot ROM's timing never enters the window the ROM never entered. The stimulus that falsifies this item is the one nobody writes, because it is not a legal boot sequence.

9. Review Item 4 — Which Reset Does This Trained Register Survive, and Does That Match the Retraining It Triggers?

FacetContent
Under reviewevery trained register's reset domain, and every reset's retraining trigger
Invariant at riska reset that clears a trained value must start the training that replaces it
Where it livesthe sensitivity list of the trained register, and the condition on the retrain request
Evidence to demanda two-column map: register → clearing reset, reset → retraining triggered
What escapesa part that boots perfectly and fails after a warm reset
How DV proves itassert a warm reset after successful training and check either survival or retraining
Telemetrya training-run counter and a reset-cause register, read together
Misleading evidenceevery cold boot works, and cold boot is what the bring-up test does

CURRICULUM-DERIVED from 19.5 §2, which owns this hazard by name: “the ordering hazards that make cold boot and warm reset behave differently.” This item is that hazard turned into a review artifact — and the artifact is two columns, because the defect is a mismatch between them rather than an error in either.

This is the one item in this chapter that earns a diagram, and the reason is specific: the defect is a wiring topology, not a value. Both builds have correct registers and a correct sequencer. What differs is which reset line reaches which register, and prose describes that badly.

The reset-domain map the review demands.

Two reset domains. The POR reset clears the trained registers and also starts the retrain trigger, which rewrites them. The functional reset clears only the functional registers and re-gates traffic, leaving trained values intact.POR resetTrained regsRetrain triggerFunctional resetFunctional regsTraffic gateclearsstartsclears12

Robust: the reset that clears a trained register is the reset that starts the retraining which rewrites it. Weak: the functional reset gains an arrow into trained and gains no sibling arrow into seq.

Read the diagram as a rule: every arrow that clears a trained register must have a sibling arrow into the retrain trigger.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: trained state lives in the POR domain, and the POR
// domain is the one that triggers retraining. The two facts are tied
// together by construction, not by a comment.
module reset_domain_map #(
    parameter int OFF_W = 8
)(
    input  logic             clk,
    input  logic             rst_por_n,    // cold: clears trained state
    input  logic             rst_func_n,   // warm: does not
    input  logic [OFF_W-1:0] trained_offset_in,
    input  logic             training_done,
    input  logic             op_request,
    output logic             retrain_req,
    output logic [OFF_W-1:0] trained_offset,
    output logic             trained_valid,
    output logic             op_grant,
    output logic [7:0]       training_runs,
    output logic [7:0]       ops_with_stale_offset
);
  // TRAINED STATE: POR domain only. A warm reset does not appear in
  // this sensitivity list, which is the entire mechanism.
  always_ff @(posedge clk or negedge rst_por_n) begin
    if (!rst_por_n) begin
      trained_offset <= '0;
      trained_valid  <= 1'b0;
      training_runs  <= '0;
    end else begin
      if (training_done) begin
        trained_offset <= trained_offset_in;
        trained_valid  <= 1'b1;
        training_runs  <= training_runs + 1'b1;
      end
    end
  end

  // RETRAIN TRIGGER: also POR domain. Same reset, so the clear and the
  // replacement cannot get out of step.
  always_ff @(posedge clk or negedge rst_por_n) begin
    if (!rst_por_n)          retrain_req <= 1'b1;   // cleared -> retrain
    else if (training_done)  retrain_req <= 1'b0;
  end

  // FUNCTIONAL STATE: warm domain. Traffic is re-gated on the warm
  // reset, but the trained value it uses is untouched.
  always_ff @(posedge clk or negedge rst_func_n) begin
    if (!rst_func_n) begin
      op_grant              <= 1'b0;
      ops_with_stale_offset <= '0;
    end else begin
      op_grant <= op_request && trained_valid;
      // Telemetry the reviewer asked for: an operation granted while the
      // offset is the reset value is the escape, counted.
      if (op_request && trained_valid && (trained_offset == '0))
        ops_with_stale_offset <= ops_with_stale_offset + 1'b1;
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: trained state moves into the
// functional domain, and the retrain trigger does not follow it.
//
//   always_ff @(posedge clk or negedge rst_func_n) begin   // <-- moved
//     if (!rst_func_n) begin
//       trained_offset <= '0;
//       trained_valid  <= 1'b0;          // cleared by a WARM reset
//     end ...
//   always_ff @(posedge clk or negedge rst_por_n)
//     if (!rst_por_n) retrain_req <= 1'b1;                 // <-- not moved
//
// CONTRACT VIOLATED: 19.5 section 2's cold-boot / warm-reset divergence.
//
// WHY IT SURVIVES: cold boot asserts BOTH resets, so `trained_valid`
// clears and `retrain_req` rises together. Every cold boot is perfect.
// Bring-up tests cold-boot. So does the regression.
//
// TRACE (ILLUSTRATIVE):
//   cold boot:  trained_valid 0 -> retrain_req 1 -> train -> valid 1
//               robust and weak IDENTICAL.
//   warm reset after training:
//     robust: trained_valid stays 1, trained_offset preserved,
//             training_runs = 1, ops_with_stale_offset = 0
//     weak:   trained_valid -> 0, trained_offset -> 0, retrain_req
//             stays 0 (POR did not fire), and `trained_valid` re-raises
//             only if `training_done` ever pulses again -- it does not.
//             -> the gate stays CLOSED and the interface is dead,
//                OR, if the gate defaults open (item 3's weak build),
//                every subsequent operation uses offset 0.
//
//   gap: cold boots to failure = 0; warm resets to failure = 1.

Two failure modes, and which one you get depends on item 3 — which is why these two items must be reviewed together. DERIVED: with item 3's robust gate, the weak reset map produces a dead interface after warm reset — bad, loud, and found in an hour. With item 3's weak gate, it produces a live interface running on reset-value delays — silent, and 28.4's “boots, self-checks clean, corrupts data hours later.” The combination of two individually survivable defects is worse than either, and no single-item review finds the combination.

The headline number is the one to remember: zero cold boots fail, one warm reset does. CURRICULUM-DERIVED from 28.1 §4's failure-domain split, which lists stale-state defects as one of its six domains — and this is the mechanism that produces them: not a bad measurement, but a good measurement cleared by a reset that did not ask for a new one.

10. Review Item 5 — Are This Recalibration's Preconditions Enforced, or Assumed?

FacetContent
Under reviewevery periodic or triggered recalibration
Invariant at riska measurement is taken only under the conditions its result is valid for
Where it livesthe condition on the start pulse, not the interval counter
Evidence to demandthe list of preconditions, and the line of RTL enforcing each
What escapesa periodic update that overwrites a good value with a worse one
How DV proves itfire the interval timer during traffic and check the start is held off
Telemetryrecalibrations started, and recalibrations deferred — the second is the useful one
Misleading evidencethe recalibration runs on schedule, converges, and commits — every time

CURRICULUM-DERIVED from 19.5 §4's one-time-versus-continuous split. A one-time value's risk is that it goes stale (item 4). A continuous value's risk is the opposite and less obvious: that it is refreshed badly.

The review question is not whether the cadence is implemented. It is whether the preconditions are. A recalibration is a measurement, and a measurement taken while the thing being measured is in use measures something else.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: the interval timer REQUESTS; the preconditions GRANT.
// Separating them is the whole item.
module recal_preconditions #(
    parameter int INTERVAL   = 256,   // ILLUSTRATIVE ticks
    parameter int QUIET_FOR  = 8,     // ILLUSTRATIVE idle cycles required
    parameter int VAL_W      = 8
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             tick,
    input  logic             bus_busy,
    input  logic             thermal_settling,   // a second precondition
    input  logic [VAL_W-1:0] measured_value,
    input  logic             measurement_done,
    output logic             recal_start,
    output logic [VAL_W-1:0] committed_value,
    output logic [15:0]      recals_started,
    output logic [15:0]      recals_deferred,
    output logic [15:0]      commits_under_traffic
);
  logic [$clog2(INTERVAL+1)-1:0]  ivl;
  logic [$clog2(QUIET_FOR+1)-1:0] quiet;
  logic                           pending, running;

  // Preconditions, named once and used once. A reviewer can point at
  // this expression and at the list it came from.
  wire preconditions_met = (quiet == QUIET_FOR[$clog2(QUIET_FOR+1)-1:0])
                        && !bus_busy
                        && !thermal_settling;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      ivl <= '0; quiet <= '0; pending <= 1'b0; running <= 1'b0;
      recal_start <= 1'b0; committed_value <= '0;
      recals_started <= '0; recals_deferred <= '0;
      commits_under_traffic <= '0;
    end else begin
      recal_start <= 1'b0;

      // Quiet-window tracker.
      if (bus_busy) quiet <= '0;
      else if (quiet != QUIET_FOR[$clog2(QUIET_FOR+1)-1:0]) quiet <= quiet + 1'b1;

      // The timer only ever sets `pending`. It never starts anything.
      if (tick) begin
        if (ivl == INTERVAL[$clog2(INTERVAL+1)-1:0]) begin
          ivl     <= '0;
          pending <= 1'b1;
        end else begin
          ivl <= ivl + 1'b1;
        end
      end

      // Deferral is counted, because an unbounded deferral is its own
      // defect and a reviewer must be able to see it.
      if (pending && !running) begin
        if (preconditions_met) begin
          pending        <= 1'b0;
          running        <= 1'b1;
          recal_start    <= 1'b1;
          recals_started <= recals_started + 1'b1;
        end else if (tick) begin
          recals_deferred <= recals_deferred + 1'b1;
        end
      end

      if (running && measurement_done) begin
        running <= 1'b0;
        // Commit only if the preconditions held for the WHOLE measurement.
        if (preconditions_met) committed_value <= measured_value;
        else commits_under_traffic <= commits_under_traffic + 1'b1;
      end
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: the timer starts the measurement.
//
//   if (tick && (ivl == INTERVAL)) begin
//     ivl <= '0; recal_start <= 1'b1; running <= 1'b1;   // <-- the defect
//   end
//   if (running && measurement_done) committed_value <= measured_value;
//
// CONTRACT VIOLATED: the measurement's own validity conditions. Not a
// timing rule, not a protocol rule -- a MEASUREMENT rule, which is why
// no protocol checker catches it.
//
// WHY IT SURVIVES: it is more robust-looking than the robust build. It
// never defers, never stalls, never reports a deferral, and always
// commits on schedule. `recals_started` matches the expected count
// exactly, which is what a reviewer checks.
//
// TRACE (ILLUSTRATIVE, 8 intervals, bus busy during 3 of them):
//   robust: recals_started = 5  recals_deferred = 3
//           commits_under_traffic = 0   committed_value: always valid
//   weak:   recals_started = 8  recals_deferred = 0
//           commits_under_traffic = 3   committed_value: 3 of 8 measured
//                                       under traffic and committed anyway
//
//   gap: 3 of 8 commits (37.5%) are measurements of the wrong thing.

The measured gap is 3 of 8, and the direction of the error is what makes this item hard to review. DERIVED: the weak build's telemetry is better-looking than the robust build's — eight starts, zero deferrals, a perfect schedule. The robust build reports three deferrals, which reads like a design that is struggling.

CURRICULUM-DERIVED from 28.4 §2's standing rule: a failure signature is evidence, not a verdict“a done flag is a signature. So is a converged result. Neither is a statement about margin.” This item is the corollary for the schedule: a recalibration that always completes on time is a signature too, and it is consistent with a design that never checks whether completing on time was possible.

And the escape has a characteristic silicon signature worth naming: a value that gets worse over hours of load and recovers when the system goes idle. Each recalibration under traffic commits a slightly worse value; each recalibration at idle commits a good one. The part appears to be thermally sensitive when it is actually load-sensitive, and the two are distinguished by 28.6's methods, not by this gate.

11. Review Item 6 — Can This Search Tell an Exhausted Range From an Absent Margin?

FacetContent
Under reviewevery training search's failure report
Invariant at riskno passing point in the range searched and no passing point are different results
Where it livesthe failure assignment at the end of the sweep, and the range bounds
Evidence to demandthe sweep bounds, and the physically possible range they are supposed to cover
What escapesa margin investigation that starts from a configuration error
How DV proves ita stimulus whose answer lies one tap outside the range, checked for a distinct code
Telemetrywhether the passing region touched either end of the sweep
Misleading evidencean all-zeros bitmap, which is a real signature of a real failure — just not this one

CURRICULUM-DERIVED from 28.1 §2, which owns the interpretation problem and states it exactly: “A bitmap of all zeros is consistent with a dead lane, a stuck classifier, a mis-programmed sweep range, an unfinished prerequisite step, and a genuine margin failure. Five causes, one signature, and nothing in the bitmap distinguishes them.”

28.1 owns what to do when you are handed that bitmap. This item owns the review question that would have prevented it: does the search distinguish the causes it can distinguish? Three of the five are digitally decidable by the search itself — a mis-programmed range, an unfinished prerequisite, and a classifier that never changes state. A search that reports one code for all five has thrown away information it had.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: one sweep, five distinguishable outcomes.
module search_range_adequacy #(
    parameter int TAPS      = 32,    // ILLUSTRATIVE sweep width
    parameter int TAP_W     = 5,
    parameter int HW_TAPS   = 64     // ILLUSTRATIVE hardware range
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             start,
    input  logic             prereq_done,     // 21.5's dependency structure
    input  logic             probe_valid,
    input  logic             probe_pass,
    input  logic             classifier_alive, // did the observable ever move?
    output logic [TAP_W-1:0] tap,
    output logic             probe_req,
    output logic             done,
    output logic             found,
    output logic [TAP_W-1:0] best_tap,
    // the five outcomes, as separate bits
    output logic             err_prereq,       // cause: unfinished prerequisite
    output logic             err_classifier,   // cause: stuck observable
    output logic             range_exhausted,  // cause: mis-programmed range
    output logic             edge_at_low,      // pass region touched tap 0
    output logic             edge_at_high,     // pass region touched TAPS-1
    output logic [TAP_W:0]   pass_count
);
  logic sweeping;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      tap <= '0; probe_req <= 1'b0; sweeping <= 1'b0;
      done <= 1'b0; found <= 1'b0; best_tap <= '0;
      err_prereq <= 1'b0; err_classifier <= 1'b0;
      range_exhausted <= 1'b0; edge_at_low <= 1'b0; edge_at_high <= 1'b0;
      pass_count <= '0;
    end else begin
      probe_req <= 1'b0;

      if (start) begin
        done <= 1'b0; found <= 1'b0; pass_count <= '0;
        err_prereq <= 1'b0; err_classifier <= 1'b0;
        range_exhausted <= 1'b0; edge_at_low <= 1'b0; edge_at_high <= 1'b0;
        // The prerequisite check is BEFORE the sweep, so a prerequisite
        // failure cannot masquerade as a margin failure.
        if (!prereq_done) begin
          err_prereq <= 1'b1;
          done       <= 1'b1;
        end else begin
          tap      <= '0;
          sweeping <= 1'b1;
        end
      end

      if (sweeping && !probe_valid) probe_req <= 1'b1;

      if (sweeping && probe_valid) begin
        if (probe_pass) begin
          pass_count <= pass_count + 1'b1;
          if (!found) begin found <= 1'b1; best_tap <= tap; end
          if (tap == '0)                                  edge_at_low  <= 1'b1;
          if (tap == TAP_W'(TAPS-1))                      edge_at_high <= 1'b1;
        end

        if (tap == TAP_W'(TAPS-1)) begin
          sweeping <= 1'b0;
          done     <= 1'b1;
          // Stuck observable: not one probe ever differed from another.
          if (!classifier_alive) err_classifier <= 1'b1;
          // Range exhausted: nothing passed AND the hardware has range
          // this sweep did not use. That second clause is the item --
          // "nothing passed" alone does not distinguish the causes.
          else if (!found && (TAPS < HW_TAPS)) range_exhausted <= 1'b1;
        end else begin
          tap <= tap + 1'b1;
        end
      end
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: one failure bit.
//
//   if (tap == TAPS-1) begin
//     done <= 1'b1;
//     failed <= !found;            // <-- the defect: one code, five causes
//   end
//
// and the prerequisite is checked NOWHERE, so an unfinished prerequisite
// runs the sweep and reports a margin failure.
//
// CONTRACT VIOLATED: 28.1 section 4's failure-domain split -- a search
// defect, an observation defect, a configuration defect, a stale-state
// defect, an ordering defect and a margin problem are six domains, and
// `failed` is one bit.
//
// WHY IT SURVIVES: `failed` is CORRECT. Nothing passed, so the search
// failed. The defect is not a wrong value; it is a report with less
// information than the design had. And on the bench, where the range is
// right and the prerequisites run in order, `failed` never asserts.
//
// TRACE (ILLUSTRATIVE, five stimuli):
//   prereq not done      robust: err_prereq=1        weak: failed=1
//   classifier stuck     robust: err_classifier=1    weak: failed=1
//   range 32 of 64 taps  robust: range_exhausted=1   weak: failed=1
//   genuine no-margin    robust: all clear, found=0  weak: failed=1
//   pass region at edge  robust: found=1 edge_at_high=1  weak: found=1
//
//   distinguishable causes: robust 4 of 4 failures; weak 1 of 4.
//   And row 5: the weak build reports SUCCESS with the answer against
//   the end of the sweep -- a pass region that is probably wider than
//   the range, i.e. an unmeasured margin reported as a measured one.

Row 5 is the finding that is worth more than the other four, and it is a success case. DERIVED: a passing region that touches an end of the sweep means the sweep did not contain the region's boundary, so the margin reported is a lower bound of unknown looseness. The weak build calls that success. CURRICULUM-DERIVED from 20.5's setup-versus-hold trade: choosing a sample point is a trade between two margins, and you cannot trade what you did not measure.

And the pass criterion for this item is a comparison, not a check. The reviewer needs two numbers: the sweep's range and the hardware's range. A sweep of 32 taps is correct or a configuration error depending entirely on the second number, and the second number is not in the RTL — which is why this item's evidence to demand is an artifact and not a line.

12. Review Item 7 — Does This Selection Rule Match the Shape of Its Pass Region?

FacetContent
Under reviewthe rule that picks an operating point from a pass region
Invariant at riska two-sided region is centred; a one-sided region is offset
Where it livesthe arithmetic that converts a pass region into a chosen tap
Evidence to demandper search, whether its pass region is one-sided or two-sided, and why
What escapesan operating point placed half-way into the failing side
How DV proves ita one-sided pass region, and a check that the choice is not its midpoint
Telemetrythe chosen tap and both region edges, read together
Misleading evidence“we centre the window” is correct practice, cited correctly, applied to the wrong search

CURRICULUM-DERIVED from 21.3 §2, which owns this and states it without hedging: the gate's pass region is one-sided and therefore not centred. And from 21.4 §2, which owns the two-sided case: the eye is searched on two axes and a centre is selected in both.

Two searches in the same PHY, two different correct selection rules. The defect is a single rule applied to both — and it is the most defensible-sounding defect in this chapter, because centring is what a careful engineer does.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: the selection rule is a parameter of the SEARCH, and
// each search declares its region shape.
module selection_rule_shape #(
    parameter int TAPS   = 32,
    parameter int TAP_W  = 5,
    // 0 = two-sided (centre it); 1 = one-sided (offset from the edge)
    parameter bit ONE_SIDED = 1'b0,
    parameter int LEAD_TAPS = 3      // ILLUSTRATIVE, 19.4's LEAD_CYCLES analogue
)(
    input  logic               clk,
    input  logic               rst_n,
    input  logic [TAPS-1:0]    pass_map,
    input  logic               map_valid,
    output logic [TAP_W-1:0]   chosen_tap,
    output logic               chosen_valid,
    output logic [TAP_W-1:0]   region_low,
    output logic [TAP_W-1:0]   region_high,
    output logic               chosen_in_region,
    output logic [TAP_W:0]     margin_to_fail
);
  logic [TAP_W-1:0] lo, hi;
  logic             any;

  always_comb begin
    lo  = '0; hi = '0; any = 1'b0;
    for (int i = 0; i < TAPS; i++) begin
      if (pass_map[i]) begin
        if (!any) begin lo = TAP_W'(i); any = 1'b1; end
        hi = TAP_W'(i);
      end
    end
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      chosen_tap <= '0; chosen_valid <= 1'b0;
      region_low <= '0; region_high <= '0;
      chosen_in_region <= 1'b0; margin_to_fail <= '0;
    end else if (map_valid) begin
      region_low   <= lo;
      region_high  <= hi;
      chosen_valid <= any;

      if (any) begin
        if (ONE_SIDED) begin
          // The region has ONE real edge. The other end is not a
          // boundary -- it is where the sweep stopped. So offset a
          // documented lead from the real edge, and do not average.
          chosen_tap     <= lo + TAP_W'(LEAD_TAPS);
          margin_to_fail <= (TAP_W+1)'(LEAD_TAPS);
        end else begin
          // Two real edges: the midpoint maximises the distance to both.
          chosen_tap     <= TAP_W'((lo + hi) >> 1);
          margin_to_fail <= (TAP_W+1)'((hi - lo) >> 1);
        end
      end
    end
  end

  // Traceability: the choice must land inside the region it came from.
  always_comb chosen_in_region = chosen_valid
                              && (chosen_tap >= region_low)
                              && (chosen_tap <= region_high);
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: one rule, both searches.
//
//   chosen_tap <= (lo + hi) >> 1;      // <-- always centre
//
// with ONE_SIDED removed from the parameter list entirely, so no
// instantiation can express the distinction.
//
// CONTRACT VIOLATED: 21.3 section 2 -- the gate's pass region is one-sided
// and therefore not centred.
//
// WHY IT SURVIVES: on a two-sided region it is IDENTICAL to the robust
// build. The eye-centring instance is correct. Only the gate instance is
// wrong, and only when the region's high end is the sweep's end rather
// than a real edge.
//
// TRACE (ILLUSTRATIVE, TAPS = 32, LEAD_TAPS = 3):
//   two-sided map, pass on taps 9..23:
//     robust (ONE_SIDED=0): chosen 16  margin 7    -- centred
//     weak:                 chosen 16  margin 7    IDENTICAL
//   one-sided map, pass on taps 6..31 (31 is the sweep end):
//     robust (ONE_SIDED=1): chosen 9   margin_to_fail 3   in_region 1
//     weak:                 chosen 18  margin_to_fail 12  in_region 1
//
//   gap: 9 taps. And the weak build's reported margin, 12, is LARGER --
//   it is measuring distance to tap 31, which is not a failing tap.
//   It is the end of the sweep.

The gap is nine taps, and the weak build reports a better margin than the robust one. DERIVED: 12 versus 3. That inversion is the item's whole difficulty — a reviewer comparing reported margins picks the wrong build.

What the weak build actually measured is the distance to the edge of its own search. CURRICULUM-DERIVED from 21.3 §2's reason the gate region is one-sided: a strobe that arrives after the gate opens is still captured, so the far side of the pass region is bounded by the sweep and not by physics. Averaging two numbers where only one is a measurement produces a number that is neither.

And this item composes with item 6 in a way that is worth stating. Item 6's row 5 flags a pass region touching an end of the sweep. Item 7 is what that flag is for: it is the input to the selection rule, and a region with an artificial edge must not be centred. DERIVED: item 6 without item 7 produces a warning nobody acts on; item 7 without item 6 cannot tell which regions are one-sided.

13. Review Item 8 — Does This Margin Name the Measurement It Came From?

FacetContent
Under reviewevery guard band, lead, trail, or margin constant
Invariant at riska margin is derived from a measured window and a documented drift budget
Where it livesthe parameter declaration, and the expression that uses it
Evidence to demandthe measured window width, the drift budget, and the arithmetic between them
What escapesa margin that exceeds the window on a narrow part, placing the point outside it
How DV proves ita narrow window, and a check that the margin still fits
Telemetrymargin requested versus margin available, both read out
Misleading evidencethe margin is generous, and generous margins are good engineering

This is the item 33.2 §24 handed forward, and the hand-off was explicit: at the RTL gate a tolerance parameter is a defect; in a PHY a margin is the point. They are the same line of Verilog.

The distinction is provenance, and it is not in the code. CURRICULUM-DERIVED from 21.4 §2, whose one-sentence model settles what a margin can and cannot be: training does not create margin — it discovers an operating point with usable margin, and “a grid with no passing cell must fail.” A margin constant that exceeds what the grid offered is not conservative. It is a request the physics cannot fill.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: the margin is computed from the measured width, and the
// design checks that the arithmetic is satisfiable before committing.
module margin_provenance #(
    parameter int TAP_W       = 6,
    // The drift budget is a DECLARED fraction of the measured window,
    // not an absolute tap count. Provenance: 19.5 section 4's continuous
    // side -- the window narrows with temperature, and the budget is the
    // allowance for that narrowing.
    parameter int DRIFT_NUM   = 1,
    parameter int DRIFT_DEN   = 4,     // ILLUSTRATIVE: 25% of the window
    parameter int MIN_USABLE  = 4      // ILLUSTRATIVE taps
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic [TAP_W-1:0] window_low,     // measured
    input  logic [TAP_W-1:0] window_high,    // measured
    input  logic             window_valid,
    output logic [TAP_W-1:0] chosen_tap,
    output logic             chosen_valid,
    output logic [TAP_W:0]   margin_required,
    output logic [TAP_W:0]   margin_available,
    output logic             margin_satisfiable,
    output logic [7:0]       margin_refusals
);
  logic [TAP_W:0] width;

  always_comb begin
    width            = (TAP_W+1)'(window_high) - (TAP_W+1)'(window_low) + 1'b1;
    // The margin is a FUNCTION of the measurement. It cannot exceed the
    // window, because it is a fraction of it.
    margin_required  = (TAP_W+1)'((width * DRIFT_NUM) / DRIFT_DEN);
    margin_available = (width >> 1);
    // The satisfiability test is the item. A margin that does not fit is
    // refused, not truncated.
    margin_satisfiable = window_valid
                      && (width >= (TAP_W+1)'(MIN_USABLE))
                      && (margin_required <= margin_available);
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      chosen_tap <= '0; chosen_valid <= 1'b0; margin_refusals <= '0;
    end else if (window_valid) begin
      if (margin_satisfiable) begin
        chosen_tap   <= TAP_W'((window_low + window_high) >> 1);
        chosen_valid <= 1'b1;
      end else begin
        // 21.4's rule, enforced: a grid with no usable cell must FAIL.
        chosen_valid    <= 1'b0;
        margin_refusals <= margin_refusals + 1'b1;
      end
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: the margin is a constant.
//
//   parameter int GUARD_TAPS = 6;      // "measured on the bench"
//   ...
//   chosen_tap   <= window_low + GUARD_TAPS;
//   chosen_valid <= window_valid;      // <-- no satisfiability test
//
// CONTRACT VIOLATED: 21.4 section 2 -- training does not create margin,
// and a constant margin asserts an amount of margin the window may not
// contain.
//
// WHY IT SURVIVES: GUARD_TAPS = 6 was measured. On the characterisation
// part the window was 24 taps wide, 6 is 25% of it, and the arithmetic
// is exactly what the robust build computes. The constant is not a
// guess -- it is a correct answer, frozen.
//
// TRACE (ILLUSTRATIVE, DRIFT 1/4):
//   wide part,   window 8..31 (width 24):
//     robust: required 6  available 12  satisfiable 1  chosen 19
//     weak:                                            chosen 14
//     -- both inside the window; different points, both usable.
//   narrow part, window 14..21 (width 8):
//     robust: required 2  available 4   satisfiable 1  chosen 17
//     weak:   chosen = 14 + 6 = 20      chosen_valid 1
//     -- inside, but 1 tap from the failing edge instead of 4.
//   very narrow, window 16..19 (width 4):
//     robust: required 1  available 2   satisfiable 1  chosen 17
//     weak:   chosen = 16 + 6 = 22      chosen_valid 1
//     -- OUTSIDE the window. The part is configured to fail, and
//        `chosen_valid` says it is fine.
//
//   gap: on the narrowest part, the chosen tap is 3 taps outside the
//   measured window and the design reports success. margin_refusals:
//   robust 0 (all three satisfiable), weak has no such counter.

The third row is the escape, and note what it is not: it is not a margin that was too small. DERIVED: the weak build fails by asking for MORE margin than exists, and the arithmetic places the operating point past the far edge. A constant margin is safe on parts at least as good as the characterisation part and unsafe on every part worse than it — which is the half of the distribution nobody characterises.

And chosen_in_region from item 7 would have caught this. DERIVED: item 7's traceability output — the check that the choice lands inside the region it came from — fires on this build. The two items are independent questions with one shared cheap detector, and that is a finding about review economics: a single assertion that a selection lies inside its own measured region covers two of the nine items in this chapter.

14. Review Item 9 — Which Direction and Which Side Does This Value Belong To?

FacetContent
Under reviewevery reference level, delay and termination value
Invariant at riskeach value is written to the side of the link that uses it, for the direction it governs
Where it livesthe register-write target, and the direction the search ran in
Evidence to demanda four-cell table: {read, write} × {host, device}, every value placed in exactly one cell
What escapesa trained value applied to the wrong side, correct whenever the two sides are similar
How DV proves itasymmetric sides — a host and device whose correct values differ measurably
Telemetryper-side read-back, not a single merged value
Misleading evidencethe value is right, the search was right, and the part works

CURRICULUM-DERIVED from 28.4 §2, which names this as one of its owned classes — the side-asymmetry error class — and from 21.4 §2, which owns the mechanism: the direction asymmetry, “which side of the link each reference level belongs to.” 21.4 explains why the sides differ. This item demands that the design's register map says which is which.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ROBUST BUILD: direction and side are part of each value's identity,
// and the write path cannot lose them.
module direction_side_map #(
    parameter int VAL_W = 8
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             wr_en,
    input  logic [VAL_W-1:0] wr_value,
    input  logic             wr_is_write_dir,  // 1 = write direction
    input  logic             wr_is_device,     // 1 = device side
    // the four cells, held separately because they are four quantities
    output logic [VAL_W-1:0] vref_rd_host,     // read dir, host samples
    output logic [VAL_W-1:0] vref_wr_device,   // write dir, device samples
    output logic [VAL_W-1:0] dly_rd_host,
    output logic [VAL_W-1:0] dly_wr_device,
    // the two cells that must stay EMPTY: 21.4's direction asymmetry
    output logic [1:0]       illegal_cell_writes,
    output logic [3:0]       cells_populated
);
  // The legality rule, stated once. A reference level belongs to the
  // side that SAMPLES, and the sampling side is decided by direction:
  // reads are sampled by the host, writes by the device.
  function automatic bit legal_cell(bit is_write_dir, bit is_device);
    return (is_write_dir == is_device);
  endfunction

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      vref_rd_host <= '0; vref_wr_device <= '0;
      dly_rd_host  <= '0; dly_wr_device  <= '0;
      illegal_cell_writes <= '0; cells_populated <= '0;
    end else if (wr_en) begin
      if (!legal_cell(wr_is_write_dir, wr_is_device)) begin
        // A write naming an impossible {direction, side} pair is REFUSED.
        // This is the whole item: the pair is checked, not assumed.
        illegal_cell_writes <= illegal_cell_writes + 1'b1;
      end else if (!wr_is_write_dir) begin
        vref_rd_host       <= wr_value;
        dly_rd_host        <= wr_value;
        cells_populated[0] <= 1'b1;
        cells_populated[2] <= 1'b1;
      end else begin
        vref_wr_device     <= wr_value;
        dly_wr_device      <= wr_value;
        cells_populated[1] <= 1'b1;
        cells_populated[3] <= 1'b1;
      end
    end
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// INTENTIONALLY DEFECTIVE. WEAK BUILD: one reference level, both sides.
//
//   input  logic [VAL_W-1:0] wr_value;
//   ...
//   always_ff ... if (wr_en) vref_all <= wr_value;   // <-- one register
//
// with `wr_is_device` declared and never read -- 33.2 section 8's tell,
// appearing for the ninth time in this track's documented defects.
//
// CONTRACT VIOLATED: 21.4 section 2's direction asymmetry, and 28.4's
// side-asymmetry error class.
//
// WHY IT SURVIVES: on a symmetric link the two sides' correct values are
// close, so one register holding either is within tolerance. The training
// search finds a passing point. The part works. The defect appears when
// the sides stop being similar -- a different device vendor, a different
// rank population, a different termination setting.
//
// TRACE (ILLUSTRATIVE, correct host Vref 0x48, correct device Vref 0x5C):
//   symmetric part  (host 0x4A, device 0x4C):
//     robust: vref_rd_host=0x4A  vref_wr_device=0x4C  illegal=0
//     weak:   vref_all=0x4C (last write wins)
//     -- read direction runs 2 codes off centre; inside the eye. WORKS.
//   asymmetric part (host 0x48, device 0x5C):
//     robust: vref_rd_host=0x48  vref_wr_device=0x5C  illegal=0
//     weak:   vref_all=0x5C
//     -- read direction runs 20 codes off centre. Reads fail; writes pass.
//
//   gap: 20 codes, and the failure is DIRECTIONAL -- one direction
//   corrupts and the other does not, which is 28.4's side-asymmetry
//   signature exactly.
//
//   And the illegal-pair check: the robust build counts a write naming
//   {read direction, device side} as illegal; the weak build cannot,
//   because it does not read `wr_is_device` at all.

The signature is what makes this item worth its place: a part where one direction works and the other does not. DERIVED: a directional failure is strong evidence of a side-asymmetry error and weak evidence of anything else, because almost every other defect in this chapter is direction-agnostic. CURRICULUM-DERIVED from 28.1 §4's failure-domain split: direction is one of the few discriminators available before a single probe is placed.

And the tell repeats. wr_is_device declared and never read. CURRICULUM-DERIVED from 33.2 §8: eight of the track's eighteen defects present this way, and this chapter adds a ninth and a tenth — item 1's trained_flight and item 9's wr_is_device. DERIVED: the unread-input tell now accounts for ten of twenty documented defects across this curriculum, and it remains the cheapest check either gate has.

15. The Review Assembled

Cost-ordered. DERIVED from §19's table, and the ordering is almost the reverse of 33.2 §15's — at the RTL gate five of nine items were free; here one is.

#ItemQuestion, in one lineCostWhat it needs
1§8 Untrained refusalWhat is the reset value of this gate?minutesone line of RTL
2§14 Direction and sideIs is_device read anywhere?minutesgrep, then a four-cell table
3§9 Reset domainsWhich reset clears this, and does that reset retrain?hoursa two-column map
4§6 Provenance censusWhich side of the line is each quantity on?hoursa census, judged on completeness
5§12 Selection ruleIs this region one-sided or two-sided?hoursper-search region shape
6§7 Flag semanticsWhat would this flag report in each of five cases?hoursfive stimuli
7§11 Range adequacyWhat is the hardware's range, and what did we sweep?daysa number that is not in the RTL
8§10 Recal preconditionsWhat conditions must hold, and which line enforces each?daysthe measurement's validity conditions
9§13 Margin provenanceWhat measurement is this margin a fraction of?dayscharacterisation data

The ordering carries this chapter's central finding about review economics. At 33.2's gate, the cheap items dominated: five of nine were decided from source text and they caught twelve of eighteen defects. Here, seven of nine require an artifact the codebase does not contain.

DERIVED: that is not a difference in review quality. It is a difference in where the information lives. A controller's obligations are in its specification; a PHY's obligations are partly in a datasheet, partly in a characterisation report, and partly in a board design owned by another discipline22.3 §3's callout. So a PHY review that produces only findings is an incomplete review. A PHY review must also produce a list of artifacts it could not obtain, and items 7, 8 and 9 are where that list comes from.

And three items compose into one cheap detector, which is the practical takeaway. Items 6, 7 and 12 all fire on a selection or a value that lies outside the region it claims to come from — item 12's chosen_in_region, item 6's census residue, item 7's trusted conjunction. DERIVED: one assertion that every committed value lies inside its own measured region covers three of the nine items, and it costs one line.

16. Quantitative Reasoning

ItemQuantityRobustWeakGapProvenance
§6boards the design is correct onall1the characterisation boardDERIVED, ILLUSTRATIVE trace lengths
§7distinguishable failure cases of five514 cases read as successDERIVED from 28.4's five
§8operations granted untrained011, and the counter under-reports by 1DERIVED
§9warm resets to failurenone10 cold boots failDERIVED
§10commits measured under traffic0 of 83 of 837.5%DERIVED, ILLUSTRATIVE interval
§11distinguishable failure causes4 of 41 of 43, plus a false successDERIVED from 28.1's five
§12chosen tap on a one-sided region9189 taps, and reported margin 3 vs 12DERIVED
§13chosen tap on the narrowest part17223 taps outside the windowDERIVED, ILLUSTRATIVE widths
§14reference-level error, asymmetric part020 codesdirectionalDERIVED, ILLUSTRATIVE codes

Three of the nine gaps are inversions — the weak build reports a better number than the robust one — and that is this chapter's signature finding.

ItemRobust reportsWeak reportsWhich looks better
§105 starts, 3 deferrals8 starts, 0 deferralsthe weak build
§12margin 3margin 12the weak build
§130 refusals, a narrower choicevalid on every partthe weak build

DERIVED: at 33.2's gate, the weak builds mostly reported nothing — a silent wrong answer. Here, three of nine actively report success metrics that beat the correct design's.

The mechanism is the same in all three, and it is worth naming as a rule: each weak build removed a check, and the removed check was the thing that produced the unflattering number. Deferrals exist because preconditions are enforced. A small margin figure exists because the margin is measured against a real edge. A refusal count exists because satisfiability is tested. DERIVED: a design that reports no failures of a check it does not perform is indistinguishable, in its telemetry, from a design that passes that checkso a review must ask which counters a design is even capable of incrementing.

CURRICULUM-DERIVED from 28.4 §2's standing rule — a failure signature is evidence, not a verdictand this chapter's corollary is the contrapositive: the absence of a failure signature is evidence only if the signature could have been produced.

17. What the Assertions Prove

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  // ---- Section 6: provenance. The measured term must be READ, which is
  // the property a formula-based build cannot satisfy.
  property p_offset_uses_trained_term;
    @(posedge clk) disable iff (!rst_n)
      launch_offset_valid |-> (launch_offset == (calc_part + trained_flight));
  endproperty
  assert property (p_offset_uses_trained_term)
    else $error("the launch offset did not include the trained flight term");

  property p_no_unclassified_quantity;
    @(posedge clk) disable iff (!rst_n) unclassified_terms == '0;
  endproperty
  assert property (p_no_unclassified_quantity)
    else $error("a quantity feeding a timing decision has no declared provenance");

  property p_refuses_without_provenance;
    @(posedge clk) disable iff (!rst_n)
      (!trained_flight_valid) |-> !launch_offset_valid;
  endproperty
  assert property (p_refuses_without_provenance)
    else $error("the launch offset was declared valid with no measured term");

  // ---- Section 7: flag semantics. `trusted` is a CONJUNCTION, and the
  // property names all three facts -- 28.4's five-into-one collapse.
  property p_trusted_implies_all_facts;
    @(posedge clk) disable iff (!rst_n)
      trusted |-> (ran && converged && in_range);
  endproperty
  assert property (p_trusted_implies_all_facts)
    else $error("trusted asserted without all of its constituent facts");

  property p_trust_is_not_monotonic;
    @(posedge clk) disable iff (!rst_n)
      (trusted && env_changed) |=> !trusted;
  endproperty
  assert property (p_trust_is_not_monotonic)
    else $error("trust survived an environment change: the flag cannot fall");

  // ---- Section 8: untrained refusal. Reset value AND the reclose path.
  property p_no_grant_while_gate_closed;
    @(posedge clk) disable iff (!rst_n) op_grant |-> $past(gate_open);
  endproperty
  assert property (p_no_grant_while_gate_closed)
    else $error("an operation was granted with the trained-value gate closed");

  property p_gate_closed_without_validity;
    @(posedge clk) disable iff (!rst_n) (!trained_valid) |=> !gate_open;
  endproperty
  assert property (p_gate_closed_without_validity)
    else $error("the gate stayed open with no valid trained value");

  // ---- Section 9: reset domains. The ONLY property in this chapter whose
  // antecedent is a reset, and it must be written outside the
  // `disable iff` that every other property uses.
  property p_clear_implies_retrain;
    @(posedge clk)
      $fell(trained_valid) |-> ##[0:2] (retrain_req || trained_valid);
  endproperty
  assert property (p_clear_implies_retrain)
    else $error("a trained value was cleared and no retraining was requested");

  property p_no_ops_on_reset_value;
    @(posedge clk) disable iff (!rst_por_n) ops_with_stale_offset == '0;
  endproperty
  assert property (p_no_ops_on_reset_value)
    else $error("an operation used the reset-value offset");

  // ---- Section 10: recalibration preconditions.
  property p_start_only_when_permitted;
    @(posedge clk) disable iff (!rst_n) recal_start |-> preconditions_met;
  endproperty
  assert property (p_start_only_when_permitted)
    else $error("recalibration started with its preconditions unmet");

  property p_commit_only_under_preconditions;
    @(posedge clk) disable iff (!rst_n) commits_under_traffic == '0;
  endproperty
  assert property (p_commit_only_under_preconditions)
    else $error("a measurement taken under traffic was committed");

  // ---- Section 11: range adequacy. Two-sided, because "failed" being
  // correct is exactly why one bit is not enough.
  property p_failure_has_a_cause;
    @(posedge clk) disable iff (!rst_n)
      (done && !found) |-> (err_prereq || err_classifier || range_exhausted
                            || (pass_count == '0));
  endproperty
  assert property (p_failure_has_a_cause)
    else $error("a search failed and reported no distinguishing cause");

  property p_prereq_checked_before_sweep;
    @(posedge clk) disable iff (!rst_n)
      (start && !prereq_done) |=> (err_prereq && done);
  endproperty
  assert property (p_prereq_checked_before_sweep)
    else $error("the sweep ran with an unfinished prerequisite");

  // ---- Section 12: selection rule. The shared cheap detector.
  property p_choice_inside_its_region;
    @(posedge clk) disable iff (!rst_n) chosen_valid |-> chosen_in_region;
  endproperty
  assert property (p_choice_inside_its_region)
    else $error("the chosen tap lies outside the region it was selected from");

  property p_one_sided_is_not_centred;
    @(posedge clk) disable iff (!rst_n)
      (chosen_valid && ONE_SIDED) |-> (chosen_tap == region_low + TAP_W'(LEAD_TAPS));
  endproperty
  assert property (p_one_sided_is_not_centred)
    else $error("a one-sided region was centred");

  // ---- Section 13: margin provenance. The satisfiability test, asserted.
  property p_margin_fits_the_window;
    @(posedge clk) disable iff (!rst_n)
      chosen_valid |-> (margin_required <= margin_available);
  endproperty
  assert property (p_margin_fits_the_window)
    else $error("a point was committed whose margin exceeds the measured window");

  property p_unsatisfiable_margin_refuses;
    @(posedge clk) disable iff (!rst_n)
      (window_valid && !margin_satisfiable) |=> !chosen_valid;
  endproperty
  assert property (p_unsatisfiable_margin_refuses)
    else $error("an unsatisfiable margin produced a valid choice");

  // ---- Section 14: direction and side.
  property p_illegal_pair_refused;
    @(posedge clk) disable iff (!rst_n)
      (wr_en && (wr_is_write_dir != wr_is_device)) |=> $stable(vref_rd_host)
                                                    && $stable(vref_wr_device);
  endproperty
  assert property (p_illegal_pair_refused)
    else $error("a write naming an impossible direction/side pair changed a cell");

  property p_sides_are_separate;
    @(posedge clk) disable iff (!rst_n)
      (wr_en && !wr_is_write_dir && !wr_is_device) |=> $stable(vref_wr_device);
  endproperty
  assert property (p_sides_are_separate)
    else $error("a read-direction host write disturbed the device-side value");

  // ---- COVERS. Each on the dimension its defect scales with.
  // Section 6: the trained term DIFFERING from any formula's answer.
  cover property (@(posedge clk) disable iff (!rst_n)
                  trained_flight_valid && (trained_flight != '0));
  // Section 7: each of the five cases reached. The antecedent of
  // p_trusted_implies_all_facts is unreachable for four of them.
  cover property (@(posedge clk) disable iff (!rst_n) fail_case == 3'd2);
  cover property (@(posedge clk) disable iff (!rst_n) fail_case == 3'd3);
  cover property (@(posedge clk) disable iff (!rst_n) fail_case == 3'd4);
  cover property (@(posedge clk) disable iff (!rst_n) fail_case == 3'd5);
  // Section 8: a request INSIDE the untrained window -- not a legal boot
  // sequence, which is why no stimulus reaches it by accident.
  cover property (@(posedge clk) disable iff (!rst_n) op_request && !gate_open);
  // Section 9: a WARM reset after successful training. The dimension is
  // the reset TYPE, and cold-booting more times never reaches it.
  cover property (@(posedge clk) trained_valid ##1 $fell(rst_func_n));
  // Section 10: the interval expiring while the bus is BUSY.
  cover property (@(posedge clk) disable iff (!rst_n)
                  (ivl == INTERVAL[$clog2(INTERVAL+1)-1:0]) && bus_busy);
  // Section 11: a pass region touching the sweep's end -- the false
  // success of row 5, which is not a failure and must still be covered.
  cover property (@(posedge clk) disable iff (!rst_n) done && found && edge_at_high);
  // Section 12: a ONE-SIDED region, which a random pass map rarely gives.
  cover property (@(posedge clk) disable iff (!rst_n)
                  map_valid && pass_map[TAPS-1] && !pass_map[0]);
  // Section 13: a window NARROW enough that the constant margin fails.
  cover property (@(posedge clk) disable iff (!rst_n)
                  window_valid && (width < (TAP_W+1)'(2*MIN_USABLE)));
  // Section 14: an ASYMMETRIC pair. Symmetric sides hide the defect.
  cover property (@(posedge clk) disable iff (!rst_n)
                  wr_en && (vref_rd_host != '0)
                        && (wr_value > vref_rd_host + 8'd16));

Reviewed against the eleven varieties, and three are worth stating because this chapter's property set had to be built around them.

Variety 9 — a property hidden by its own reset guard — governs §9, and it forced the only structural exception in this chapter. p_clear_implies_retrain has no disable iff, because the event it checks is a reset. CURRICULUM-DERIVED from 30.10 §12: a property whose antecedent is masked by the guard every other property needs is vacuous in exactly the window it was written for. Every other property here disables on reset. This one cannot, and a review that applies the house style uniformly deletes the item.

Variety 4 — the environment shares the design's wrong model — governs §6 and §8. §6's environment shares a constant (the board's trace length, in both design and testbench). §8's shares a schedule — a testbench modelling the boot ROM never drives the window the ROM never drove. DERIVED: variety 4's original form was a shared constant (30.7 §10) and 32.2 §16 broadened it to a shared model; §8 is a third form, a shared sequence, and it is the one no amount of randomisation reaches because the sequence is a legality constraint.

Variety 11 — the evidence-grade escape — governs §13. The margin constant is grade A evidence: documented for a named configuration — the characterisation part. It is used as though it were grade B: a documented mechanism. CURRICULUM-DERIVED from 18.4 §1's four grades and 32.1 §15's variety: the failure mode is category drift, and a frozen measurement drifting into a general rule is the cleanest instance of it in this curriculum.

18. Mutation Testing

Baseline first: all nineteen assertions pass and all twelve covers are non-zero.

#MutationKilled bySurvived?
M1§6: set ALLOW_CALC_FLIGHT = 1p_offset_uses_trained_termkilled
M2§6: drop the unclassified_terms residuep_no_unclassified_quantity, by one coverkilled
M3§7: trusted <= engine_returnedp_trusted_implies_all_factskilled
M4§7: delete the env_changed clausep_trust_is_not_monotonickilled
M5§8: gate_open <= 1'b1 at resetp_no_grant_while_gate_closed, by one coverkilled
M6§9: move trained regs to rst_func_np_clear_implies_retrain, by one coverkilled
M7§10: recal_start on the timerp_start_only_when_permittedkilled
M8§10: commit without rechecking preconditionsp_commit_only_under_preconditionskilled
M9§11: collapse the causes into one failed bitp_failure_has_a_causekilled
M10§11: check the prerequisite after the sweepp_prereq_checked_before_sweepkilled
M11§12: always centrep_one_sided_is_not_centred, by one coverkilled
M12§13: GUARD_TAPS constant, no satisfiability testp_margin_fits_the_windowkilled
M13§14: one merged vref_all registerp_sides_are_separatekilled
M14§11: widen TAPS to HW_TAPSnothingSURVIVES
M15§7: STALE_AT raised to its maximumnothingSURVIVES
M16§13: DRIFT_NUM/DRIFT_DEN set to 0nothingSURVIVES

DERIVED: thirteen of sixteen killed, three survived — and all three survivors are the same finding, which is the most useful result in this chapter.

M14, M15 and M16 each change a quantity rather than a mechanism, and every property here checks mechanism. Widening the sweep to the full hardware range is arguably an improvement and arguably a boot-time regression; raising the staleness threshold makes trusted almost permanent; zeroing the drift budget makes every margin satisfiable. All three keep the code structurally correct and make the design worse.

That is not a coverage gap. It is the boundary of what this gate can prove, and it is exactly where §23 draws the residual risk. CURRICULUM-DERIVED from 20.5, which owns the published figures this chapter deliberately does not derive: whether 32 taps, 512 ticks or a quarter of the window are the right numbers is a question about a datasheet and a characterisation report. DERIVED: a PHY review can prove that a design uses a measurement correctly. It cannot prove the measurement was the right one to take, and three mutations are the mechanical demonstration.

And four mutations are killed only by a cover — M2, M5, M6 and M11. Each property is correct and its antecedent is unreachable under a benign stimulus: no unclassified quantity ever appears, no request lands in the untrained window, no warm reset follows training, no one-sided pass map arises. M6's cover is the sharpest of the four, because its dimension is the reset typeCURRICULUM-DERIVED from 31.2 §14's coverage-dimension rule: cold-booting a thousand times never reaches a warm reset, and duration is not the dimension this defect scales with.

19. Baseline Defects Found Before Mutation

Each of the nine weak builds run against the robust build's property set, before any mutation.

ItemWeak build caught byAt what cost
§6p_offset_uses_trained_termnothing on a differing board — a grep finds the unread input
§7p_trusted_implies_all_factsfour stimuli, one per unreached case
§8p_no_grant_while_gate_closednothing — one reset branch
§9p_clear_implies_retrainone warm reset, after training
§10p_start_only_when_permittedtraffic concurrent with the interval
§11p_failure_has_a_causea deliberately wrong sweep range
§12p_one_sided_is_not_centreda one-sided pass map
§13p_margin_fits_the_windowa narrow part
§14p_sides_are_separatean asymmetric device

DERIVED: two of nine are visible in source text — §8's reset branch and §6's unread input. Seven require a stimulus, and five of those seven require a stimulus that is not a variation of the nominal one.

That is the inverse of 33.2 §19's result, where five of nine needed no simulation. The reason is structural: an RTL defect is a wrong line, and a line can be read. A PHY defect is a wrong belief about a measured value, and a belief is only visible when the value it is about behaves unexpectedly.

And the five stimuli that are not variations of the nominal one deserve naming, because each is a category of test a project either has or does not have.

ItemThe stimulusWhy more of the nominal test never reaches it
§9a warm reset after trainingthe dimension is reset type, not count
§12a one-sided pass maprandom maps are two-sided; one-sidedness is a property of the search
§13a narrow partthe nominal part is the characterisation part
§14an asymmetric deviceone vendor, one population, one termination setting
§11a wrong sweep rangenobody deliberately mis-programmes a register that works

DERIVED: all five require the testbench to model a different system, not different traffic. CURRICULUM-DERIVED from 31.2 §14's refinement and this track's coverage-dimension rule: when the dimension a defect scales with belongs to the environment's model rather than its stimulus, running longer never reaches itand at this gate, five of nine defects live on exactly that kind of dimension. That is the strongest argument this curriculum has for a configurable, multi-part PHY verification environment, and it is an argument 33.4 inherits.

20. Silicon Observability

ItemWhat silicon can showWhat it cannot
§6the same part working on one board and failing on anotherwhich term carried the board's value
§7a done flag that has never been observed low since bootwhich of five things it meant
§8an early-operation counter reading lower than the request countwhether the gap is refusal or a miscount
§9a part that passes cold boot and fails after warm reset, repeatablywhich register lost its value
§10performance degrading under sustained load and recovering at idlethat the mechanism is recalibration, not temperature
§11an all-zeros bitmapany of 28.1's five causes
§12a chosen tap at the midpoint of a region touching the sweep endthat the far edge was artificial
§13a yield cliff on parts with narrow windowsthat the margin constant is the cause
§14one direction corrupting while the other is cleanwhich side's register is wrong

Three signatures in this table are diagnostic — they point at one item and few others — and they are the three worth memorising.

§9: cold boot passes, warm reset fails, repeatably. DERIVED: almost nothing else in this curriculum produces that pattern, because almost nothing else distinguishes reset types. CURRICULUM-DERIVED from 19.5 §2's ordering hazards — this is what they look like from a bench.

§14: one direction corrupts, the other does not. CURRICULUM-DERIVED from 28.4's side-asymmetry class. DERIVED: direction is a free discriminator — it costs one read test and one write test — and it eliminates every direction-agnostic item in this chapter at once.

§6: the part moves and the failure moves with the board, not with the part. CURRICULUM-DERIVED from 22.3 §3: board design is a separate discipline, so a failure that swaps with the board and not with the die is a failure whose cause was transcribed across that boundary.

And one row is a warning rather than an observation: §11's. An all-zeros bitmap is silicon telling you nothing, and 28.1 §2 is the chapter that says so. DERIVED: the only fix is at design time, which is what makes item 6 a review item rather than a debug technique. A design that cannot distinguish its failure causes cannot be made to, after tapeout, by any amount of bench work.

21. Common Wrong Answers

  1. “Training passed, so the PHY is configured correctly.” Seven of the nine weak builds train successfully. Training reports that a search found a point; it does not report that the point was selected by the right rule (§12), fits the window (§13), was written to the right side (§14), or will survive the next reset (§9).

  2. “The formula gives the same answer as training, so training is redundant.” It gives the same answer on the board the formula's inputs describe. §6's trace: identical on board A, one cycle off on board B — and nothing in the RTL domain can revalidate a trace length.

  3. calib_done is high, so calibration succeeded.” It means one of five things (28.4 §2), and the worst of the five “boots, passes its own self-checks, and corrupts data hours later.” A flag that has never been low is not evidence; it is an untested output.

  4. “The gate opens at reset, but it is corrected on the first clock.” One cycle is enough for one operation, and §8's weak build grants exactly one — with a reset-value delay and no error. And the escape widens the moment anything changes the boot sequence.

  5. “Cold boot works, so the reset logic is fine.” Cold boot works in every build in §9. Cold boot asserts both resets, so the mismatch between them is invisible. The defect is visible only on the reset that asserts one and not the other.

  6. “The recalibration runs on schedule every time, so it is healthy.” Or it never checks whether running was valid. §10's weak build has a perfect schedule and commits three of eight measurements taken under traffic. A schedule with no deferrals is consistent with a design that cannot defer.

  7. “We defer recalibrations sometimes, which is a problem to fix.” Inverted. The deferral count is what enforcement looks like. A design reporting zero deferrals has either a very quiet bus or no preconditions.

  8. “The bitmap is all zeros, so we have a margin problem.” Five causes, one signature (28.1 §2). Three of the five are digitally decidable by the search itself, and a search reporting one bit threw that away.

  9. “The search passed, so we measured the margin.” Not if the pass region touched the end of the sweep. §11 row 5: a reported success whose margin is a lower bound of unknown looseness — and the weak build cannot tell you it happened.

  10. “We centre the window. That is best practice.” It is, for a two-sided region. 21.3 §2 states that the gate's pass region is one-sided and therefore not centred — and §12's weak build lands nine taps away while reporting a margin four times larger.

  11. “The larger reported margin means the better configuration.” §12: robust 3, weak 12, and the weak number measures the distance to the end of a sweep. A margin is only a margin if the thing it is measured to is a failing point.

  12. “A generous constant guard band is conservative engineering.” §13's weak build places the operating point three taps outside the measured window on a narrow part. A constant margin is conservative on parts better than the characterisation part and reckless on parts worse than it.

  13. GUARD_TAPS was measured, so it has provenance.” It has provenance for one configuration — evidence grade A — and it is being used as a general rule, grade B. CURRICULUM-DERIVED from 18.4 §1: the failure mode is category drift, not fabrication.

  14. “One Vref register is simpler, and the sides are nearly the same.” Nearly the same on the part you have. §14: 2 codes apart on a symmetric part, 20 on an asymmetric one, and the failure is directional.

  15. “The unread is_device input is a lint warning.” It is the tenth instance of this tell in this curriculum (33.2 §8 counted eight; this chapter adds two). In every instance the unread port carried the value the design should have used.

  16. “The provenance census is clean, so provenance is fine.” The census counts the declaration. §6's weak build reports three classified terms and zero unclassified because the declaration was edited to match the code. A self-reported census is evidence about the declaration.

  17. “A mutation survived, so we need more properties.” Not for M14, M15 or M16. All three change a quantity — a sweep width, a staleness threshold, a drift fraction — and no property about mechanism can adjudicate a quantity. The answer is a datasheet, not an assertion.

  18. “The PHY is the analogue part, so a digital review has little to say.” Nine items, and not one of them needs a volt. Every defect here is a digital belief about a physical quantity — a reset domain, a flag's meaning, a selection rule, a range bound. CURRICULUM-DERIVED from 20.3: sample quality is not digitally observable, and none of these nine items asks about sample quality.

  19. “Our PHY is vendor IP, so this checklist is not ours to run.” Items 1, 3, 4, 5 and 9 are about the integration, not the IP — which quantities you supply, what your reset tree does to its registers, when you trigger its recalibration, and which side's register your register map writes. 19.1 §3: six rows of the ownership table are implementation-dependent, so the boundary is yours to establish and therefore yours to review.

  20. “We will find these in bring-up.” Five of the nine require the bench to model a different system — a warm reset, a narrow part, an asymmetric device, a one-sided region, a wrong sweep range (§19). Bring-up uses the boards and parts it has.

22. Self-Check

  1. A launch offset is cfg_cwl + cfg_ser_depth + (TRACE_MM * PROP_NS_PER_MM) / CLK_PERIOD_NS. The expression is dimensionally correct. State the finding in one sentence, and name the input that is now unread.
  2. calib_done has been high since boot on every part you have tested. Give the five things it could mean, and the one observation that would narrow it.
  3. A trained-value gate's reset branch assigns 1'b1. How wide is the escape window, and what makes it wider?
  4. A design passes cold boot on every part and fails after a warm reset. Name the mechanism, and say which two columns of a table you would ask for.
  5. A recalibration block reports 64 starts and 0 deferrals over a busy hour. Is that good? Give the one question that decides it.
  6. A training search reports failed. The report is correct. Say what is wrong with it, and how many of 28.1's five causes the design could have distinguished.
  7. A pass region runs from tap 6 to tap 31 in a 32-tap sweep, and the design chooses tap 18. Two things are wrong. Name both.
  8. Two builds report margins of 3 and 12 taps for the same search. Which is more likely to be correct, and why is the question not about the numbers?
  9. GUARD_TAPS = 6 was measured on real silicon. Under what conditions is it correct, and what is the evidence grade it is being used at versus the grade it holds?
  10. One direction of the interface corrupts data; the other is clean. Which item does this point at, and what makes the signature diagnostic rather than merely suggestive?
  11. Three mutations survived this chapter's property set. What do all three have in common, and what artifact — not assertion — would kill them?
  12. Of the nine items, how many are decided by source text, how many by a stimulus, and how many by a stimulus that requires modelling a different system? Give the counts and name the five.

23. The Residual Risk

What this gate cannot catch, stated plainly — and here the boundary is unusually sharp, because three mutations already demonstrated it.

It cannot adjudicate a quantity. M14, M15 and M16 changed a sweep width, a staleness threshold and a drift fraction, and no property fired. Every item here checks that a design uses a measurement correctly; none can check that the measurement was the right one to take. CURRICULUM-DERIVED from 20.5, which owns the published figures: the answer to “is 32 taps enough” is in a datasheet and a characterisation report, and this chapter derives neither.

It cannot tell you that a converged value is wrong. CURRICULUM-DERIVED from 28.4 §2's sixth and worst case, which it inherits from 7.7: a calibration “whose outcome the interface does not report”for that mechanism, “did it work?” is not a question digital logic can answer at all. Item 2 makes a done flag honest about what it observed. It cannot make the interface report something it does not report.

It cannot see a defect in the electrical domain that produced the measurement. Every item takes a pass/fail probe as a given. If the probe's classifier is miscalibrated, every search in this chapter converges confidently on the wrong point, and item 6's classifier_alive catches only a stuck classifier, not a biased one. Module 22 owns the channel and 28.6 owns its failures.

It cannot review the sequencer's order. 21.5 §2 owns the dependency structure and states the rule — the order is determined by which observable each step requires — and item 6 checks only that this search's prerequisite was done. A globally wrong order in which every step's immediate prerequisite is satisfied passes all nine items. DERIVED: checking an order requires a declared relation and a topological validation rather than a per-step precondition, and that is 33.6's subject — so this limit is not a gap in the module, it is a boundary between two of its gates.

And it cannot prove that the environment which exercised these nine items is capable of failing. §19 named five stimuli that require modelling a different system. A project can hold every artifact this chapter demands, pass every property, and have a testbench that cannot produce a narrow part or an asymmetric device. That is the next gate's subject, and it is why 33.4 reviews the environment rather than the design.

The honest summary: this gate's nine items decide whether a design's beliefs about measured values are warranted. It cannot decide whether the measurements were right, whether the probe that produced them was honest, or whether anything ever tested the beliefs it just checked.

24. Where This Goes

This gate reviewed the design's beliefs. The next gate reviews the thing that was supposed to test them.

Chapter 33.4 takes the environment as its subject. The question changes from is this belief warranted to could the thing that checked this belief ever have found it false and this chapter hands it an unusually concrete brief, because §19 measured the answer for nine items and found it wanting in five.

From hereWhat 33.4 must settle
§19's five model-dimension stimuliCan this environment produce a different system, or only different traffic?
§17's variety-9 exceptionWhich properties in this project are disabled in the window they were written for?
§18's three quantity mutationsWhat kills a mutation that no property can express?

The last row is the one to carry forward, and it is a genuinely open question rather than a rhetorical one. DERIVED: three mutations in this chapter changed a number, kept every mechanism correct, made the design worse, and were killed by nothing. A coverage report would show no gap. A property review would find no missing property. CURRICULUM-DERIVED from the eleven-variety taxonomy this track has built across 30.9 §6, 31.1 §14 and 32.1 §15: every variety so far describes a property that is wrong, vacuous, or unreachable. None describes a property that is right, reachable, non-vacuous — and silent about the thing that matters.

That gap is where 33.4 starts. The eleven varieties explain why a green assertion proves nothing. The next gate has to explain why a complete, green, fully covered assertion set can still leave a design worse than it should be — and the candidate mechanism is the one this chapter's survivors point at: a property set that is a perfect description of the mechanism and says nothing about the quantities the mechanism operates on.

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.