Skip to content
VLSI Mentor

DDR · Module 28

Signal-Integrity Problems

RTL cannot measure an eye. The answerable question is which digital observations make a physical hypothesis the cheapest remaining one — and what that domain then requires.

Chapter 28.5 kept deferring one hypothesis. Pattern dependence, frequency sensitivity, and a lane-local failure surviving every digital exclusion all pointed the same way — and each time the chapter said not yet.

This chapter is where that hypothesis is taken seriously, and it starts by refusing the obvious framing. The question is not what is the channel doing. Digital logic cannot answer that, and neither can any RTL in this module.

The question is:

WHAT DIGITAL OBSERVATION JUSTIFIES MOVING A HYPOTHESIS INTO A DOMAIN WHERE RTL CANNOT FOLLOW?

That is answerable, it is cheap, and getting it wrong is expensive in both directions. Escalate too early and a team spends a week with a scope on a problem that was a unit-conversion error. Escalate too late and a team spends a month excluding digital causes that were already excluded.

1. The Escalation Criterion

State it precisely, because the rest of the chapter is its justification.

A physical hypothesis is justified when every cheaper hypothesis has been excluded by experiment, and the surviving digital evidence has a structure the digital causes do not explain.

Two clauses, and both are required. Exclusion alone is not enough — you can exclude everything and still have no reason to think the channel is involved. Structure alone is not enough either, because every structure in 28.5 has at least one digital explanation.

ClauseWhy it is necessary
Cheaper causes excluded by experimentotherwise you are escalating on a hunch, and the digital cause is still there
Surviving structure not explained by themotherwise the structure is the digital cause, and the channel is a coincidence

The exclusions, gathered from the whole module:

CauseExcluded byOwner
Training committed a bad settingbitmap structure, window width, a finer sweep28.1
A timing contract is violatedan empty violation snapshot over a long run28.2
Parameter conversion or roundingre-deriving the applied counts by hand28.2 §11
A refresh obligation was missedzero deadline misses28.3
Calibration never started, converged, or committedthe four lifecycle fields28.4
A committed value is stalethe provenance tag comparison28.4 §5
Correction is hiding the fault structurecorrection disabled for a debug run28.5 §12

Seven exclusions, all digital, all cheaper than a physical measurement. §11's gate counts them, and it will not report escalation as justified until they are recorded.

2. Three Experiments Mistaken for Proof

The three results that get reported as it is signal integrity, and what each actually supports.

Lower frequency helps

Supports: that something scales with the clock period.

Also consistent withDigital?Cheaper to test?
A unit-conversion error — 28.2 §11yesyes
The wrong frequency bin's settingsyesyes
A max(nCK, ns) dual-term crossover — 28.2 §12yesyes
A calibration valid only at the trained frequency — 28.4 §5yesyes
Fewer accesses per second, so less exposureyesyes
Channel marginnono

Five digital explanations, all cheaper. And the fifth is a measurement artefact rather than a mechanism: lower frequency usually means fewer accesses per unit time, so an error rate per second falls even when the rate per access is unchanged. Report per access or the experiment is uninterpretable.

One lane fails

Supports: that the fault follows that lane's path.

CURRICULUM-DERIVED from 19.1 and 28.1 §8, that path contains: the lane's delay setting, its capture logic, its share of the classifier, its package trace, its board trace, and its device pin. Four of the six are digital.

ExperimentIf the cause is digitalIf it is the physical path
Remap the lane — 28.5 §9the failure follows the logical lanethe failure stays with the physical pin
Swap the devicethe failure staysthe failure may move
Swap the boardthe failure staysthe failure may move

The remap experiment is the decisive one and it is digital. If the failure follows the logical lane through a remap, the cause is in logic that the remap moved — and no channel measurement was needed to establish that.

ODT sensitivity

Supports: that termination configuration affects the outcome.

Chapter 22.1 owns the three selectable values, the dynamic switch, and the timing that makes the switch land where the data is — and that last clause is the reason ODT sensitivity is ambiguous.

HypothesisMechanismDigital?
The termination value is wrong for this channelelectricalno
The switch timing is wrong, so termination is absent when data arrivesdigital — a timing parameteryes
The wrong ranks are being told to terminate — 6.7digital — a configuration fieldyes

Two of three are digital, and both are cheaper than a measurement. So a failure that changes with ODT settings is not evidence of a channel problem until the switch timing and the rank selection have been checked — and both are register reads.

3. Digital Observables That Genuinely Bear on the Channel

Not everything is ambiguous. Four digital observations carry real information about channel behaviour, and three of them come from mechanisms Module 22 and 25.4 already own.

Pattern structure. Chapter 22.3 establishes that the three degradation mechanisms interact through the data pattern. So a failure rate that varies with the number of transitions in the pattern — rather than with a specific value — is a digital measurement of a pattern dependence the mechanisms predict. §4 makes this a counter rather than an impression.

The aggressor/victim separation. Chapter 22.2 owns a precise and unusually testable fact: a reflection arrives late, and therefore corrupts a different bit than the one that caused it. That is a digital prediction — the corrupted position is displaced from the transition that produced it — and §5 shows how to measure the displacement.

CRC reports. Chapter 22.4 owns write CRC including its detection guarantee and its error report, and 25.4 owns CRC in both directions and ALERT_n's semantics. A CRC error is a real, reported, digital event about a transfer that was corrupted in flight — which is closer to a channel observation than anything else available without instrumentation.

Data bus inversion behaviour. Chapter 22.3 owns DBI, its encoding and its decision policy. If a failure rate changes when DBI is enabled or disabled, the transition count of what is actually on the wires changed — which is a pattern-structure experiment with a single configuration bit.

ObservableWhat it measuresWhat it still does not give you
Errors versus transition counta pattern dependence the mechanisms predictwhich mechanism, or any magnitude
Aggressor/victim displacementthat corruption is displaced from its causethe reflection's amplitude or timing
CRC error ratein-flight corruption, reported by hardwarewhere on the channel, or why
DBI on/off deltasensitivity to wire-level transition densityany electrical quantity

All four are digital, all four are cheap, and none of them is a measurement of the channel. They make a physical hypothesis more likely and they do not make it established — which is the distinction §11's gate encodes.

4. Measuring Pattern Dependence Properly

The most valuable experiment in this chapter, and it is usually done badly.

Done badly: run a random pattern, run a walking-ones pattern, note that random is worse, conclude pattern dependence.

The problem is that those two patterns differ in several ways at once — transition count, transition density per lane, the number of simultaneously switching lanes, and the specific values. A difference between them localises nothing.

Done properly: vary transition count while holding everything else you can hold, and measure errors per access at each level.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   errors per 10^9 accesses versus transitions per beat, ILLUSTRATIVE

   transitions/beat   errors/10^9   what the shape says
   ----------------   -----------   -------------------
          0                0
          2                0
          4                1
          8               11
         16               47
         32              198

   monotone and steeply rising: consistent with a pattern-dependent
   mechanism, which 22.3 says all three degradation mechanisms are.

   contrast with a DIGITAL cause that also looks pattern-dependent:

   transitions/beat   errors/10^9
   ----------------   -----------
          0                0
          2               43     <-- one specific VALUE in this set
          4                0
          8                0
         32                0

   non-monotone, and concentrated at one level -- which is a value
   effect, not a transition effect. 28.5 §7 makes the same point: a
   channel responds to transitions, it does not single out a value.

Monotonicity in transition count is the signature, and it is what separates a pattern-dependent mechanism from a pattern-specific bug. A non-monotone profile with a spike is a decode, mask, or alignment problem wearing pattern dependence as a disguise.

And the profile must be errors per access. Different patterns may be generated at different rates; a profile in errors per second measures the generator as much as the channel.

5. The Aggressor/Victim Displacement

Chapter 22.2's fact, turned into a measurement.

The prediction: the corrupted bit position is displaced from the transition that caused it, because the disturbance arrives late.

So the measurement is a joint distribution: for each error, the displacement between the corrupted position and the nearest large transition. A histogram over that displacement is a digital object.

Displacement histogramSupports
Peaked at zerothe corruption coincides with its own transition — not a late-arriving mechanism
Peaked at a consistent non-zero displacementa late-arriving disturbance, which is what 22.2 predicts
Flatno relationship between transitions and corruption
Peaked at one displacement, and that displacement changes with frequencyconsistent with a fixed time delay expressed in a changing number of beats

Row four is the strongest digital evidence in this chapter, and it is worth being precise about why. A fixed physical delay occupies a fixed time. Expressed in beats, that time is more beats at higher frequency. So a displacement that grows with frequency in proportion to the frequency behaves like a fixed time delay — and no digital mechanism has that property, because digital delays are counted in cycles and stay constant in cycles.

That is an inference from a digital measurement to a physical character, not a measurement of a physical quantity. It says something here behaves like a fixed time rather than a fixed number of cycles. It does not say how long, how large, or where — and those are exactly the questions that require the instrumentation §13 describes.

6. A Displaced Error, Cycle by Cycle

The aggressor and the victim in one burst. ILLUSTRATIVE data and displacement.

The corrupted beat is not the beat that caused it

10 cycles
A ten-cycle write burst trace showing a displaced corruption. The clock runs throughout. The beat index counts zero through seven across cycles one to eight. The pattern lane shows the bytes driven on each beat. The transition count lane shows how many bits changed relative to the previous beat: low values on most beats, and a value of thirty-two on beat two, which is the high-transition beat. The aggressor marker signal is high only on beat two. The error exclusive-or lane is zero on every beat except beat four, where it shows hexadecimal zero four, a single bit. The victim signal is high only on beat four. The displacement lane shows the value two on beat four, being the difference between the victim beat index of four and the aggressor beat index of two. The mismatch output pulses on beat four only. The first marker at cycle three notes the high-transition beat, the aggressor, with thirty-two bits changing. The second marker at cycle five notes the corrupted beat, the victim, two beats later, with a single bit wrong. The third marker at cycle five notes that the displacement of two beats is the measurement, and that a displacement which scales with frequency behaves like a fixed time delay rather than a fixed cycle count. The first phase spans cycles one to eight and covers the burst. The second phase spans cycles three to five and covers the interval between aggressor and victim.one burstone burstaggressor to victimaggressor to victimaggressor: 32 transitionsaggressor: 32 transitionsvictim: 2 beats later, 1 bitvictim: 2 beats later, 1bitdisplacement 2 is the measurementdisplacement 2 is themeasurementCKbeat0012345677pattern00000FFFFFFFFFFFFFFtransitions00032000000aggressorerr_xor0000000000400000000victimmismatcht0t1t2t3t4t5t6t7t8t9

The displacement of two beats is the entire finding, and it is a digital number. No voltage, no time, no amplitude — a difference between two beat indices.

What makes it evidence rather than a coincidence is repetition. One displaced error is noise; a histogram peaked at displacement two over thousands of errors is a structure, and §5 row four's frequency test is what turns that structure into an argument about character.

And what it is not: a statement that a reflection occurred. Chapter 22.2 predicts displaced corruption from a reflection, and a prediction being satisfied is not the same as its mechanism being established — an equaliser with wrong taps (22.4) produces the same digital signature, and that is a register you can read.

7. The Escalation Boundary

The escalation boundary between the digital and physical domains, in four rows. The top row holds the digital evidence sources: the corruption structure from chapter 28.5, the pattern-dependence profile measured as errors per access against transition count, the aggressor-to-victim displacement histogram, and the CRC and ALERT_n reports that hardware itself produces. The second row holds the seven digital exclusions that must be recorded before escalation is justified: training, timing contracts, parameter conversion, refresh obligations, the calibration lifecycle, staleness, and whether error correction was masking the fault structure. The third row holds the escalation gate itself, which counts the recorded exclusions and evaluates whether the surviving structure is unexplained by any digital cause, together with the two outcomes it can produce: not yet justified, which routes back to the remaining digital work, and justified, which routes onward. The bottom row is the physical domain, which is drawn as a destination reached only through the gate and which is explicitly outside the reach of any register or assertion in this module, because it requires instrumentation and modelling that digital logic cannot substitute for. Edges run from each evidence source into the gate, from each exclusion into the gate, from the gate to its two outcomes, and from the justified outcome alone into the physical domain.Corruption structure28.5 — lane, beat,addressPattern profileerrors/access vstransitions — §4Displacementaggressor to victim — §5CRC / ALERT_n22.4, 25.4 — hardwarereportsTraining excluded28.1 — bitmap, windowTiming excluded28.2 — empty snapshotRefresh excluded28.3 — zero missesCalib excluded28.4 — four fields + tagEscalation gatecounts, never concludes —§11Not yet justifiedback to the digital workJustifiedcheapest remaininghypothesisPhysical domaininstrumentation, not RTL— §1312

Three things the structure makes explicit.

Only one edge crosses into the physical domain, and it comes from Justified. There is no path from evidence directly to the physical domain — every route passes through the gate, which is the architectural form of §1's two-clause criterion.

The exclusions are inputs, not conclusions. They arrive as recorded facts from four other chapters, and §11's gate cannot derive them. An investigation that skipped an exclusion produces a gate that says not yet, which is the correct answer.

And Not yet justified routes back rather than terminating. That is the common outcome and it is not a failure: most escalation candidates are digital causes that have not been excluded yet.

8. The Gate

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// si_escalation_gate -- SIMULATION-ONLY.
//
// WHAT IT DOES: §1's two-clause criterion, executable. Clause one is
// the seven digital exclusions; clause two is a surviving structure
// that no digital cause explains.
//
// WHY IT CANNOT RETURN A PHYSICAL VERDICT: nothing digital measures a
// channel. 22.3 owns why a measured pass/fail grid is not an eye
// diagram, and a gate that returned "signal integrity" would be a
// fabrication wearing the clothes of evidence. The method that would
// return one is a REFUSAL, so a caller cannot ask.
//
// WHY THE EXCLUSIONS ARE INPUTS: they are facts about which
// EXPERIMENTS were run, in four other chapters. No register can
// derive them, and a gate that defaulted them to true would let an
// investigation skip the cheap work and escalate on a hunch.
//
// WHAT IT DOES NOT MODEL: anything electrical. No impedance, no
// amplitude, no time, no eye, no jitter, no crosstalk magnitude.
//
// WHAT IT WOULD MISS: a physical problem coexisting with an
// unexcluded digital one -- common, which is why the output is
// "cheapest remaining hypothesis" and not "cause".
// ---------------------------------------------------------------------
typedef enum {
  EX_TRAINING,      // 28.1: bitmap structure, window width, finer sweep
  EX_TIMING,        // 28.2: empty violation snapshot over a long run
  EX_CONVERSION,    // 28.2 §11: applied counts re-derived by hand
  EX_REFRESH,       // 28.3: zero deadline misses
  EX_CAL_LIFECYCLE, // 28.4: started, converged, committed, readback
  EX_CAL_STALENESS, // 28.4 §5: provenance tag comparison
  EX_ECC_MASKING    // 28.5 §12: correction disabled for a debug run
} si_exclusion_e;

class si_evidence;
  // clause two: surviving structure
  bit  pattern_profile_monotone;   // §4 -- monotone in TRANSITION count
  int  pattern_levels_measured;    // how many transition levels were run
  int  displacement_peak;          // §5 -- beats, -1 if no peak
  bit  displacement_scales_with_freq; // §5 row four
  bit  errors_per_access_normalised;  // §2 -- was the rate normalised?
  int  crc_errors;                 // 22.4, 25.4
  int  alert_events;               // 25.4
  bit  equaliser_config_checked;   // §5's callout -- a digital cause
  bit  odt_switch_timing_checked;  // §2 -- a digital cause
  bit  odt_rank_selection_checked; // §2, 6.7 -- a digital cause
  bit  lane_remap_experiment_done; // §2 -- the decisive digital test
  bit  failure_followed_logical_lane; // result of that experiment
endclass


class si_escalation_gate;

  protected bit m_excluded[si_exclusion_e];
  protected string m_method[si_exclusion_e];

  // An exclusion requires the METHOD that established it, for the same
  // reason 27.6 §10's capability register does: an experiment nobody
  // can describe was not run.
  function bit record_exclusion(si_exclusion_e e, string method);
    if (method == "") begin
      $error("si_gate: exclusion of %s refused -- no method given", e.name());
      return 0;
    end
    m_excluded[e] = 1'b1;
    m_method[e]   = method;
    return 1;
  endfunction

  function int exclusions_recorded();
    int n = 0;
    foreach (m_excluded[e]) if (m_excluded[e]) n++;
    return n;
  endfunction

  function void missing_exclusions(ref string out[$]);
    out.delete();
    for (si_exclusion_e e = e.first(); ; e = e.next()) begin
      if (!m_excluded.exists(e) || !m_excluded[e]) out.push_back(e.name());
      if (e == e.last()) break;
    end
  endfunction

  // Clause two. A structure "unexplained by digital causes" is not a
  // judgement -- it is a conjunction of specific digital checks having
  // been run and come back clean.
  function bit structure_unexplained(si_evidence v);
    // §2: the lane remap is the decisive digital test. If the failure
    // followed the LOGICAL lane, the cause is in logic the remap
    // moved, and no physical hypothesis is warranted at all.
    if (v.lane_remap_experiment_done && v.failure_followed_logical_lane)
      return 0;
    // §2: ODT sensitivity has two digital explanations that must be
    // checked before it counts as channel evidence.
    if (!v.odt_switch_timing_checked)  return 0;
    if (!v.odt_rank_selection_checked) return 0;
    // §5's callout: an equaliser with wrong taps produces the same
    // displacement signature.
    if (!v.equaliser_config_checked)   return 0;
    // §2, §4: an un-normalised rate makes every frequency and pattern
    // result uninterpretable.
    if (!v.errors_per_access_normalised) return 0;
    // §4: a pattern profile is evidence only if it is monotone in
    // transition count AND enough levels were measured to see a shape.
    if (v.pattern_profile_monotone && v.pattern_levels_measured >= 4)
      return 1;
    // §5 row four: a displacement that scales with frequency behaves
    // like a fixed TIME rather than a fixed cycle count, and no
    // digital mechanism has that property.
    if (v.displacement_peak > 0 && v.displacement_scales_with_freq)
      return 1;
    // Hardware-reported in-flight corruption, with the digital causes
    // above already checked.
    if (v.crc_errors > 0 || v.alert_events > 0) return 1;
    return 0;
  endfunction

  // §1: BOTH clauses. Neither alone.
  function bit escalation_justified(si_evidence v);
    return (exclusions_recorded() == 7) && structure_unexplained(v);
  endfunction

  // The honest output: a routing decision plus the reason.
  function string recommendation(si_evidence v);
    string miss[$];
    missing_exclusions(miss);
    if (miss.size() != 0)
      return $sformatf("not yet: %0d digital exclusion(s) unrecorded, starting with %s",
                       miss.size(), miss[0]);
    if (v.lane_remap_experiment_done && v.failure_followed_logical_lane)
      return "not physical: the failure followed the logical lane through a remap, so the cause is in logic the remap moved";
    if (!v.errors_per_access_normalised)
      return "not yet: normalise the error rate per ACCESS before interpreting any frequency or pattern result";
    if (!v.equaliser_config_checked)
      return "not yet: an equaliser with wrong taps produces the same displacement signature (22.4) -- read its configuration";
    if (!v.odt_switch_timing_checked || !v.odt_rank_selection_checked)
      return "not yet: ODT sensitivity has two digital explanations (switch timing, rank selection) -- check both";
    if (!structure_unexplained(v))
      return "not yet: no surviving structure that a digital cause fails to explain";
    return "justified: a physical hypothesis is now the cheapest remaining one -- see §13 for what that domain requires";
  endfunction

  // §1 and 22.3's boundary, enforced in code rather than in a comment.
  function string physical_verdict(si_evidence v);
    return "unavailable: no digital observation measures an eye, jitter, crosstalk, impedance or settling. 22.3 owns why a pass/fail grid is not an eye diagram; this gate routes a hypothesis and does not diagnose one";
  endfunction

  // §4: the profile shape, computed so "monotone" is a fact rather
  // than an impression. Returns -1 when too few levels were measured
  // for a shape to exist -- not 0, which would read as "not monotone".
  function int monotone_run(int errors_per_level[$]);
    int run = 0;
    if (errors_per_level.size() < 3) return -1;
    for (int i = 1; i < errors_per_level.size(); i++)
      if (errors_per_level[i] >= errors_per_level[i-1]) run++;
    return run;
  endfunction
endclass

physical_verdict() is a refusal, and it is the most important method in the chapter. A gate that could be asked for a channel diagnosis would be asked for one. Replacing the answer with the reason it is unavailable is the only version that survives a reviewer who wants a verdict.

structure_unexplained() returns false when the lane remap showed the failure following the logical lane. That is not a missing exclusion — it is positive evidence against a physical cause, and the gate treats it as disqualifying rather than merely absent.

And monotone_run() returns −1 for fewer than three levels. Two points cannot have a shape, and returning 0 would read as not monotone — the same three-valued discipline this curriculum has needed in 27.3 §6, 27.4 §2, 28.1 §18, 28.2 §17 and 28.3 §13.

9. The Pattern and Displacement Accumulator

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// pattern_displacement_counter -- CLASSIFICATION: synthesisable, BINDABLE.
//
// WHAT IT DOES: counts TRANSITIONS per beat and the DISPLACEMENT in
// beats between an error and the most recent high-transition beat.
// Both are digital counts.
//
// WHY TRANSITIONS AND NOT PATTERNS (§4): 22.3 establishes the three
// degradation mechanisms interact through the data pattern, and the
// aspect they interact through is transitions. A profile over
// transition COUNT is monotone for a pattern-dependent mechanism and
// spiky for a value-specific bug -- which is the discrimination.
//
// WHY DISPLACEMENT (§5): 22.2 owns the fact that a reflection arrives
// late and corrupts a DIFFERENT bit than the one that caused it. The
// displacement is that prediction made countable.
//
// WHAT IT CANNOT TELL YOU: amplitude, time, or mechanism. This is a
// distribution over beat indices. 22.3 owns why a pass/fail grid is
// not an eye diagram, and this is not even a grid.
//
// SYNTHESIS: an XOR-popcount, two small histograms, a shift of beat
// indices. No DUT handle, no electrical model of any kind.
// ---------------------------------------------------------------------
module pattern_displacement_counter #(
  parameter int DATA_W    = 64,
  parameter int TRANS_HI  = 24,   // "high transition" threshold, ILLUSTRATIVE
  parameter int DISP_MAX  = 8,    // displacement bins, in beats
  parameter int LEVELS    = 8     // transition-count buckets -- §4
)(
  input  logic                        clk,
  input  logic                        rst_n,

  input  logic                        beat_valid,
  input  logic [DATA_W-1:0]           beat_data,
  input  logic                        err_valid,      // from the scoreboard
  input  logic                        clear,

  output logic [$clog2(DATA_W+1)-1:0] transitions,
  output logic                        aggressor,
  output logic                        victim,
  output logic [15:0]                 trans_hist [LEVELS],
  output logic [15:0]                 disp_hist  [DISP_MAX],
  output logic [31:0]                 beats_at_level [LEVELS],
  output logic [31:0]                 errors_at_level[LEVELS],
  output logic [31:0]                 total_beats,
  output logic [31:0]                 total_errors,
  output logic                        disp_overflow
);
  initial begin
    if (DATA_W   < 2) $fatal(1, "pattern_displacement_counter: DATA_W must be >= 2");
    if (DISP_MAX < 2) $fatal(1, "pattern_displacement_counter: DISP_MAX must be >= 2");
    if (LEVELS   < 2) $fatal(1, "pattern_displacement_counter: LEVELS must be >= 2");
    if (TRANS_HI < 1 || TRANS_HI > DATA_W)
      $fatal(1, "pattern_displacement_counter: TRANS_HI must be in 1..DATA_W");
  end

  logic [DATA_W-1:0] prev_data;
  logic              have_prev;
  // Beats since the most recent aggressor. Saturating: a wrapped value
  // would place a displacement in the wrong bin, which inverts the
  // histogram's shape -- the one thing it exists to show.
  logic [$clog2(DISP_MAX+1)-1:0] since_aggr;
  logic                          aggr_seen;

  // Bucket a transition count into one of LEVELS buckets.
  function automatic int level_of(int t);
    int L = (t * LEVELS) / (DATA_W + 1);
    return (L >= LEVELS) ? LEVELS - 1 : L;
  endfunction

  always_comb begin
    transitions = have_prev ? $countones(beat_data ^ prev_data)
                            : {$clog2(DATA_W+1){1'b0}};
    aggressor   = beat_valid && have_prev && (transitions >= TRANS_HI);
    victim      = err_valid;
  end

  always_ff @(posedge clk) begin
    if (!rst_n || clear) begin
      prev_data     <= '0;
      have_prev     <= 1'b0;
      since_aggr    <= '0;
      aggr_seen     <= 1'b0;
      total_beats   <= '0;
      total_errors  <= '0;
      disp_overflow <= 1'b0;
      for (int i = 0; i < LEVELS;   i++) begin
        trans_hist[i]      <= '0;
        beats_at_level[i]  <= '0;
        errors_at_level[i] <= '0;
      end
      for (int i = 0; i < DISP_MAX; i++) disp_hist[i] <= '0;
    end else begin
      if (beat_valid) begin
        // have_prev gates the transition count: the FIRST beat has no
        // predecessor, and counting against a reset value of zero
        // would report a spurious aggressor whenever the first beat
        // happened to be dense.
        if (have_prev) begin
          automatic int L = level_of(int'(transitions));
          if (trans_hist[L]     != 16'hFFFF)      trans_hist[L]     <= trans_hist[L] + 1'b1;
          if (beats_at_level[L] != 32'hFFFF_FFFF) beats_at_level[L] <= beats_at_level[L] + 1'b1;
        end
        prev_data <= beat_data;
        have_prev <= 1'b1;
        if (total_beats != 32'hFFFF_FFFF) total_beats <= total_beats + 1'b1;

        // Displacement bookkeeping. An aggressor restarts the count;
        // otherwise it ages, saturating at DISP_MAX.
        if (aggressor) begin
          since_aggr <= '0;
          aggr_seen  <= 1'b1;
        end else if (aggr_seen && since_aggr != DISP_MAX[$clog2(DISP_MAX+1)-1:0]) begin
          since_aggr <= since_aggr + 1'b1;
        end
      end

      if (err_valid) begin
        automatic int L = level_of(int'(transitions));
        if (errors_at_level[L] != 32'hFFFF_FFFF)
          errors_at_level[L] <= errors_at_level[L] + 1'b1;
        if (total_errors != 32'hFFFF_FFFF) total_errors <= total_errors + 1'b1;

        // §5: bin the displacement -- but only if an aggressor has
        // been seen. Without one there is no displacement to measure,
        // and binning at zero would manufacture a peak at zero, which
        // §5's table reads as "coincides with its own transition".
        if (aggr_seen) begin
          if (since_aggr < DISP_MAX[$clog2(DISP_MAX+1)-1:0]) begin
            if (disp_hist[since_aggr] != 16'hFFFF)
              disp_hist[since_aggr] <= disp_hist[since_aggr] + 1'b1;
          end else begin
            // Beyond the window: recorded as an overflow rather than
            // folded into the last bin, which would create a false peak.
            disp_overflow <= 1'b1;
          end
        end
      end
    end
  end
endmodule

aggr_seen gates the displacement binning, and omitting it would manufacture the chapter's most misleading result. Without it, every error before the first aggressor bins at displacement zero — and §5's table reads a peak at zero as the corruption coincides with its own transition, which is the signature that argues against a late-arriving mechanism. The gate would then reach the opposite conclusion from the truth.

Displacements beyond the window set disp_overflow rather than folding into the last bin. Folding creates a peak at DISP_MAX − 1 that is an artefact of the window size, and a peak is exactly what §5 interprets.

And errors_at_level alongside beats_at_level is what makes §4's profile per-access. Errors per level divided by beats per level is a rate; errors per level alone measures the pattern generator's distribution, which is the mistake §4 warns about.

10. What the Physical Domain Requires

The gate says justified. What happens next is worth stating, because it is the part RTL cannot do and therefore the part this module must hand off honestly.

What the digital investigation delivers to that domain:

DeliverableWhy it matters there
A minimal reproducer28.5 §15measurement time is expensive; a narrow reproducer makes it feasible
The error rate per access, with the duration it was measured overso a change can be shown to have done something — 28.5 §3
The lane, beat and address structureit says where to probe
The pattern profileit says what to drive while probing
The displacement peak and whether it scaled with frequencyit says what character of disturbance to look for
The seven exclusions with their methodsso the physical work is not repeating digital work

That list is the chapter's real product. Not a verdict — a well-characterised digital experiment plus a named unanswered physical question.

And what the physical domain requires that no register provides: instrumentation that measures voltage against time on the actual channel, a model of the channel, and the ability to compare a measurement against a specification. None of those is a simulation of a reflection, and this chapter builds none of them for that reason.

11. What the Assertions Prove

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bound to §9's counter. Every property carries `disable iff`, and
// every antecedent is covered below -- 27.2 measured this curriculum
// at 78.53% implications, so a silent pass is otherwise
// indistinguishable from an unbound block.
//
// NOTE ON SCOPE: every property here constrains COUNTING. None of them
// is an electrical statement, and none could be.
module pattern_displacement_sva #(
  parameter int DATA_W = 64, parameter int DISP_MAX = 8,
  parameter int LEVELS = 8,  parameter int TRANS_HI = 24
)(
  input logic clk, rst_n, clear,
  input logic beat_valid, err_valid, aggressor, victim, disp_overflow,
  input logic [$clog2(DATA_W+1)-1:0] transitions,
  input logic [31:0] total_beats, total_errors,
  input logic [15:0] disp_hist [DISP_MAX],
  input logic [31:0] beats_at_level [LEVELS], errors_at_level [LEVELS]
);
  // ---- P1. FORBIDDEN. An aggressor is never flagged below the
  // threshold. §9: the threshold defines the measurement.
  property p_aggressor_threshold;
    @(posedge clk) disable iff (!rst_n)
      aggressor |-> (transitions >= TRANS_HI);
  endproperty
  assert property (p_aggressor_threshold)
    else $error("counter: aggressor flagged with %0d transitions", transitions);

  // ---- P2. FORBIDDEN. No aggressor on the very first beat. §9: the
  // first beat has no predecessor, and counting against a reset value
  // would report a spurious aggressor on a dense first beat.
  property p_no_aggressor_without_predecessor;
    @(posedge clk) disable iff (!rst_n)
      (beat_valid && total_beats == 32'd0) |-> !aggressor;
  endproperty
  assert property (p_no_aggressor_without_predecessor)
    else $error("counter: aggressor on the first beat");

  // ---- P3. victim tracks the error strobe exactly. The displacement
  // measurement is between these two events and nothing else.
  property p_victim_is_error;
    @(posedge clk) disable iff (!rst_n)
      victim == err_valid;
  endproperty
  assert property (p_victim_is_error)
    else $error("counter: victim does not track err_valid");

  // ---- P4. INVARIANT. total_beats advances only on a valid beat.
  property p_beats_only_on_valid;
    @(posedge clk) disable iff (!rst_n)
      (!beat_valid) |=> (total_beats == $past(total_beats));
  endproperty
  assert property (p_beats_only_on_valid)
    else $error("counter: total_beats advanced with no beat");

  // ---- P5. INVARIANT. total_errors advances only on an error.
  property p_errors_only_on_error;
    @(posedge clk) disable iff (!rst_n)
      (!err_valid) |=> (total_errors == $past(total_errors));
  endproperty
  assert property (p_errors_only_on_error)
    else $error("counter: total_errors advanced with no error");

  // ---- P6. FORBIDDEN. Errors at a level never exceed beats at that
  // level. §9: errors per beat is the rate, and a rate above one means
  // the two counters are driven from different events.
  property p_rate_is_a_rate;
    @(posedge clk) disable iff (!rst_n)
      (errors_at_level[0] <= beats_at_level[0]);
  endproperty
  assert property (p_rate_is_a_rate)
    else $error("counter: more errors than beats at level 0");

  // ---- P7. INVARIANT. The displacement histogram is monotone
  // non-decreasing per bin -- bins only ever fill.
  property p_disp_hist_monotone;
    @(posedge clk) disable iff (!rst_n)
      (!clear) |=> (disp_hist[0] >= $past(disp_hist[0]));
  endproperty
  assert property (p_disp_hist_monotone)
    else $error("counter: a displacement bin decreased");

  // ---- P8. FORBIDDEN. An out-of-window displacement sets the
  // overflow flag rather than folding into the last bin. §9: folding
  // creates a peak that is an artefact of the window size.
  property p_overflow_is_sticky;
    @(posedge clk) disable iff (!rst_n)
      (disp_overflow && !clear) |=> disp_overflow;
  endproperty
  assert property (p_overflow_is_sticky)
    else $error("counter: disp_overflow cleared without a clear");

  // ---- P9. FORBIDDEN. The transition count never exceeds the bus
  // width. A count above DATA_W means the XOR or the popcount is wrong.
  property p_transitions_bounded;
    @(posedge clk) disable iff (!rst_n)
      (transitions <= DATA_W);
  endproperty
  assert property (p_transitions_bounded)
    else $error("counter: %0d transitions on a %0d-bit bus", transitions, DATA_W);

  // ---- P10. INVARIANT. Level counters sum to no more than the total.
  property p_levels_bounded_by_total;
    @(posedge clk) disable iff (!rst_n)
      (beats_at_level[0] <= total_beats);
  endproperty
  assert property (p_levels_bounded_by_total)
    else $error("counter: level-0 beats exceed total beats");

  // ---- P11. Clear releases everything, including the overflow flag.
  property p_clear_releases;
    @(posedge clk) disable iff (!rst_n)
      clear |=> (total_beats == 32'd0 && total_errors == 32'd0 && !disp_overflow);
  endproperty
  assert property (p_clear_releases)
    else $error("counter: clear did not release the accumulators");

  // ---- P12. FORBIDDEN. An aggressor and a zero transition count
  // never coincide. This is P1's degenerate case and it is the one a
  // reset-value bug produces.
  property p_no_aggressor_at_zero;
    @(posedge clk) disable iff (!rst_n)
      (transitions == 0) |-> !aggressor;
  endproperty
  assert property (p_no_aggressor_at_zero)
    else $error("counter: aggressor flagged at zero transitions");

  // ---- 27.2 §7: publish every antecedent.
  cover property (@(posedge clk) disable iff (!rst_n) beat_valid);
  cover property (@(posedge clk) disable iff (!rst_n) err_valid);
  cover property (@(posedge clk) disable iff (!rst_n) aggressor);
  cover property (@(posedge clk) disable iff (!rst_n) victim);
  cover property (@(posedge clk) disable iff (!rst_n) aggressor && victim);
  cover property (@(posedge clk) disable iff (!rst_n) clear);
  cover property (@(posedge clk) disable iff (!rst_n) disp_overflow);
  cover property (@(posedge clk) disable iff (!rst_n) transitions == 0);
  cover property (@(posedge clk) disable iff (!rst_n) transitions >= TRANS_HI);
  cover property (@(posedge clk) disable iff (!rst_n) transitions == DATA_W);
  cover property (@(posedge clk) disable iff (!rst_n) disp_hist[0] != 16'd0);
  cover property (@(posedge clk) disable iff (!rst_n) disp_hist[2] != 16'd0);
  cover property (@(posedge clk) disable iff (!rst_n) errors_at_level[0] != 32'd0);
  cover property (@(posedge clk) disable iff (!rst_n) total_errors > 32'd1000);
endmodule

12. DV — Testing the Counters

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// SIMULATION-ONLY. Independent reference. It stores the beat stream in
// a QUEUE and computes transitions and displacements by RESCANNING,
// rather than accumulating incrementally as §9 does. A different
// algorithm, so agreement is evidence -- 27.4 §15's argument.
//
// WHAT IT DOES NOT MODEL: anything electrical. Like §9, it counts bit
// changes and beat-index differences and nothing else.
class pattern_reference #(parameter int DATA_W = 64, parameter int TRANS_HI = 24);
  typedef struct { longint data; bit err; } beat_t;
  beat_t log[$];

  function void beat(longint d, bit e);
    beat_t b; b.data = d; b.err = e;
    log.push_back(b);
  endfunction

  function int transitions_at(int i);
    if (i <= 0 || i >= log.size()) return -1;      // no predecessor
    return $countones(log[i].data ^ log[i-1].data);
  endfunction

  function bit is_aggressor(int i);
    int t = transitions_at(i);
    return (t >= 0) && (t >= TRANS_HI);
  endfunction

  // §5: the displacement is measured backwards from an error to the
  // most recent aggressor. Returns -1 when no aggressor precedes it,
  // which §9's aggr_seen gate exists to reproduce -- and which a
  // naive implementation reports as 0, manufacturing a peak at zero.
  function int displacement_of(int i);
    if (i < 0 || i >= log.size() || !log[i].err) return -1;
    for (int k = i; k >= 0; k--) if (is_aggressor(k)) return i - k;
    return -1;
  endfunction

  function int errors_with_no_aggressor();
    int n = 0;
    foreach (log[i]) if (log[i].err && displacement_of(i) < 0) n++;
    return n;
  endfunction

  function int disp_count(int d);
    int n = 0;
    foreach (log[i]) if (log[i].err && displacement_of(i) == d) n++;
    return n;
  endfunction

  // §4: the per-access rate at a transition level. Returns -1.0 when
  // no beats landed at that level, because zero errors over zero
  // beats is not a rate.
  function real rate_at_level(int lo, int hi);
    int beats = 0, errs = 0;
    for (int i = 1; i < log.size(); i++) begin
      int tr = transitions_at(i);
      if (tr >= lo && tr <= hi) begin
        beats++;
        if (log[i].err) errs++;
      end
    end
    if (beats == 0) return -1.0;
    return real'(errs) / real'(beats);
  endfunction

  // §8: monotonicity as a fact. Needs three levels to have a shape.
  function bit profile_monotone(real r[$]);
    if (r.size() < 3) return 1'b0;
    for (int i = 1; i < r.size(); i++) if (r[i] < r[i-1]) return 1'b0;
    return 1'b1;
  endfunction
endclass
CheckWhat it establishes
Replay §6's burst through both; compare every fieldIncremental counter and rescanning reference agree
40,000 random beat streams through bothTwo algorithms agree on transitions, aggressors and displacements
First beat after resetReference returns −1 transitions; counter reports no aggressor — P2
All-zero beat streamZero transitions everywhere; no aggressor — P12
Beat stream alternating all-zeros and all-onesTransitions equal DATA_W; aggressor every beat
Errors before any aggressorReference errors_with_no_aggressor() > 0; counter bins none
Remove aggr_seen from §9 and rerun that caseCounter bins them all at 0 — the manufactured peak
Error at displacement 2, repeateddisp_hist[2] and disp_count(2) agree
Error at displacement DISP_MAXdisp_overflow set; no bin incremented — P8
Level with zero beatsrate_at_level() returns −1.0, not 0.0
Two transition levels measuredprofile_monotone() false; gate's monotone_run() returns −1
Record six of seven exclusionsescalation_justified() false; recommendation() names the seventh
Record an exclusion with an empty methodRefused, count unchanged
Lane remap followed the logical laneescalation_justified() false and disqualifying
Call physical_verdict()Returns a refusal, never a verdict
Run with the data lanes disconnectedAll 12 properties pass; all 14 covers empty

Two reports are worth publishing, and the second is the specific way this chapter's work goes wrong:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  TWO PASSING SI INVESTIGATIONS

  (A) the counter was never connected
        all 12 properties            PASS
        total_beats                  0
        total_errors                 0
        aggressor                    never asserted
        disp_hist[*]                 all zero
        ------------------------------------------------
        cover beat_valid             0 hits
        ... all 14 covers            0 hits

        seven of the twelve properties are implications and never
        armed. The five INVARIANTS -- transition bound, level bounds,
        rate bound, histogram monotonicity, aggressor-at-zero -- pass
        on a block at reset.

        a report reading "no pattern dependence observed" is produced
        by this run AND by a genuinely pattern-independent failure.
        total_beats is the field that separates them.

  (B) a confident escalation that was digital all along
        stimulus : 2,900 errors; a displacement histogram peaked
                   sharply at 2; monotone pattern profile over 6
                   transition levels; errors normalised per access
        disp_hist[2]                 2,731
        disp_hist[others]            169 combined
        profile monotone             TRUE, 6 levels
        exclusions recorded          7 of 7
        ------------------------------------------------
        escalation_justified()       FALSE
        recommendation()             "not yet: an equaliser with wrong
                                     taps produces the same
                                     displacement signature (22.4) --
                                     read its configuration"

        every clause-one exclusion was recorded and the structure is
        textbook: displaced, pattern-dependent, repeatable. A team
        reading only the histogram escalates here, and books a
        measurement session.

        the gate refuses, because equaliser_config_checked is false.
        22.4 owns equalisation as the predict-and-subtract family, and
        an equaliser whose taps are wrong ADDS a displaced
        disturbance -- producing this exact signature from a register
        value.

    diagnosis : (A) is the vacuity case, and its trap is that an
      empty histogram reads as a negative RESULT rather than an
      absent measurement. (B) is §5's callout doing its job: the
      structure was real, the mechanism was digital, and the gate's
      refusal saved the measurement session.

    the fix : (A) read total_beats before any histogram. (B) nothing
      -- the gate already did it. Which is the argument for encoding
      §1's criterion as a data structure rather than as advice.

Report (B) is the strongest case in this chapter for building the gate at all. The structure was genuine, repeatable and textbook, and the correct action was still to read a register — which is exactly the decision a team under pressure does not make when the histogram is in front of them.

13. Corner Cases

CaseBehaviourWhy
DATA_W, DISP_MAX or LEVELS below 2Elaboration failsa histogram or count needs at least two values
TRANS_HI above DATA_WElaboration failsthe threshold would be unreachable
First beat after resetNo aggressorP2 — no predecessor to compare against
Transition count zeroNo aggressorP12 — the reset-value bug's signature
Error before any aggressorNot binned§9 — binning would manufacture a peak at zero
Displacement beyond the windowdisp_overflow set, not folded§9 — folding creates an artefact peak
Errors per level exceed beats per levelP6 firesthe counters are driven from different events
Two transition levels measuredmonotone_run() returns −1§8 — two points have no shape
Six of seven exclusions recordedescalation_justified() false§1 — both clauses required
All seven recorded, no surviving structureFalse§1 clause two
Remap showed the failure followed the logical laneFalse, and disqualifying§8 — positive evidence against physical
Exclusion recorded with no methodRefused§8 — an experiment nobody can describe was not run
physical_verdict() calledReturns a refusal§10 — nothing digital measures a channel
CRC errors non-zero, digital causes checkedStructure counts as unexplained§3 — hardware-reported in-flight corruption
Error rate not normalised per accessrecommendation() says not yet§2, §4 — un-normalised rates are uninterpretable

Rows eleven and twelve are the two that stop an escalation for good reasons. One is evidence against the hypothesis; the other is an investigation that did not happen.

14. Misconceptions

“It fails at high frequency, so it is signal integrity.” §2. Five digital explanations come first, all cheaper, and one of them is that fewer accesses happen per second at lower frequency.

“One lane fails, so that lane's channel is bad.” §2. Four of the six things in a lane's path are digital, and the remap experiment settles it without a scope.

“Changing ODT changes the failure, so it is termination.” §2. Two of three hypotheses are digital — the switch timing and which ranks were told to terminate — and both are register reads.

“Random data fails and walking-ones passes, so it is pattern-dependent.” §4. Those two patterns differ in several ways at once. Vary transition count and measure a profile.

“A pattern-dependent failure is a channel problem.” §4. Monotone in transition count is consistent with one; a spike at one transition level is a value effect, which is logic.

“The displacement histogram measures the reflection.” §5's callout. It is a distribution over beat indices. It gives no amplitude, no time, and does not identify a mechanism.

“A displaced error proves a reflection.” §5. An equaliser with wrong taps produces the same digital signature, and that is a register you can read.

“A pass bitmap shows the eye is closing.” 28.1 §1, and 22.3 owns the underlying statement that a pass/fail grid is not an eye diagram.

“The assertions prove the channel is fine.” §11's callout. Every property constrains a counter. The design has no voltage for a property to constrain.

“We excluded the digital causes, so it is physical.” §1. Exclusion is one clause of two. Without surviving structure that the digital causes fail to explain, there is no positive reason to escalate.

“We can simulate the channel in RTL to check.” The opening callout. Such a model would be a fabrication wearing the clothes of evidence, and this chapter deliberately contains none.

15. Interview Reasoning

When is a signal-integrity hypothesis justified? When every cheaper digital cause has been excluded by experiment and the surviving evidence has a structure those causes do not explain. Either clause alone is insufficient.

A failure goes away at lower frequency. What do you conclude? That something scales with the period. Five digital explanations come before the channel, and one is simply that fewer accesses occur per second — so re-measure per access first.

One byte lane fails. What is the decisive experiment? Remap the lane. If the failure follows the logical lane the cause is in logic the remap moved; if it stays with the physical pin, the physical path is implicated. No measurement needed.

Changing ODT settings changes the failure. Is that signal integrity? Not yet. The switch timing and the rank selection are both digital and both register reads, and either can make termination absent when the data arrives.

How do you measure pattern dependence properly? Vary the transition count across several levels and measure errors per access at each. A monotone rise is consistent with a pattern-dependent mechanism; a spike at one level is a value-specific bug.

What is the aggressor/victim displacement and why does it matter? The gap in beats between a high-transition beat and a corrupted one. A consistent non-zero peak is consistent with a late-arriving disturbance, which is what a reflection predicts.

What makes that evidence stronger? If the displacement grows with frequency in proportion, it behaves like a fixed time rather than a fixed number of cycles — and no digital mechanism has that property.

Does that measure the reflection? No. It gives no amplitude, no time and no mechanism, and an equaliser with wrong taps produces the same signature.

What do you hand to the physical investigation? A minimal reproducer, the error rate per access with its measurement duration, the lane, beat and address structure, the pattern profile, the displacement peak and its frequency behaviour, and the seven exclusions with the method used for each.

Why not model the channel in RTL to test the hypothesis? Because the model would not be evidence. RTL has no voltage and no time; a simulated reflection would only demonstrate the assumptions used to write it.

16. Exercises

  1. §1 requires both clauses. Construct the case where all seven exclusions are recorded, real channel degradation is present, and the gate correctly says not yet — then say what is missing.

  2. §2 gives five digital explanations for frequency sensitivity. Design the smallest set of runs that excludes all five, and state the total cost relative to one measurement session.

  3. §4 contrasts a monotone profile with a spike. Construct the digital bug that produces a monotone profile, and say what additional observation would distinguish it.

  4. §5 row four argues that a frequency-scaling displacement behaves like a fixed time. Derive the displacement in beats for a fixed delay at two frequencies, and state the assumption your derivation makes.

  5. §8's gate refuses an exclusion without a method. Write the three weakest "methods" you have seen accepted in practice, and say what each fails to establish.

  6. §9 gates displacement binning on aggr_seen. Remove that gate and derive the resulting histogram for a run whose first hundred errors precede any aggressor, then say which of §5's rows the gate would report.

  7. §11 argues no property here can be electrical. Construct the strongest electrical-sounding property you can over this design's signals, and identify precisely what it actually constrains.

  8. A colleague proposes adding an RTL channel model with a configurable reflection coefficient so the team can "reproduce the SI failure in simulation". Write the objection, and describe what such a model would legitimately be useful for.

17. Where This Goes

Signal integrity is the hypothesis this module defers longest and escalates to most carelessly. The criterion has two clauses — every cheaper digital cause excluded by experiment, and a surviving structure those causes do not explain — and the three experiments most often cited as proof each have digital explanations that are cheaper to test. What genuinely bears on the channel is digital too: a monotone pattern profile in transition count, a displacement between aggressor and victim that scales with frequency, and hardware's own CRC and alert reports.

Four results carry forward. The lane remap is decisive and digital — if the failure follows the logical lane, no physical hypothesis is warranted. Monotone in transition count, measured per access, is what separates a pattern-dependent mechanism from a value-specific bug. A displacement that scales with frequency behaves like a fixed time, which is the strongest digital evidence available here and still not a measurement. And the product of a digital investigation is a characterised experiment plus a named unanswered question, not a verdict.

Two things stay open, and neither is a gap. No property in this chapter is electrical, because the design has no electrical signal for a property to constrain — §11 states that as structural. And the gate is not assertable: its inputs are facts about which experiments a human actually ran, which no register can establish.

Chapter 28.7 closes the module by asking what would have prevented most of it. Every chapter here began with a system already running and a failure already present, and the investigations were expensive largely because many variables had changed at once before anyone looked. Bring-up is the discipline that stops that: stage the system so that each layer is established and believed before the next depends on it, change one controlled variable at a time, and capture evidence before recovering — so that when a failure does appear, the list of things that could have caused it is short by construction rather than by investigation.

Continue learning

Standards & specifications

Governing standard
JEDEC JESD79 (DDR SDRAM)(opens JEDEC Solid State Technology Association in a new tab)

Defines the DDR SDRAM device itself — signals, command encoding, mode registers, timing parameters and the initialisation sequence — one document per generation. Memory-controller microarchitecture, address-mapping policy, PHY training algorithms and board-level design are not specified by it.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the DDR curriculum.