Skip to content
VLSI Mentor

Ethernet · Module 21

Link Failures

A down link has no frames, so every instrument in Module 21 is unavailable at once; the replacement space has fourteen sites and MDIO separates nine classes of them.

Every instrument Module 21 has built is a statistic over frames. A link that will not come up produces none of them, so all of it is unavailable at once.

InstrumentFromAvailable on a link that will not come up?
twelve fault sitesChapter 21.1 §1no — all twelve are receive-path stages frames pass through
the conservation identityChapter 21.1 §7no — frames_in is zero
thirteen error classesChapter 21.2 §12no — every one is a predicate on a frame
the length slopeChapter 21.3 §4no — it is a ratio over size buckets
the residue combChapter 21.3 §8no
the clustering testChapter 21.3 §9no

Six for six. And it is worse than a table of unavailable tools: 332 of the 557 properties Modules 19, 20 and 21 have published — 59.6% — have an antecedent that requires a frame, so on exactly the fault this chapter is about three of every five checks go quiet rather than failing.

What replaces them is a different fault space with a different shape.

Count
sites a link that will not come up can be broken at14
observables, all of them registers or actions12
classes MDIO alone separates them into9
sites in the largest of those classes5
classes with a cooperating partner as well11
sites no observation in the space ever separates3

And the structural contrast with Chapter 21.1 is exact and opposite. There, twelve sites were separable and the search was inefficient — seven observations against a floor of four. Here the search is optimal — four observations, which is the floor — and the space is not separable. Different problem, different fix: Chapter 21.1 wanted better questions; this chapter wants a second observer.


1. Scope, and a Fault Space With No Frames In It

Scope: a link that never reaches a usable state. The sites it can be broken at, the registers that observe them, and what is left unseparated when every register has been read.

Not in scope: a link that comes up and then misbehaves. Chapter 21.1, Chapter 21.2 and Chapter 21.3 own that entirely, and the boundary between the two chapters is sharp: frames exist, or they do not. Nor negotiation's outcomeChapter 21.5 takes a link that comes up at the wrong speed or duplex, which is a different failure from one that does not come up at all.

Start from why the previous three chapters stop.

Chapter 21.1 §1's twelve sites are the receive path — the channel, the PHY's lane alignment, the xMII, preamble detection, the parser, the check engine, the validity classifier, the filter, VLAN membership, the FIFO, the DMA, the driver. Every one of them is a stage a frame passes through, and its fault is detected by observing what happened to frames that passed.

A link that will not come up has passed nothing. So:

Reads
frames_in0
frames_out0
every RMON error counter0
Chapter 21.1 §3's candidate maskall twelve bits still set, and none of them right

Row four is the specific failure and it is worth stating plainly. Chapter 21.1's method intersects a mask with the sites each observation is consistent with. With every counter at zero, every observation is EV_ZERO — and a zero eliminates the sites its counter moves for, so the mask converges quickly and confidently on the sites that no counter watches. Which is class G: the filter, VLAN, the FIFO, the DMA and the driver, none of which is the fault, and all of which are downstream of a link that never came up.

Chapter 21.1's method does not fail to diagnose a down link. It diagnoses one, wrongly, with five candidates and full confidence — because every one of its observations reads as evidence.

That is the strongest argument for treating this as a separate chapter rather than an extension. A method whose failure mode on an out-of-scope input is a confident wrong answer needs an explicit guard, and Section 16's monitor is that guard: frames_in at zero is not an observation, it is a different problem.

Three things this chapter is and is not:

Choice
the space is three-partylocal, medium, remote — and that is the whole difficulty
the instruments are registers and actionsnot statistics — there is no population to be statistical about
it stops at the partner's boundarywhat the partner will tell us is a protocol question, not ours

Row one is the structural difference from every previous chapter in the module. Chapter 21.1's twelve sites are all ours; a frame that reaches our parser was already ours to account for. Here a failing receive gate implicates three parties at once — our receiver, the medium, and their transmitter — and MDIO reads exactly one of the three.


2. The Ladder as a Fault Space

A link that will not come up can be broken at fourteen sites, and they divide by party. Eight are local: our transmit driver or optic, our receive front end, our clock recovery, our block lock, our lane deskew, our forward error correction codeword lock, our auto negotiation state machine, and our elastic buffer. Three belong to the medium: attenuation or a break, an inverted polarity or swapped lanes, and a wrong optic or cable category. Three belong to the far end: their transmit driver, their configuration when it is forced rather than negotiated, and their port being administratively switched off. Every register the management interface can read describes our own receive direction, so a failing gate on that ladder is consistent with our receiver, with the medium and with their transmitter simultaneously. The previous chapter's twelve fault sites were all ours, because a frame that reached our parser was already ours to account for. Here six of the fourteen are not ours at all, and nothing in our chip reads any of them. That is the structural change that makes this a separate chapter: the question stops being which of our blocks failed and becomes whose problem this is, and the answer decides whether the next step is a register read, a screwdriver or a telephone call.Our transmittersite 1 — unobservablehereOur receive chainsites 2 to 6Our AN and buffersites 7 and 8The mediumsites 9, 10, 11What MDIO readsour receive directiononlyThe far endsites 12, 13, 14Three parties pergatea rung is not a site8 of 14 are ours6 need somebody else12
Figure 1 — fourteen sites, three parties, and only eight of them behind a register we own.

Chapter 3.8 §2 built the bring-up ladder as a sequence of gates. This section reads it backwards: as a partition of the ways a link can fail.

The six gates, and what each one's failure means:

GateChapter 3.8 §2's dependencyIf it never passes
signal detectphysicalnothing is arriving at all
clock lockneeds signalsomething arrives and has no recoverable timing
block lockneeds clockbits arrive and do not parse as blocks
marker lockneeds block lockblocks parse and no marker is recognised
lane deskewneeds marker lock on every lanemarkers found and the lanes will not align
codeword lockneeds deskewlanes aligned and the FEC structure will not lock

Plus two gates that are not on the receive ladder and fail differently:

GateOwnerIf it never passes
auto-negotiation completeboth ends, jointlyChapter 11.1's exchange never resolves
the link stays upChapter 4.4it comes up and drops — a different symptom entirely

Now the fourteen sites, arranged by party, because the party is what decides who can observe them.

#SiteParty
1our transmit driver or opticlocal — and unobservable locally
2our receive front endlocal
3our clock recovery — Chapter 3.4 §10's PMAlocal
4our block lock — Chapter 3.4 §11's alignerlocal
5our lane deskew — Chapter 3.8 §7local
6our FEC codeword lock — Chapter 3.7local
7our auto-negotiation state machine — Chapter 3.8 §8local
8our elastic buffer — Chapter 4.4 §9local
9the medium: attenuation, a break, a bendmedium
10the medium: polarity inverted or lanes swappedmedium
11the medium: the wrong optic or cable categorymedium
12their transmit driver or opticremote
13their configuration — forced where we auto-negotiateremote
14their port administratively downremote

Eight local, three medium, three remote — and the count is the point. Chapter 21.1's twelve sites were twelve of ours. Six of these fourteen are not ours at all, and nothing in our chip can read them.

Two of the fourteen deserve a note because they are the ones people leave out.

Site 1 — our own transmitter — is invisible from here. Whatever our driver is doing, we do not receive it. Every register in our PHY describes the receive direction; our transmit direction is observable only at the far end. A dead local transmitter therefore produces a perfect local status vector, which is the single most misleading reading in the chapter and is Section 8's subject.

Site 8 — the elastic buffer — is not a bring-up fault at all. Chapter 4.4 §9 separates overrun from underrun and both happen after the link is up: the ladder completes, traffic flows, and the buffer drifts to a limit. The symptom is a link that comes up and drops, repeatedly, and it is in this chapter's space because that is what the ticket says — not because the ladder failed.

The ticket saysWhich space is it in?
"the link is down"the ladder never completedthis chapter
"the link keeps bouncing"it completes and then does not holdthis chapter, site 8
"the link is up and lossy"frames existChapter 21.1

Row two is the reason Section 13 exists, and distinguishing it from row one costs one timer.


3. RTL 1 — The Bring-Up Package and the Gate Vector

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// linkdiag_pkg -- fourteen sites, twelve observables, and the one
// structural fact that shapes everything: the receive ladder is a
// MONOTONE CHAIN, so five registers have six readings and not
// thirty-two.
//
// Chapter 3.4 Section 13 built the ordered status vector and said the
// lowest deasserted bit names the sublayer. This package says what
// that is worth in bits, and it is 2.585.
// ---------------------------------------------------------------------
package linkdiag_pkg;

  // Section 2's fourteen, grouped by PARTY because the party decides
  // who is able to observe the site at all.
  typedef enum logic [3:0] {
    S_L_TX       = 4'd0,   // our transmitter -- unobservable locally
    S_L_RX_FE    = 4'd1,
    S_L_CDR      = 4'd2,
    S_L_BLOCK    = 4'd3,
    S_L_DESKEW   = 4'd4,
    S_L_FEC      = 4'd5,
    S_L_AN       = 4'd6,
    S_L_ELASTIC  = 4'd7,   // comes up and drops -- Section 13
    S_M_ATTEN    = 4'd8,
    S_M_POLARITY = 4'd9,
    S_M_WRONGOPT = 4'd10,
    S_R_TX       = 4'd11,
    S_R_CONFIG   = 4'd12,
    S_R_ADMIN    = 4'd13
  } site_e;

  typedef logic [13:0] site_mask_t;
  localparam site_mask_t ALL_SITES = 14'h3FFF;

  // Party masks. Section 6: what MDIO reads is entirely the LOCAL
  // receive direction, and six of the fourteen sites are not local.
  localparam site_mask_t LOCAL_SITES  = 14'b00_0000_1111_1111;
  localparam site_mask_t MEDIUM_SITES = 14'b00_0111_0000_0000;
  localparam site_mask_t REMOTE_SITES = 14'b11_1000_0000_0000;

  // Chapter 3.8 Section 2's ladder, lowest rung first. The ORDER is
  // the diagnostic and the MONOTONICITY is the cost -- Section 4.
  typedef enum logic [2:0] {
    G_SIGNAL = 3'd0,
    G_CLOCK  = 3'd1,
    G_BLOCK  = 3'd2,
    G_MARKER = 3'd3,
    G_FEC    = 3'd4,
    G_NONE   = 3'd7      // every rung passed
  } gate_e;

  localparam int N_GATES = 5;

  // Section 8: the class MDIO cannot break apart. Five sites, one
  // reading -- "nothing is arriving", which is true of a dead receiver,
  // a broken cable, a wrong optic, a dead far-end transmitter and a
  // port somebody turned off.
  localparam site_mask_t CLASS_DARK = 14'b10_1101_0000_0010;

  // Section 17: the three that survive every observation in the space.
  localparam site_mask_t CLASS_UNSEPARABLE = 14'b10_0101_0000_0000;

  function automatic int popcount14(site_mask_t m);
    int n = 0;
    for (int i = 0; i < 14; i++) if (m[i]) n++;
    return n;
  endfunction

  // Chapter 3.4 Section 13's rule, as a function: the lowest deasserted
  // bit names the rung that owns the problem.
  function automatic gate_e lowest_failed(logic [N_GATES-1:0] gates);
    for (int i = 0; i < N_GATES; i++) if (!gates[i]) return gate_e'(i);
    return G_NONE;
  endfunction

endpackage

Classification: a package whose central content is a monotone chain and three party masks.

What it teaches: that the party masks are the chapter's real type distinction. Chapter 21.1's twelve sites needed no such thing — they were all ours. Here LOCAL_SITES has eight members and the other six are behind an interface nothing in our chip reads, so a diagnosis that does not track which party a candidate belongs to cannot say whether the next step is a register read or a phone call.

And it teaches that lowest_failed is Chapter 3.4 §13's rule written as code, and that it is a projection. The five ladder bits collapse to one gate number; Section 4 shows that the collapse loses nothing, because the chain has only six reachable states anyway.

Deliberately simplified: CLASS_DARK and CLASS_UNSEPARABLE are literals where they should fall out of Section 6's incidence table by construction — Section 16's monitor recomputes them and compares. The ladder has five rungs where Chapter 3.8 §2 notes a single-lane link has three, so G_MARKER and G_FEC are trivially passed on such a link and the package does not say so. And site_e has no representation of two simultaneous faults, which Section 18's row seven is about.

Production implication: LOCAL_SITES is the mask worth printing at the top of any automated link diagnosis. Eight of fourteen candidates can be investigated by the machine holding the port; six cannot, at any price, without a second party. A tool that reports fourteen candidates undifferentiated has told an operator to investigate things they have no access to — and the split is free, because it is a property of the site rather than of the run.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// gate_vector_reader -- Chapter 3.4 Section 13's status vector, read as
// a diagnosis rather than as a status.
//
// One output matters: the lowest rung that has not passed. Everything
// above it is UNDEFINED rather than failed -- a gate that cannot be
// attempted has not failed, and reporting it as failed is Section 14's
// second prohibition.
// ---------------------------------------------------------------------
module gate_vector_reader
  import linkdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  // Chapter 3.4 Section 13's evidence, from the medium upward.
  input  logic        signal_detect,
  input  logic        clock_locked,
  input  logic        block_locked,
  input  logic        lanes_aligned,
  input  logic        fec_locked,

  input  logic        single_lane,      // Chapter 3.8 Section 2's note

  output logic [N_GATES-1:0] gates,
  output gate_e       failed_gate,
  output logic [2:0]  rungs_passed,
  output logic        ladder_complete,
  output logic        vector_not_monotone
);
  always_comb begin
    gates[G_SIGNAL] = signal_detect;
    gates[G_CLOCK]  = clock_locked;
    gates[G_BLOCK]  = block_locked;
    // Chapter 3.8 Section 2: marker lock and deskew exist only because
    // there are multiple lanes. On a single-lane family they are
    // trivially true rather than absent.
    gates[G_MARKER] = single_lane ? 1'b1 : lanes_aligned;
    gates[G_FEC]    = fec_locked;

    failed_gate = lowest_failed(gates);
    ladder_complete = (failed_gate == G_NONE);

    rungs_passed = 3'd0;
    for (int i = 0; i < N_GATES; i++)
      if (gates[i] && (3'(i) == rungs_passed)) rungs_passed = rungs_passed + 3'd1;

    // A gate asserted above a deasserted one. Section 4: only six of
    // the thirty-two combinations are reachable, so this is a broken
    // PHY or a stale read rather than a link fault.
    vector_not_monotone = 1'b0;
    for (int i = 1; i < N_GATES; i++)
      if (gates[i] && !gates[i-1]) vector_not_monotone = 1'b1;
  end
endmodule

Classification: a priority encoder over a chain, and one consistency check the chain makes possible.

What it teaches: that vector_not_monotone is checkable only because the ladder is a chain, and that it catches a class of fault nothing else does. Chapter 3.8 §2 establishes five dependencies of five different kinds — physical, definitional, structural, measurement, structural — so block_locked asserted while clock_locked is low is not a link condition at all. It is a PHY reporting nonsense, a stale MDIO read, or Chapter 4.5 §7's sample-age problem arriving as a contradiction.

And it teaches that rungs_passed and failed_gate are the same information twice, deliberately. A number is what a monitoring system charts over time; a named gate is what an engineer reads. The chapter uses the number in Section 13's stability test and the name everywhere else.

Deliberately simplified: the five inputs are assumed sampled at one instant, which MDIO cannot do — Chapter 4.5 §7's sample age is milliseconds per register and five registers are five separate transactions. A link flapping faster than the read sequence produces a non-monotone vector from a healthy PHY. rungs_passed's loop is a sequential comb over a combinational variable and will not synthesise as written. And single_lane silences two rungs rather than marking them inapplicable, so a single-lane link and a multi-lane link both report rungs_passed of 5 when complete.

Production implication: the sample-age problem is the one to design around rather than to document. Five MDIO reads at a millisecond each is five milliseconds of skew, and Chapter 3.8 §11 showed bring-up is a distribution — a link can pass three rungs inside that window. The correct instrument is a latched snapshot in the PHY, read as one transaction; where that does not exist, vector_not_monotone is the flag that says the reading cannot be trusted, and it should suppress the diagnosis rather than appear beside it.


4. Five Registers, Six Readings, 2.58 Bits

The bring up ladder has five gates and each one can be attempted only after the one below it has succeeded. Clock lock needs a signal because no clock is transmitted and timing is extracted from transitions in the data. Block lock needs recovered timing because without it there are no bits, only a waveform. Marker lock needs block lock because an alignment marker is a block with recognisable content. Deskew needs marker lock on every lane because skew is measured by comparing when the same marker arrives on different lanes. And codeword lock needs deskew because a forward error correction codeword spans lanes. Five dependencies of five different kinds: physical, definitional, structural, measurement and structural again. The consequence for diagnosis is arithmetic. Five bits would be thirty two readings, but a monotone chain has only the six prefixes: all five low, then one high, then two, three, four and five. Six of thirty two is eighteen point seven five per cent reachable, and the information the five registers carry is the base two logarithm of six, which is two point five eight five bits rather than five. A single link up bit carries one bit, so the ordered vector buys one point five eight five and names a rung. Any other reading is a physical layer reporting nonsense or a sweep taken across a link that moved while it was being read.Signal detectphysicalClock lockneeds signalBlock lockneeds clockMarker lockneeds block lockCodeword lockneeds deskew6 readings of 3218.75% reachable2.585 bitsnot 5.000link_up alone1.000 bitThe ordering buys1.585 bits12
Figure 2 — a monotone chain: six of thirty-two readings occur, and the rest are PHY faults.

The ladder's five gates are five bits, so thirty-two readings. Six of them occur.

Chapter 3.8 §2's five dependencies make the chain monotone: a gate can pass only if every gate below it has passed. So the reachable vectors are exactly the prefixes:

ReadingLowest failed gateSites consistent with it
00000signal detect5 — Section 8's dark class
10000clock lock1 — our CDR
11000block lock2 — our PCS, or polarity/lane swap
11100marker lock and deskew1 — our deskew
11110codeword lock1 — our FEC
11111none — the ladder completed4 — the rest

Six readings of thirty-two: 18.75% of the encoding is reachable, and the other 81.25% would be a PHY fault rather than a link fault.

Value
bits in the vector5
reachable readings6
information the five registers carrylog₂ 6 = 2.585 bits
information five independent bits would carry5.000 bits
the loss2.415 bits — 48.3%

Nearly half the apparent information in the status vector is not there, and the reason is the thing that makes the vector useful: the ordering. Chapter 3.4 §13 argued that the ordered vector turns "the link is down" into "the link is down here", and that is exactly right — it is worth 2.585 bits and a single link_up bit is worth 1.000. The gain is real and it is smaller than five registers suggests.

Which is the structural opposite of Chapter 21.1's problem, and worth putting side by side.

Chapter 21.1this chapter
sites1214
information floor4 observations4 observations
optimal achieved74
whyfour counters are one-site indicatorsthe observations are well balanced
classes reachable12 with full instrumentation9 with MDIO, 12 with everything
the binding constraintefficiencyseparability

Rows three and six are the contrast. Chapter 21.1's search was 75% worse than its floor and eventually reached every site; this chapter's search is at its floor and cannot reach every site at all. More questions do not help here — there are no more questions, only a second observer.

And the ladder has one more property that a diagnosis has to respect.

A gate above the lowest failed one has not failed. It has not been attempted.

Reading 11000
block lockfailed
marker locknot attempted
lane deskewnot attempted
codeword locknot attempted

Reporting four failed gates where one failed and three were never tried is Section 14's second prohibition, and it is the commonest way a bring-up status page misleads: a wall of red that names one fault.


5. RTL 2 — The MDIO Evidence Reader

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// mdio_evidence_map -- the ten readings a local PHY can supply, and the
// mask of sites each one is consistent with.
//
// Chapter 21.2 Section 9 and Chapter 21.3 Section 15 both reached for
// MDIO and both noted it goes unread. This block is what reading it is
// worth: nine classes of fourteen sites, and the largest holds five.
// ---------------------------------------------------------------------
module mdio_evidence_map
  import linkdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic        sample_valid,
  input  logic [15:0] sample_age_us,     // Chapter 4.5 Section 7

  // The ladder, from Section 3.
  input  logic [N_GATES-1:0] gates,
  // Link-level evidence, also in the local PHY.
  input  logic        an_complete,
  input  logic        lp_ability_valid,  // their advertisement, parsed
  input  logic        remote_fault_rx,   // they told us they cannot hear
  input  logic        flp_bursts_seen,   // Chapter 11.1's detector
  input  logic        link_stable_1s,

  output site_mask_t  consistent,
  output logic        consistent_valid,
  output logic [3:0]  readings_used,
  output logic        evidence_stale
);
  // Section 6's table, one mask per reading: the sites at which this
  // reading is ABNORMAL. A reading that is normal intersects with the
  // complement, which is the half people forget -- Chapter 21.1 §10.
  localparam site_mask_t M_SIGNAL = 14'b10_1101_0000_0010;
  localparam site_mask_t M_CLOCK  = 14'b10_1101_0000_0110;
  localparam site_mask_t M_BLOCK  = 14'b10_1111_0000_1110;
  localparam site_mask_t M_MARKER = 14'b10_1111_0001_1110;
  localparam site_mask_t M_FEC    = 14'b10_1111_0011_1110;
  localparam site_mask_t M_AN     = 14'b11_1111_0111_1111;
  localparam site_mask_t M_LP     = 14'b11_1111_0111_1110;
  localparam site_mask_t M_RF     = 14'b00_0000_0000_0001;
  localparam site_mask_t M_FLP    = 14'b11_1101_0000_0010;
  localparam site_mask_t M_STABLE = 14'h3FFF;

  function automatic site_mask_t apply(site_mask_t cur, logic reading_ok,
                                       site_mask_t abnormal_at);
    return reading_ok ? (cur & ~abnormal_at) : (cur & abnormal_at);
  endfunction

  always_comb begin
    consistent = ALL_SITES;
    consistent = apply(consistent, gates[G_SIGNAL],  M_SIGNAL);
    consistent = apply(consistent, gates[G_CLOCK],   M_CLOCK);
    consistent = apply(consistent, gates[G_BLOCK],   M_BLOCK);
    consistent = apply(consistent, gates[G_MARKER],  M_MARKER);
    consistent = apply(consistent, gates[G_FEC],     M_FEC);
    consistent = apply(consistent, an_complete,      M_AN);
    consistent = apply(consistent, lp_ability_valid, M_LP);
    consistent = apply(consistent, !remote_fault_rx, M_RF);
    consistent = apply(consistent, flp_bursts_seen,  M_FLP);
    // link_stable_1s is abnormal at EVERY site -- it is the trigger,
    // not a measurement. Section 6 computes what it is worth: nothing.
    consistent = apply(consistent, link_stable_1s,   M_STABLE);

    readings_used = 4'd10;
    // Chapter 4.5 Section 7: a reading older than the flap it is meant
    // to describe is not evidence.
    evidence_stale = (sample_age_us > 16'd1000);
    consistent_valid = sample_valid && !evidence_stale;
  end
endmodule

Classification: a ten-way intersection, and the only block in the chapter that touches the management bus.

What it teaches: that the ten masks are nested for five of their members and independent for the rest. M_CLOCK contains M_SIGNAL, M_BLOCK contains M_CLOCK, and so on — which is Section 4's monotonicity expressed as set containment, and it is why five of the ten readings carry 2.585 bits between them rather than five. M_AN, M_LP, M_RF and M_FLP are not nested in the chain, and that is exactly why they are worth having.

And it teaches that M_RF has one member. A remote fault indication is the only reading in the entire local instrument set that is abnormal at exactly one site — our own transmitter — because it is the only reading that is not ours: the partner computed it and sent it to us. It is the smallest mask in the table and the most valuable, and Section 8 is about why.

Deliberately simplified: evidence_stale's 1 ms threshold is a judgement against Chapter 4.5 §7's per-register sample age, and ten registers is ten transactions, so the set is stale even when each member is fresh. The masks are literals rather than derived from a machine-readable model. readings_used is hardcoded to ten where a PHY missing the FEC or FLP registers supplies fewer. And link_stable_1s is applied at all, which Section 6 shows changes nothing — it is in the block to make its worthlessness visible rather than assumed.

Production implication: the ten transactions are the real cost and they are not free. At Chapter 4.5's Clause 22 timings a register read is tens of microseconds and a Clause 45 indirect read is two transactions, so a full evidence sweep is a millisecond or more — during which Chapter 3.8 §11's bring-up distribution says a link can pass three rungs. A diagnosis built from ten separately-timed reads of a moving target needs vector_not_monotone from Section 3 as a gate on the whole result, and a PHY with a latched snapshot register is worth more than any additional status bit.


6. What MDIO Separates: Nine Classes of Fourteen

Run Section 5's ten readings over Section 2's fourteen sites and count the distinct signatures.

ReadingAbnormal atBits
partner_link_up7 of 141.000 — and it is not local
clock_locked60.985
block_locked80.985
flp_bursts_seen60.985
signal_detect50.940
lanes_aligned90.940
local_loopback_passes50.940
fec_locked100.863
lp_ability_valid120.592
an_complete130.371
remote_fault_rx10.371
link_stable_1s140.000

The last row is Chapter 21.1 §6's frames_out arriving in a different chapter. A link that will not come up is unstable at every one of the fourteen sites — that is what the ticket means — so the reading carries no information at all. It is the trigger.

The first row is the finding, and it is the only observable in the space that splits the fourteen almost evenly. partner_link_up is abnormal at seven of fourteen: exactly half, 1.000 bits, a perfectly balanced questionand it is the one reading no local register supplies.

Now the classes.

Instrument setClassesLargest class
MDIO alone — ten local readings95
MDIO + a cooperating partner113
MDIO + local loopback114
all three123

Nine of fourteen with MDIO alone, and the fused groups are these:

Fused under MDIO aloneWhy
our receiver, attenuation, a wrong optic, their transmitter, their admin statenothing arrives — five sites, one reading
our block lock, polarity or lane swapbits arrive and do not parse — two sites, one reading

The second pair is the easier one and it is worth naming because the fix differs completely. Chapter 3.4 §11's aligner failing to find block boundaries is what an inverted pair or a swapped lane looks like from inside the PCS — the bits are there, the timing is recovered, and the content is scrambled. One is a chip; the other is a connector installed backwards, and the reading is identical.

The first group is five sites and Section 8 is about it.

And the search's efficiency, for the contrast with Chapter 21.1:

Value
fourteen sites3.807 bits
information floor4 observations
optimal decision tree, MDIO alone4
optimal decision tree, all twelve observables4

The search is at its floor with the local instruments alone, which is a much better position than Chapter 21.1's seven-against-four — and it does not help, because the ceiling is nine classes and no ordering of questions raises a ceiling.

Chapter 21.1 needed better questions. This chapter needs a second observer — and no arrangement of the first one's questions substitutes for it.


7. RTL 3 — The Three-Party Attribution

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// three_party_attributor -- which of the three parties owns the
// surviving candidates, and therefore what the next action is.
//
// This block has no analogue in Chapter 21.1, because there every site
// was ours. Here a diagnosis that has narrowed to three candidates
// spread across three parties has NOT told an operator what to do.
// ---------------------------------------------------------------------
module three_party_attributor
  import linkdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic        consistent_valid,
  input  site_mask_t  consistent,

  output logic [3:0]  n_local,
  output logic [3:0]  n_medium,
  output logic [3:0]  n_remote,
  output logic        single_party,
  output logic        needs_partner,
  output logic        needs_physical_access,
  output logic [1:0]  next_action        // 0 register, 1 hands, 2 phone, 3 mixed
);
  site_mask_t loc, med, rem;

  always_comb begin
    loc = consistent & LOCAL_SITES;
    med = consistent & MEDIUM_SITES;
    rem = consistent & REMOTE_SITES;

    n_local  = 4'(popcount14(loc));
    n_medium = 4'(popcount14(med));
    n_remote = 4'(popcount14(rem));

    single_party = ((n_local  != 4'd0) + (n_medium != 4'd0) +
                    (n_remote != 4'd0)) == 1;

    // A remote candidate cannot be investigated from here at ANY cost.
    needs_partner         = (n_remote != 4'd0);
    needs_physical_access = (n_medium != 4'd0);

    // The cheapest action that could still be the right one.
    if      (n_local != 4'd0 && n_medium == 4'd0 && n_remote == 4'd0) next_action = 2'd0;
    else if (n_medium != 4'd0 && n_local == 4'd0 && n_remote == 4'd0) next_action = 2'd1;
    else if (n_remote != 4'd0 && n_local == 4'd0 && n_medium == 4'd0) next_action = 2'd2;
    else                                                             next_action = 2'd3;
  end
endmodule

Classification: a partition of a candidate set by who can act on it.

What it teaches: that a candidate count is not a diagnosis until it is attributed. Three surviving candidates all local is one engineer with a register map; three candidates spread one per party is a register read, a site visit and a phone call — same number, three times the cost, and a report that gives only the number has concealed the difference.

And it teaches that needs_partner is an absolute rather than an economic statement. A remote site cannot be investigated from here at any cost, with any instrument, by anybody with access only to this end. Chapter 21.1 §15's best_possible_answer was about a platform's instrumentation and could be bought; this is about the topology and cannot.

Deliberately simplified: the action encoding collapses "mixed" into one value where an operator needs to know which mixture. single_party sums three comparisons as integers, which is legal SystemVerilog and reads badly. And the block assumes exactly one fault — Section 18's row seven — so a mask spanning two parties is reported as ambiguity where it may be two simultaneous faults, which is Chapter 21.1 §17's case arriving where masking does not apply, because no frame passes through both.

Production implication: next_action is the field that belongs in a ticket rather than in a log. A link-down ticket that says "3 candidates" gets triaged by whoever is free; one that says "3 candidates, all local, all readable from this switch" gets closed in five minutes, and one that says "1 candidate, remote" gets routed to the other team immediately instead of after an hour. The attribution is free — it is a mask AND — and it is the single highest-value output in the chapter for an operations organisation.


8. The Class of Five, and Why It Is the Darkest One

The commonest reading in the whole fault space is that nothing is arriving at all, and five sites produce it. Our receive front end may be dead. The medium may be attenuated or broken. The optic may be the wrong wavelength or the cable the wrong category. Their transmitter may have failed. Or their port may simply have been switched off by somebody. Every local register agrees on all five. Signal detect being low forces clock lock, block lock, lane alignment and codeword lock low by the ladder's monotonicity, so four of the ten readings are determined by the first and add nothing. Auto negotiation cannot complete and the partner's advertisement cannot be parsed. No link pulses are seen. And no remote fault indication arrives, because a remote fault indication has to arrive over the very link that is carrying nothing. So zero of the ten management readings narrows the class, and sweeping all ten is ten transactions whose outcome was fixed by the first. What splits it is a local loopback, which takes out our receiver, or the partner's own link status, which takes out our receiver and their transmitter together because both are faults that are dark in only one direction. What remains after both is attenuation, a wrong optic and their administrative state, and those three need an instrument on a different bus or a question asked of a person.signal_detect lowthe commonest reading4 gates forcedlowmonotonicity5 sites, 3partiesone signature0 of 10 narrow itthe sweep is wastedA loopbacktakes out our receiverThe partner'sstatustakes out two3 remainatten, optic, adminOptical power,DDMa different bus12
Figure 3 — nothing arrives: five sites, three parties, and ten registers that all agree.

Section 6's largest fused group is the reading every link-down investigation starts from: nothing is arriving.

SitePartyWhy it produces no signal
our receive front endlocalour detector is dead
attenuation or a breakmediumthe signal does not survive the path
the wrong optic or cablemediumwavelength or category mismatch
their transmitterremotethey are not sending
their port administratively downremotethey are deliberately not sending

Five sites, three parties, one reading — and the reading is the most common one in the whole space.

Every local register agrees. signal_detect low forces clock_locked, block_locked, lanes_aligned and fec_locked low by Section 4's monotonicity — so five of the ten MDIO readings are determined by the first one and add nothing. an_complete and lp_ability_valid are low; flp_bursts_seen is low; remote_fault_rx is low because a remote fault indication has to arrive, and nothing is arriving.

Readings that distinguish anything within this class
of the ten MDIO readings0
of the twelve observables in the space2 — loopback and the partner's status

Zero of ten. A full MDIO sweep on this fault is ten transactions that cannot change the answer, and doing it is Section 14's fifth prohibition.

What does split the class:

ObservationSplits offCost
local loopback passesour receive front endan action, and it breaks the link further
the partner reports signalour transmitter's health, and their admin statea second party
optical power at our receiverattenuation from everything elsea meter, or DDM over I2C — not MDIO
optical power at our transmitterour transmitterthe same

Row three and four are the ones that are not in the Ethernet management path at all. Chapter 4.5's MDIO addresses the PHY; the optic's digital diagnostics live on a separate two-wire bus, and a switch that reads them is doing so through a different driver, a different address space and often a different team's code. That is why the darkest class in the space is resolved by an instrument the protocol does not define.

And one member of the class deserves separating out, because it is the only one that is not a fault.

"Their port is administratively down" is indistinguishable from a broken cable by every instrument this chapter has, and it is the most common cause of the reading.

A broken cableA port somebody turned off
our signal detectlowlow
our every other registerlowlow
their link statuslowlow
their admin stateupdown
the distinguishing evidenceone register, at the other end

Row four is a single register and it is on the other machine. Which is the chapter's recurring shape: the cheapest fact is the one you do not own, and the whole of Section 10 is about what it is worth to be able to ask for it.


9. RTL 4 — The FLP Detector as a Diagnostic

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// flp_presence_probe -- Chapter 11.1's parallel detection, used to
// answer a question it was not built for.
//
// That chapter asks "what kind of partner is this". This block asks a
// narrower one: are link pulses arriving AT ALL? The answer separates
// "our negotiation state machine is broken" from "their end does not
// negotiate", which Section 6 found fused under every other reading.
// ---------------------------------------------------------------------
module flp_presence_probe
  import linkdiag_pkg::*;
#(
  parameter int PULSE_WINDOW_MS = 100    // Chapter 11.1 Section 13
)(
  input  logic        clk,
  input  logic        rst_n,

  input  logic        pulse_edge,        // any link pulse on the pair
  input  logic        burst_decoded,     // a full 33-pulse FLP burst
  input  logic        tick_ms,

  output logic        pulses_present,
  output logic        bursts_present,
  output logic        partner_is_forced, // pulses, no bursts
  output logic        we_cannot_parse,   // bursts arriving, AN stuck
  output logic [15:0] c_pulses,
  output logic [15:0] c_bursts,
  output logic        window_elapsed
);
  logic [15:0] ms_count;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      c_pulses <= '0; c_bursts <= '0; ms_count <= '0; window_elapsed <= 1'b0;
    end else begin
      if (pulse_edge)    c_pulses <= c_pulses + 16'd1;
      if (burst_decoded) c_bursts <= c_bursts + 16'd1;
      if (tick_ms) begin
        ms_count <= ms_count + 16'd1;
        if (ms_count == 16'(PULSE_WINDOW_MS) - 16'd1) window_elapsed <= 1'b1;
      end
    end
  end

  assign pulses_present = (c_pulses != 16'd0);
  assign bursts_present = (c_bursts != 16'd0);

  // Chapter 11.1 Section 6: a one and a zero are not symmetric, and a
  // legacy 10BASE-T partner emits a SINGLE normal link pulse rather
  // than a burst. Pulses without bursts is that partner -- or a
  // modern one configured for a forced speed.
  assign partner_is_forced = window_elapsed && pulses_present && !bursts_present;

  // Bursts arriving and negotiation not completing is OURS.
  assign we_cannot_parse   = window_elapsed && bursts_present;
endmodule

Classification: a presence detector, and the only block in the chapter that observes the wire rather than a register.

What it teaches: that Chapter 11.1's parallel detection is a diagnostic instrument and is almost never read as one. That chapter built it to decide what kind of partner is present so that a link can be brought up; here the same evidence separates two sites Section 6 found fused — our auto-negotiation state machine, and a partner configured for a forced speed. Both produce "every ladder gate passes and negotiation never completes"; only the presence or absence of bursts tells them apart.

And it teaches why the two outputs are not complements. partner_is_forced requires pulses and no bursts; we_cannot_parse requires bursts. Neither asserts when nothing at all arrives — which is Section 8's dark class, where this block correctly says nothing. A detector that reported "not forced" on silence would have converted an absence into a conclusion.

Deliberately simplified: the window is 100 ms against Chapter 11.1 §13's timers, which is a judgement rather than a derivation. burst_decoded is an input, so the block trusts somebody else's burst decoder — Chapter 11.1 §5's receiver is the one that matters and it is the harder half. window_elapsed never clears. And the block is copper-only: an optical link has no link pulses at all, so both outputs are permanently low there and the AN pair stays fused.

Production implication: the copper-only limitation is the important one and it changes which chapters apply. On a fibre link Chapter 11.1's FLP mechanism does not exist, so Section 6's flp_bursts_seen reading is unavailable and the class count falls from nine to eight. The equivalent evidence on fibre is the Clause 73 auto-negotiation page exchange, which is visible in MDIO rather than on the wire — the same distinction, a different register, and a diagnosis written for one medium silently loses a reading on the other.


10. What a Cooperating Partner Is Worth

Section 6 measured it: nine classes become eleven, and the largest class falls from five to three. This section is about why that is a larger improvement than the numbers suggest.

partner_link_up is abnormal at seven of fourteen sites — 1.000 bits, the only perfectly balanced observable in the space. No local register comes close: the best is clock_locked at 0.985, and the ladder's monotonicity means the five gates share 2.585 bits between them.

MDIO alone+ partner
classes911
largest class53
sites uniquely named79

And the two splits it makes are the two that matter most.

First, it splits the dark class. The five sites that all read "nothing arrives" divide by what the partner sees:

SitePartner's link status
our receive front endUP — they hear us fine
their transmitterUP — they think they are fine
attenuation or a breakdown
the wrong opticdown
their admin statedown

Two of five split off immediately, and both are the asymmetric cases — the ones where the link is dark in one direction only. That asymmetry is invisible from either end alone and obvious from both, which is the general principle the whole section rests on.

Second, it makes site 1 — our own transmitter — diagnosable at all. Section 2 noted that our transmit direction is unobservable locally: every register in our PHY describes the receive path. With the partner's status:

Our transmitter is dead
our laddercomplete — we hear them perfectly
our an_completelow
our remote_fault_rxasserted — they told us
their link statusdown
the diagnosisunambiguous

remote_fault_rx is doing the partner's job through the protocol, which is why Section 5 called it the smallest and most valuable mask in the table: one site, 0.371 bits, and it is the only local reading that is not about us. A partner that sets it has cooperated without being asked.

Which gives the ranking of what to want from a partner, cheapest first:

WantCostsWorth
a remote fault bit, in the protocolnothing — it is standardnames site 1 alone
their link status, on requesta management path between two machines1.000 bits
their full gate vectorthe same path, more fieldssplits the remaining three-site class no further

Row three is the honest limit and it is worth stating because it is counter-intuitive. Asking the partner for its whole status vector rather than one bit adds nothing — the three sites that remain fused after partner_link_up are attenuation, a wrong optic and their admin state, and all three look identical in the partner's registers too. Cooperation is worth exactly one bit, and the second bit is free and useless.

And the mechanism by which a partner's bit resolves anything is worth naming, because it generalises past this chapter.

A second observation resolves a fault exactly when the fault is asymmetric — when the link is dark in one direction and not the other. Symmetric faults look the same from both ends and defeat any number of observers.

FaultOur viewTheir viewAsymmetric?
our transmitter deadwe hear themthey hear nothingyes — named by one bit
our receiver deadwe hear nothingthey hear usyes
their transmitter deadwe hear nothingthey hear usyes
a broken cablenothingnothingno
a wrong opticnothingnothingno
their port switched offnothingnothingno

The three asymmetric rows are exactly the three that partner_link_up splits off, and the three symmetric rows are exactly Section 17's unseparable set. That is not a coincidence and it is not an artefact of this particular instrument list: a second observer adds information only about the direction it observes differently, so a fault that is identical in both directions is invisible to any number of them.

What a second observer can decide
which direction is darkyes
whether both directions are darkyes
why both directions are darkno — and that is three of the fourteen

11. RTL 5 — The Loopback Sequencer

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// loopback_diagnostic -- an ACTION rather than an observation, and the
// distinction matters: it changes the system it measures.
//
// A local loopback connects our transmitter to our receiver inside the
// PHY. If the ladder then completes, our receive path works and our
// transmitter produces something -- which eliminates two sites at once
// and eliminates them WITHOUT a partner.
// ---------------------------------------------------------------------
module loopback_diagnostic
  import linkdiag_pkg::*;
#(
  parameter int SETTLE_MS = 50
)(
  input  logic        clk,
  input  logic        rst_n,
  input  logic        tick_ms,

  input  logic        request,
  input  logic        link_was_up,       // before we broke it
  input  logic [N_GATES-1:0] gates,

  output logic        loopback_enable,
  output logic        busy,
  output logic        result_valid,
  output logic        loopback_passed,
  output site_mask_t  eliminated,
  output logic        refused
);
  logic [15:0] settle;

  // Section 14's first prohibition: a loopback breaks a link that is
  // carrying traffic. Refusing is the block's most important behaviour.
  assign refused = request && link_was_up;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      loopback_enable <= 1'b0; busy <= 1'b0; settle <= '0;
      result_valid <= 1'b0; loopback_passed <= 1'b0;
    end else if (request && !link_was_up && !busy) begin
      loopback_enable <= 1'b1; busy <= 1'b1; settle <= '0;
      result_valid <= 1'b0;
    end else if (busy && tick_ms) begin
      settle <= settle + 16'd1;
      if (settle == 16'(SETTLE_MS) - 16'd1) begin
        // Chapter 3.8 Section 11: bring-up is a DISTRIBUTION, so a
        // fixed settle time is a probability rather than a proof.
        loopback_passed <= (gates == {N_GATES{1'b1}});
        result_valid    <= 1'b1;
        busy            <= 1'b0;
        loopback_enable <= 1'b0;
      end
    end
  end

  // A pass eliminates our receive chain AND says our transmitter emits
  // something. It says nothing about whether what it emits is at the
  // right power, wavelength or polarity to cross a real medium.
  always_comb
    eliminated = (result_valid && loopback_passed)
               ? 14'b00_0000_0011_1110    // sites 1..5
               : 14'd0;
endmodule

Classification: an intervention, and the only block in the chapter that writes a register rather than reading one.

What it teaches: that refused is the block's most important output. A loopback breaks the link — it disconnects the receiver from the medium — so requesting one on a link that is currently up converts a working port into a down port, and the request usually arrives because somebody is investigating a neighbouring port. An instrument that changes what it measures needs a guard, and the guard belongs in the instrument.

And it teaches the precise limit of what a pass proves. A passing local loopback eliminates sites 1 through 5 — our receive front end, CDR, block lock, deskew and FECand does not eliminate site 1 in the sense that matters. Our transmitter emitted something the internal path could parse; whether it emits enough optical power, at the right wavelength, with the right polarity, to survive a real medium and be parsed by a different chip is not tested at all.

Deliberately simplified: SETTLE_MS is 50 against Chapter 3.8 §11's distribution — block lock on a 64b/66b link is variable and data-dependent, so a fixed settle time turns a bring-up into a coin flip at the tail. The block tests only the deepest loopback; Chapter 3.4's three sublayers each support one and they eliminate different sets. And eliminated is a literal rather than derived from which loopback was taken.

Production implication: the three loopback depths are the feature this block is missing and they are the reason loopback is worth having at all. A PMD-level loopback tests the optic; a PMA-level one tests the serialiser; a PCS-level one tests the codingChapter 3.4 §2's stack, walked from the top down. Each one that passes eliminates one more sublayer, so three loopbacks separate five local sites where one loopback separates them as a block. It is the one instrument in the chapter that can be made finer without a second party, and it costs a mux per sublayer, which Chapter 3.4 already has for other reasons.


12. Loopback Against Cooperation: 4 Against 3

Two ways to improve on MDIO alone, and they cost completely different things.

MDIO + loopbackMDIO + partner
classes1111
largest class43
needs a second partynoyes
breaks the linkyesno
available at 3 a.m. with nobody awakeyesrarely

Same class count, different largest class, and the difference is which fusion each one breaks.

Loopback splits our receive chain off from everything else, so the dark five become our-receiver plus a group of four — attenuation, a wrong optic, their transmitter, their admin state. The partner's status splits the dark five into two and three, taking our receiver and their transmitter out together, because both are cases where the link is dark in one direction only.

Fused afterSites
loopbackattenuation, wrong optic, their TX, their admin — 4
partnerattenuation, wrong optic, their admin — 3
bothattenuation, wrong optic, their admin — 3

Row three is the finding: adding loopback to a diagnosis that already has the partner's status changes nothing at all. The partner's bit already separates what loopback separates, and it separates one more. So:

If you can ask the partner, do not run a loopback. If you cannot, run one — and know that it leaves four candidates where the partner would have left three.

And the ordering matters in the other direction too, because loopback is destructive. A loopback taken first on a link that somebody is still trying to bring up destroys the evidence of what it was doingChapter 3.8 §11's bring-up is a search with state, and interrupting it restarts the search. The MDIO sweep is free and non-destructive and must come first, which is Section 14's fourth prohibition.

StepInstrumentDestructive?
1the ten MDIO readingsno
2Chapter 11.1's pulse presenceno
3ask the partnerno
4local loopbackYES
5swap the optic, measure poweryes, and physical

Four of the five steps are free and the destructive one is fourth, which is the same shape as Chapter 21.1 §12's procedure — register reads before equipment — arriving in a chapter where the equipment is a screwdriver rather than a capture tool.


Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// intermittent_link_detector -- site 8, and it is the only site in the
// space whose symptom is a TIME SERIES rather than a state.
//
// Chapter 3.8 Section 10: one lane cycling in and out of lock makes the
// whole link flap, and from the combined bit that is indistinguishable
// from every lane being marginal. This block keeps the per-lane history
// because that is the distinction, and it is a completely different fix.
// ---------------------------------------------------------------------
module intermittent_link_detector
  import linkdiag_pkg::*;
#(
  parameter int LANES  = 4,
  parameter int WINDOW_S = 60
)(
  input  logic        clk,
  input  logic        rst_n,
  input  logic        tick_s,

  input  logic        link_up,
  input  logic [LANES-1:0] lane_locked,

  // Chapter 4.4 Section 9: two faults, not one.
  input  logic        elastic_overrun,
  input  logic        elastic_underrun,

  output logic [15:0] c_link_transitions,
  output logic [15:0] c_lane_transitions [LANES],
  output logic [15:0] uptime_s,
  output logic        is_flapping,
  output logic        one_lane_dominates,
  output logic [3:0]  worst_lane,
  output logic        elastic_suspected,
  output logic        lossy_flap            // overrun -- data was lost
);
  logic        link_prev;
  logic [LANES-1:0] lane_prev;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      c_link_transitions <= '0; uptime_s <= '0;
      link_prev <= 1'b0; lane_prev <= '0;
      for (int i = 0; i < LANES; i++) c_lane_transitions[i] <= '0;
    end else begin
      link_prev <= link_up;
      lane_prev <= lane_locked;
      if (link_up != link_prev) c_link_transitions <= c_link_transitions + 16'd1;
      for (int i = 0; i < LANES; i++)
        if (lane_locked[i] != lane_prev[i])
          c_lane_transitions[i] <= c_lane_transitions[i] + 16'd1;
      if (tick_s && link_up) uptime_s <= uptime_s + 16'd1;
    end
  end

  logic [15:0] lane_total, lane_max;

  always_comb begin
    lane_total = 16'd0; lane_max = 16'd0; worst_lane = 4'd0;
    for (int i = 0; i < LANES; i++) begin
      lane_total += c_lane_transitions[i];
      if (c_lane_transitions[i] > lane_max) begin
        lane_max = c_lane_transitions[i]; worst_lane = 4'(i);
      end
    end

    is_flapping = (c_link_transitions > 16'd4) && (uptime_s < 16'(WINDOW_S));

    // Chapter 3.8 Section 10's asymmetry: one lane owning most of the
    // transitions is a LANE fault; transitions spread evenly across
    // lanes is a MARGIN fault, and the fixes are a fibre and a budget.
    one_lane_dominates = (lane_total > 16'd8) &&
                         (lane_max > ((lane_total * 16'd3) / 16'd4));

    // Chapter 4.4 Section 9: overrun destroys data, underrun does not.
    elastic_suspected = elastic_overrun || elastic_underrun;
    lossy_flap        = elastic_overrun;
  end
endmodule

Classification: a history keeper, and the only block in the chapter that has to run before the fault is reported.

What it teaches: that one_lane_dominates is Chapter 3.8 §10's argument made into a comparison. A link is up only when every lane is locked, so the combined bit is dominated by the worst lane — and one lane cycling produces exactly the same link_up trace as four lanes all marginal. Three quarters of the transitions on one lane is a fibre, a connector or a lane's receiver; transitions spread evenly is a link budget, and no aggregate bit tells them apart.

And it teaches that lossy_flap is not a severity refinement but a different fault. Chapter 4.4 §9 is explicit: an overrun destroys data and an underrun does not, because the read side must emit something and what it emits is idle. A shared "elastic buffer error" counter makes a lossy link and a merely mistimed one read identically, which is the same shape as Chapter 21.2 §11's discard-versus-damage distinction, in the physical layer.

Deliberately simplified: is_flapping's thresholds — four transitions, sixty seconds — are judgements. The per-lane counters are LANES × 16 bits with no saturation. uptime_s accumulates rather than measuring the current up interval, so a link that was up for an hour and then flapped four times reads as healthy. And the block cannot run retroactively: a flap that happened before anybody looked leaves no evidence at all, which is the whole reason it must be always-on.

Production implication: always-on is the requirement and it is the one usually missed. A flap is a transition and a transition is only observable while it happens — so a diagnosis that begins after the ticket arrives starts with c_link_transitions at zero and no way to distinguish "it is not flapping" from "it has not flapped since I started watching". The counters are about 100 flops for four lanes, they must be free-running from reset, and the alternative is asking an operator to leave a terminal open overnight, which is what actually happens.


Six prohibitions. Two are about the ladder's structure, two about the three parties, and two about the instruments — and every one produces a confident wrong answer rather than a visible failure.

NeverBecause
1run Chapter 21.1's frame method on a down linkSection 1 — it converges on class G with full confidence
2report gates above the lowest failed one as failedSection 4 — they were not attempted
3conclude a local site from a receive-side gatea failing gate implicates three parties
4take a loopback before the MDIO sweepSection 12 — it destroys a search in progress
5sweep all ten registers on a dark linkSection 8 — zero of ten can change the answer
6treat a flap as a down linkSection 13 — it is a different site and a time series

Row one is the prohibition with the highest cost and it needs a mechanical guard. Chapter 21.1's method is correct, well-specified and completely wrong on this input — every counter reads zero, every zero eliminates the sites its counter watches, and the mask converges on the five sites past the MAC. The guard is one comparison: frames_in at zero is not an observation. Section 16's monitor is where it lives.

Row three is the one that is violated hourly and it is structural rather than careless. Every register in our PHY describes our receive direction, so block_locked low is a fact about what arrived here — and what arrived here is a function of our receiver, the medium and their transmitter. Concluding "our PCS is broken" from it is right about one time in two at best, and Section 6 measured it: the block-lock reading alone leaves two candidates and one of them is a connector installed backwards.

And the two that look like impatience and are not:

Why it is a prohibition
row fourChapter 3.8 §11 — bring-up is a search with state, and a loopback restarts it
row fivethe ladder's monotonicity makes nine of the ten readings determined by the first

Both spend an instrument on a question whose answer is already fixed, which is what all six share: each one produces activity whose outcome was decided before it began.


15. RTL 7 — Bring-Up Telemetry

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// linkdiag_telemetry -- three groups, and the first thing it reports is
// which of Module 21's two problems this is.
//
// Chapter 21.1's method and this chapter's are both correct and they
// are correct on disjoint inputs. Choosing between them is a one-bit
// decision and getting it wrong costs an investigation.
// ---------------------------------------------------------------------
module linkdiag_telemetry
  import linkdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [31:0] frames_in,
  input  site_mask_t  consistent,
  input  logic        consistent_valid,
  input  gate_e       failed_gate,
  input  logic [3:0]  n_local,
  input  logic [3:0]  n_medium,
  input  logic [3:0]  n_remote,
  input  logic        partner_status_known,
  input  logic        loopback_done,
  input  logic        is_flapping,
  input  logic        evidence_stale,

  // Which problem is this?
  output logic        is_link_down,
  output logic        is_frame_problem,
  output logic        wrong_chapter,

  // Where are we?
  output logic [3:0]  n_candidates,
  output gate_e       rung,
  output logic [1:0]  next_action,

  // What is the ceiling?
  output logic [3:0]  best_possible,
  output logic        needs_second_party,
  output logic        at_ceiling
);
  assign is_link_down     = (frames_in == 32'd0);
  assign is_frame_problem = (frames_in != 32'd0);
  // Section 14's row one, as a bit.
  assign wrong_chapter    = is_frame_problem;

  assign n_candidates = 4'(popcount14(consistent));
  assign rung         = failed_gate;

  assign next_action = (n_remote != 4'd0) ? 2'd2
                     : (n_medium != 4'd0) ? 2'd1
                     : 2'd0;

  // Section 6's table, as arithmetic rather than as prose. Nine classes
  // with MDIO alone; the partner's bit buys two more.
  always_comb begin
    best_possible = partner_status_known ? 4'd3
                  : loopback_done        ? 4'd4
                                         : 4'd5;
    needs_second_party = (best_possible > 4'd3);
    at_ceiling = consistent_valid && !evidence_stale &&
                 (n_candidates <= best_possible);
  end
endmodule

Classification: a reporting block whose first output decides which chapter applies.

What it teaches: that wrong_chapter is the most valuable bit in the block and it is one comparison. Module 21 now contains two complete and correct diagnostic methods that are correct on disjoint inputs — frames exist, or they do not — and each one produces a confident wrong answer on the other's input. A single frames_in == 0 test routes between them, and without it an operator reaches for whichever method they used last.

And it teaches that best_possible is knowable before any reading, exactly as Chapter 21.1 §15's was. It depends only on which instruments are available — can we ask the partner, can we take a loopback — and not on anything about this fault. Five candidates is the ceiling with local registers alone; telling an operator that at the start changes the plan, and telling them after an hour changes only the mood.

Deliberately simplified: best_possible returns the largest class size rather than the achievable candidate count for this reading, so a fault that lands in a singleton class reports a ceiling of five and reaches one. next_action prioritises the most expensive party, which is right for planning and wrong for ordering. And is_link_down uses frames_in alone where a link that is up and idle also reads zero — Section 18's row two.

Production implication: the frames_in-alone test is the simplification to fix before shipping, and the fix is one more input. An idle link and a down link both have frames_in at zero; what separates them is link_up, which the telemetry already has in is_flapping's neighbourhood. The correct test is !link_up, and the reason it is worth being pedantic is that an idle port on a lightly loaded switch is the normal case — a monitoring system that routes every idle port into this chapter's method will generate a link-down diagnosis for every unused port in a building.


16. RTL 8 — The Bring-Up Conformance Monitor

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// linkdiag_conformance_monitor -- six verdicts, and the first one is
// about which method is being run rather than about the link.
// ---------------------------------------------------------------------
module linkdiag_conformance_monitor
  import linkdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [31:0] frames_in,
  input  logic        link_up,
  input  logic        frame_method_running,
  input  logic [N_GATES-1:0] gates,
  input  logic        vector_not_monotone,
  input  logic        evidence_stale,
  input  site_mask_t  consistent,
  input  logic        loopback_requested,
  input  logic        mdio_sweep_done,
  input  logic        partner_status_known,

  output logic        wrong_method_running,
  output logic        vector_impossible,
  output logic        evidence_too_old,
  output logic        loopback_out_of_order,
  output logic        unseparable_remains,
  output logic        candidates_span_parties,
  output logic        diagnosis_sound
);
  // Section 14's row one. Chapter 21.1's method on a link with no
  // frames converges, confidently, on the wrong five sites.
  assign wrong_method_running = frame_method_running && !link_up &&
                                (frames_in == 32'd0);

  // Section 4: six of thirty-two readings are reachable. Anything else
  // is a PHY fault or a stale read, not a link fault.
  assign vector_impossible = vector_not_monotone;

  assign evidence_too_old = evidence_stale;

  // Section 12: the MDIO sweep is free and non-destructive; a loopback
  // restarts a search in progress.
  assign loopback_out_of_order = loopback_requested && !mdio_sweep_done;

  // Section 17: three sites that no observation in this space splits.
  assign unseparable_remains = ((consistent & CLASS_UNSEPARABLE) == CLASS_UNSEPARABLE)
                            && (popcount14(consistent) == 3);

  // Section 7: a candidate set spread across parties is a triage
  // problem as well as a diagnostic one.
  assign candidates_span_parties =
      (((consistent & LOCAL_SITES)  != 14'd0) +
       ((consistent & MEDIUM_SITES) != 14'd0) +
       ((consistent & REMOTE_SITES) != 14'd0)) > 1;

  assign diagnosis_sound = !wrong_method_running && !vector_impossible &&
                           !evidence_too_old && !loopback_out_of_order;

  always_ff @(posedge clk) begin
    if (rst_n && unseparable_remains)
      $display("[linkdiag] attenuation, wrong optic and remote admin-down are not separable from here");
  end
endmodule

Classification: an auditor whose loudest verdict names a limit rather than a fault.

What it teaches: that unseparable_remains is deliberately not a term of diagnosis_sound. Reaching three fused candidates is the correct terminal state of a correctly run diagnosis — the instruments genuinely cannot separate them — and calling that unsound would blame an engineer for a property of the observation set. It is the same split Chapter 21.1 §16 made for instrumentation_limited and Chapter 21.2 §16 for order_unexpected: a loud report, never a failure.

And it teaches that wrong_method_running is the only verdict in Module 21 that audits a different chapter's method. It fires when Chapter 21.1's frame-based procedure is running against a link with no frames, which is a correct method applied to an input it was never specified for — and the reason it belongs here rather than there is that only this chapter knows the input is out of scope.

Deliberately simplified: candidates_span_parties sums three comparisons as integers. unseparable_remains tests for exactly that three-site set where a superset containing it should also report. evidence_too_old is a pass-through. And diagnosis_sound omits candidates_span_parties, which is right — a candidate set spanning parties is a triage fact and not an error.

Production implication: wrong_method_running is the verdict to wire into tooling rather than into a report, and it is worth one sentence about why. The two methods in Module 21 look interchangeable from outside — both take a port, both read counters, both produce a candidate list — and they are correct on disjoint inputs with no overlap at all. One comparison routes between them. Without it the common failure is not that the wrong method fails; it is that the wrong method succeeds, producing five plausible candidates that an operator will spend a morning eliminating.


17. The Three Sites Nothing Separates

Section 6's table has one row that does not improve: attenuation, a wrong optic and a remote port that is administratively down stay fused under MDIO, under loopback, under a cooperating partner, and under all three together.

ObservableAttenuationWrong opticTheir admin state
our signal detectlowlowlow
our whole ladderlow, by monotonicitylowlow
an_complete, lp_ability_validlowlowlow
remote_fault_rxabsentabsentabsent
flp_bursts_seenlowlowlow
local loopbackpassespassespasses
their link statusdowndowndown

Seven observations, three sites, one signature. All three are dark in both directions, and that is the whole reason: every instrument in the space is an Ethernet instrument, and Ethernet instruments observe a signal. When there is no signal in either direction, the protocol has nothing to say.

What does split them is not Ethernet.

InstrumentSplits offWhere it lives
received optical power at our endattenuation — a number, not a bitDDM, over a two-wire bus
the optic's part number and wavelengtha wrong opticthe same bus, a different page
the far end's administrative configurationtheir admin statea management system, or a person
swap the cableattenuation, by substitutionhands

Three of the four are outside the Ethernet management path entirely — a different bus, a different address space, often a different team's driver. The fourth is a person walking to a rack.

Which is a stronger statement than "the instruments are incomplete", and it is worth making precisely.

The three sites are not unobserved because nobody built a register. They are unobserved because a protocol that communicates over a link cannot report on a link that carries nothing.

And that explains why the resolution is by substitution rather than by measurement. The standard field procedure for the dark class is swap the optic, swap the cable, ask the far end — three actions in the order of increasing cost — and it is not a failure of rigour. It is the only method available, because every instrument that could have measured instead of substituting is on a different bus.

StepCostResolves
read optical power, if the platform exposes ita register on another busattenuation, quantitatively
swap the opticminutes, and a sparea wrong or dead optic
swap the cableminutesattenuation and breaks
ask the far enda person, or a management systemadmin state

Row one is worth insisting on because it is the one step that is a measurement. Chapter 3.3's channel has a loss budget, and a received power reading against that budget answers "attenuation or not" in one number — where the other three steps answer it by elimination, over minutes, destructively. A platform that exposes DDM turns the darkest class in the chapter from a substitution exercise into a reading, and the cost is a driver rather than a gate.

Two sites that people expect to be in this class and are not:

Why it is separable
their transmitterthe partner's own link status is up — they hear us
our receivera loopback passes, or the partner hears us

Both are asymmetric faults — dark in one direction and not the otherand asymmetry is exactly what a second observation detects. The three that remain are symmetric, and no amount of observing from either end distinguishes them, because both ends see the same nothing.


18. What the Diagnosis Assumes

Nine assumptions. Three are about the ladder, three about the instruments and three about the fault — and the one that is false most often is the second.

AssumptionFromIf false
1the ladder is monotoneChapter 3.8 §2's five dependenciesSection 4's six readings become thirty-two and the vector is meaningless
2frames_in at zero means the link is downconvenienceevery idle port is diagnosed as broken
3the ten MDIO reads describe one instantnothingChapter 4.5 §7 — five rungs can pass inside the sweep
4the PHY implements the registers we readthe datasheetabsent registers read as zero — Chapter 21.1 §10's trap
5this link has all five rungsChapter 3.8 §2's notea single-lane family has three, and two read as passed
6exactly one site is faultyconvenienceSection 7 — a mask spanning parties may be two faults
7the medium is symmetricconventionfibre is two strands and one can break alone
8the partner will answer honestlycooperationa partner reporting stale status is worse than none
9link pulses existChapter 11.1fibre has none; the class count falls from nine to eight

Row two is false on most ports of most switches and the consequence is operational rather than technical. An idle port and a down port both have frames_in at zero. A monitoring system that routes on frames_in alone will run this chapter's method against every unused port in a building and report a link-down diagnosis for each. The correct test is !link_up and Section 15 says so; the reason it is worth a row of its own is that the wrong test is the one that is natural when you have just finished writing Chapter 21.1's method.

Row seven is the assumption that turns one fault into two and is invisible until it does. A fibre pair is two strands, and one can break while the other does not:

One strand broken
our receive laddercomplete — their strand is fine
their receive ladderdark
our remote_fault_rxasserted, if they can tell us — and they can, on our good strand
which site is this?site 1's signature exactly

A single broken strand is indistinguishable from our own transmitter being dead, because both are "we hear them, they do not hear us." Site 1 and a unidirectional medium fault are fused and Section 2's site list does not contain the second one — which is an omission in the fault space rather than in the instruments, and the fix is a fifteenth site rather than another register.

Row three is the assumption whose failure is hardest to see. Ten MDIO transactions at tens of microseconds each is hundreds of microseconds to a millisecond, and Chapter 3.8 §11 showed bring-up is a distribution: block lock is evidence-driven and data-dependent. A link actively searching can pass three rungs inside one sweep, producing a vector that is internally inconsistent — which vector_not_monotone catches and which a reader who trusts the sweep does not.

And three things deliberately not assumed:

Not assumedWhy not
that a failing gate names a local siteSection 6 — three parties per reading
that reading more registers helpsSection 8 — zero of ten on the dark class
that the diagnosis can reach one siteSection 17 — three of fourteen never separate

Row three is the chapter's honest terminal position, and it is the one that distinguishes it from the three chapters before it: Chapter 21.1, Chapter 21.2 and Chapter 21.3 all reach a single site with enough instrumentation. This one does not, at any price, from one end.


19. The Cost, Accounted

A link diagnosis is masks and counters, and the counters are small because there is no population to count.

BlockFlopsNature
linkdiag_pkg0fourteen sites and ten masks
gate_vector_reader0combinational
mdio_evidence_map0combinational
three_party_attributor0combinational
flp_presence_probe~50two counters and a window
loopback_diagnostic~21a settle timer and three flags
intermittent_link_detector — 4 lanes~97the history, and it must be always-on
linkdiag_telemetry0combinational
linkdiag_conformance_monitor0combinational
total~168 flops

Six of the nine blocks are pure combinational logic, and the total is the smallest in Module 21 by a factor of two. Chapter 21.1 §19's method was 299 flops; this one is 168, and the reason is structural: a decision procedure over fourteen candidates has almost no state, and there is no traffic to accumulate statistics about.

FlopsWhat it stores
Chapter 21.3 §19's diagnosis~4 856a histogram over 64 residues
Chapter 21.2 §19's taxonomy~785thirteen class counters
Chapter 21.1 §19's method~299a mask and an audit log
this chapter~168a flap history

The trend is the module's shape stated as a number: the more traffic a diagnosis reasons about, the more it has to remember. This chapter reasons about none, and 97 of its 168 flops are the one block that has to observe something over time.

And the instrumentation this chapter would add to a design is almost nothing, because the registers already exist.

AdditionFlopsBuys
a latched snapshot of the gate vector~5Section 18's row three — one read instead of ten
per-lane transition counters, 4 lanes~64Chapter 3.8 §10's lane-versus-margin split
an FLP presence bit~2the AN pair, on copper
all three~710.5% of Chapter 19.7 §19's 14 166-flop datapath

Half of one per cent, and the first row is the one that matters most: a latched snapshot turns ten skewed reads into one atomic one and makes vector_not_monotone a real fault indicator rather than a reason to distrust the sweep.

Module 21's whole instrumentation bill, now four chapters in:

ChapterFlops to addShare of the datapath
Chapter 21.1 §19~2972.1%
Chapter 21.2 §19~4263.0%
Chapter 21.3 §19, logged rather than binned~7925.6%
this chapter~710.5%
total~1 58611.2%

Eleven point two per cent of a datapath for every diagnosis Module 21 has built — and this chapter's contribution is the cheapest and, on the fault that takes a network down completely, the one that gets used first.


20. Properties Worth Asserting, and One Worth Refusing

A natural way to validate a bring up rung is to check it against the traffic it describes: if block lock is asserted then blocks must be arriving and parsing. The property is sound and its antecedent is produced by the very mechanism it checks. On a healthy link it evaluates millions of times and can fail millions of times. On a link that will not come up it evaluates zero times, can fail zero times, and reports a pass. Its coverage is not merely uncorrelated with the fault, it is anti correlated: the property goes silent exactly as the fault becomes certain. And it is not one property. Counting across the track's three most recent modules, the datapath module has two hundred and thirty eight published assertions of which one hundred and sixty two need traffic, the verification environment module has two hundred and four of which ninety five do, and this debugging module so far has one hundred and fifteen of which seventy five do. Three hundred and thirty two of five hundred and fifty seven, which is fifty nine point six per cent, go quiet on this fault and none of them fails. A regression binding all of them to a design whose link never comes up reports five hundred and fifty seven passes. The repair is to assert the ladder's structural dependencies, which hold with no traffic whatsoever, to bound the bring up time rather than the traffic, and to cover the antecedent so that its silence is visible.block_lock meansblocksthe tempting propertyLink healthymillions ofevaluationsLink will notcome upzero evaluationsBoth report passsilent, not wrong332 of 55759.6% go quietAssert thedependenciesthey need no trafficBound thebring-upantecedent is thefaultCover theantecedentmake the silencevisible12
Figure 4 — a property whose coverage is anti-correlated with the fault it targets.

Thirty-three properties and eight covers, in four groups: the ladder, the three parties, the instruments, and the two methods.

Group one — the ladder, and its monotonicity.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Chapter 3.8 Section 2's five dependencies, as five properties. They
// are the only properties in this chapter that hold with no traffic on
// the wire, which is the whole point -- Section 20's refused property.
p_clock_needs_sig:   assert property (@(posedge clk) disable iff (!rst_n)
                       gates[G_CLOCK] |-> gates[G_SIGNAL]);

p_block_needs_clk:   assert property (@(posedge clk) disable iff (!rst_n)
                       gates[G_BLOCK] |-> gates[G_CLOCK]);

p_marker_needs_blk:  assert property (@(posedge clk) disable iff (!rst_n)
                       gates[G_MARKER] |-> gates[G_BLOCK]);

p_fec_needs_marker:  assert property (@(posedge clk) disable iff (!rst_n)
                       gates[G_FEC] |-> gates[G_MARKER]);

p_six_readings:      assert property (@(posedge clk) disable iff (!rst_n)
                       !vector_not_monotone);

p_lowest_is_first:   assert property (@(posedge clk) disable iff (!rst_n)
                       (failed_gate != G_NONE) |-> !gates[failed_gate]);

p_below_all_passed:  assert property (@(posedge clk) disable iff (!rst_n)
                       (failed_gate != G_NONE) |->
                         ((gates & ((1 << failed_gate) - 1)) ==
                          ((1 << failed_gate) - 1)));

p_complete_is_all:   assert property (@(posedge clk) disable iff (!rst_n)
                       ladder_complete |-> (gates == {N_GATES{1'b1}}));

Group two — the three parties.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
p_mask_only_shrinks: assert property (@(posedge clk) disable iff (!rst_n)
                       consistent_valid |=>
                         ((consistent & $past(consistent)) == consistent));

p_parties_partition: assert property (@(posedge clk) disable iff (!rst_n)
                       ((LOCAL_SITES | MEDIUM_SITES | REMOTE_SITES) == ALL_SITES) &&
                       ((LOCAL_SITES & MEDIUM_SITES) == 14'd0) &&
                       ((LOCAL_SITES & REMOTE_SITES) == 14'd0) &&
                       ((MEDIUM_SITES & REMOTE_SITES) == 14'd0));

p_counts_sum:        assert property (@(posedge clk) disable iff (!rst_n)
                       consistent_valid |->
                         ((n_local + n_medium + n_remote) == n_candidates));

p_remote_needs_ask:  assert property (@(posedge clk) disable iff (!rst_n)
                       (n_remote != 4'd0) |-> needs_partner);

p_medium_needs_hand: assert property (@(posedge clk) disable iff (!rst_n)
                       (n_medium != 4'd0) |-> needs_physical_access);

p_single_party_act:  assert property (@(posedge clk) disable iff (!rst_n)
                       single_party |-> (next_action != 2'd3));

p_tx_needs_partner:  assert property (@(posedge clk) disable iff (!rst_n)
                       (consistent == (14'd1 << S_L_TX)) |->
                         (partner_status_known || remote_fault_rx));

p_dark_is_five:      assert property (@(posedge clk) disable iff (!rst_n)
                       (!gates[G_SIGNAL] && consistent_valid && !loopback_done &&
                        !partner_status_known) |-> (n_candidates == 4'd5));

Group three — the instruments, and what each may and may not conclude.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
p_stale_no_verdict:  assert property (@(posedge clk) disable iff (!rst_n)
                       evidence_stale |-> !consistent_valid);

p_loopback_refuses:  assert property (@(posedge clk) disable iff (!rst_n)
                       (loopback_requested && link_was_up) |-> refused);

p_loopback_order:    assert property (@(posedge clk) disable iff (!rst_n)
                       loopback_enable |-> mdio_sweep_done);

p_loopback_scope:    assert property (@(posedge clk) disable iff (!rst_n)
                       (result_valid && loopback_passed) |->
                         (eliminated == 14'b00_0000_0011_1110));

p_flp_needs_window:  assert property (@(posedge clk) disable iff (!rst_n)
                       (partner_is_forced || we_cannot_parse) |-> window_elapsed);

p_flp_silent_on_dark:assert property (@(posedge clk) disable iff (!rst_n)
                       (!pulses_present && !bursts_present) |->
                         (!partner_is_forced && !we_cannot_parse));

p_flap_needs_history:assert property (@(posedge clk) disable iff (!rst_n)
                       is_flapping |-> (c_link_transitions > 16'd4));

p_lane_dominance:    assert property (@(posedge clk) disable iff (!rst_n)
                       one_lane_dominates |->
                         (c_lane_transitions[worst_lane] ==
                          $past(c_lane_transitions[worst_lane]) ||
                          c_lane_transitions[worst_lane] >=
                          $past(c_lane_transitions[worst_lane])));

p_overrun_is_lossy:  assert property (@(posedge clk) disable iff (!rst_n)
                       lossy_flap |-> elastic_overrun);

Group four — the two methods, and the boundary between them.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
p_methods_disjoint:  assert property (@(posedge clk) disable iff (!rst_n)
                       !(is_link_down && is_frame_problem));

p_wrong_method:      assert property (@(posedge clk) disable iff (!rst_n)
                       (frame_method_running && !link_up && (frames_in == 32'd0))
                         |-> wrong_method_running);

p_sound_excludes:    assert property (@(posedge clk) disable iff (!rst_n)
                       diagnosis_sound |->
                         (!wrong_method_running && !vector_impossible));

p_ceiling_static:    assert property (@(posedge clk) disable iff (!rst_n)
                       ($stable(partner_status_known) && $stable(loopback_done))
                         |=> $stable(best_possible));

p_ceiling_five:      assert property (@(posedge clk) disable iff (!rst_n)
                       (!partner_status_known && !loopback_done) |->
                         (best_possible == 4'd5));

p_second_party:      assert property (@(posedge clk) disable iff (!rst_n)
                       (best_possible > 4'd3) |-> needs_second_party);

p_unseparable_flag:  assert property (@(posedge clk) disable iff (!rst_n)
                       ((consistent == CLASS_UNSEPARABLE)) |-> unseparable_remains);

p_never_below_three: assert property (@(posedge clk) disable iff (!rst_n)
                       ((consistent & CLASS_UNSEPARABLE) == CLASS_UNSEPARABLE)
                         |-> (n_candidates >= 4'd3));

p_at_ceiling_needs:  assert property (@(posedge clk) disable iff (!rst_n)
                       at_ceiling |-> (consistent_valid && !evidence_stale));

And eight covers, because six of these are states a reviewer needs to have seen reached.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
c_dark_class:      cover property (@(posedge clk) n_candidates == 4'd5 && !gates[G_SIGNAL]);
c_unseparable:     cover property (@(posedge clk) unseparable_remains);
c_our_tx_named:    cover property (@(posedge clk) consistent == (14'd1 << S_L_TX));
c_spans_parties:   cover property (@(posedge clk) candidates_span_parties);
c_flap_one_lane:   cover property (@(posedge clk) one_lane_dominates);
c_flap_all_lanes:  cover property (@(posedge clk) is_flapping && !one_lane_dominates);
c_partner_used:    cover property (@(posedge clk) partner_status_known);
c_every_rung:      cover property (@(posedge clk) rungs_seen == 6'b111111);

21. Verification Scenarios

Fifty-eight scenarios, plus a five-run directed test whose variable is which party is broken — which no frame-level generator can vary, because the fault is that there are no frames.

The ladder — 11 scenarios.

#ScenarioExpected
1all five gates highladder_complete; failed_gate = G_NONE
2signal low, everything else lowfailed_gate = G_SIGNAL; reading 00000
3signal high, clock lowG_CLOCK; reading 10000
4signal, clock high, block lowG_BLOCK; reading 11000
5three rungs high, marker lowG_MARKER
6four rungs high, FEC lowG_FEC
7block high with clock lowvector_not_monotone — a PHY fault
8all 32 vectors driven26 of them assert vector_not_monotone
9single_lane set, marker lowmarker reads passed; G_FEC or none
10rungs_passed on reading 110002
11gates above failed_gatereported as not-attempted, never as failed

MDIO evidence — 10 scenarios.

#ScenarioExpected
12every reading normal except an_complete2 candidates — our AN, or their config
13the same plus flp_bursts_seen low1 — their config
14the same plus bursts present1 — our AN state machine
15on a fibre link, no pulses existthe pair stays fused — Section 9
16remote_fault_rx asserted, ladder complete1 candidate — our transmitter
17signal low5 candidates — the dark class
18the nine other readings on that faultnone narrows it
19sample_age_us = 2 000evidence_stale; no verdict
20an absent register reading zeroindistinguishable from a real zero
21all ten readings normal, link down1 candidate — the elastic buffer

Party attribution — 9 scenarios.

#ScenarioExpected
22candidates all in LOCAL_SITESsingle_party; next_action = register
23candidates all mediumneeds_physical_access
24candidates all remoteneeds_partner; next_action = phone
25the dark classspans all three parties
26candidates_span_parties on itasserts
27n_local + n_medium + n_remoteequals n_candidates, always
28a remote candidate and full local instrumentationstill needs_partner
29the party maskspartition ALL_SITES exactly
30a mask spanning two partiesmay be two faults — Section 18's row six

The instruments — 10 scenarios.

#ScenarioExpected
31loopback requested while link is uprefused
32loopback before the MDIO sweeploopback_out_of_order
33loopback passessites 1 to 5 eliminated
34loopback passes, transmitter still dead on the wirenot detected — Section 11's limit
35SETTLE_MS shorter than block lock's taila false fail — Chapter 3.8 §11
36pulses, no bursts, window elapsedpartner_is_forced
37bursts arriving, AN incompletewe_cannot_parse
38silenceboth outputs low — no conclusion from nothing
3999 ms elapsedwindow_elapsed low; no verdict yet
40DDM power reading availableattenuation separates — and it is not MDIO

Flapping — 9 scenarios.

#ScenarioExpected
41five link transitions in 60 sis_flapping
42lane 2 owns 9 of 10 transitionsone_lane_dominates; worst_lane = 2
43transitions spread evenlyis_flapping, not one_lane_dominates
44the combined bit alone on bothidentical — Chapter 3.8 §10
45elastic overrunlossy_flap; data was lost
46elastic underrunelastic_suspected, not lossy_flap
47a shared elastic error counterthe two read identically — Chapter 4.4 §9
48counters started after the ticketzero transitions; no evidence
49uptime_s after an hour up then four flapsreads healthy — the block's known defect

Method selection and the ceiling — 9 scenarios.

#ScenarioExpected
50frames_in = 0, link_up lowis_link_down; this chapter
51frames_in = 0, link_up high — an idle portNOT link-down; Section 18's row two
52Chapter 21.1's method run on a dead linkconverges on class G — five wrong sites
53wrong_method_running on thatasserts
54best_possible with no partner, no loopback5, before any reading
55with loopback4
56with the partner3
57with both3 — the loopback adds nothing
58the three unseparable sitesunseparable_remains, and a $display

And the directed test, because random stimulus will not produce it.

The case: one symptom, five parties broken in turn, and the diagnosis must attribute each one correctly using only what a local machine can read.

A constrained-random frame generator reaches none of this. The variable is which party is faulty, and three of the five settings are not in our design at all — a cable, a far-end transmitter, a far-end configuration. Chapter 20.5 §10 split injections into what a wire can produce and what needs a fault inside the design; this test needs a third category: faults inside somebody else's design.

RunWhat is brokenParty
Aour block-lock alignerlocal
Bthe cable, unpluggedmedium
Cone strand of the fibre pairmedium, asymmetric
Dthe far end's transmitterremote
Ethe far end configured for a forced speedremote

The oracle is four-part and every part is a register or a bit.

PartABCDE
our failed_gateG_BLOCKG_SIGNALnone — ladder completeG_SIGNALnone
our remote_fault_rxabsentabsentASSERTEDabsentabsent
candidates, MDIO alone25152
candidates, with the partner23122

Row two is the test's most instructive line and run C is why. A single broken strand of a fibre pair leaves our receive ladder complete — we hear them perfectly — and the only evidence anything is wrong is that they told us. remote_fault_rx is the one local reading that is not about us, and on run C it is the entire diagnosis.

Run C also exposes the fault space's own gap. Section 18's row seven: a single broken strand and a dead local transmitter have identical signatures, so run C's "1 candidate" is site 1 — our transmitter — and the answer is the cable. The diagnosis is confidently wrong, and it is wrong because the site list has fourteen members and should have fifteen.

Runs B and D are the dark class from both sides, and the contrast with run C is the point: B and D are symmetric faults and stay fused at five candidates until the partner speaks; C is asymmetric and is named by one bit. Asymmetry is what a second observation detects, and a fault that is symmetric in both directions is the one that defeats every observer.

Run E needs no fault at all. A far end configured for a forced speed is a correctly working device, and every gate on our ladder passes. It is in this chapter because the ticket says the link is down, and it is the case Chapter 11.1's parallel detection was built for — which is why Section 9 exists and why it stops working on fibre.


Six complaints.

Complaint 1 — "every counter is zero so we have no information."

CheckIf yesMeaning
is link_up low?yesthis chapter, not Chapter 21.1
was Chapter 21.1's method run?yesit produced five wrong candidates
have the MDIO gates been read?nothere is the information
what is failed_gate?the answer's first halfSection 4

The counters being zero is not an absence of information; it is a statement that the wrong instrument was consulted. A link with no frames has a status vector, and Chapter 3.4 §13's ordered vector names the rung. The information is in a different register file, on a different bus, behind a driver most monitoring systems do not call.

Complaint 2 — "we replaced the cable and the optic and it is still down."

CheckIf yesMeaning
is signal_detect still low?yesstill the dark class
did anybody ask the far end?notwo of five candidates are theirs
is their port administratively down?oftenSection 17 — one register, at the other end
how many substitutions so far?twoand neither could have resolved it

Substitution resolves the medium's two members and cannot resolve the remote's. Attenuation and a wrong optic are 2 of the 5; their transmitter and their admin state are another 2, and no amount of swapping at this end touches them. The phone call is cheaper than the second optic and it is made third.

Complaint 3 — "the status vector says four gates failed."

CheckIf yesMeaning
is the lowest failed gate block lock?yesone gate failed
are marker, deskew and FEC also low?yesthey were never attempted
does the display distinguish them?nothat is the defect
is the vector monotone?yesso the reading is fine

Four red indicators naming one fault is Section 14's second prohibition and it is a display problem rather than a link problem. Chapter 3.8 §2's dependencies mean a gate above the lowest failed one cannot have been tried, and rendering "not attempted" the same as "failed" turns a precise diagnosis into a wall of alarm.

Complaint 4 — "the ladder reads 10100 and that is impossible."

CheckIf yesMeaning
vector_not_monotone?yescorrectly flagged
how many MDIO transactions?ten, sequentialChapter 4.5 §7's sample age
how long did the sweep take?about a millisecondand bring-up is a distribution
is the link actively searching?yesit passed rungs during the read

It is not impossible; it is not simultaneous. Chapter 3.8 §11 showed block lock is evidence-driven and data-dependent — a link can pass three rungs inside a millisecond — so ten sequentially-timed reads of a moving target produce an inconsistent vector from a perfectly healthy PHY. The fix is a latched snapshot, five flops; the workaround is to re-read and require two consistent sweeps.

Complaint 5 — "the link comes up and drops every few minutes."

CheckIf yesMeaning
is this a bring-up failure at all?noSection 13 — site 8, a different symptom
one_lane_dominates?yesone lane, not a budget — Chapter 3.8 §10
which lane?worst_laneand that names a fibre in a ribbon
elastic_overrun?if set, data was lostChapter 4.4 §9

Row two is the split that decides the fix. One lane owning three quarters of the transitions is one fibre, one connector or one lane's receiver — a component; transitions spread evenly across lanes is a link budget — a distance, a patch count, a dirty connector everywhere. The combined link_up trace is identical for both, and the per-lane counters are 64 flops.

Complaint 6 — "the diagnosis says our transmitter and we replaced the optic."

CheckIf yesMeaning
is our receive ladder complete?yeswe hear them
is remote_fault_rx asserted?yesthey do not hear us
is this fibre?yestwo strands, and one can break alone
is site 15 in the list?noSection 18's row seven — the space is short one member

A unidirectional medium fault and a dead local transmitter are the same signature and only one of them is in the fault space. Swapping the optic is the right first action and it is right for the wrong reason; the second action is swapping the strands, which costs nothing and resolves it.

Complaint 7 — "the monitoring system opened a link-down ticket for two hundred ports."

CheckIf yesMeaning
what triggered it?frames_in = 0Section 18's row two
is link_up high on those ports?yesthey are idle, not down
how many are genuinely down?usually nonethe test was wrong, not the ports
what is the correct trigger?!link_upone signal, and it already exists

An idle port and a down port both have frames_in at zero, and on a lightly loaded switch most ports are idle most of the time. The wrong trigger is the natural one for anybody who has just finished writing Chapter 21.1's method, where frames_in is the first thing read — and it turns a diagnostic into a pager storm.

And the three symptoms this chapter is systematically blamed for:

SymptomBlamed onUsually is
"we have no information"the instrumentationthe wrong register file was read
"four gates failed"the linkthree were never attempted
"the vector is impossible"the PHYten reads of a moving target

23. Misconceptions

Misconception 1 — "a link that is down gives you nothing to work with."

The wrong model: all the counters read zero, so there is no evidence.

What it costs: it sends an investigation straight to substitution — swap the cable, swap the optic — skipping ten readings that would have named a rung. Chapter 3.4 §13's ordered status vector exists precisely for this, and it is worth 2.585 bits: enough to reduce fourteen candidates to a class, before anybody walks to a rack.

The corrected model: the counters are the wrong instrument, not an absent one. A down link has a status vector, an FLP presence bit and a remote-fault bit, and together they separate the fourteen sites into nine classes. Section 12's procedure spends four free readings before the first destructive one.

Misconception 2 — "block lock is low, so our PCS is broken."

The wrong model: the register is in our chip, so it describes our chip.

What it costs: every register in our PHY describes what arrived at our receiver, and what arrived is a function of three parties — our receiver, the medium, and their transmitter. A failing block lock has two candidates in Section 6's table and one of them is a connector installed backwards. Concluding "our PCS" is right about half the time and wrong in a way that costs a chip investigation.

The corrected model: a receive-side gate names a rung, not a site. Section 7's attribution splits the survivors by party, and the party decides whether the next step is a register read, a screwdriver or a phone call — three costs that differ by orders of magnitude.

Misconception 3 — "five status registers is five bits of diagnosis."

The wrong model: the vector has five independent bits, so thirty-two readings.

What it costs: Chapter 3.8 §2's five dependencies make the chain monotone, so six of the thirty-two readings are reachable and the other twenty-six are PHY faults. The vector carries 2.585 bits, not 5.000 — and a diagnosis budgeted on five bits expects the vector to do twice the work it can.

The corrected model: the ordering is what makes the vector useful and it is also what caps it. A single link_up bit is 1.000 bits; the ordered vector is 2.585; the gain is real, it is 1.585 bits, and it is not four.

Misconception 4 — "more registers would resolve the dark class."

The wrong model: five fused sites means the PHY needs more status bits.

What it costs: on the dark class zero of the ten existing readings narrows anything, because signal_detect low forces four of the others low by monotonicity and the rest describe a signal that is not there. An eleventh local register would be the same nothing. The class is symmetric — dark in both directions — and a protocol that communicates over a link cannot report on a link that carries nothing.

The corrected model: the dark class is broken by a second observer or a different bus. The partner's link status splits it five into two and three; optical power over DDM splits attenuation off quantitatively; the rest is substitution. Section 17 is the honest limit and it is not an instrumentation gap.

Misconception 5 — "run the standard diagnostic procedure."

The wrong model: Module 21 has a method; apply it.

What it costs: Module 21 has two methods, correct on disjoint inputs, and each produces a confident wrong answer on the other's. Chapter 21.1's procedure on a link with no frames reads every counter as zero, eliminates every site each counter watches, and converges on the five sites past the MAC — none of which is the fault and all of which are downstream of a link that never came up.

The corrected model: one comparison routes between them. link_up low is this chapter; frames exist is Chapter 21.1. Section 16's wrong_method_running is the guard, and the failure it prevents is not that the wrong method fails — it is that the wrong method succeeds.

Misconception 6 — "the link is flapping, so the link is marginal."

The wrong model: link_up toggling means the whole link is near its budget.

What it costs: Chapter 3.8 §10's asymmetry — a link is up only when every lane is locked, so the combined bit is dominated by the worst lane. One lane cycling produces exactly the same link_up trace as four lanes all marginal, and the fixes are a single fibre and a whole link budget. A team that reads "marginal" shortens the run or adds a repeater when one connector needed cleaning.

The corrected model: keep the per-lane transition counts. Three quarters on one lane is a component; evenly spread is a budget. Sixty-four flops for four lanes, and they must be free-running from reset, because a flap leaves no evidence after it stops.


24. Interview Questions

Question 1 — "A link will not come up and every counter reads zero. Where do you start?"

What the answer should establish: that the counters are the wrong instrument and the status vector is the right one. A strong answer names it: Chapter 3.4 §13's ordered vector, read over MDIO, whose lowest deasserted bit names the rung. The strongest answer adds the guard: do not run the frame-based procedure — it will converge, confidently, on five sites that are all downstream of a link that never came up.

Question 2 — "Block lock is low. Is your PCS broken?"

What the answer should establish: possibly, and there are two candidates. Every register in our PHY describes the receive direction, so a failing gate implicates our receiver, the medium and their transmitter at once. A strong answer names the second candidate: an inverted pair or a swapped lane looks exactly like an aligner that cannot find block boundaries — the bits are there, the timing is recovered, the content is scrambled.

Question 3 — "How much diagnosis is in a five-bit status vector?"

What the answer should establish: 2.585 bits, not 5. The ladder is monotone — a gate can pass only if every gate below it has — so six of the thirty-two readings occur and the other twenty-six would be a PHY fault. A strong answer says why that is still worth having: a single link_up bit is 1.000 bits, so the ordering buys 1.585 and names a rung. The strongest adds that gates above the lowest failed one were not attempted, not failed.

Question 4 — "What is a cooperating partner worth?"

What the answer should establish: one bit, and it is the only balanced question in the space. partner_link_up is abnormal at seven of fourteen sites — exactly half — where the best local reading is 0.985 and the five ladder bits share 2.585 between them. A strong answer says what it buys concretely: nine classes become eleven and the largest falls from five to three, because the two splits it makes are the asymmetric faults that are invisible from either end alone.

Question 5 — "Your local loopback passes. What have you proved?"

What the answer should establish: that our receive chain works and our transmitter emits something the internal path can parse. A strong answer states the limit immediately: it says nothing about power, wavelength or polarity, so an optic that cannot drive a real medium passes. The strongest answer notes the cost and the ordering: a loopback breaks the link and restarts a bring-up search, so it comes fourth, after the MDIO sweep, the pulse check and the phone call.

Question 6 — "Which link faults can you never separate from one end?"

What the answer should establish: three — attenuation, a wrong optic, and a far-end port that is administratively down. All three are dark in both directions, so every instrument in the Ethernet management path sees the same nothing, and they stay fused under MDIO, under loopback, under a cooperating partner and under all three. A strong answer names what does split them: received optical power over DDM — a different bus — the optic's part number, and a question asked of a person.


25. Questions and Answers


26. What's Next

Module 21 has five chapters left, and this one has drawn the boundary the rest sit inside.

ChapterTakesFrames exist?
this chapterthe link never comes upno
Chapter 21.5it comes up wrongyes, and some of them collide
Chapter 21.6Chapter 21.1 §4's class Gyes
Chapter 21.7Chapter 19.6's descriptorsyes
Chapter 21.8a healthy link that is slowyes, and none of them is wrong

Chapter 21.5 is the near neighbour and the boundary between them is worth stating. A link that comes up at the wrong duplex has completed every rung of Section 2's ladder — the fault is in what the two ends agreed, not in whether they can hear each other — and the symptom is frames, collisions and a throughput figure rather than a status vector. Chapter 11.4 already built the many-to-many symptom matrix and class 48; the next chapter prices it, because a duplex mismatch's cost is a function of load and the load is what decides whether anybody notices.

Chapter 21.6 is the batch's hardest and it is the one this module has been deferring since Chapter 21.1 §4. Five sites, byte-identical on every RMON-required counter, and Chapter 21.3 §17 priced the four counters that would separate them at about 297 flops. The question that chapter will answer is what can be done without them — and the only instrument in a MAC that is conditioned on size is Chapter 19.7 §2's histogram, which is exactly what an MTU mismatch is visible in.

And the series is now ninety-seven classes long. Chapter 20.2 §8's six-group taxonomy took an eighth group in Chapter 21.2 §26 — a property bound to the wrong side of a function, holding 93 through 96. Class 97 is not a member of it. It is about a property that is bound to exactly the right thing and stops being evaluated, which is a property of the stimulus rather than of the binding — and 332 of the track's 557 published properties share it. Whether that is a ninth group or a sharpening of group 4's "unevaluable" is the argument Chapter 21.6 will have to have, because a chapter about five indistinguishable sites is where a taxonomy of indistinguishability belongs.


Continue learning

Standards & specifications

Governing standard
IEEE Std 802.3 (Ethernet)(opens IEEE in a new tab)

Defines the Ethernet MAC, the media-independent interfaces and the physical-layer sublayers, including framing, access control, auto-negotiation and per-rate PHY specifications. VLAN tagging, priority and time-sensitive shaping are defined by IEEE 802.1, not by 802.3.

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 Ethernet curriculum.