DDR · Module 33
Debug Review Checklist
Eight questions asked of a finished investigation. Every weak record here contains no false statement and an unlicensed inference — and the difference between a cause eliminated and a cause never examined is a column most write-ups do not have.
33.6 reviewed a plan that was followed. This gate reviews a conclusion that was reached.
The shift is from an order to an inference. A bring-up has a structure to lean on — each step's evidence is the ground for the next. A debug has none: it is an argument from an observation to a cause, and the only thing holding it up is whether the evidence eliminates the alternatives.
What is the set of causes consistent with this evidence, which of them were eliminated, and which were never examined?
Three clauses, and the third is where investigations go wrong. DERIVED: a write-up that names one cause has either eliminated the others or omitted them, and the two look identical in a document that does not distinguish them. §10 is that item, and in the weak build it finds four un-investigated causes recorded as eliminated.
The track's first principle here is not this chapter's, and it is stated better than this chapter could state it. CURRICULUM-DERIVED from 28.4 §2: “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.” And 28.5 §1 puts the same rule in its title: a mismatch is not a finding.
Both chapters own the rule and the method. This gate owns the review of what somebody produced with them — and 33.6 §24 named the boundary precisely: that chapter used a signature as an identity, to tell two failures apart. A debug uses the same bits as evidence about a cause, which is a much stronger reading.
1. How To Use This Chapter
Each of the eight review items answers the same eight questions.
| Facet | What it settles |
|---|---|
| Under review | the claim, experiment, or instrument being examined |
| Invariant at risk | the inference that becomes unsupported if it is wrong |
| Where it lives | the write-up's evidence section, or a commit history |
| Evidence to demand | the eliminated set, the predicted rate, the refutation |
| What escapes | a closed investigation and a defect still present |
| How DV proves it | plant a known cause and check the method reaches it |
| Telemetry | what the investigation record must carry to be checkable |
| Misleading evidence | a conclusion that is consistent with every observation made |
The eighth facet has a form here that appears nowhere else in the module, and it is the reason a debug review is hard. DERIVED: a wrong conclusion in a debug is almost always consistent with the evidence — that is why it was reached. It is not contradicted; it is under-determined. Seven of the eight weak builds below produce a conclusion that no observation in the record refutes.
CURRICULUM-DERIVED from 28.1 §2's measured case, which is this gate's canonical example: an all-zeros training bitmap 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. DERIVED: any one of the five, written up as the conclusion, is consistent with the whole record, and four of the five are wrong.
2. The One-Sentence Model
A debug review is sound when every cited signature names the set of causes consistent with it, when every experiment records how many candidates it eliminated rather than whether it passed, when a layer is attributed before any within-layer discriminator is applied, when an observed failure rate is compared against the rate each hypothesis predicts, when causes eliminated and causes never examined are two separate lists, when the instrument that reported the failure is independent of the block the conclusion accuses, when every threshold change in the checker's history cites a specification rather than a failing run, and when the conclusion states the observation that would have refuted it — and “root cause identified” is bit 0.
3. What This Chapter Owns
| Ground | Owner |
|---|---|
| A signature is evidence, not a verdict | 28.4 §2 |
| The eleven corruption signatures, their mechanisms and next experiments | 28.5 §9 |
| The ECC visibility problem; first-error capture; the localisation funnel | 28.5 §12, 28.5 §13, 28.5 §11 |
| The escalation criterion, and the three experiments mistaken for proof | 28.6 §1, 28.6 §2 |
| Pattern dependence measured properly; the aggressor/victim separation | 28.6 §4, 28.6 §5 |
| Reconstructing a timing violation; the resource-identity error class | 28.2 |
| The obligation / service / correlation split for refresh | 28.3 |
| The eleven training-failure signatures and the failure-domain split | 28.1 |
| The observability collapse; the decision-sequence form; the four perturbations | 30.10 §2, 30.10 §3 |
| A checker that samples late and was “fixed” by widening its tolerance | 30.9 §9, 30.9 §10 |
| The independence requirement and the cannot-fail failure mode | 27.3 |
| Reviewing a finished investigation against the evidence behind it | this chapter |
Module 28 is seven chapters of method and this chapter adds none. The boundary is therefore unusually easy to state and unusually easy to violate, so it is stated as a rule.
DERIVED: Module 28 answers what should I do next. This chapter answers does what you did support what you wrote. The first is a question asked by the person holding the failure; the second is asked by somebody reading a closed ticket.
| Module 28 supplies | This chapter's item consumes it as |
|---|---|
| 28.5 §9's signature → hypotheses → experiment | §6: the hypothesis set the write-up must publish |
| 28.6 §2's three experiments mistaken for proof | §7: the eliminated-set size an experiment must report |
| 28.6 §1's escalation criterion | §8: the layer attribution that must precede a discriminator |
| 28.5 §7's pattern, frequency and temperature axes | §9: the rate each hypothesis predicts |
| 28.5 §11's localisation funnel | §10: eliminated versus never examined |
| 27.3's independence requirement | §11: the accusing instrument versus the accused block |
| 30.9 §10's widened tolerance | §12: the checker's change history |
And one item has no source in the track at all, which is why it is stated as a rule rather than cited. §13 requires that a conclusion name the observation that would have refuted it. DERIVED: no chapter of this curriculum asks for that, and every one of Module 28's methods produces it as a by-product — a discriminating experiment is precisely an observation that would have refuted one branch. The item is therefore a demand that the by-product be written down.
4. Teaching-Model Boundary And Source Discipline
Every SystemVerilog block below models an investigation record — a hypothesis set, an experiment log, an elimination ledger — and not a design.
DERIVED: that choice is what makes this gate's items checkable at all. An inference cannot be asserted about; a record of an inference can. CURRICULUM-DERIVED from 28.5 §17, which already tests its evidence accumulator in SystemVerilog, and from 28.5 §13's first-error capture: this track has established that debug evidence is a data structure, and this chapter reviews the data structure.
| Claim class | What it means here | Example below |
|---|---|---|
| Structural | a documented mechanism or a rule of this track | 28.5's eleven signatures; 28.6's three experiments; 28.1's five causes |
| Curriculum-derived | follows from a cited chapter | every pass criterion |
| Derived | computed in this chapter from the models below | every elimination count in §16 |
| Illustrative | a chosen scenario or rate that makes a mechanism visible | hypothesis sets, failure rates, run counts |
Every failure rate in this chapter is ILLUSTRATIVE, and the arithmetic done with it is the point rather than the number. CURRICULUM-DERIVED from 28.5 §7, which owns the pattern, frequency and temperature axes: a real rate comes from a real part on a real board, and this chapter derives none. DERIVED: §9's argument is that a rate is comparable against a prediction, and it holds for any pair of numbers that differ by orders of magnitude.
One discipline is specific to a chapter about debugging and worth stating. DERIVED: no scenario below is presented as a case study of a real system. Each is a constructed record with a known planted cause, because the only way to measure an investigation method is to know the answer in advance — which is the same reason 33.4 §10 demanded an injection matrix.
No external source was consulted and no network tool was used.
5. Why a Consistent Conclusion Is Not a Supported One
This gate's entire subject is the gap between consistent with and implied by, and the gap has a size that can be counted.
CURRICULUM-DERIVED from 28.1 §2's five-causes-one-signature result and 28.5 §9's signature → hypotheses → experiment structure. DERIVED: if a signature admits five causes, then a write-up naming one has a 1-in-5 chance of being right by construction, and nothing in the record distinguishes the lucky case from the unlucky one.
| The defect | The conclusion is | And the record |
|---|---|---|
| a signature read as a cause | consistent with the evidence | does not list the other four |
| an experiment that correlates | consistent with the evidence | does not say what it eliminated |
| a discriminator before a layer | consistent with the evidence | discriminates within the wrong layer |
| intermittency read as a cause class | consistent with the evidence | never compared a rate to a prediction |
| an omission recorded as an elimination | consistent with the evidence | has one list where it needs two |
| a scoreboard accusing its own subject | consistent with the evidence | does not name the instrument |
| a threshold widened after a failure | consistent with the evidence | has no change history |
| an unfalsifiable conclusion | consistent with every evidence | states no refutation |
Eight rows, and consistent with the evidence is true in all eight. DERIVED: this gate cannot work by looking for contradictions, because there are none. It works by counting what is absent — a hypothesis set, an eliminated count, a layer attribution, a predicted rate, a second list, an instrument name, a change history, a refutation.
And the last row is qualitatively worse than the other seven, which is why §13 is the item that closes the chapter's argument. DERIVED: marginal signal integrity is consistent with every observation any investigation could make, so it cannot be refuted, cannot be confirmed, and closes a ticket. CURRICULUM-DERIVED from 28.6 §1's escalation criterion, which exists precisely to stop that: the criterion asks which digital observations make a physical hypothesis the cheapest remaining one, which is a statement about a set that has been narrowed — not a place to put a failure nobody localised.
6. Review Item 1 — Does This Signature's Citation Name the Set of Causes Consistent With It?
| Facet | Content |
|---|---|
| Under review | every signature cited as evidence in the write-up |
| Invariant at risk | a signature narrows a hypothesis set; it does not select from it |
| Where it lives | the evidence section, beside each observation |
| Evidence to demand | per signature: the consistent-cause set, and the next discriminating experiment |
| What escapes | four wrong causes left unexamined, one of which is the real one |
| How DV proves it | plant each of the five causes and check the method reaches each |
| Telemetry | the hypothesis set's size, recorded as it shrinks |
| Misleading evidence | the named cause really does produce this signature |
CURRICULUM-DERIVED from 28.5 §9, which owns the signature → hypotheses → experiment structure, and from 28.1 §2's measured instance. Module 28 supplies the mapping. This item requires that a write-up publish the set it used and the set that remained.
// ROBUST INVESTIGATION RECORD: a signature maps to a SET, and the
// record carries the set plus the experiment that shrinks it fastest.
package signature_cause_pkg;
// 28.1 section 2's five causes for an all-zeros training bitmap, taken
// as given and not re-derived.
typedef enum int { C_DEAD_LANE, C_STUCK_CLASSIFIER, C_BAD_SWEEP_RANGE,
C_UNFINISHED_PREREQ, C_REAL_MARGIN,
C_RECOVERY_ARTEFACT } cause_e;
typedef enum int { X_LOOPBACK, // eliminates a dead lane
X_FORCE_PASS, // eliminates a stuck classifier
X_WIDEN_SWEEP, // eliminates a bad range
X_CHECK_PREREQ, // eliminates an unfinished prereq
X_CAPTURE_ORDER // eliminates the recovery artefact
} expt_e;
// ELIMINATES[x][c] = 1 means experiment x, if it passes, removes c.
// ILLUSTRATIVE, and every row is 28.1 section 4's failure-domain split
// applied to one signature.
localparam bit ELIMINATES [0:4][0:5] = '{
'{1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0}, // loopback
'{1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0}, // force a known pass
'{1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0}, // widen the sweep
'{1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0}, // check the prerequisite
'{1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1} // capture-order check: two
};
endpackage
module signature_cause_set (
input logic clk,
input logic rst_n,
input logic observe, // a signature was cited
input logic run_expt,
input logic [2:0] expt_id,
input logic expt_eliminates, // the experiment's result
output logic [5:0] live_set,
output logic [3:0] live_count,
output logic [2:0] best_next_expt,
output logic [3:0] best_next_yield,
output logic conclusion_licensed
);
import signature_cause_pkg::*;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
live_set <= 6'b111111; live_count <= 4'd6;
best_next_expt <= '0; best_next_yield <= '0;
conclusion_licensed <= 1'b0;
end else begin
// Citing a signature RESETS the set to everything consistent with
// it. This is the line the weak build does not have.
if (observe) begin
live_set <= 6'b111111;
live_count <= 4'd6;
end
if (run_expt && expt_eliminates) begin
automatic logic [5:0] nxt = live_set;
for (int c = 0; c < 6; c++)
if (ELIMINATES[expt_id][c]) nxt[c] = 1'b0;
live_set <= nxt;
live_count <= 4'($countones(nxt));
end
// The next experiment to run is the one eliminating the most
// LIVE causes -- 28.5 section 9's "next discriminating experiment",
// computed rather than chosen.
begin
automatic int bestx = 0, besty = 0;
for (int x = 0; x < 5; x++) begin
automatic int y = 0;
for (int c = 0; c < 6; c++)
if (ELIMINATES[x][c] && live_set[c]) y++;
if (y > besty) begin besty = y; bestx = x; end
end
best_next_expt <= 3'(bestx);
best_next_yield <= 4'(besty);
end
// A conclusion naming ONE cause is licensed only when the set has
// been reduced to one.
conclusion_licensed <= ($countones(live_set) == 1);
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK RECORD: the signature names the cause.
//
// // ticket DDR-4412
// // Observation: training bitmap all zeros on lane 17.
// // Root cause: marginal read margin on lane 17.
// // Action: increase the read delay by 2 taps. Closed.
// //
// conclusion_licensed <= observe; // <-- the defect
//
// CONTRACT VIOLATED: 28.4 section 2 -- a signature is evidence, not a
// verdict. And 28.1 section 2 lists five causes for exactly this bitmap.
//
// WHY IT SURVIVES: marginal read margin DOES produce an all-zeros
// bitmap. The conclusion is consistent with the observation, the action
// is plausible, and increasing the delay may even make the symptom go
// away -- which 33.6 section 12 already established is not a proof.
//
// TRACE (ILLUSTRATIVE, the real planted cause is C_BAD_SWEEP_RANGE --
// the sweep covered 32 of the hardware's 64 taps):
// robust: cite the signature -> live_count 6, conclusion_licensed 0
// best_next_expt = X_CAPTURE_ORDER (yield 2: it eliminates both the
// stuck classifier and the recovery artefact)
// run it, passes -> live_set {dead lane, bad range, prereq, margin},
// live_count 4
// best_next = X_LOOPBACK (yield 1, as are all remaining)
// loopback passes -> live_count 3
// check prereq, passes -> live_count 2 {bad range, margin}
// widen the sweep -> the bitmap is no longer all zeros.
// live_count 1 {bad range}. conclusion_licensed 1.
// Four experiments, and the last one IS the fix.
// weak: one observation, one conclusion, delay increased by 2 taps.
// The sweep still covers 32 of 64 taps. The symptom moves because
// the delay change shifts which taps the truncated sweep sees.
// Closed, and it returns at the next frequency bin.
//
// gap: robust reaches the planted cause in four experiments and its
// record shows 6 -> 4 -> 3 -> 2 -> 1. Weak names one of six causes
// with no elimination at all -- and the experiment that would have
// found it, widening the sweep, is 33.3 section 11's range-adequacy item.The robust record's value is the sequence 6 → 4 → 3 → 2 → 1, not the answer. DERIVED: a set size that shrinks is a record of an argument; a single named cause is a record of an opinion. And the sequence tells a later reader exactly which experiments were run and what each bought, which is what makes a reopened ticket cheap.
X_CAPTURE_ORDER eliminating two causes at once is the item's practical payoff. DERIVED: the best next experiment is computed from the live set rather than chosen by intuition, and its yield is 2 where every other available experiment's is 1 — so the order of experiments is derivable, and the derivation is nine lines. CURRICULUM-DERIVED from 28.5 §9's next discriminating experiment: this item's contribution is that next is a maximisation over the live set, and the maximisation needs the set to be written down.
And the sixth cause is one this track added after 28.1 was written, which is worth noting for what it says about hypothesis sets. CURRICULUM-DERIVED from 33.6 §10: an all-zeros bitmap can be an artefact of the recovery reset that the failure itself triggered. DERIVED: 28.1's five became six, so a hypothesis set is a living document — and a write-up citing a set of five when the project knows six has a stale set, which is variety 10's shape applied to evidence.
7. Review Item 2 — Does This Experiment Report What It Eliminated, or Whether It Passed?
| Facet | Content |
|---|---|
| Under review | every experiment in the record |
| Invariant at risk | an experiment's value is the candidates it removes |
| Where it lives | the experiment's result field |
| Evidence to demand | the eliminated set, per experiment, and the live set after |
| What escapes | an experiment that changed the symptom and eliminated nothing, read as proof |
| How DV proves it | run the experiment against each planted cause; count which it distinguishes |
| Telemetry | eliminated count per experiment |
| Misleading evidence | the symptom changed when we changed that, so that is the cause |
CURRICULUM-DERIVED from 28.6 §2, which owns the three experiments most often mistaken for proof — frequency, lane, and ODT — and states for each “what it actually supports.”
28.6 supplies the analysis. This item makes it mechanical, and the mechanism is a count. DERIVED: an experiment whose eliminated set is empty has produced a change in the symptom and no information about the cause, and those are different results that a pass/fail field cannot distinguish.
// ROBUST EXPERIMENT LOG: each experiment records what it eliminated.
module discriminating_power #(
parameter int NCAUSE = 6
)(
input logic clk,
input logic rst_n,
input logic log_expt,
input logic [NCAUSE-1:0] live_before,
input logic [NCAUSE-1:0] eliminated_by_this, // computed, not typed
input logic symptom_changed,
output logic [NCAUSE-1:0] live_after,
output logic [3:0] eliminated_count,
output logic informative,
output logic [7:0] expts_run,
output logic [7:0] expts_informative,
output logic [7:0] expts_symptom_only
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
live_after <= '1; eliminated_count <= '0; informative <= 1'b0;
expts_run <= '0; expts_informative <= '0; expts_symptom_only <= '0;
end else if (log_expt) begin
automatic logic [NCAUSE-1:0] elim = eliminated_by_this & live_before;
live_after <= live_before & ~elim;
eliminated_count <= 4'($countones(elim));
// The classification the item demands. A changed symptom with an
// empty eliminated set is 28.6 section 2's case exactly.
informative <= ($countones(elim) != 0);
expts_run <= expts_run + 1'b1;
if ($countones(elim) != 0)
expts_informative <= expts_informative + 1'b1;
else if (symptom_changed)
expts_symptom_only <= expts_symptom_only + 1'b1;
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK LOG: pass or fail.
//
// // ticket DDR-4412, evidence section
// // "Dropped to 1600 MT/s: errors stop. -> confirms SI."
// // "Swapped to spare lane: errors stop. -> confirms lane 17."
// // "Disabled ODT: errors stop. -> confirms termination."
// //
// informative <= symptom_changed; // <-- the defect
//
// CONTRACT VIOLATED: 28.6 section 2 -- all three of those experiments are
// on its list of experiments mistaken for proof.
//
// WHY IT SURVIVES: each observation is TRUE. The errors really do stop.
// And each conclusion is one of the causes consistent with the result --
// so the write-up is never contradicted, only under-determined.
//
// TRACE (ILLUSTRATIVE, six live causes: dead lane, stuck classifier,
// bad sweep range, unfinished prereq, real margin, recovery artefact):
// expt 1 drop the frequency
// eliminates: {} -- every one of the six is frequency-sensitive or
// is masked by a lower rate. 28.6 section 2's point about the
// frequency test.
// robust: eliminated_count 0, informative 0, symptom_only++
// weak: "confirms SI"
// expt 2 swap to a spare lane
// eliminates: {} -- a dead lane, a stuck per-lane classifier and a
// truncated per-lane sweep all move with the lane.
// robust: eliminated_count 0, informative 0, symptom_only++
// weak: "confirms lane 17"
// expt 3 disable ODT
// eliminates: {} -- changes the eye for every hypothesis at once.
// robust: eliminated_count 0, informative 0, symptom_only++
// weak: "confirms termination"
// expt 4 widen the sweep to the full hardware range
// eliminates: {bad sweep range} if the bitmap changes
// robust: eliminated_count 1, informative 1
// weak: not run -- three experiments already "confirmed" three
// different causes and the ticket was closed on the third.
//
// gap: robust 1 informative experiment of 4 and 3 symptom-only;
// weak 3 confirmations of three mutually exclusive causes, none of
// them eliminating anything.Three experiments confirming three mutually exclusive causes is the finding, and it is the shape a real under-determined investigation takes. DERIVED: the record contains “confirms SI”, “confirms lane 17” and “confirms termination”, and at most one can be right. A record whose confirmations contradict each other has confirmed nothing, and it is the cheapest possible finding to spot — count the confirmations and check they are consistent.
And the reason all three eliminate nothing is worth stating, because it is not obvious. DERIVED: each of the three changes a condition that every live hypothesis depends on. CURRICULUM-DERIVED from 28.6 §2: the frequency test changes the eye, the cycle time and the derived counts together, so no hypothesis is exempt; a lane swap moves everything that is per-lane; and ODT changes the eye for all of them. An experiment that perturbs a condition common to the whole live set cannot partition it.
The pass criterion is therefore a partition test, and it is the item's most useful export. DERIVED: before running an experiment, ask which live hypotheses it keeps. If the answer is none or all, the experiment produces a symptom change and no information. CURRICULUM-DERIVED from 28.5 §9's discriminating experiment: discriminating is the whole requirement, and it is a property of the experiment against the live set rather than of the experiment alone.
8. Review Item 3 — Was the Layer Attributed Before a Within-Layer Discriminator Was Applied?
| Facet | Content |
|---|---|
| Under review | the order in which the investigation narrowed |
| Invariant at risk | a discriminator is applied inside a layer that was established |
| Where it lives | the sequence of experiments, read as a sequence |
| Evidence to demand | the observation that placed the failure in this layer, dated before the discriminators |
| What escapes | a precisely localised cause inside the wrong layer |
| How DV proves it | plant a cause in a different layer and check the record's first step rejects it |
| Telemetry | a layer attribution with its supporting observation, timestamped |
| Misleading evidence | the within-layer discrimination was rigorous, and it was |
CURRICULUM-DERIVED from 28.6 §1, which owns the escalation criterion — “which digital observations make a physical hypothesis the cheapest remaining one” — and from 28.6 §7's escalation boundary. And from 28.1 §4's failure-domain split, which is the same idea for training: six domains, and the domain comes first.
Both establish that a layer must be reached before work inside it means anything. This item is the review question about order, and it is the one item in this chapter that is about a sequence rather than a set. DERIVED: a rigorous discrimination inside the wrong layer produces a precise, confident, wrong answer — and precision is what makes it convincing.
// ROBUST RECORD: a layer attribution is a first-class entry with its
// own supporting observation, and discriminators are refused until one
// exists.
package layer_order_pkg;
typedef enum int { L_CONFIG, // a programmed value is wrong
L_RTL, // controller logic
L_PHY, // trained values, calibration
L_CHANNEL, // board, package, physics
L_DEVICE // the DRAM itself
} layer_e;
endpackage
module layer_then_discriminator (
input logic clk,
input logic rst_n,
input logic attribute, // a layer attribution is offered
input logic [2:0] layer_id,
input logic supporting_obs, // is there an observation for it?
input logic discriminate, // a within-layer experiment
input logic [2:0] disc_layer,
output logic layer_established,
output logic [2:0] established_layer,
output logic disc_accepted,
output logic [7:0] disc_refused,
output logic [7:0] disc_out_of_layer
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
layer_established <= 1'b0; established_layer <= '0;
disc_accepted <= 1'b0; disc_refused <= '0; disc_out_of_layer <= '0;
end else begin
// An attribution requires an OBSERVATION. 28.6 section 1's criterion
// is that the observation makes the layer the cheapest remaining
// hypothesis -- a claim about evidence, not a preference.
if (attribute && supporting_obs) begin
layer_established <= 1'b1;
established_layer <= layer_id;
end
disc_accepted <= 1'b0;
if (discriminate) begin
if (!layer_established) begin
// The item. A discriminator before any layer attribution is
// REFUSED rather than run, because its result cannot be
// interpreted.
disc_refused <= disc_refused + 1'b1;
end else if (disc_layer != established_layer) begin
// Discriminating inside a layer that was not the one
// established: also refused, and counted separately because
// it is a different mistake.
disc_out_of_layer <= disc_out_of_layer + 1'b1;
end else begin
disc_accepted <= 1'b1;
end
end
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK RECORD: discriminate first.
//
// // ticket DDR-4412, work log
// // 09:10 measured the eye at lane 17: width 6 taps, centred
// // 10:40 swept Vref: passing band 0x44-0x52
// // 11:15 measured per-lane skew: lane 17 is 0.4 UI late
// // 14:30 conclusion: lane 17 channel skew. Escalate to board.
// //
// disc_accepted <= discriminate; // <-- the defect
//
// CONTRACT VIOLATED: 28.6 section 1's escalation criterion. Nothing in the
// log establishes that the failure is in the CHANNEL layer; three
// channel-layer measurements were taken because channel-layer
// instruments were the ones at hand.
//
// WHY IT SURVIVES: all three measurements are real, careful and
// correct. Lane 17 IS 0.4 UI late. The eye IS 6 taps wide. And the
// conclusion follows from them -- inside the channel layer.
//
// TRACE (ILLUSTRATIVE, the planted cause is in L_CONFIG: the per-lane
// deskew register for lane 17 was programmed from a stale table):
// robust: three discriminators offered with no layer established
// -> disc_refused 3. The record's first required entry is an
// attribution with an observation, and the cheapest available one
// is 33.6 section 9's provenance check: read back the deskew register and
// compare against its derivation. It mismatches.
// attribute(L_CONFIG, supporting_obs=1) -> established.
// Then one discriminator inside L_CONFIG finds the stale table.
// Total: one read-back and one table diff.
// weak: three channel measurements, one correct escalation to a board
// team, and a board team that finds nothing wrong with the board --
// because nothing is. Lane 17 is 0.4 UI late BECAUSE the deskew
// register says so.
//
// gap: robust reaches the cause with two cheap steps in one layer;
// weak produces three correct measurements, a confident conclusion,
// and an escalation to the most expensive team in the building. And
// every number in the weak log is right.The escape is an escalation, and that is what makes this item expensive rather than merely wrong. DERIVED: the weak record's conclusion is correct within the channel layer — lane 17 really is 0.4 UI late — and the reason it is late is a register in a different layer. CURRICULUM-DERIVED from 28.6 §7's escalation boundary: crossing it costs a team with different instruments and a different schedule, and crossing it wrongly costs that and produces no finding.
And the diagnostic asymmetry is the item's practical content. DERIVED: the cheapest layer to eliminate is the configuration layer, and eliminating it costs one read-back — CURRICULUM-DERIVED from 33.6 §9's provenance check and 28.2's provenance chain. So the order that follows from cost rather than from instrument availability is: configuration, then RTL, then PHY, then channel — and the weak record ran the most expensive layer first because its instruments were the interesting ones.
The pass criterion is a dated entry, and the review is a date comparison. DERIVED: the layer attribution must appear in the log before the first within-layer discriminator, with an observation attached — so this item is checkable from timestamps alone, which puts it in §15's cheap half.
9. Review Item 4 — Is the Observed Rate Compared Against the Rate Each Hypothesis Predicts?
| Facet | Content |
|---|---|
| Under review | every intermittent failure's rate, and the hypotheses on the list |
| Invariant at risk | a hypothesis whose predicted rate is inconsistent with the observed rate is eliminated |
| Where it lives | the rate measurement, and whether any prediction sits beside it |
| Evidence to demand | per live hypothesis, the rate it predicts, with an order of magnitude |
| What escapes | hypotheses that the data already eliminated, kept alive for weeks |
| How DV proves it | plant causes with different natural rates and check the arithmetic separates them |
| Telemetry | errors per operation, per hour, and per thermal cycle — three denominators |
| Misleading evidence | it is intermittent, and intermittency is characteristically a physical problem |
CURRICULUM-DERIVED from 28.5 §7, which owns the pattern, frequency and temperature axes, and from 30.10 §7, which owns “it is intermittent” as an interview perturbation.
Module 28 establishes that a rate is an axis. This item is the arithmetic nobody does: a rate is a quantitative constraint, and most hypotheses predict a rate that differs from the others by orders of magnitude. DERIVED: a rate therefore eliminates hypotheses for free, using data already in hand, and it is the only item in this chapter whose experiment has already been run.
// ROBUST RECORD: each hypothesis carries a predicted rate range, and
// the observed rate eliminates those it contradicts.
package rate_consistency_pkg;
// ILLUSTRATIVE predicted rates, as log10(errors per operation) x10,
// so -70 means 1e-7. Each range is a band, because a prediction with
// no width is not a prediction.
typedef struct {
string name;
int lo_x10; // most frequent plausible
int hi_x10; // least frequent plausible
} hyp_t;
hyp_t HYPS[] = '{
'{"stuck_bit_in_datapath", 0, 0}, // 1e0: every operation
'{"stale_deskew_register", -10, -5}, // 1e-1 .. 1e-0.5: pattern-dep
'{"marginal_eye_1_tap", -40, -20}, // 1e-4 .. 1e-2
'{"crosstalk_aggressor", -70, -40}, // 1e-7 .. 1e-4
'{"retention_at_temp", -90, -70}, // 1e-9 .. 1e-7
'{"cosmic_soft_error", -140, -110} // 1e-14 .. 1e-11
};
endpackage
module rate_consistency (
input logic clk,
input logic rst_n,
input logic measure,
input logic [31:0] errors,
input logic [47:0] operations,
input logic [5:0] live_before,
output logic [5:0] live_after,
output logic signed [15:0] observed_x10,
output logic [3:0] eliminated_by_rate,
output logic rate_is_decisive
);
import rate_consistency_pkg::*;
// log10(errors/operations) x 10, by bit position. A crude log is
// sufficient: the hypothesis bands are orders of magnitude apart,
// which is exactly why this item works at all.
function automatic int signed log10_x10(logic [31:0] e, logic [47:0] n);
int el = 0, nl = 0;
if (e == 0) return -16'sd2000; // no errors: unbounded below
for (int i = 31; i >= 0; i--) if (e[i]) begin el = i; break; end
for (int i = 47; i >= 0; i--) if (n[i]) begin nl = i; break; end
// log10(x) ~ 0.301 * log2(x); x10 and integer-scaled by 3.
return 16'sd3 * (16'sd1 * el - 16'sd1 * nl);
endfunction
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
live_after <= '1; observed_x10 <= '0;
eliminated_by_rate <= '0; rate_is_decisive <= 1'b0;
end else if (measure) begin
automatic int signed obs = log10_x10(errors, operations);
automatic logic [5:0] nxt = live_before;
automatic int elim = 0;
observed_x10 <= 16'(obs);
foreach (HYPS[h]) begin
if (live_before[h]) begin
// A hypothesis is eliminated when the observed rate is
// outside its band by a full order of magnitude -- a margin,
// because the log is crude and the bands are estimates.
if ((obs > HYPS[h].hi_x10 + 10) || (obs < HYPS[h].lo_x10 - 10)) begin
nxt[h] = 1'b0;
elim++;
end
end
end
live_after <= nxt;
eliminated_by_rate <= 4'(elim);
rate_is_decisive <= (elim != 0);
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK RECORD: intermittency as a cause class.
//
// // ticket DDR-4412
// // "Failure is intermittent -- roughly one error every few
// // minutes under load. Intermittent failures at this data rate
// // are characteristically signal-integrity related. Escalating
// // for channel measurement."
// //
// // no rate arithmetic, no predicted rates, no eliminations
//
// CONTRACT VIOLATED: nothing 28.5 section 7 states as a rule -- it names the
// axes and this record ignores one of them quantitatively.
//
// WHY IT SURVIVES: "intermittent implies physical" is a real heuristic
// with real predictive value, and the escalation it produces sometimes
// finds something. It is a prior, applied as a conclusion.
//
// TRACE (ILLUSTRATIVE, the observed rate is 1 error per 4.3e6
// operations -- about 2.3e-7):
// observed_x10 ~ -67
// robust: against the six bands:
// stuck_bit [0, 0] -> obs -67 far below. ELIMINATED
// stale_deskew [-10, -5] -> far below. ELIMINATED
// marginal_eye_1_tap [-40, -20] -> below by 2.7 dec. ELIMINATED
// crosstalk [-70, -40] -> INSIDE. live
// retention_at_temp [-90, -70] -> obs -67 is above -70 by 0.3
// decades, inside the margin. live
// cosmic_soft_error [-140, -110] -> far above. ELIMINATED
// eliminated_by_rate 4, live 2, rate_is_decisive 1
// weak: live 6, and the escalation is to the channel team, which is
// one of the two survivors -- so the weak record's action is not
// wrong, it is unjustified and it skips the cheaper survivor.
//
// gap: four of six hypotheses eliminated by arithmetic on data
// already collected, at zero additional cost. And the two survivors
// are distinguished by a temperature sweep, which is 28.5 section 7's
// third axis and costs an afternoon.Four of six hypotheses eliminated at zero cost is the finding, and zero is literal. DERIVED: the errors and the operations were already counted; the elimination is a comparison against six ranges somebody has to write down once. The experiment has already been run and its result is unanalysed.
And the weak record's action turns out to be reasonable, which is the honest and more interesting result. DERIVED: escalating to the channel team targets one of the two survivors, so the conclusion is not refuted — it is unjustified, it skips the other survivor, and it cannot say why it chose between them. CURRICULUM-DERIVED from 28.6 §1's escalation criterion: the criterion is that the physical hypothesis be the cheapest remaining one, and with two survivors the cheaper is the temperature sweep. A right action for no reason is indistinguishable from a wrong one until it fails.
The pass criterion is a column of predicted ranges, and the width of each range is the part that needs care. DERIVED: a prediction with no width is not a prediction, and a band that spans six decades eliminates nothing — so the artifact's value depends on bands that are tight enough to partition and loose enough to be honest. CURRICULUM-DERIVED from 18.4 §1's grades: each band is grade C at best — recovered by measurement — and labelling it so prevents the bands from hardening into grade B rules.
10. Review Item 5 — Are Causes Eliminated and Causes Never Examined Two Separate Lists?
| Facet | Content |
|---|---|
| Under review | the record's account of the hypotheses it did not conclude |
| Invariant at risk | eliminated and not investigated are distinguishable in the record |
| Where it lives | the absence of a second column |
| Evidence to demand | two lists, with the eliminating experiment named for each member of the first |
| What escapes | the real cause, sitting in the un-investigated list, recorded as ruled out |
| How DV proves it | plant the cause in the un-investigated set and check the record says so |
| Telemetry | eliminated count, live count, and un-investigated count — three numbers |
| Misleading evidence | the write-up considered six hypotheses, which is thorough |
This is the item the chapter's central question exists for, and it has no source in the track. CURRICULUM-DERIVED from 28.5 §11's localisation funnel, which narrows a hypothesis set — but a funnel records what came out, not what was never poured in.
DERIVED: a hypothesis can leave the live set two ways — an experiment removed it, or nobody tried — and a record with one list conflates them. The conflation is invisible because both appear as not the conclusion.
// ROBUST LEDGER: three states per hypothesis, and the eliminating
// experiment is named.
package elimination_pkg;
typedef enum int { H_LIVE, H_ELIMINATED, H_NOT_INVESTIGATED,
H_CONCLUDED } state_e;
endpackage
module elimination_vs_omission #(
parameter int NH = 6
)(
input logic clk,
input logic rst_n,
input logic eliminate,
input logic [2:0] hyp_id,
input logic [2:0] by_experiment, // which experiment did it
input logic conclude,
input logic [2:0] concluded_hyp,
input logic close,
output logic [3:0] eliminated_count,
output logic [3:0] not_investigated_count,
output logic [3:0] live_count,
output logic closure_licensed,
output logic [2:0] first_uninvestigated
);
import elimination_pkg::*;
state_e st [0:NH-1];
logic [2:0] elim_by [0:NH-1];
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (int h = 0; h < NH; h++) begin
st[h] <= H_LIVE; elim_by[h] <= 3'd7;
end
eliminated_count <= '0; not_investigated_count <= '0;
live_count <= 4'(NH); closure_licensed <= 1'b0;
first_uninvestigated <= 3'd7;
end else begin
// Elimination requires an experiment id. A hypothesis cannot be
// eliminated by assertion, which is the whole item.
if (eliminate && (by_experiment != 3'd7)) begin
st[hyp_id] <= H_ELIMINATED;
elim_by[hyp_id] <= by_experiment;
end
if (conclude) st[concluded_hyp] <= H_CONCLUDED;
// On closure, every remaining LIVE hypothesis is reclassified as
// NOT INVESTIGATED -- honestly, and in its own column.
if (close)
for (int h = 0; h < NH; h++)
if (st[h] == H_LIVE) st[h] <= H_NOT_INVESTIGATED;
begin
automatic int e = 0, n = 0, l = 0;
automatic int firstn = 7;
for (int h = 0; h < NH; h++) begin
case (st[h])
H_ELIMINATED: e++;
H_NOT_INVESTIGATED: begin n++; if (firstn == 7) firstn = h; end
H_LIVE: l++;
default: ;
endcase
end
eliminated_count <= 4'(e);
not_investigated_count <= 4'(n);
live_count <= 4'(l);
first_uninvestigated <= 3'(firstn);
// A closure is licensed only when NOTHING is un-investigated.
closure_licensed <= (n == 0) && (l == 0);
end
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK LEDGER: one list.
//
// // ticket DDR-4412, closing note
// // "Considered: stuck bit, stale deskew, marginal eye, crosstalk,
// // retention, soft error. Root cause: crosstalk aggressor on
// // lane 16. Closed."
// //
// closure_licensed <= conclude; // <-- the defect
// // and there is no H_NOT_INVESTIGATED state at all
//
// CONTRACT VIOLATED: none stated in the track. 28.5 section 11's funnel
// narrows a set and does not require an account of what left it
// un-narrowed.
//
// WHY IT SURVIVES: the closing note is honest about what was
// CONSIDERED, and considering six hypotheses is thorough. The word
// "considered" does the damage: it covers both "eliminated by
// experiment 3" and "thought about for a minute".
//
// TRACE (ILLUSTRATIVE, the same investigation; the planted cause is
// `retention_at_temp`):
// what actually happened:
// stuck_bit eliminated by the rate arithmetic (section 9)
// stale_deskew eliminated by the rate arithmetic
// marginal_eye eliminated by the rate arithmetic
// soft_error eliminated by the rate arithmetic
// crosstalk CONCLUDED
// retention_at_temp never investigated -- the temperature sweep
// was scheduled and the ticket closed first
// robust: eliminated 4, concluded 1, NOT_INVESTIGATED 1,
// first_uninvestigated = retention_at_temp,
// closure_licensed 0. The ticket cannot close.
// weak: "considered 6, root cause crosstalk", closed.
//
// gap: one un-investigated hypothesis, and it is the planted cause.
// The record says six were considered and four were tested. And the
// un-investigated one is precisely the survivor section 9's arithmetic
// left alive alongside the conclusion.One un-investigated hypothesis, and it is the answer. That is the item. DERIVED: the weak record is not dishonest — six hypotheses really were considered — and the word considered covers both eliminated by experiment 3 and thought about. A single list cannot carry the distinction, so the fix is a column and not a habit.
And the composition with §9 is what makes this item's finding predictable rather than unlucky. DERIVED: §9's arithmetic left exactly two survivors, and the investigation concluded on one of them without testing the other — so the un-investigated hypothesis is not an arbitrary omission, it is the sibling of the conclusion. CURRICULUM-DERIVED from 28.6 §1's escalation criterion: with two survivors the criterion requires the cheapest remaining hypothesis be tested, and the temperature sweep is cheaper than a channel escalation. The record inverted the order and then stopped.
The pass criterion is closure_licensed, and it is deliberately strict. DERIVED: a ticket closes only when every hypothesis is either eliminated with a named experiment or concluded — and a real project will sometimes close with an un-investigated hypothesis, for schedule reasons. The item does not forbid that; it forbids doing it silently. A closure note reading “retention at temperature was not investigated” is a legitimate engineering decision and a reopenable record. The same closure without that line is the same decision with the evidence removed.
11. Review Item 6 — Is the Instrument That Reported This Failure Independent of the Block the Conclusion Accuses?
| Facet | Content |
|---|---|
| Under review | the instrument behind the observation, and the block the conclusion names |
| Invariant at risk | the accuser and the accused are independent |
| Where it lives | the monitor's or scoreboard's inputs |
| Evidence to demand | the instrument's input list, compared against the accused block's outputs |
| What escapes | a defect in the instrument, attributed to the design |
| How DV proves it | inject a fault into the instrument and check the conclusion changes |
| Telemetry | per observation, the instrument and its inputs |
| Misleading evidence | the mismatch is real and reproducible |
CURRICULUM-DERIVED from 27.3, which owns the independence requirement and its cannot-fail failure mode. 27.3 applies it to a checker that cannot report a real failure. This item applies it to the mirror case: a checker that reports a failure that is its own.
DERIVED: the two are the same defect read in opposite directions. A monitor sharing the design's state cannot see the design's error; a monitor sharing a different block's state can report that block's error as this one's. And in a debug the second is more expensive, because it produces work rather than silence.
// ROBUST RECORD: each observation names its instrument and the
// instrument's inputs, and an accusation is checked for overlap.
module accusation_independence #(
parameter int NBLK = 8
)(
input logic clk,
input logic rst_n,
input logic observe,
input logic [NBLK-1:0] instrument_inputs, // blocks the monitor reads
input logic accuse,
input logic [2:0] accused_block,
output logic independent,
output logic accusation_licensed,
output logic [7:0] accusations_made,
output logic [7:0] accusations_dependent,
output logic [NBLK-1:0] overlap
);
logic [NBLK-1:0] inputs_held;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
inputs_held <= '0; independent <= 1'b0;
accusation_licensed <= 1'b0; accusations_made <= '0;
accusations_dependent <= '0; overlap <= '0;
end else begin
if (observe) inputs_held <= instrument_inputs;
accusation_licensed <= 1'b0;
if (accuse) begin
automatic logic [NBLK-1:0] ov = inputs_held & (8'b1 << accused_block);
overlap <= ov;
independent <= (ov == '0);
accusations_made <= accusations_made + 1'b1;
if (ov == '0) begin
accusation_licensed <= 1'b1;
end else begin
// The instrument reads the block it is accusing. The
// observation is still real; the ATTRIBUTION is not licensed.
accusations_dependent <= accusations_dependent + 1'b1;
end
end
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK RECORD: the observation is the
// attribution.
//
// // ticket DDR-4487
// // "Scoreboard reports read-data mismatch at 0x4000_1180.
// // Data returned does not match the write. Root cause: the read
// // return path in the controller. Closed pending RTL fix."
// //
// accusation_licensed <= accuse; // <-- the defect
//
// CONTRACT VIOLATED: 27.3's independence requirement, in its mirror
// direction.
//
// WHY IT SURVIVES: the mismatch is real, reproducible, and at a stable
// address. A scoreboard reporting a mismatch is the most trusted
// observation a verification environment produces.
//
// TRACE (ILLUSTRATIVE, blocks: 0 requester 1 fabric 2 ctrl_front
// 3 scheduler 4 ctrl_return 5 phy 6 device 7 addr_decode):
// the scoreboard's expected value is computed from a reference memory
// INDEXED BY THE DECODED ADDRESS -- so instrument_inputs includes
// block 7, addr_decode.
// the planted cause: addr_decode maps two different host addresses
// to the same device location under one configuration. The write and
// the read land in different reference-model entries and the same
// device row.
// robust: accuse(ctrl_return) -> overlap with inputs_held = {7}?
// no: ctrl_return is block 4 and is not in the instrument's inputs
// -> independent 1, accusation_licensed 1.
// But the record's instrument-input list NAMES addr_decode, so the
// review's next question is the one the list makes obvious:
// accuse(addr_decode) -> overlap = {7}, independent 0,
// accusations_dependent 1. The scoreboard CANNOT adjudicate its own
// address decode, and the investigation moves to an instrument that
// does not share it.
// weak: the return path is blamed, an RTL engineer spends a week on a
// block that is correct, and the address-decode configuration --
// which the scoreboard shares -- is never suspected because the
// scoreboard is the thing that reported the problem.
//
// gap: robust licenses the return-path accusation AND surfaces that
// one candidate block is un-adjudicable by this instrument. Weak
// produces a week of work on a correct block. accusations_dependent:
// robust 1 (correctly flagged), weak 0 (the concept does not exist).The finding is not that the weak record accused the wrong block — it is that one candidate was un-adjudicable by the only instrument in use, and nothing said so. DERIVED: a scoreboard whose expected value is indexed by a decoded address cannot distinguish a data error from a decode error, because both produce a mismatch at an address. The observation is real either way.
CURRICULUM-DERIVED from 27.4, which owns where a DDR expected value comes from and establishes that the reference model is a memory — DERIVED: a memory is indexed, the index comes from somewhere, and whatever supplies the index is outside the instrument's reach. So this item's finding is structural rather than incidental: every scoreboard has at least one block it cannot adjudicate, and the review question is which one.
The pass criterion is an input list beside each observation, and the cost is a line. DERIVED: the list is knowable from the instrument's source and changes only when the instrument changes — so it is written once, like 33.6 §10's survival classes and 33.6 §8's consequence map. This gate's fourth once-written document.
12. Review Item 7 — Does Every Threshold in the Checker's History Cite a Specification?
| Facet | Content |
|---|---|
| Under review | the change history of every checker, threshold and tolerance in use |
| Invariant at risk | a checker's configuration is derived from a specification, not from a run |
| Where it lives | the commit history, not the current source |
| Evidence to demand | per change: the specification clause, or the failing run that prompted it |
| What escapes | a checker calibrated against the design, reporting nothing wrong forever |
| How DV proves it | revert each change and check whether a real violation reappears |
| Telemetry | a provenance field per threshold, maintained with the threshold |
| Misleading evidence | the checker is quiet, which is what a correct design produces |
CURRICULUM-DERIVED from 30.9 §9 and 30.9 §10, which own the review of a checker that samples one cycle late and was “fixed” by widening its tolerance, and record what the fix did. And from 33.2 §14's rule, which this chapter applies to a repository rather than to a line: “a checker adjusted until it stopped complaining has been calibrated against the design rather than against the specification.”
30.9 reviews one such checker in one state. This item reviews the history, and the history is where the evidence is. DERIVED: a widened tolerance in the current source looks like a design decision; the same tolerance with a commit message naming a failing run is a confession.
// ROBUST RECORD: every threshold carries its provenance, and a change
// prompted by a run is classified rather than merged.
package checker_change_pkg;
typedef enum int { P_SPEC, // a specification clause
P_MEASUREMENT, // a characterisation result
P_FAILING_RUN, // "it was firing" -- the defect
P_NONE // no reason recorded
} prov_e;
typedef struct {
string checker;
int value;
prov_e prov;
string citation; // clause, report, or run id
} change_t;
// ILLUSTRATIVE history of seven changes to one project's checkers.
change_t HISTORY[] = '{
'{"p_trcd_respected", 14, P_SPEC, "JEDEC tRCD, bin 1866"},
'{"p_tras_respected", 34, P_SPEC, "JEDEC tRAS, bin 1866"},
'{"sb_latency_window", 6, P_FAILING_RUN, "run 8841 was firing"},
'{"p_turn_respected", 8, P_MEASUREMENT, "turnaround char. r3"},
'{"sb_latency_window", 11, P_FAILING_RUN, "run 9102 was firing"},
'{"mon_beat_align", 2, P_NONE, ""},
'{"sb_latency_window", 18, P_FAILING_RUN, "run 9417 was firing"}
};
endpackage
module checker_change_provenance (
input logic clk,
input logic rst_n,
input logic audit,
output logic [3:0] changes_spec_backed,
output logic [3:0] changes_run_driven,
output logic [3:0] changes_unjustified,
output logic [3:0] worst_drift_ratio_x10,
output logic history_clean,
output logic [3:0] ratchet_count
);
import checker_change_pkg::*;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
changes_spec_backed <= '0; changes_run_driven <= '0;
changes_unjustified <= '0; worst_drift_ratio_x10 <= '0;
history_clean <= 1'b0; ratchet_count <= '0;
end else if (audit) begin
automatic int s = 0, r = 0, u = 0, ratchet = 0;
automatic int first_val = 0, last_val = 0;
foreach (HISTORY[i]) begin
case (HISTORY[i].prov)
P_SPEC, P_MEASUREMENT: s++;
P_FAILING_RUN: r++;
default: u++;
endcase
// The RATCHET: the same checker widened more than once, each
// time after a failing run. A single widening is a judgement
// call; a monotone sequence of them is a calibration against
// the design.
if (HISTORY[i].prov == P_FAILING_RUN) begin
if (first_val == 0) first_val = HISTORY[i].value;
if (HISTORY[i].value > last_val) begin
last_val = HISTORY[i].value;
ratchet++;
end
end
end
changes_spec_backed <= 4'(s);
changes_run_driven <= 4'(r);
changes_unjustified <= 4'(u);
ratchet_count <= 4'(ratchet);
// 6 -> 18 is a 3.0x drift, reported x10.
worst_drift_ratio_x10 <= (first_val == 0) ? 4'd0
: 4'((last_val * 10) / first_val);
history_clean <= ((r == 0) && (u == 0));
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK RECORD: no provenance field.
//
// // sb_latency_window has been 18 for as long as anyone remembers.
// // git log --oneline -- scoreboard/latency.sv
// // 9417a1 loosen latency window
// // 9102b7 loosen latency window
// // 8841c3 loosen latency window
// // ...
// //
// history_clean <= 1'b1; // there is nothing to audit
//
// CONTRACT VIOLATED: 33.2 section 14's rule about tolerance parameters, at
// repository scale. And note that the three commits are HONEST: each
// says exactly what it did.
//
// WHY IT SURVIVES: the checker is quiet, and every one of the three
// changes was made by somebody who looked at a firing checker, decided
// it was over-strict, and widened it. Each decision was defensible in
// isolation. Nobody ever looked at all three together.
//
// TRACE (ILLUSTRATIVE, the seven-change history above):
// robust: changes_spec_backed 3, changes_run_driven 3,
// changes_unjustified 1, RATCHET_COUNT 3,
// worst_drift_ratio_x10 30 (3.0x: 6 -> 11 -> 18),
// history_clean 0
// weak: nothing computed; the window is 18 and nobody asks why.
//
// and the consequence, measured: the real latency obligation is
// 11 cycles. A window of 18 admits a 7-cycle violation silently.
// Errors per 1e6 operations detected by the checker:
// window 6: 4100 (mostly false -- it WAS over-strict)
// window 11: 12 (the real violations)
// window 18: 0
// The first widening, 6 -> 11, was CORRECT: it moved the checker to
// the specification. The second and third were the defect, and they
// are indistinguishable from the first in the commit log.
//
// gap: 12 real violations per million operations, undetectable, and
// the ratchet count of 3 is the only thing in the record that
// distinguishes the correct widening from the two that followed.The first widening was correct and the second and third were not, and nothing in the commit log distinguishes them. That is the finding. DERIVED: 6 → 11 moved an over-strict checker to its specification; 11 → 18 moved it past it. All three commits are honest, all three say loosen latency window, and the only signal in the record is that there were three.
The ratchet count is therefore the item's instrument rather than the provenance field. DERIVED: a single widening prompted by a firing checker is a legitimate engineering judgement — checkers are sometimes over-strict, and 30.9 §10 documents exactly that case. A monotone sequence of them is a calibration against the design, and monotonicity is the property a review can count without knowing the specification.
And the measured consequence is the number to carry: twelve real violations per million operations, at a window nobody chose. DERIVED: the window's final value is not a decision, it is the sum of three decisions each of which only had to be locally defensible. CURRICULUM-DERIVED from 30.9 §11's treatment of vacuity as a deliverable: the same discipline applies here — a threshold's provenance is a deliverable, and a project that publishes it cannot ratchet silently.
13. Review Item 8 — Does the Conclusion State the Observation That Would Have Refuted It?
| Facet | Content |
|---|---|
| Under review | the conclusion, as a claim |
| Invariant at risk | the conclusion is falsifiable by an observation the project could make |
| Where it lives | the field that most write-ups do not have |
| Evidence to demand | one sentence: what would we have seen if this were wrong? |
| What escapes | an unfalsifiable conclusion, which closes a ticket and cannot be reopened on evidence |
| How DV proves it | make the stated observation; if the conclusion survives it, the field is wrong too |
| Telemetry | a refutation field per conclusion |
| Misleading evidence | the conclusion is consistent with everything observed |
This item has no source in the track, and §3 says so plainly. It is stated as a rule here because every method in Module 28 produces the artifact as a by-product and none of them requires that it be written down.
DERIVED: a discriminating experiment is an observation that would have refuted one branch — CURRICULUM-DERIVED from 28.5 §9's signature → hypotheses → experiment structure, whose third element is exactly that. So this item asks a project that already runs discriminating experiments to record, for its final conclusion, the one it would run next if challenged.
// ROBUST RECORD: a conclusion carries a refutation, and a refutation
// that no observation can make is rejected.
package falsifiability_pkg;
typedef enum int { R_MEASURABLE, // an observation the project can make
R_UNOBSERVABLE, // 7.7's unverifiable class
R_NONE // no refutation stated
} refut_e;
typedef struct {
string conclusion;
string refutation;
refut_e kind;
} concl_t;
// ILLUSTRATIVE, eight conclusions from one project's tickets.
concl_t RECORD[] = '{
'{"stale deskew table", "readback matches derivation", R_MEASURABLE},
'{"truncated sweep range", "full-range sweep still zeros", R_MEASURABLE},
'{"retention at 95C", "error rate flat vs temp", R_MEASURABLE},
'{"crosstalk on lane 16", "victim moves with aggressor", R_MEASURABLE},
'{"tRCD one cycle short", "violation absent at act+13", R_MEASURABLE},
'{"marginal signal integrity", "", R_NONE},
'{"ZQ calibration drift", "", R_UNOBSERVABLE},
'{"intermittent hardware", "", R_NONE}
};
endpackage
module falsifiability_record (
input logic clk,
input logic rst_n,
input logic audit,
output logic [3:0] falsifiable,
output logic [3:0] unobservable,
output logic [3:0] unfalsifiable,
output logic record_sound,
output logic [3:0] closable
);
import falsifiability_pkg::*;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
falsifiable <= '0; unobservable <= '0; unfalsifiable <= '0;
record_sound <= 1'b0; closable <= '0;
end else if (audit) begin
automatic int f = 0, u = 0, n = 0;
foreach (RECORD[i]) begin
case (RECORD[i].kind)
R_MEASURABLE: f++;
// 7.7's class: the interface does not report the outcome, so
// no observation can refute it. This is NOT the same defect
// as R_NONE and must not be counted with it.
R_UNOBSERVABLE: u++;
default: n++;
endcase
end
falsifiable <= 4'(f);
unobservable <= 4'(u);
unfalsifiable <= 4'(n);
// A conclusion is closable when it is falsifiable, or when it is
// unobservable AND recorded as a standing residual risk.
closable <= 4'(f + u);
record_sound <= (n == 0);
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK RECORD: no refutation field.
//
// // ticket DDR-4501
// // Root cause: marginal signal integrity at this data rate.
// // Action: reduce the operating bin by one step. Closed.
// //
// record_sound <= 1'b1; // every conclusion is a conclusion
//
// CONTRACT VIOLATED: none stated anywhere. 28.6 section 1's escalation
// criterion is the closest thing, and it constrains when a physical
// hypothesis becomes CHEAPEST -- not what a physical conclusion must
// state to be closable.
//
// WHY IT SURVIVES: the conclusion is true in a useless way. Every
// system has finite margin, so "marginal signal integrity" is
// literally correct about every DDR interface ever built, and the
// action -- drop a bin -- reliably works. It is the most effective
// unfalsifiable conclusion available.
//
// TRACE (ILLUSTRATIVE, the eight-conclusion record above):
// robust: falsifiable 5, unobservable 1, UNFALSIFIABLE 2,
// closable 6, record_sound 0
// -- and the two unfalsifiable ones are named: "marginal
// signal integrity" and "intermittent hardware".
// weak: 8 conclusions, 8 closed.
//
// the distinction that matters most: "ZQ calibration drift" has no
// refutation and is NOT the same defect. 7.7 establishes that the
// interface does not report the outcome, so no observation refutes
// it -- it is a standing residual risk, correctly classified, and it
// stays on a list rather than being investigated further.
// The other two are conclusions that COULD have been made
// falsifiable and were not.
//
// gap: 2 of 8 conclusions cannot be reopened on evidence, because
// there is no evidence that bears on them. And both of those two
// are the ones whose corresponding defect is still in the product.The R_UNOBSERVABLE row is the reason this item has three classes rather than two, and it is the honest part. CURRICULUM-DERIVED from 7.7 via 28.4 §2: for a mechanism whose outcome the interface does not report, “did it work?” is not a question digital logic can answer. DERIVED: a conclusion about such a mechanism is unfalsifiable for a reason that is a property of the protocol, and collapsing it with “marginal signal integrity” would make the item unusable in practice — projects have real unobservable mechanisms, and an item that flagged them as defects would be ignored.
And “marginal signal integrity” earns its place as the chapter's worst conclusion because it is true. DERIVED: every DDR interface has finite margin, so the claim is correct about every system, and its action — drop a bin — works. CURRICULUM-DERIVED from 28.6 §1's escalation criterion, which exists to prevent exactly this: the criterion asks which observations make a physical hypothesis the cheapest remaining one, which presupposes a narrowed set. Marginal signal integrity as a first conclusion is the criterion used as a destination.
The pass criterion is one sentence per conclusion, and its cheapness is the argument for it. DERIVED: a project running Module 28's methods already computes the refutation — it is the next discriminating experiment it chose not to run — so the field's cost is transcription, and its value is that a ticket closed with it can be reopened by an observation rather than by an argument.
14. The Five Ways a Wrong Conclusion Survives
Eight items, and they are not eight independent defects. Sorted by how the wrong conclusion stayed alive, they collapse into five mechanisms — and the collapse is what makes the chapter usable.
| # | Mechanism | Items | The one-line test |
|---|---|---|---|
| 1 | Under-determination — the evidence admits several causes | §6, §7 | how many causes are consistent with this? |
| 2 | Mis-ordering — the work was rigorous in the wrong place | §8 | what observation established this layer? |
| 3 | Unanalysed data — the answer was already collected | §9 | what rate does each hypothesis predict? |
| 4 | Conflation — two states recorded as one | §10, §12 | are these two lists, or one? |
| 5 | Unfalsifiability — no observation bears on the claim | §11, §13 | what would we have seen if this were wrong? |
DERIVED: mechanism 3 is the only one that costs nothing to fix, and mechanism 5 is the only one that cannot be fixed after the ticket closes.
Mechanism 4 is the one worth dwelling on, because its two items look unrelated and are the same defect. DERIVED: §10 conflates eliminated with never examined; §12 conflates a correct widening with two that followed it. In both cases the record has one field where it needs two, and in both cases the missing field is a reason rather than a value — the eliminating experiment, the specification clause. CURRICULUM-DERIVED from 30.9 §11's treatment of vacuity as a deliverable: the general form is that a project which publishes its reasons cannot conflate silently.
Mechanism 5's two items are also the same defect seen from two sides, and that is less obvious. DERIVED: §13's unfalsifiable conclusion has no observation that bears on it; §11's dependent accusation has an observation that cannot bear on it — the instrument shares the accused block, so the mismatch is consistent with both hypotheses and refutes neither. CURRICULUM-DERIVED from 27.3: the cannot-fail checker is the same structure, and here it produces an unfalsifiable attribution rather than a silent one.
And the five mechanisms have a strict cost order, which is the practical output of this section.
DERIVED: check mechanism 3 first — it is arithmetic on data in hand and it eliminated four of six hypotheses in §9. Then mechanism 4, which is a field comparison. Then mechanism 1, which needs a hypothesis set written once. Then mechanism 5, which needs one sentence per conclusion. Mechanism 2 last, because a layer attribution requires agreeing on what the layers are — and that agreement is 19.1 §3's ownership table, of which six rows are implementation-dependent.
15. The Review Assembled
Cost-ordered, and the ordering is §14's five mechanisms applied to the eight items.
| # | Item | Question, in one line | Cost | What it needs |
|---|---|---|---|---|
| 1 | §9 Rate consistency | What rate does each hypothesis predict? | minutes | arithmetic on data already collected |
| 2 | §10 Two lists | Which hypotheses were eliminated, and by which experiment? | minutes | a second column |
| 3 | §12 Threshold history | How many times has this threshold been widened? | minutes | git log on one file |
| 4 | §13 Refutation | What would we have seen if this were wrong? | minutes | one sentence per conclusion |
| 5 | §8 Layer order | What observation established this layer, and when? | minutes | compare two timestamps |
| 6 | §7 Eliminated set | What did this experiment remove from the live set? | hours | the live set, which §6 supplies |
| 7 | §11 Instrument independence | Does the instrument read the block it accuses? | hours | the instrument's input list |
| 8 | §6 Hypothesis set | What causes are consistent with this signature? | days | a signature → causes table |
Five of eight take minutes, and three of those five are answered without any domain knowledge at all. DERIVED: counting widenings in a commit log, checking whether a document has two columns, and comparing two timestamps require no understanding of DDR. CURRICULUM-DERIVED from nothing — that is the point: three of this gate's eight findings are available to a reviewer who has never seen a memory controller, which is not true of any other gate in this module.
Item 8 is last and most expensive, and it is the one that makes the other seven work. DERIVED: §7 needs a live set, §9 needs hypotheses to attach rates to, §10 needs a list to partition, §13 needs a branch to refute. All four consume §6's table. So the ordering is a review ordering rather than a build ordering: a reviewer checks the cheap items first, and a project builds the expensive one first.
And the signature → causes table is this gate's fifth once-written document, joining 33.6's four. CURRICULUM-DERIVED from 28.5 §9's eleven corruption signatures with their mechanisms and next experiments, and 28.1 §2's five causes for one bitmap: the table's seed exists in this curriculum, and §6 demonstrated that it needed a sixth row the seed does not have.
16. Quantitative Reasoning
| Item | Quantity | Robust | Weak | Gap | Provenance |
|---|---|---|---|---|---|
| §6 | causes named for one signature | 6, narrowed 6→4→3→2→1 | 1 | 5 unexamined, 1 of them right | DERIVED from 28.1 §2's five, plus one |
| §7 | informative experiments of four | 1, with 3 symptom-only | 3 "confirmations" | three mutually exclusive causes confirmed | DERIVED from 28.6 §2 |
| §8 | steps taken to reach the cause | 2, in one layer | 3 measurements + an escalation | a board team with nothing to find | DERIVED |
| §9 | hypotheses eliminated by the rate | 4 of 6 | 0 | at zero additional cost | DERIVED, ILLUSTRATIVE bands |
| §10 | un-investigated causes at closure | 1, named | 0 reported | the named one is the planted cause | DERIVED |
| §11 | un-adjudicable blocks surfaced | 1 | 0 | a week on a correct block | DERIVED |
| §12 | threshold widenings, and drift | ratchet 3, drift 3.0× | not computed | 12 real violations per 1e6 hidden | DERIVED |
| §13 | unfalsifiable conclusions of eight | 2, named; 1 unobservable kept separate | 0 | both defects still in the product | DERIVED |
Sort the eight by what was wrong with the weak record and this gate's signature is unlike the six before it.
| Item | The weak record's defect | Was it false? |
|---|---|---|
| §6 | named one of six consistent causes | no |
| §7 | called three correlations confirmations | no |
| §8 | measured the channel layer carefully | no |
| §9 | applied a valid heuristic as a conclusion | no |
| §10 | said six hypotheses were considered | no |
| §11 | reported a real, reproducible mismatch | no |
| §12 | widened an over-strict checker | no (the first time) |
| §13 | concluded marginal signal integrity | no |
DERIVED: not one of the eight weak records contains a false statement. At 33.5's gate the numbers were correct and about the wrong thing; at 33.6's the records were correct and omitted their limits. Here every claim is true and the inference is unlicensed — which is a third distinct failure mode and the hardest of the three to argue against, because there is no error to point at.
The count that carries the chapter is in §9's row, and it is worth isolating. DERIVED: four of six hypotheses were eliminated by arithmetic on data that had already been collected, at zero additional cost — so the single highest-yield action in a stalled DDR investigation is to compute a rate and compare it against what each live hypothesis predicts. CURRICULUM-DERIVED from 28.5 §7, which names the rate as an axis: this chapter's contribution is that it is a quantitative axis, and most hypotheses' predictions differ by orders of magnitude.
And the drift figure in §12's row is the only number here that measures a project rather than an investigation. DERIVED: a 3.0× ratchet on one threshold, arrived at by three individually defensible commits, hides twelve real violations per million operations — and the ratchet count is the only signal in the repository that distinguishes the correct first widening from the two that followed.
17. What the Assertions Prove
// ---- Section 6: the hypothesis set. A conclusion is licensed only by a
// set of size one, which is the whole of 28.4 section 2's rule as a property.
property p_conclusion_requires_a_singleton;
@(posedge clk) disable iff (!rst_n)
conclusion_licensed |-> (live_count == 4'd1);
endproperty
assert property (p_conclusion_requires_a_singleton)
else $error("a conclusion was licensed with more than one live cause");
property p_citing_a_signature_resets_the_set;
@(posedge clk) disable iff (!rst_n)
observe |=> (live_count == 4'd6);
endproperty
assert property (p_citing_a_signature_resets_the_set)
else $error("citing a signature did not restore its full consistent set");
property p_next_experiment_is_maximal;
@(posedge clk) disable iff (!rst_n)
(live_count > 4'd1) |-> (best_next_yield != '0);
endproperty
assert property (p_next_experiment_is_maximal)
else $error("no experiment eliminates any live cause: the set is stuck");
// ---- Section 7: discriminating power.
property p_informative_means_nonempty_elimination;
@(posedge clk) disable iff (!rst_n)
informative |-> (eliminated_count != '0);
endproperty
assert property (p_informative_means_nonempty_elimination)
else $error("an experiment was called informative and eliminated nothing");
property p_live_set_is_monotone;
@(posedge clk) disable iff (!rst_n)
log_expt |=> ((live_after & $past(live_before)) == live_after);
endproperty
assert property (p_live_set_is_monotone)
else $error("an experiment added a cause back to the live set");
// ---- Section 8: layer before discriminator.
property p_no_discriminator_before_a_layer;
@(posedge clk) disable iff (!rst_n)
(discriminate && !layer_established) |=> !disc_accepted;
endproperty
assert property (p_no_discriminator_before_a_layer)
else $error("a within-layer discriminator ran with no layer established");
property p_attribution_needs_an_observation;
@(posedge clk) disable iff (!rst_n)
(attribute && !supporting_obs) |=> !layer_established;
endproperty
assert property (p_attribution_needs_an_observation)
else $error("a layer was attributed with no supporting observation");
// And the two-sided companion -- 30.3 section 9's variety 8: a record that
// refuses every discriminator satisfies both properties above.
property p_in_layer_discriminator_is_accepted;
@(posedge clk) disable iff (!rst_n)
(discriminate && layer_established && (disc_layer == established_layer))
|=> disc_accepted;
endproperty
assert property (p_in_layer_discriminator_is_accepted)
else $error("a valid in-layer discriminator was refused");
// ---- Section 9: rate consistency. 30.8 section 11's variety 5 applied to a
// log: the derived statistic must be in range, and here the range is
// each hypothesis's band.
property p_rate_eliminates_inconsistent_bands;
@(posedge clk) disable iff (!rst_n)
(measure && rate_is_decisive) |-> (eliminated_by_rate != '0);
endproperty
assert property (p_rate_eliminates_inconsistent_bands)
else $error("the rate was called decisive and eliminated nothing");
property p_no_errors_eliminates_nothing_upward;
@(posedge clk) disable iff (!rst_n)
(measure && (errors == '0)) |-> (live_after[0] == 1'b0);
endproperty
assert property (p_no_errors_eliminates_nothing_upward)
else $error("zero errors did not eliminate the every-operation hypothesis");
// ---- Section 10: the two lists.
property p_closure_requires_no_uninvestigated;
@(posedge clk) disable iff (!rst_n)
closure_licensed |-> ((not_investigated_count == '0) && (live_count == '0));
endproperty
assert property (p_closure_requires_no_uninvestigated)
else $error("a ticket closed with an un-investigated hypothesis");
property p_elimination_names_an_experiment;
@(posedge clk) disable iff (!rst_n)
(eliminate && (by_experiment == 3'd7)) |=> (eliminated_count == $past(eliminated_count));
endproperty
assert property (p_elimination_names_an_experiment)
else $error("a hypothesis was eliminated with no experiment named");
property p_states_partition_the_set;
@(posedge clk) disable iff (!rst_n)
close |=> ((eliminated_count + not_investigated_count + live_count) <= 4'd6);
endproperty
assert property (p_states_partition_the_set)
else $error("the hypothesis states do not partition the set");
// ---- Section 11: the accuser and the accused.
property p_accusation_requires_independence;
@(posedge clk) disable iff (!rst_n)
accusation_licensed |-> independent;
endproperty
assert property (p_accusation_requires_independence)
else $error("a block was accused by an instrument that reads it");
property p_dependent_accusation_is_counted;
@(posedge clk) disable iff (!rst_n)
(accuse && (overlap != '0)) |=> (accusations_dependent != '0);
endproperty
assert property (p_dependent_accusation_is_counted)
else $error("a dependent accusation was not classified");
// ---- Section 12: the threshold history. The RATCHET is the property,
// because a single widening is legitimate.
property p_no_ratchet;
@(posedge clk) disable iff (!rst_n)
audit |=> (ratchet_count <= 4'd1);
endproperty
assert property (p_no_ratchet)
else $error("a threshold was widened repeatedly after failing runs");
property p_every_change_has_a_reason;
@(posedge clk) disable iff (!rst_n)
audit |=> (changes_unjustified == '0);
endproperty
assert property (p_every_change_has_a_reason)
else $error("a threshold change records no reason at all");
property p_history_clean_means_spec_backed;
@(posedge clk) disable iff (!rst_n)
history_clean |-> ((changes_run_driven == '0) && (changes_unjustified == '0));
endproperty
assert property (p_history_clean_means_spec_backed)
else $error("the history was called clean with run-driven changes in it");
// ---- Section 13: falsifiability. Three classes, and the property must not
// collapse the unobservable one into the defect.
property p_sound_record_has_no_unfalsifiable;
@(posedge clk) disable iff (!rst_n)
record_sound |-> (unfalsifiable == '0);
endproperty
assert property (p_sound_record_has_no_unfalsifiable)
else $error("a record was called sound with an unfalsifiable conclusion");
property p_unobservable_is_still_closable;
@(posedge clk) disable iff (!rst_n)
audit |=> (closable == (falsifiable + unobservable));
endproperty
assert property (p_unobservable_is_still_closable)
else $error("an unobservable conclusion was treated as a defect in the record");
// ---- COVERS. Each on the dimension its defect scales with.
// Section 6: a set that reaches ONE. A record that never narrows satisfies
// p_conclusion_requires_a_singleton by never concluding.
cover property (@(posedge clk) disable iff (!rst_n) live_count == 4'd1);
// And the intermediate state the whole item is about: several live.
cover property (@(posedge clk) disable iff (!rst_n)
(live_count > 4'd1) && (live_count < 4'd6));
// Section 7: a SYMPTOM-ONLY experiment. 28.6 section 2's three are the
// common case and a log of only informative experiments is a log
// that did not record the others.
cover property (@(posedge clk) disable iff (!rst_n)
log_expt && symptom_changed && (eliminated_by_this == '0));
// Section 8: a discriminator offered BEFORE any attribution. The
// dimension is the record's order, not its content.
cover property (@(posedge clk) disable iff (!rst_n)
discriminate && !layer_established);
// Section 9: a rate that eliminates MORE THAN ONE band -- the case that
// makes the arithmetic worth doing.
cover property (@(posedge clk) disable iff (!rst_n)
measure && (eliminated_by_rate > 4'd1));
// Section 10: a closure attempt WITH something un-investigated. A project
// that never closes early never reaches it.
cover property (@(posedge clk) disable iff (!rst_n)
close && (not_investigated_count != '0));
// Section 11: an accusation of a block the instrument READS. A single
// instrument accusing only blocks outside its inputs never reaches it.
cover property (@(posedge clk) disable iff (!rst_n)
accuse && (overlap != '0));
// Section 12: a ratchet of THREE. The dimension is the history's length,
// and auditing one commit never reaches it -- 31.2 section 14.
cover property (@(posedge clk) disable iff (!rst_n)
audit && (ratchet_count >= 4'd3));
// Section 13: an UNOBSERVABLE conclusion beside an unfalsifiable one, so
// the two classes are exercised separately.
cover property (@(posedge clk) disable iff (!rst_n)
audit && (unobservable != '0) && (unfalsifiable != '0));
// And a record that is SOUND -- every conclusion falsifiable. Without
// it, p_sound_record_has_no_unfalsifiable is satisfied by a project
// whose records are never sound, which is 27.2's vacuity exposure
// reached through the antecedent rather than the consequent.
cover property (@(posedge clk) disable iff (!rst_n)
audit && record_sound && (falsifiable != '0));Reviewed against the twelve varieties, and three matter.
Variety 3 — the obligation is inexpressible without a model — governs §6 and §7, and the model is the ELIMINATES matrix. CURRICULUM-DERIVED from 30.6 §11: best available needs the alternatives. DERIVED: the next discriminating experiment is exactly a best available obligation — a maximisation over the live set — so best_next_yield is a reference model and p_next_experiment_is_maximal is a comparison against it. This is the fourth place in the module where a comparative obligation forced a model rather than a property.
Variety 8 — safety cannot see conservatism — forced p_in_layer_discriminator_is_accepted, and the do-nothing solution here is a record that refuses everything. DERIVED: p_no_discriminator_before_a_layer and p_attribution_needs_an_observation are both satisfied by an investigation that never runs an experiment, which reads as rigour. CURRICULUM-DERIVED from 30.3 §9: the two-sided pair is mandatory wherever a one-sided property admits inaction.
And p_unobservable_is_still_closable is the only property in this module written to prevent a finding, which is worth explaining. DERIVED: it asserts that an unobservable conclusion counts toward closable, so a project with a genuine 7.7-class mechanism is not penalised for it. CURRICULUM-DERIVED from 28.4 §2's sixth case: an item that flagged real unobservability as a defect would be switched off, and an item that is switched off has a yield of zero.
18. Mutation Testing
Baseline first: all twenty assertions pass and all eleven covers are non-zero.
| # | Mutation | Killed by | Survived? |
|---|---|---|---|
| M1 | §6: conclusion_licensed <= observe | p_conclusion_requires_a_singleton | killed |
| M2 | §6: citing a signature leaves the set unchanged | p_citing_a_signature_resets_the_set | killed |
| M3 | §6: best_next_expt fixed at 0 | p_next_experiment_is_maximal, by one cover | killed |
| M4 | §7: informative <= symptom_changed | p_informative_means_nonempty_elimination, by one cover | killed |
| M5 | §7: live_after <= live_before | elim | p_live_set_is_monotone | killed |
| M6 | §8: disc_accepted <= discriminate | p_no_discriminator_before_a_layer, by one cover | killed |
| M7 | §8: attribution ignores supporting_obs | p_attribution_needs_an_observation | killed |
| M8 | §8: disc_accepted <= 1'b0 always | p_in_layer_discriminator_is_accepted | killed |
| M9 | §9: drop the one-decade margin from the band test | nothing | SURVIVES |
| M10 | §9: rate_is_decisive <= measure | p_rate_eliminates_inconsistent_bands | killed |
| M11 | §10: closure_licensed <= conclude | p_closure_requires_no_uninvestigated | killed |
| M12 | §10: eliminate without an experiment id | p_elimination_names_an_experiment | killed |
| M13 | §11: accusation_licensed <= accuse | p_accusation_requires_independence, by one cover | killed |
| M14 | §12: ratchet_count counts only the last change | p_no_ratchet, by one cover | killed |
| M15 | §12: history_clean <= 1'b1 | p_history_clean_means_spec_backed | killed |
| M16 | §13: R_UNOBSERVABLE folded into R_NONE | p_unobservable_is_still_closable | killed |
| M17 | §9: every band widened to span all rates | nothing | SURVIVES |
| M18 | §6: ELIMINATES matrix emptied | nothing | SURVIVES |
| M19 | §13: RECORD reduced to one conclusion | nothing | SURVIVES |
DERIVED: fifteen of nineteen killed, four survived, and all four are variety 12 — the fourth consecutive gate at which this is the result.
M9, M17, M18 and M19 each change a quantity or a scope and keep every mechanism intact. A band test without its margin is still a band test; bands that span every rate are still bands; an empty ELIMINATES matrix still supports a set that never narrows; one conclusion is still a record. DERIVED: M17 and M18 are the same defect in the two artifacts this gate depends on most — a hypothesis table and a set of predicted-rate bands — and both make their items report nothing wrong on every input.
M9 is the one worth acting on, because it moves in the direction nobody guards against. Dropping the one-decade margin makes the band test stricter and eliminates hypotheses the data does not actually exclude. DERIVED: §9's log is crude by construction — a three-times-log2 approximation — and its bands are grade C estimates, so a test without a margin converts estimation error into false eliminations. CURRICULUM-DERIVED from 18.4 §1: a grade C quantity used without an allowance for its own uncertainty is category drift, and here the drift produces confident wrong eliminations rather than a missed one.
And M19 is the first mutation in this module whose damage is to a review, not to a design or an instrument. Reducing the conclusion record to a single row satisfies every property in §13 and makes the audit meaningless. DERIVED: a falsifiability audit over one conclusion cannot find a pattern, and the item's value was always the ratio — two of eight. The fix is a scope requirement: audit every conclusion in a release, not the one in front of you — which is a process document, exactly as variety 12 predicts.
Five mutations are killed only by a cover — M3, M4, M6, M13 and M14. M14's is the sharpest and the most specific to this chapter: counting only the last change makes the ratchet invisible unless the history is audited as a whole, so the cover on ratchet_count >= 3 is what forces a multi-commit history into the run. CURRICULUM-DERIVED from 31.2 §14's coverage-dimension rule: the dimension is the history's length, and auditing one commit a thousand times never reaches it.
19. Baseline Defects Found Before Mutation
Each of the eight weak records run against the robust property set, before any mutation.
| Item | Weak record caught by | At what cost |
|---|---|---|
| §6 | p_conclusion_requires_a_singleton | a signature → causes table somebody must write |
| §7 | p_informative_means_nonempty_elimination | the live set, which §6 supplies |
| §8 | p_no_discriminator_before_a_layer | nothing — compare two timestamps |
| §9 | p_rate_eliminates_inconsistent_bands | nothing — arithmetic on data in hand |
| §10 | p_closure_requires_no_uninvestigated | nothing — the second column is absent |
| §11 | p_accusation_requires_independence | the instrument's input list |
| §12 | p_no_ratchet | nothing — git log on one file |
| §13 | p_sound_record_has_no_unfalsifiable | nothing — the field is absent |
DERIVED: five of eight are found without running anything and without domain knowledge, and three need a document written once. That is the same split 33.6 §19 found, and the documents are the same kind of thing — a table, a list, an input map.
The three once-written documents, with their seeds:
| Item | The artifact | Seed in this track |
|---|---|---|
| §6 | signature → consistent causes → next experiment | 28.5 §9's eleven signatures; 28.1 §2's five causes |
| §9 | predicted-rate band per hypothesis | 28.5 §7's pattern/frequency/temperature axes |
| §11 | input list per instrument | 27.3's independence requirement; 27.4's reference memory |
DERIVED: all three are extensions of tables this curriculum already contains, and §6's had to gain a row this chapter discovered — the recovery artefact, from 33.6 §10. So the documents are living, and the review of a stale one is variety 10's shape applied to evidence.
And the five free items have a property no other gate's cheap items have, which is worth stating as the section's finding. DERIVED: §8, §9, §10, §12 and §13 are answerable by someone who cannot read a timing diagram. Compare two dates. Divide two integers. Check for a second column. Count commits. Check for a sentence. CURRICULUM-DERIVED from 30.10 §2's observability collapse, which explains why: when the physical observables are unavailable, what remains is the structure of the argument, and structure is domain-independent.
20. Silicon Observability
This gate's subject is a document, so this section reads from the later silicon symptom back to the item that was skipped.
| Item | The later symptom | What it says about the investigation |
|---|---|---|
| §6 | the same signature returns after the fix ships | a conclusion drawn from a set of six |
| §7 | three tickets, three different root causes, one defect | correlations recorded as confirmations |
| §8 | a board team that finds nothing wrong with the board | a layer never established |
| §9 | a hypothesis chased for weeks that the rate excluded on day one | the arithmetic was never done |
| §10 | the defect is in the hypothesis the closing note listed | one list where two were needed |
| §11 | an RTL fix to a correct block, and the failure persists | the accuser read the accused |
| §12 | a class of violation that no checker has ever reported | a ratchet nobody counted |
| §13 | a ticket reopened three times with the same conclusion | no refutation, so no evidence can close it |
Three rows are diagnostic, and each points at one item.
§8: a board team that finds nothing wrong. DERIVED: an escalation across 28.6 §7's boundary that returns no finding is strong evidence that the layer was never established, because the channel layer is expensive to investigate and thorough when it is. The symptom is a negative result from an expensive team, and it is the cheapest available signal that mechanism 2 was the failure.
§12: a class of violation that no checker has ever reported. DERIVED: a checker that has never fired in the project's history is either protecting something that never breaks or has been widened past the obligation — and 33.4 §10's positive control distinguishes them. CURRICULUM-DERIVED from 27.3's cannot-fail mode: the ratchet is one mechanism that produces it, and the commit log is the only place the mechanism is visible.
§10: the defect is in the hypothesis the closing note listed. DERIVED: that is the most specific signature in this table, because it is the one case where the record names the answer. A reopened ticket whose cause appears in the original considered list has confirmed that considered and eliminated were conflated. The finding is available from the two documents alone, with no new measurement.
And one row is a statement about cost rather than a signature: §9's. DERIVED: a hypothesis chased for weeks that the observed rate excluded on the first day is the largest single waste this chapter can prevent, and the prevention is a division. CURRICULUM-DERIVED from 28.5 §7: the rate axis was always there; what this chapter adds is that it is quantitative and therefore decisive.
21. Common Wrong Answers
-
“Root cause identified.” §6: the signature was consistent with six causes and one was named. CURRICULUM-DERIVED from 28.4 §2: a signature is evidence, not a verdict — and 28.1 §2 already counted five for this bitmap, before this chapter added a sixth.
-
“Marginal read margin produces exactly this bitmap, so that is the cause.” It does, and so do five other things. DERIVED: consistency with the observation is a necessary condition that every member of the set satisfies.
-
“We dropped the frequency and the errors stopped — it is signal integrity.” CURRICULUM-DERIVED from 28.6 §2: the frequency test is on its list of experiments mistaken for proof. §7: it eliminated zero of six hypotheses, because every one of them is rate-sensitive.
-
“We swapped to a spare lane and the errors stopped — it is lane 17.” A dead lane, a stuck per-lane classifier and a truncated per-lane sweep all move with the lane. DERIVED: an experiment that perturbs a condition the whole live set depends on cannot partition it.
-
“Three experiments confirmed three causes, so we have converging evidence.” They are mutually exclusive, so at most one is right. DERIVED: a record whose confirmations contradict each other has confirmed nothing, and counting them is the cheapest finding in this chapter.
-
“We measured the eye, the Vref band and the per-lane skew — the investigation was rigorous.” §8: rigorous inside a layer nothing established. Lane 17 really is 0.4 UI late, and the reason is a deskew register in the configuration layer — CURRICULUM-DERIVED from 28.6 §1's escalation criterion.
-
“We used the instruments we had.” That is the mechanism, not a defence. DERIVED: the cheapest layer to eliminate is configuration and it costs one read-back (33.6 §9), so an order driven by instrument availability inverts the cost order.
-
“It is intermittent, and intermittent failures at this rate are characteristically physical.” A prior applied as a conclusion. §9: the observed rate eliminated four of six hypotheses by arithmetic, including two physical ones.
-
“We cannot do statistics on one failure per few minutes.” You do not need statistics — you need orders of magnitude. DERIVED: the hypothesis bands in §9 are decades apart, so a crude log on errors and operations partitions them, and both counts were already being collected.
-
“We considered six hypotheses.” §10: four were eliminated, one was concluded, and one was never investigated — and the un-investigated one was the cause. Considered covers both eliminated by experiment 3 and thought about.
-
“Closing with an untested hypothesis is unavoidable under schedule pressure.” Agreed, and the item does not forbid it. DERIVED: it forbids doing it silently — a closing note reading “retention at temperature was not investigated” is a legitimate decision and a reopenable record.
-
“The scoreboard reported the mismatch, so the data path is wrong.” §11: the scoreboard's expected value is indexed by the decoded address, so it cannot distinguish a data error from a decode error. CURRICULUM-DERIVED from 27.4: the reference model is a memory, and whatever supplies its index is outside its reach.
-
“A reproducible mismatch at a stable address is the strongest evidence we have.” It is strong evidence that something is wrong and weak evidence about where. DERIVED: every scoreboard has at least one block it cannot adjudicate, and the review question is which one.
-
“The checker was over-strict, so we widened it.” §12: the first widening was correct. DERIVED: the second and third were the defect and all three commits say the same thing — the ratchet count is the only signal in the repository that separates them.
-
“The checker is quiet, so the design is clean.” CURRICULUM-DERIVED from 33.2 §14: a checker adjusted until it stopped complaining has been calibrated against the design. §12: twelve real violations per million operations, undetectable at a window of 18.
-
“Marginal signal integrity at this data rate.” True of every DDR interface ever built. DERIVED: a conclusion consistent with every possible observation cannot be refuted, cannot be confirmed, and closes a ticket — and the action it implies, dropping a bin, reliably works.
-
“Some things genuinely cannot be observed, so demanding a refutation is unrealistic.” §13 keeps those separate and counts them as closable. CURRICULUM-DERIVED from 7.7 via 28.4 §2: an unobservable mechanism is a standing residual risk, correctly classified — and an item that called it a defect would be switched off.
-
“The ticket was reopened, so the conclusion was wrong.” Or the conclusion was unfalsifiable and the ticket had nowhere to go. DERIVED: three reopenings with the same conclusion is §13's signature, not §6's.
-
“A debug review needs a DDR expert.” Five of eight items are answerable by someone who cannot read a timing diagram — compare two dates, divide two integers, look for a second column, count commits, look for a sentence. CURRICULUM-DERIVED from 30.10 §2's observability collapse: when the observables are gone, what is left is the argument's structure.
-
“We will review the investigation once it closes.” §10 and §13 become unanswerable at closure — DERIVED: once a ticket closes, the un-investigated hypotheses are recorded as considered and the missing refutation is recorded as a conclusion. The review has to happen while the live set still exists.
-
“A surviving mutation means a missing property.” Four survived here and none has a property fix. A band margin, a band width, a table's contents, a record's scope. CURRICULUM-DERIVED from 33.4 §15's variety 12 — the fourth consecutive gate where the survivors are quantities and scopes.
-
“Tightening the rate bands would make §9 stronger.” M9: dropping the one-decade margin produces confident false eliminations. DERIVED: the bands are grade C and the log is crude, so the margin is what keeps estimation error from becoming an exclusion — CURRICULUM-DERIVED from 18.4 §1.
22. Self-Check
- A write-up cites an all-zeros training bitmap and names marginal read margin. How many causes are consistent with that signature in this curriculum, and which chapter added the most recent one?
- An experiment drops the frequency and the errors stop. State what it eliminated, and give the general rule about experiments that perturb a shared condition.
- A record contains three confirmations of three different causes. What is the finding, and how long does it take to reach?
- A work log shows an eye measurement, a Vref sweep and a skew measurement, then an escalation. Name the missing entry, and say what it would have cost to produce.
- A failure occurs about once per four million operations. Given six hypotheses with predicted bands decades apart, how many can you eliminate, and what does the elimination cost?
- Why does §9's band test need a one-decade margin, and what does removing it produce?
- A closing note reads “considered six hypotheses; root cause crosstalk.” Name the two lists that should be there, and say what makes the un-investigated one predictable rather than arbitrary.
- A scoreboard reports a reproducible read-data mismatch. Name one block it cannot adjudicate and say why, citing the chapter that establishes it.
git logshows three commits reading “loosen latency window.” Which of the three might have been correct, what separates it from the others, and what does the record need to make the separation visible?- A conclusion reads “marginal signal integrity.” Say why it is unfalsifiable, why it is nonetheless true, and how it differs from an unobservable conclusion.
- Four mutations survived this chapter's property set. Group them and say which one makes the item stricter rather than weaker.
- Of the eight items, which five need no domain knowledge, and what does that fact follow from?
23. The Residual Risk
What this gate cannot catch, stated plainly.
It cannot tell you that a hypothesis set is complete. §6's table has six rows because 28.1 §2 supplied five and 33.6 §10 supplied a sixth. DERIVED: a seventh cause, unlisted, is never in the live set, is never eliminated, is never recorded as un-investigated, and closure_licensed reports the ticket closable. CURRICULUM-DERIVED from 27.1's completeness argument: an unenumerable domain is not covered by an enumeration, and the best available check is that the table contains at least what this track documents.
It cannot validate its own bands or tables. M17 widened every predicted-rate band to span all rates and M18 emptied the eliminates matrix; both report nothing wrong on every input. DERIVED: this is the fourth consecutive gate whose instruments depend on inputs nothing inside engineering establishes — CURRICULUM-DERIVED from 33.4 §15, 33.5 §18 and 33.6 §17. The chain is unchanged: a mechanism by a property, a quantity by a bound, a bound by an objective, an objective by a requirement.
It cannot supply the layer taxonomy §8 depends on. CURRICULUM-DERIVED from 19.1 §3: six rows of the controller/PHY/DRAM ownership table are implementation-dependent and one is strongly so, so the boundary between the RTL and PHY layers is a per-product decision. DERIVED: two projects can classify the same defect into different layers and both be right, and this item checks only that the attribution precedes the discriminators.
It cannot recover evidence the failure destroyed. CURRICULUM-DERIVED from 30.10 §11 and 33.6 §10: an observable cleared by the recovery reset is gone before any review applies. DERIVED: §6's sixth cause exists precisely because that loss produces a signature, so this gate can name the artefact and cannot undo it.
And it cannot make an unobservable mechanism observable. §13 classifies 7.7's class correctly and stops there. DERIVED: a conclusion about a mechanism whose outcome the interface does not report stays a standing residual risk indefinitely, and the only remedy is a design change — a reported outcome, which is 33.1's gate.
The honest summary: this gate's eight items decide whether an investigation's evidence supports its conclusion. It cannot decide whether the hypothesis set was complete, whether the rate bands were right, or whether the layers were the right layers.
24. Where This Goes
Seven gates have reviewed a design, its code, its registers, its testbench, its numbers, its bring-up and its investigations. The last gate turns the same method on the reviewer.
Chapter 33.8 is a self-audit. The question changes from does this evidence support this conclusion to does what I know support what I am about to say — and it is not a set of interview questions. Module 30 owns those: ten chapters of questions, answers and the reasoning behind them. This gate owns the eight ways an engineer's own answer fails the seven checklists that came before it.
| From here | What 33.8 must settle |
|---|---|
| §6's hypothesis set | When you name one cause, how many did you consider? |
| §9's unanalysed data | Which number in your answer did you recall, and which did you derive? |
| §13's refutation | What would have to be true for your answer to be wrong? |
The middle row is the one to carry forward, and it is the sharpest self-test this module can offer. DERIVED: every chapter of this module has demanded that a claim carry its provenance — a denominator, an operating point, an evidence grade, a specification clause — and an answer given out loud carries none of them unless the speaker supplies them.
CURRICULUM-DERIVED from 30.8, whose framing applies to the speaker rather than to the system: “a proposal offered before a measurement is a guess with engineering vocabulary.” DERIVED: the same sentence with answer in place of proposal is 33.8's entire subject — and the module's final item is the one no checklist so far has asked: can you say, of the number you just quoted, whether you recognised it, recalled it, or rebuilt it?
Continue learning
Related tutorials
- Related topic
Architecture Review Checklist
The first of eight pre-tapeout gates. Eight review items asked of a controller architecture before RTL exists, each one a question whose pass criterion is a named mechanism rather than an intention — and whose weak build produces a document that reads as thorough.
- Related topic
RTL Review Checklist
Nine questions drawn from the eighteen documented defects this track already carries. Every finding is code that is legal, lint-clean, passes a nominal test and is wrong — and five of the nine are decided by reading a port list.
- Related topic
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.
- Related topic
Verification Review Checklist
The gate that reviews the environment rather than the design. Nine items on configuration reach, antecedent publication, scale-vacuity, model independence and checker liveness — and it opens a twelfth variety the eleven-item taxonomy does not cover.
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.
