Skip to content
VLSI Mentor

Ethernet · Module 21

Packet Drops

Five sites, one signature, and two ratios over counters that already exist take them to three classes — plus the finding that two of the four optional counters are nearly redundant.

Chapter 21.1 §4 found five fault sites with one signature between them and deferred the problem. This is the chapter that takes it.

SiteWhy the frame vanishedIs it an error?
the address filternot addressed to this portno — Chapter 7.4
VLAN membershipthe port is not in that VLANno — Chapter 13.2
the receive FIFOthe consumer stalledno — Chapter 19.5 §14
the DMA pathno descriptor, or a buffer too smallno — Chapter 19.6
the host driverbuffers not reapedno

Every one of the five is a legal discard, so no error counter moves, so the RMON set is silentChapter 21.2 §10 established exactly why: the standard counts errors and none of these is one. Chapter 21.3 §17 priced the four counters that would separate them at about 297 flops.

This chapter asks what can be done without them, and the answer is two ratios over counters every MAC already has.

Value
classes the RMON six separate the five sites into1
classes two free ratios separate them into3
largest class after the two ratios3
hardware addednone
classes the four optional counters give5
hardware they cost~297 flops

And the first of the two ratios is the chapter's headline, because it separates two runs that are identical in every aggregate number.

Run ARun B
frames received1 000 0001 000 000
frames delivered600 000600 000
total loss40.0%40.0%
mean received size645.6 octets645.6
mean delivered size645.664.0
selectivity index1.0000.099

Every number a monitoring system collects is identical in the two columns except the last two, and the last two come from octet counters the RMON set already requires. Run A is a flat drop — a filter, a full ring, a stalled driver. Run B dropped every large frame and nothing else, which is one site of the five.


1. Scope, and Five Sites With One Signature

Scope: the frames that vanish without incrementing anything. Which of the five sites produced them, what free evidence separates which, and what the four optional counters buy that the free evidence cannot.

Not in scope: the drops that do increment something. Chapter 21.2 §12's thirteen classes cover those — a bad check value, an alignment error, a runt, a giant — and every one of them has a counter. Nor a mid-frame truncation: Chapter 19.5 §14 makes that a fragment, which is an error class, so it leaves class G by being visible.

Start from the exact statement of the problem, because the previous chapters have narrowed it precisely.

Chapter 21.1 §2's incidence table gives the five sites one row between them:

ReadingFilterVLANFIFODMADriver
c_crc_errorsnonononono
c_alignment_errorsnonononono
c_undersizenonononono
c_oversizenonononono
frames_inhealthyhealthyhealthyhealthyhealthy
frames_outshortshortshortshortshort

Six readings, five sites, one signature — and Chapter 21.1 §6 measured what that costs: the RMON six separate twelve fault sites into seven classes, and this is the class that holds five of them.

Chapter 21.2 §10 explained why it is five and not one or zero.

NeedsDecided by
filteredthe address tableconfiguration
VLAN discardport membershipconfiguration
buffer dropFIFO occupancythe system's timing
descriptor errorthe host's ring statesoftware
driverthe host's schedulingsoftware

None of the five is a property of the frame, so none of them is a predicate a receiver can evaluate from the octets it holds — and the RMON standard specifies counters for frame properties. The omission is principled and it is what produces the class.

Three things this chapter is and is not.

Choice
it uses only counters that already existthe four optional ones are the comparison, not the method
it works on aggregate counters, not per-frame datathere is no per-frame data — the frames are gone
it stops at three classesand says which three, and why not five

Row two is the structural constraint and it is worth stating early. Every other chapter in Module 21 reasons about frames that arrivedChapter 21.3 bins them by residue, Chapter 21.5 by size. These frames did not arrive anywhere, so the only evidence is what the aggregate counters say about the ones that did, and the whole of Sections 4 to 12 is what can be inferred from a difference between two populations.


Five sites in the receive path can remove a frame without any error counter moving. The address filter discards a frame not addressed to this port. Virtual local area network membership discards a frame for a network the port is not in. The receive buffer discards a whole frame when it is full at the frame's start. The direct memory access path discards a frame when no descriptor has been posted, and separately when the posted buffer is smaller than the frame. And the host driver discards one when it has not reaped its buffers. That is five sites and six mechanisms. Every one of them removes a frame the receiver judged valid, which is why no error counter moves: the remote monitoring standard counts frames the receiver judged invalid, and none of these is. So the signature across the six required counters is identical for all five sites: no check sequence errors, no alignment errors, no undersize, no oversize, a healthy received frame count and a short delivered count. Six readings, five sites, one signature, which is the largest indistinguishable class in the whole of the debugging module.Address filternot for usVLAN membershipnot our networkReceive FIFOfull at start-of-frameDMA: ring orbuffertwo mechanismsHost driverbuffers not reapedEvery frame wasvalidso nothing is an errorThe RMON sixall read the sameOne class of five21.1 Section 412
Figure 1 — five sites, six mechanisms, and one signature across every required counter.

The RMON counter set is not incomplete by oversight. It counts a specific thing and these five are not it.

An RMON error counter records a frame the receiver judged invalid. A class G drop is a frame the receiver judged valid and then did not deliver.

InvalidValid, not delivered
decided bythe octetsconfiguration or system state
Chapter 7.3 covers ityesno
a required counter existsyes, six of themno
the frame wasdamagedperfect

Row four is the distinction that matters operationally. A frame dropped by the address filter was a correct frame that the port was correct to discardChapter 7.4's whole purpose. Counting it as an error would make every switch port on a shared segment report a permanent fault, which is why nobody does.

And the five divide into two groups by who decides.

GroupSitesDecided byChanges when
configurationfilter, VLANa table somebody wrotesomebody changes it
system stateFIFO, DMA, drivertiming and memory pressurecontinuously

That split is the chapter's second free axis and Section 10 measures it. A configuration drop is steady — the same share of traffic, hour after hour, because the table does not change. A system-state drop is an event: a stall, a burst, a scheduling gap, and it clusters in time.

One more property of the five, because it decides what the free evidence can reach.

SiteDoes the drop depend on the frame's size?
the address filterno — the decision is in the first six octets
VLAN membershipno — the decision is in the tag
the receive FIFO, whole-frame dropno — the decision is at start-of-frame
the DMA, no descriptor postedno — the ring is empty or it is not
the DMA, buffer smaller than the frameYES — a hard threshold
the host driverno

One of the six mechanisms is size-selective and five are not, which bounds what Section 6's index can do before any measurement is taken: it names one site and rules out the rest. Whether that is worth having is Section 17's arithmetic, and the answer is yes, because it costs nothing and it names the site whose symptom is the most confusing.


3. RTL 1 — The Drop Package and the Class-G Mask

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// dropdiag_pkg -- five sites, six mechanisms, and the two free axes
// that separate them.
//
// The package's one claim: the evidence available is two RATIOS over
// counters that already exist, and neither of them is a drop counter.
// A drop counter for these sites is exactly what does not exist.
// ---------------------------------------------------------------------
package dropdiag_pkg;

  // Chapter 21.1 Section 4's class G, and the DMA appears twice
  // because it has two mechanisms with different signatures.
  typedef enum logic [2:0] {
    G_FILTER   = 3'd0,
    G_VLAN     = 3'd1,
    G_FIFO     = 3'd2,
    G_DMA_RING = 3'd3,   // no descriptor posted
    G_DMA_SIZE = 3'd4,   // descriptor buffer smaller than the frame
    G_DRIVER   = 3'd5,
    G_NONE     = 3'd7
  } gsite_e;

  typedef logic [5:0] gmask_t;
  localparam gmask_t ALL_G = 6'b11_1111;

  // Section 2's two groups. Configuration drops are steady because a
  // table does not change; system-state drops are events.
  localparam gmask_t CONFIG_SITES = 6'b00_0011;  // filter, VLAN
  localparam gmask_t STATE_SITES  = 6'b11_1100;  // FIFO, ring, size, driver

  // Section 2's size axis. Exactly one mechanism is size-selective.
  localparam gmask_t SIZE_SELECTIVE = 6'b01_0000; // G_DMA_SIZE
  localparam gmask_t SIZE_FLAT      = 6'b10_1111;

  // The selectivity index, in parts per thousand of 1.000. A flat
  // drop reads 1000; a drop that removes only large frames reads far
  // below it; one that removes only small frames reads above.
  localparam int S_FLAT_PPT = 1000;
  localparam int S_TOLERANCE_PPT = 30;    // Section 6's sensitivity

  function automatic int popcount6(gmask_t m);
    int n = 0;
    for (int i = 0; i < 6; i++) if (m[i]) n++;
    return n;
  endfunction

  // Section 12: the three classes two free ratios produce.
  localparam gmask_t CLASS_SELECTIVE = 6'b01_0000;  // 1 site
  localparam gmask_t CLASS_STEADY    = 6'b00_0011;  // 2 sites
  localparam gmask_t CLASS_CLUSTERED = 6'b10_1100;  // 3 sites

endpackage

Classification: a package whose site list has six members for five sites, and the duplication is the point.

What it teaches: that the DMA path has two mechanisms with opposite signatures and treating it as one site loses the only free discrimination available. A ring with no posted descriptors drops every frame equally; a descriptor buffer smaller than the frame drops only the frames above its size. Same block, same counter, and one of the two is the single size-selective mechanism in class G.

And it teaches that the two free axes are orthogonal by construction. CONFIG_SITES against STATE_SITES splits by who decides — a table or the system's timing — and SIZE_SELECTIVE against SIZE_FLAT splits by the frame's length. Neither axis is derived from the other, so the two together give at most four classes and in practice give three, which Section 12 works out.

Deliberately simplified: S_TOLERANCE_PPT of 30 is a judgement against Section 6's sensitivity analysis, which showed a 10% large-frame loss shifts the index by 56 parts per thousand — so the tolerance admits anything below about a 5% selective loss. The site enum has no representation of two simultaneous mechanisms. And CLASS_CLUSTERED contains G_DMA_SIZE's sibling G_DMA_RING alongside the FIFO and the driver, which means the DMA path appears in two of the three classes — correct, and awkward to report.

Production implication: the awkwardness is worth keeping rather than smoothing away. A diagnosis that says "the DMA path, or the FIFO, or the driver" and separately "the DMA path" is telling an operator something true: the DMA is a candidate under both shapes, for two different reasons, and the two reasons have different fixes — post more descriptors, or make the buffers large enough for the MTU. Collapsing the enum to five sites would report one candidate where there are two questions.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// mean_size_tracker -- the mean frame size on each side of the MAC,
// from counters the RMON set already requires.
//
// Received octets and received frames give the mean that arrived.
// Delivered octets and delivered frames give the mean that survived.
// Their ratio is Section 6's index, and no new counter is involved.
// ---------------------------------------------------------------------
module mean_size_tracker
  import dropdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  // Receive side -- RMON requires both of these.
  input  logic [47:0] octets_in,
  input  logic [31:0] frames_in,

  // Delivered to the host. Every DMA engine counts both.
  input  logic [47:0] octets_delivered,
  input  logic [31:0] frames_delivered,

  output logic [15:0] mean_in,
  output logic [15:0] mean_delivered,
  output logic [31:0] frames_lost,
  output logic [15:0] loss_ppt,
  output logic        both_sides_valid
);
  always_comb begin
    mean_in = (frames_in == 32'd0) ? 16'd0
            : 16'(octets_in / 48'(frames_in));

    mean_delivered = (frames_delivered == 32'd0) ? 16'd0
                   : 16'(octets_delivered / 48'(frames_delivered));

    frames_lost = (frames_in > frames_delivered)
                ? (frames_in - frames_delivered) : 32'd0;

    loss_ppt = (frames_in == 32'd0) ? 16'd0
             : 16'((frames_lost * 32'd1000) / frames_in);

    // Both means need a population. Below a thousand frames the means
    // are dominated by whatever happened to arrive.
    both_sides_valid = (frames_in > 32'd1000) && (frames_delivered > 32'd1000);
  end
endmodule

Classification: four divisions over four counters, and every one of the four is already required.

What it teaches: that the octet counters are the instrument and nobody uses them for this. RMON requires octets alongside frames on the receive side, and every DMA engine counts bytes delivered because a driver needs them — so both means are computable today, on any platform, with no change at all. The reason nobody computes them is that a mean frame size looks like a traffic statistic rather than a diagnostic.

And it teaches that both_sides_valid is not a formality. A mean over a few hundred frames is dominated by whichever sizes happened to arrive, and the index Section 6 builds is a ratio of two such means — so the noise compounds. A thousand frames on each side is a floor rather than a target.

Deliberately simplified: the divisions are combinational over 48-bit octet counters, which is four wide dividers and belongs in software. There is no windowing: the means are since reset, so a fault that began an hour ago is diluted — the same gap Chapter 21.3 §3 flagged for its size cross. And octets_delivered is assumed to count the same octets as octets_in, which a DMA engine that strips the check value before delivery does not: a four-octet-per-frame bias that shifts the index by about 0.6% at this traffic mix.

Production implication: the check-value stripping bias is real and it is the one systematic error in the method. If the receive path delivers the frame without its four-octet check sequence — which most do — then mean_delivered is understated by exactly four octets. At a mean of 645.6 that is 0.62%, well inside Section 6's 3% tolerance and comfortably outside it on a link carrying only minimum-size frames, where four octets of sixty-four is 6.25%. The correction is one subtraction and it must be applied before the index is believed on small-frame traffic.


4. What the Size Histogram Actually Bins

The obvious instrument for a size-conditioned diagnosis is Chapter 19.7 §2's RMON histogram, and it does not do what this chapter needs.

What RMON's histogram bins
sidereceive only
populationframes that arrived at the port
what it can computethe size distribution of arrivals
what it cannot computethe size distribution of deliveries

A per-bucket delivery ratio would name every size-selective mechanism immediately — a step at the descriptor buffer size, a slope with occupancy, a flat line for a filter — and it requires a second histogram on the delivered side, which no standard requires and few implementations have.

CountersFlops
a second, delivered-side size histogram7~693
Chapter 21.3 §17's four optional counters4~297

The size-conditioned route costs more than twice the direct one and separates fewer sites, which is the honest answer to whether it is the way to attack class G. It is not. Chapter 21.1 §8's argument applies unchanged: the counters that observe a non-error are the ones that separate non-error drops, and there is no clever substitute.

What is available for nothing is a projection of the same information onto one number.

A histogram is a distribution. A mean is one moment of it. The delivered-side mean is free because the octet and frame counters already exist; the delivered-side histogram is not free because it does not.

Delivered-side histogramDelivered-side mean
cost~693 flops0 — both counters exist
detects a stepyes, and locates ityes, and does not locate it
detects a slopeyesyes, weakly
distinguishes step from slopeyesno
detects a flat dropyesyes — the index reads 1.000

Row four is what the free instrument gives up, and Section 8 argues it does not matter much: only one mechanism in class G is size-selective at all, so distinguishing a step from a slope separates nothing that is not already separated.

And there is one more thing the received-side histogram alone can do, which is worth noting because it is outside class G.

ObservationMeans
no frames arrive above some sizesomething upstream is not forwarding them
that is not one of the five sitesit is a path MTU problem, before us
the evidencea truncated arrival distribution

A hard absence of arrivals above a threshold is a path problem rather than a port problem, and it is visible in the received histogram with no second instrument. It is the one size-conditioned diagnosis the existing hardware fully supports, and it is about a site that is not ours.


5. RTL 2 — The Selectivity Index

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// size_selectivity_index -- one ratio, four existing counters, and it
// separates a flat drop from a size-selective one.
//
// S = mean(delivered) / mean(received). A drop that removes frames
// without regard to size leaves the mean unchanged and S reads 1.000.
// A drop that removes large frames pulls the mean down.
// ---------------------------------------------------------------------
module size_selectivity_index
  import dropdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [15:0] mean_in,
  input  logic [15:0] mean_delivered,
  input  logic        both_sides_valid,
  input  logic [15:0] loss_ppt,
  input  logic        fcs_stripped_on_delivery,

  output logic [15:0] s_index_ppt,
  output logic        s_valid,
  output logic        drop_is_flat,
  output logic        drops_large_frames,
  output logic        drops_small_frames,
  output logic        below_detection_floor
);
  logic [15:0] mean_corrected;

  always_comb begin
    // Section 3: a receive path that strips the four-octet check value
    // before delivery understates the delivered mean by exactly four.
    // At a 645-octet mean that is 0.62%; on minimum-size traffic it is
    // 6.25% and it dominates the measurement.
    mean_corrected = fcs_stripped_on_delivery ? (mean_delivered + 16'd4)
                                              : mean_delivered;

    s_index_ppt = (mean_in == 16'd0) ? 16'd0
                : 16'((32'(mean_corrected) * 32'd1000) / 32'(mean_in));

    s_valid = both_sides_valid;

    drop_is_flat = s_valid &&
      (s_index_ppt > (16'(S_FLAT_PPT) - 16'(S_TOLERANCE_PPT))) &&
      (s_index_ppt < (16'(S_FLAT_PPT) + 16'(S_TOLERANCE_PPT)));

    drops_large_frames = s_valid &&
      (s_index_ppt <= (16'(S_FLAT_PPT) - 16'(S_TOLERANCE_PPT)));

    drops_small_frames = s_valid &&
      (s_index_ppt >= (16'(S_FLAT_PPT) + 16'(S_TOLERANCE_PPT)));

    // Section 6: the index moves 5.63% for a 10% large-frame-only
    // loss. Below about a 4% total loss the shift is inside the
    // tolerance and the instrument says nothing.
    below_detection_floor = s_valid && (loss_ppt < 16'd40);
  end
endmodule

Classification: a single division whose value is entirely in what its two operands are.

What it teaches: that a flat drop leaves the mean exactly unchanged, and that is an identity rather than an approximation. Removing a random 40% of frames removes 40% of the octets too, so both the numerator and the denominator of the delivered mean fall by the same factor and the mean is untouched. The index reads 1.000 and it reads it precisely — which makes any departure from 1.000 evidence rather than noise.

And it teaches that the check-value correction is not cosmetic. Four octets of 645.6 is 0.62% and four octets of 64 is 6.25%more than twice the tolerance. On a link carrying control traffic, an uncorrected index reads 0.938 and drops_large_frames asserts on a perfectly healthy link. The correction is one addition and the flag that says whether to apply it is a property of the DMA engine.

Deliberately simplified: S_TOLERANCE_PPT of 30 is a judgement, and the right value depends on the traffic's size variance — a link carrying one frame size has an index that is exactly 1.000 or exactly the ratio of two sizes, with nothing in between. The index is computed since reset with the same windowing gap as Section 3. And drops_small_frames is implemented and has no member in class G: no mechanism in the five drops small frames preferentially, so an assertion of it means the model is wrong for this platform.

Production implication: drops_small_frames firing is the most informative thing this block can do and it is not in the fault space. Nothing in class G removes small frames preferentially — a filter is size-blind, a ring is size-blind, a buffer-size mismatch removes the large ones. So an index above 1.030 is a fault outside the five sites: a policer configured on packet rate, a queue with a minimum-length discipline, or an upstream device doing something nobody documented. It is the chapter's contradiction, and it is worth a distinct message rather than being folded into "not flat".


6. The Size-Selectivity Index, and Two Runs With the Same Loss

Take a bimodal traffic mix of sixty per cent minimum size frames and forty per cent maximum size ones. The mean received frame size is six hundred and forty five point six octets. Now drop forty per cent of the frames two different ways. In the first run the drop is flat: frames are removed at random without regard to their size. Because a random share of frames carries the same share of octets, the delivered octet count and the delivered frame count both fall by the same factor, so the mean delivered size is unchanged at six hundred and forty five point six and the selectivity index, which is the delivered mean divided by the received mean, reads exactly one point zero zero zero. In the second run every maximum size frame is dropped and nothing else. The same forty per cent of frames are lost, but the survivors are all sixty four octets, so the mean delivered size is sixty four and the index reads nought point zero nine nine. Every aggregate figure a monitoring system collects is identical between the two runs: frames received, frames delivered, loss percentage, mean received size. Only the delivered mean differs, and its two operands are the octet and frame counters that the remote monitoring standard already requires on the receive side and that every direct memory access engine already keeps on the delivery side.60% at 64, 40% at1518mean 645.6 octetsRun A: drop atrandom40% lossRun B: drop everylarge40% lossMean delivered645.6unchanged — anidentityMean delivered64.0the survivors aresmallIndex 1.000flatIndex 0.099selectiveEvery othernumberidentical12
Figure 2 — the same loss, the same mean received size, and a tenfold difference in one free ratio.

Take a classic bimodal traffic mix — 60% minimum-size frames and 40% maximum-size ones — and drop 40% of the frames two different ways.

Mean received size
0.60 × 64 + 0.40 × 1 518645.6 octets

Run A drops 40% of frames at random. Run B drops every maximum-size frame and nothing else.

Run A — flatRun B — selective
frames delivered600 000 of 1 000 000600 000 of 1 000 000
total loss40.0%40.0%
mean delivered size645.664.0
selectivity index1.0000.099

Identical in every aggregate figure a monitoring system collects, and different by a factor of ten in one ratio it does not.

The index across the whole range of selectivity:

What is droppedTotal lossIndex
40% at random40.0%1.000
10% of the large frames only4.0%0.944
25% of the large only10.0%0.850
50% of the large only20.0%0.662
all of the large40.0%0.099
all of the small60.0%2.351

The index is monotone in selectivity and independent of the loss rate, which is the property that makes it usable: run A's 40% loss and a 4% loss that is entirely large frames are distinguishable, and the distinguishing number is not the loss.

Now the sensitivity, because an instrument is only as good as the smallest effect it sees.

Large-frame-only lossTotal lossIndexShift from 1.000
2%0.80%0.9891.1%
5%2.00%0.9722.8%
10%4.00%0.9445.6%
20%8.00%0.88311.8%

With a 3% tolerance the instrument detects a selective loss from about 5% of large frames upwarda 2% total loss — and says nothing below that. That floor is the honest limit and it is not tight: 2% total loss is well below most alarm thresholds, so the index reaches faults that nothing else in the free instrument set reaches at all.

Two properties of the index worth stating as rules.

A flat drop reads exactly 1.000, whatever the loss rate. The identity is exact because removing a random share of frames removes the same share of octets.

The index is a shape measurement and the loss is a magnitude one. Neither implies the other, and reporting only the second is why class G has stayed fused.

And one caveat that decides whether the index works on a given link.

TrafficIndex behaviour
a broad size mixworks — the mean has room to move
two sizes, well separatedworks best
one frame size onlythe index is exactly 1.000 or undefined
all minimum-sizeplus the check-value bias, which dominates

Row three is the blind case and it is the same shape as Chapter 21.5 §6's structural zero: a link carrying one frame size cannot have a size-selective drop distinguished from a flat one, because every frame is the same size and selecting by size selects everything or nothing. The instrument is blind and both_sides_valid does not say so — Section 16's monitor does.

One more property of the index that decides how it should be reported, because it is not symmetric.

The index's distance from 1.000 is not proportional to the selectivity. It is a ratio of means, so it is compressed above 1.000 and stretched below it:

What is droppedIndexDistance from 1.000
all large frames0.0990.901
all small frames2.3511.351
half the large0.6620.338
half the small1.3860.386

Removing all the small frames moves the index further than removing all the large ones, even though the second removes far more octets — because the surviving mean is bounded below by the smallest frame present and bounded above only by the largest. The index is compressed below 1.000 and stretched above it, so the two directions are not on the same scale at large effects.

At the detection floor, though, they very nearly are.

Selectivity5% of that population droppedDistance
large framesindex 0.9720.028
small framesindex 1.0280.028

So a symmetric tolerance of 30 parts per thousand gives essentially the same floor in both directions — about five per cent of either population — and the asymmetry only matters for reporting large effects, where the number below 1.000 understates how selective the drop was. A report that quotes the index should quote the mean sizes beside it, because 0.099 and 64 octets against 645.6 are the same fact and only the second is legible.


7. RTL 3 — The Drop-Shape Classifier

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// drop_shape_classifier -- turn the two free ratios into a mask over
// Section 3's six mechanisms.
//
// Two axes, four quadrants, three of them occupied. The fourth --
// selective AND clustered -- has no member in class G, which makes it
// this chapter's contradiction rather than a fourth class.
// ---------------------------------------------------------------------
module drop_shape_classifier
  import dropdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic        s_valid,
  input  logic        drop_is_flat,
  input  logic        drops_large_frames,
  input  logic        drops_small_frames,
  input  logic        clustering_valid,
  input  logic        drop_is_clustered,
  input  logic        below_detection_floor,

  output gmask_t      candidates,
  output logic [2:0]  n_candidates,
  output logic        classified,
  output logic        outside_class_g,
  output logic        instrument_blind
);
  gmask_t by_size, by_time;

  always_comb begin
    // Axis one: the selectivity index.
    if      (!s_valid || below_detection_floor) by_size = ALL_G;
    else if (drops_large_frames)                by_size = SIZE_SELECTIVE;
    else if (drop_is_flat)                      by_size = SIZE_FLAT;
    else                                        by_size = 6'd0;  // small-selective

    // Axis two: steady or clustered. Section 2's configuration group
    // is steady because a table does not change; the system-state
    // group is an event.
    if      (!clustering_valid)  by_time = ALL_G;
    else if (drop_is_clustered)  by_time = STATE_SITES;
    else                         by_time = CONFIG_SITES;

    candidates   = by_size & by_time;
    n_candidates = 3'(popcount6(candidates));

    // A size-selective drop is G_DMA_SIZE, which is in STATE_SITES --
    // but the buffer size does not change, so it is STEADY. The
    // intersection is empty unless the time axis agrees, and when it
    // does not, the model is wrong.
    classified = s_valid && clustering_valid && (n_candidates > 3'd0);

    // Section 5: nothing in class G removes small frames.
    outside_class_g = s_valid && drops_small_frames;

    instrument_blind = !s_valid || below_detection_floor || !clustering_valid;
  end
endmodule

Classification: a two-axis intersection over six mechanisms, and one of its four quadrants is empty by construction.

What it teaches: that outside_class_g is a real terminal state and it is the block's most informative output. No mechanism among the five sites removes small frames preferentially — a filter is size-blind, a ring is size-blind, and a buffer-size mismatch removes the large ones — so an index above 1.030 means the fault is not one of the five. It is a policer, a rate-limiting discipline, or an upstream device, and saying so is worth more than naming a candidate.

And it teaches that G_DMA_SIZE sits awkwardly across the two axes, which is correct. It is a system-state site by ownership and a steady fault by behaviour — a descriptor buffer's size does not change from second to second — so the two axes disagree about it, and the intersection has to be read with that in mind. Section 12's table resolves it explicitly rather than letting the mask do it silently.

Deliberately simplified: by_size returns the empty mask on a small-selective reading rather than a distinct value, so outside_class_g is the only way to tell an empty intersection from a contradiction. The two axes are ANDed with no weighting, where the size axis is far more reliable than the time axis. And instrument_blind folds three different blindnesses into one bit — too few frames, too little loss, too little time — with three different responses.

Production implication: the three blindnesses deserve separating because their fixes differ completely. Too few frames is solved by waiting; too little loss is solved by nothing — the fault is genuinely small; too little time is solved by the clustering window, which must be free-running. A single flag sends an operator to wait in all three cases, and in the second case waiting is exactly wrong: a 1% selective loss is invisible to this instrument at any duration, and the right response is the four optional counters.


8. Which of the Five a Selective Drop Names

Section 2's table has one size-selective mechanism. This section says precisely which and why the others are not.

MechanismWhere the decision is madeSize-selective?
the address filterthe destination address, octets 0 to 5no
VLAN membershipthe tag, octets 12 to 15no
the FIFO, whole-frame dropoccupancy at start-of-frameno
the DMA, ring emptythe descriptor ring's stateno
the DMA, buffer too smallthe frame's length against the buffer'sYES
the driverthe host's schedulingno

Every one of the five "no" rows makes its decision from information available before the frame's length is known — the first six octets, the tag, the FIFO's state at the first beat, the ring's state. A decision taken at the start of a frame cannot depend on how long the frame turns out to be.

The one "yes" row is the only mechanism that compares a length against something.

A descriptor buffer of B octets accepts a frame of L octets if and only if L ≤ B, assuming the driver does not chain descriptors. That is a step function in the frame's length and nothing else in class G has one.

And the step's location is diagnostic on its own.

Buffer sizeFrames droppedTypical cause
2 048 octetsjumbo frames onlyan MTU raised without resizing buffers
1 536 octetsnothing on a standard MTUcorrect
1 518 octetsVLAN-tagged frames at 1 522Chapter 21.2 §18's four octets
256 octetsmost traffica misconfigured small-buffer pool

Row three is the case worth expecting. Chapter 21.2 §18 showed the MTU boundary moves from 1 518 to 1 522 with one VLAN tag and 1 526 with two — and a descriptor buffer sized for an untagged MTU drops exactly the tagged frames, silently, while every error counter stays at zero. The selectivity index sees it and the four-octet difference is invisible to everything else.

Now what the index does not do, stated precisely.

The index
names G_DMA_SIZE when it firesyes
locates the stepno — that needs the delivered-side histogram
separates the other five from each otherno
rules the other five out when it firesyes

Row two is the cost of projecting a distribution onto a mean. The index says "large frames are being removed"; it cannot say at what size the removal begins, and knowing the threshold is what identifies the buffer. The workaround is a bisection with the traffic: send frames at 1 518 and at 1 500 and compare — which is an experiment rather than an observation, and the chapter's only one.

Row four is why the index is worth having despite row two. Firing eliminates five of the six mechanisms, which is 2.58 bits from four counters that already exist — better than any single observation in Chapter 21.1 §6's table except the partner's status in Chapter 21.4.

And there is a cheap experiment that recovers row two, which is worth spelling out because it is the chapter's only active step.

The index says large frames are being removed and does not say above what size. A bisection with the traffic finds the threshold in a handful of steps:

StepSendIf deliveredIf dropped
11 518 octetsthe threshold is above 1 518continue
21 024between 1 024 and 1 518continue
3512between 512 and 1 024continue
4256between 256 and 512below 256 — a small-buffer pool

Four frames locate the threshold to within a factor of two, and the threshold is what identifies the buffer: 2 048 means an MTU raised without resizing; 1 518 means Chapter 21.2 §18's four octets of VLAN tag; 256 means a pool nobody meant to use.

Cost
the bisectionfour frames and the ability to send them
a delivered-side size histogram~693 flops, permanently
what each givesthe same threshold

Four frames against 693 flops is the trade, and the only thing the histogram has over the bisection is that it works retrospectively, on a fault that has already stopped. That is a real advantage and it is not worth 693 flops, because a descriptor buffer's size does not change and the fault does not stop by itself.


9. RTL 4 — The Drop Clustering Probe

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// drop_clustering_probe -- the second free axis: is the loss steady or
// is it an event?
//
// Section 2's split. A configuration drop is a fixed share of traffic,
// hour after hour, because a table does not change. A system-state
// drop happens when something stalls, and a stall has a beginning and
// an end.
// ---------------------------------------------------------------------
module drop_clustering_probe
  import dropdiag_pkg::*;
#(
  parameter int WINDOW_FRAMES = 4096,
  parameter int N_WINDOWS     = 64
)(
  input  logic        clk,
  input  logic        rst_n,

  input  logic        frame_in,
  input  logic        frame_delivered,

  output logic [15:0] c_windows,
  output logic [15:0] c_windows_with_loss,
  output logic [15:0] max_loss_in_window_ppt,
  output logic [15:0] mean_loss_ppt,
  output logic        drop_is_clustered,
  output logic        clustering_valid
);
  logic [15:0] in_win, lost_win;
  logic [31:0] total_in, total_lost;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      in_win <= '0; lost_win <= '0;
      c_windows <= '0; c_windows_with_loss <= '0;
      max_loss_in_window_ppt <= '0;
      total_in <= '0; total_lost <= '0;
    end else begin
      if (frame_in) begin
        in_win   <= in_win + 16'd1;
        total_in <= total_in + 32'd1;
        if (!frame_delivered) begin
          lost_win   <= lost_win + 16'd1;
          total_lost <= total_lost + 32'd1;
        end
      end
      if (in_win == 16'(WINDOW_FRAMES) - 16'd1) begin
        c_windows <= c_windows + 16'd1;
        if (lost_win != 16'd0)
          c_windows_with_loss <= c_windows_with_loss + 16'd1;
        if (((lost_win * 16'd1000) / 16'(WINDOW_FRAMES)) > max_loss_in_window_ppt)
          max_loss_in_window_ppt <= (lost_win * 16'd1000) / 16'(WINDOW_FRAMES);
        in_win <= '0; lost_win <= '0;
      end
    end
  end

  always_comb begin
    mean_loss_ppt = (total_in == 32'd0) ? 16'd0
                  : 16'((total_lost * 32'd1000) / total_in);

    // A steady drop puts its share in EVERY window. A clustered one
    // concentrates it: the worst window is far above the mean and
    // many windows have none at all.
    drop_is_clustered = (c_windows > 16'd8) && (mean_loss_ppt > 16'd0) &&
                        (max_loss_in_window_ppt > (mean_loss_ppt * 16'd4)) &&
                        (c_windows_with_loss < ((c_windows * 16'd3) / 16'd4));

    clustering_valid = (c_windows >= 16'(N_WINDOWS));
  end
endmodule

Classification: a temporal variance test, and it is Chapter 21.3 §9's clustering probe applied to drops instead of to errors.

What it teaches: that the two conditions in drop_is_clustered are checking different things and both are needed. The worst window being four times the mean says the loss has a peak; fewer than three quarters of windows having any loss says it has gaps. A steady drop at 5% puts about 5% in every window — a peak and no gaps is a burst, gaps and no peak is a low-rate steady drop measured too finely, and only both together is an event.

And it teaches why this axis separates exactly what Section 2's grouping predicted. A filter's drop rate is the foreign-traffic share of the segment, which changes over minutes and hours rather than milliseconds; a FIFO overflow is a consumer stall, which Chapter 20.5 §12 proved no frame can cause and which therefore arrives as an external event with a duration.

Deliberately simplified: the window is a fixed number of frames rather than of time, so on a link whose rate varies the windows have varying durations — and a stall correlates with time. frame_delivered is assumed to be available per frame, which requires the delivery decision to be traceable back to the frame; on a real DMA path the delivery is asynchronous and the pairing is exactly Chapter 20.6's join problem. And the factor of four is a judgement.

Production implication: the per-frame pairing is the practical obstacle and there is a cheaper approximation that works. Comparing frames_in and frames_delivered deltas per window needs no pairing at all — two counters read at each window boundary — and it is exactly as good for this test, because the test is about the loss's variance rather than about which frame was lost. The pairing version is what a testbench builds; the delta version is what a monitoring system can actually collect, and they answer the same question.


10. Steady Against Clustered: the Second Free Axis

Section 2 split the five sites by who decides. This section is what that split looks like in a counter over time.

SiteWhat sets the drop rateHow fast it changes
the address filterthe foreign-traffic share of the segmentminutes to hours
VLAN membershipthe non-member traffic shareminutes to hours
the receive FIFOwhether the consumer is stalledmicroseconds — an event
the DMA, ring emptywhether the driver has postedmilliseconds — an event
the DMA, buffer too smallthe buffer's size against the traffic'snever — it is a constant
the driverthe host's schedulingmilliseconds — an event

Three rates of change and they map onto the axis directly. Rows one and two are steady at any window a diagnosis uses; rows three, four and six are events; row five does not change at all, which makes it steady too — and that is the awkwardness Section 7's classifier has to carry.

So the time axis alone gives:

ReadingCandidates
steadyfilter, VLAN, and the descriptor-buffer size — 3
clusteredFIFO, empty ring, driver — 3

Three and three, which is 1.000 bits — a perfectly balanced question, and it is the only such question in this chapter. Chapter 21.4 §6 found the same thing about its partner's-status reading, and for the same structural reason: a question that splits a space evenly is worth exactly one bit, and most questions do not.

And the two axes together are what Section 12 counts.

Size axisTime axis
what it splits onthe frame's lengththe drop's variance in time
cost0 — four existing counters0 — two existing counters, per window
bits2.58 when it fires, 0.22 when it does not1.000
blind whenone frame size, or loss below 2%the loss is very low, or the window is wrong

Row three's asymmetry is worth explaining. The size axis is lopsided: it separates one mechanism from five. Firing is worth log₂ 6 = 2.58 bits — it names a single site out of six — and not firing is worth only 0.22, because five of six were already the likely answer. The time axis is balanced and worth one bit either way.

The size axis is a rare, decisive question. The time axis is a common, moderate one. Together they are worth about 1.58 bits on the flat branch and 2.58 on the selective one, which is why the flat branch keeps three candidates and the selective branch keeps one.

One caution about the time axis that the size axis does not have.

Problem
a filter drop looks clusteredif the foreign traffic is itself bursty
a FIFO drop looks steadyif the consumer stalls regularly and often
the axis measures the trafficas much as the fault

Row three is the honest limit and it is the same shape as Chapter 21.5's load dependence: the instrument reads a property of the environment as well as of the fault, and on a link whose foreign traffic arrives in bursts the two branches blur. The size axis has no such problem — a frame's length is a property of the frame — which is why Section 7's classifier weights it first in practice even though the code ANDs them.

There is a third free axis worth naming and rejecting, because it is the one people reach for.

The rate of the drop — what fraction of traffic vanishes — looks like it should discriminate. It does not:

SiteTypical drop rateBounded?
the address filteranything from 0% to 99%by the segment's traffic
VLAN membershipanything from 0% to 99%by the VLAN mix
the receive FIFOanythingby the stall's duration
the DMA, ring emptyanythingby the driver
the DMA, buffer too smallthe large-frame shareby the traffic's size mix
the driveranythingby the host

Every row's range overlaps every other row's, so the magnitude separates nothing — which is why Sections 6 and 10 are both about shape. A 90% drop rate is consistent with a filter on a busy shared segment and with a driver that stopped, and a 0.5% rate is consistent with both too.

Magnitude separates nothing in class G. Shape separates it into three. That is the chapter's whole method, and it is why the loss figure — the one number a monitoring system does collect — is the one that has never helped.


11. RTL 5 — The Optional-Counter Gate

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// optional_counter_gate -- decide whether this platform needs the free
// method at all, and say what it is giving up by using it.
//
// Chapter 21.3 Section 17 priced the four optional counters at about
// 297 flops. If they exist, use them: they give five classes where
// this chapter's free ratios give three. This block is the switch.
// ---------------------------------------------------------------------
module optional_counter_gate
  import dropdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  // Chapter 21.1 Section 11's probe result, per counter.
  input  logic [3:0]  optional_present,   // filtered, vlan, fifo, desc
  input  logic [3:0]  optional_proven,

  input  gmask_t      free_candidates,
  input  logic [31:0] c_filtered,
  input  logic [31:0] c_vlan_discards,
  input  logic [31:0] c_fifo_drops,
  input  logic [31:0] c_desc_errors,

  output gmask_t      best_candidates,
  output logic        used_optional,
  output logic [2:0]  ceiling,
  output logic        free_method_only,
  output logic        probe_required
);
  gmask_t direct;

  always_comb begin
    // With the optional counters, the answer is whichever one moved.
    direct = ALL_G;
    if (optional_present[0] && optional_proven[0])
      direct = (c_filtered      != 32'd0) ? (6'd1 << G_FILTER)   : (direct & ~(6'd1 << G_FILTER));
    if (optional_present[1] && optional_proven[1])
      direct = (c_vlan_discards != 32'd0) ? (6'd1 << G_VLAN)     : (direct & ~(6'd1 << G_VLAN));
    if (optional_present[2] && optional_proven[2])
      direct = (c_fifo_drops    != 32'd0) ? (6'd1 << G_FIFO)     : (direct & ~(6'd1 << G_FIFO));
    if (optional_present[3] && optional_proven[3])
      direct = (c_desc_errors   != 32'd0) ? (6'd1 << G_DMA_RING) : (direct & ~(6'd1 << G_DMA_RING));

    used_optional   = (optional_present != 4'd0);
    best_candidates = used_optional ? (direct & free_candidates) : free_candidates;

    // Section 17's arithmetic, as a number an operator can read.
    ceiling = (optional_present == 4'hF) ? 3'd1 : 3'd3;

    free_method_only = (optional_present == 4'd0);

    // Chapter 21.1 Section 10: an unimplemented counter reads zero,
    // which is indistinguishable from a real zero. The probe is a
    // precondition, not a refinement.
    probe_required = (optional_present != 4'd0) &&
                     (optional_proven != optional_present);
  end
endmodule

Classification: a selector, and its most useful behaviour is to intersect rather than to replace.

What it teaches: that the two methods are complementary rather than alternative. The optional counters say which site fired; the free ratios say what shape the loss hasand intersecting them catches a case neither catches alone: c_desc_errors moving and the index reading 0.94 is a descriptor problem of the size kind, which the counter alone does not distinguish from an empty ring. Section 3's two DMA mechanisms share one counter and the free axis splits them.

And it teaches that probe_required is inherited wholesale from Chapter 21.1 §10 and must not be skipped. An unimplemented optional counter reads zero exactly like an implemented one at rest, and reading a zero as "this site is exonerated" eliminates the site the fault is at. The probe is four thousand frames, once per platform, and it is the precondition for every use of direct in this block.

Deliberately simplified: direct sets a one-hot mask on the first counter that moved rather than accumulating, so two simultaneous mechanisms report the last one tested. The four if statements are written as a sequence with an assignment that later statements can override — which is a bug in the style of Chapter 21.2 §7's priority chain, left in deliberately for the same reason. And ceiling returns 1 or 3 with nothing in between, where a platform with two of the four counters sits at two.

Production implication: the intersection is the design decision worth defending in review. A team that has the optional counters will be tempted to skip the free ratios entirely — the counters are direct evidence and the ratios are inference — and the case they lose is the DMA's two mechanisms, which share one counter. c_desc_errors firing tells you the DMA path dropped frames; the index tells you whether the buffers were too small or the ring was empty, and those are two different bugs in two different pieces of software. Two lines of arithmetic, and no hardware.


12. Three Classes of Five, for Nothing

Two axes, both free. The first is the size selectivity index: does the drop remove large frames preferentially, or is it indifferent to size. The second is the drop's behaviour in time: is it a steady share of traffic window after window, or does it concentrate in a few windows and vanish in the rest. Crossing them gives four quadrants and three of them are occupied. Selective and steady holds exactly one mechanism, a descriptor buffer smaller than the frames arriving, because a buffer's size does not change from second to second and it is the only mechanism that compares a length against a number. Flat and steady holds two, the address filter and virtual network membership, because both are configuration tables and a table does not change. Flat and clustered holds three, the receive buffer, an empty descriptor ring and an unreaped driver buffer, because all three are system state and a stall is an event with a beginning and an end. The fourth quadrant, selective and clustered, has no member in the class at all, which makes an observation landing there a contradiction rather than a fourth answer. Three classes, largest three, expected candidates falling from five point zero to two point three three, and the hardware added is nothing.Axis 1:selectivity2.58 bits when itfiresAxis 2:clustering1.000 bits, balancedSelective, steadythe buffer size — 1Flat, steadyfilter, VLAN — 2Flat, clusteredFIFO, ring, driver — 3Selective,clusteredno member — acontradiction5.00 to 2.33for zero flops12
Figure 3 — two free axes, three occupied quadrants, and one that has no member at all.

Run both axes over Section 3's six mechanisms and count the distinct signatures.

MechanismSize axisTime axis
the address filterflatsteady
VLAN membershipflatsteady
the receive FIFOflatclustered
the DMA, ring emptyflatclustered
the DMA, buffer too smallSELECTIVEsteady
the host driverflatclustered

Three distinct signatures:

ClassSignatureMembers
Aselective, steadythe descriptor buffer size — 1
Bflat, steadythe filter, VLAN membership — 2
Cflat, clusteredthe FIFO, the empty ring, the driver — 3

Six mechanisms, five sites, three classes, largest three — and the cost is zero.

Against what Chapter 21.1 §4 started with:

Instrument setClassesLargest classFlops
the RMON six alone150
plus the two free ratios330
plus the four optional counters51~297
plus a delivered-side histogram51~990

Row two is this chapter's result and row four is the instructive one. A delivered-side size histogram — the obvious instrument for a size-conditioned diagnosiscosts 693 flops more than the optional counters and separates nothing further, because the sites it would separate are separated already. The size-conditioned route is not the cheap way to attack class G and it is worth saying so plainly.

What the free ratios are good for is a platform that has none of the optional counters, which is most of them.

Without the free ratiosWith them
candidates51, 2 or 3
expected candidates, uniform prior52.33
what the operator does nextcheck all fivecheck two or three
hardwarenone

Row two is the honest average: (1 + 2 + 3) / 3 = 2.00 classes weighted by class, or 2.33 weighted by sitea better than twofold reduction from four counters, two divisions and one variance test, all over registers that are already there.

And the one thing the free method does that the optional counters do not:

It splits the DMA path's two mechanisms, which share one counter. c_desc_errors says the DMA dropped frames; the selectivity index says whether the buffers were too small or the ring was empty.

Which is why Section 11's gate intersects rather than replaces, and why a platform with all four optional counters should still compute the index: five classes become six, and the sixth is the one that distinguishes two bugs in two different pieces of software.

And one accounting of the whole module's class-G problem, because four chapters have now touched it.

ChapterWhat it contributed
Chapter 21.1 §4found the class and measured it: 5 sites, 1 signature
Chapter 21.2 §10explained it: four of the five are legal discards
Chapter 21.3 §17priced the direct fix: four counters, ~297 flops
this chapterfound three classes for free, and halved the bill

Four chapters, one class, and the useful result is the last row's second half. Chapter 21.3 §17's four counters were priced as a block; this chapter shows that two of them do work the free ratios already do, so the marginal value of c_filtered and c_vlan_discards after the time axis is one split between two configuration tables on the same switch.

FlopsMarginal classes
the free ratios01 → 3
c_fifo_drops + c_desc_errors~1983 → 5
c_filtered + c_vlan_discards~995 → 5, largest 2 → 1

Row three buys a smaller largest class and no new class at all, which is a real improvement and the least valuable of the three purchases — and it is the one a team reading Chapter 21.1 §19's list alphabetically would buy first.


13. RTL 6 — The Reason-Field Absence

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// reason_field_absence -- make explicit what the design does NOT carry.
//
// A frame is dropped. Five sites could have dropped it. The design's
// representation of which one is: nothing. There is no reason field,
// no tag, no per-drop record. This block exists to say so in a place a
// reviewer will read, and to compute what the absence costs in bits.
// ---------------------------------------------------------------------
module reason_field_absence
  import dropdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic        frame_dropped,
  // The ONLY thing the design carries about a class G drop.
  input  logic        drop_is_silent,

  // What a reason field would have carried, if one existed. These are
  // inputs from a TESTBENCH model, and that is the whole difficulty.
  input  gsite_e      model_reason,
  input  logic        model_valid,

  output logic [31:0] c_drops,
  output logic [2:0]  reason_bits_carried,
  output logic [2:0]  reason_bits_needed,
  output logic        reason_is_modelled,
  output logic        model_is_the_only_source
);
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n)                          c_drops <= '0;
    else if (frame_dropped && drop_is_silent) c_drops <= c_drops + 32'd1;
  end

  always_comb begin
    // The design carries one bit: it happened. Six mechanisms need
    // ceil(log2 6) = 3 bits to name. The gap is the chapter.
    reason_bits_carried = 3'd0;
    reason_bits_needed  = 3'd3;

    reason_is_modelled = model_valid;

    // Section 20's rejected class: if the reason exists only in the
    // testbench, a property quantified over reasons checks the model.
    // If it is added to the design, the property checks the design's
    // own label and is a tautology.
    model_is_the_only_source = model_valid && (reason_bits_carried == 3'd0);
  end
endmodule

Classification: a block whose outputs are two constants and a flag, and whose purpose is to make an absence reviewable.

What it teaches: that the design carries zero bits about why a frame was dropped and naming the mechanism needs three. Six mechanisms is ceil(log₂ 6) = 3 bits; the receive path has a drop signal and no companion field. Every inference in this chapter — the selectivity index, the clustering test, the optional counters — exists to reconstruct those three bits from side effects, and none of them reconstructs all three.

And it teaches that model_is_the_only_source is the flag Section 20's rejected property turns on. When the reason exists only in a testbench model, a property quantified over reasons is checking the model; when it is added to the design, the property is checking the design's own label. There is no third option and the block makes which one you are in a signal rather than an assumption.

Deliberately simplified: reason_bits_carried is a hardcoded zero, which is true of the MACs this track has built and not of every MAC — some carry a drop-reason field and the block should read it rather than assume its absence. model_reason is an input of a type the design has no producer for, which is the point and is also why this block is unsynthesisable in any useful sense. And c_drops counts only silent drops, which requires drop_is_silent to be computed somewhere, which requires knowing the reason.

Production implication: the last simplification is not a flaw in the block; it is the problem restated. drop_is_silent means "no error counter moved for this frame", which is a statement about five counters at the moment the frame was dropped — and a MAC that could compute it could equally well have recorded the reason. The circularity is real and it is the argument for the three bits: a three-bit reason field on the drop path, about 3 flops plus a small encoder, replaces this entire chapter's inference with a read. Chapter 21.3 §19's rule applies exactly — log what has a frame — and a drop has one.


14. What a Drop Diagnosis Must Never Do

Six prohibitions. Two are about the free ratios, two about the optional counters, and two about what a silent drop is not.

NeverBecause
1read a zero optional counter as exoneratingChapter 21.1 §10 — it may not exist
2compute the index without the check-value correctionSection 5 — 6.25% bias on minimum-size traffic
3use the index on single-size trafficSection 6 — the mean cannot move
4treat the DMA as one mechanismSection 8 — two mechanisms, opposite signatures
5conclude a site from the time axis aloneSection 10 — it measures the traffic too
6call a silent drop an errorSection 2 — four of the five are legal

Row two is the prohibition that produces a false positive on the commonest traffic there is. A receive path that strips the four-octet check value before delivery understates the delivered mean by exactly four octets — 0.62% at a mixed-traffic mean of 645.6 and 6.25% on a link carrying only 64-octet frames. Uncorrected, the index reads 0.938 on a perfectly healthy control-traffic link and drops_large_frames asserts. One addition, and the flag that says whether to apply it is a property of the DMA engine rather than of the link.

Row six is the prohibition with the operational cost. A port on a shared segment filters most of what it hears, and that is Chapter 7.4 working exactly as designed. Chapter 21.2 §15's discards_exceed_errors made the same point: a link discarding sixteen times more than it errors is configured that way. Reporting class G drops in an "errors" figure makes a healthy busy port look like a failing one.

And the two that look like precision and are not:

Why it is a prohibition
row threeon single-size traffic the index is 1.000 by construction, not by evidence
row fivebursty foreign traffic makes a filter drop look clustered

Both produce a reading that is a property of the traffic — which is what this chapter shares with Chapter 21.5 and what makes the two of them a pair: in both, the fault's visibility is set by what the network happens to be carrying.


15. RTL 7 — Drop Telemetry

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// dropdiag_telemetry -- three groups: the shape, the candidates, and
// what the platform's instrumentation ceiling is.
//
// The ceiling is knowable at step zero, exactly as in Chapter 21.1
// Section 15 and Chapter 21.4 Section 15. Three chapters, one pattern.
// ---------------------------------------------------------------------
module dropdiag_telemetry
  import dropdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [15:0] s_index_ppt,
  input  logic        s_valid,
  input  logic        drop_is_clustered,
  input  logic        clustering_valid,
  input  gmask_t      best_candidates,
  input  logic [15:0] loss_ppt,
  input  logic [3:0]  optional_present,
  input  logic        instrument_blind,
  input  logic        outside_class_g,

  // Shape.
  output logic [15:0] selectivity_ppt,
  output logic [1:0]  shape,          // 0 unknown 1 flat-steady 2 flat-clustered 3 selective
  output logic [15:0] loss_reported_ppt,

  // Candidates.
  output logic [2:0]  n_candidates,
  output logic        single_site,
  output logic        not_in_class_g,

  // Ceiling.
  output logic [2:0]  best_possible,
  output logic        free_method_ceiling,
  output logic        blind
);
  assign selectivity_ppt   = s_index_ppt;
  assign loss_reported_ppt = loss_ppt;
  assign n_candidates      = 3'(popcount6(best_candidates));
  assign single_site       = (n_candidates == 3'd1);
  assign not_in_class_g    = outside_class_g;
  assign blind             = instrument_blind;

  always_comb begin
    if      (!s_valid || !clustering_valid)  shape = 2'd0;
    else if (s_index_ppt < 16'd970)          shape = 2'd3;
    else if (drop_is_clustered)              shape = 2'd2;
    else                                     shape = 2'd1;

    // Section 12's table, as arithmetic. Four optional counters give a
    // ceiling of one; the free ratios alone give three.
    best_possible       = (optional_present == 4'hF) ? 3'd1 : 3'd3;
    free_method_ceiling = (optional_present != 4'hF);
  end
endmodule

Classification: a reporting block whose third group is a property of the platform and not of the fault.

What it teaches: that shape is the output a report should lead with, ahead of the candidate list. "Flat and clustered" is a sentence an operator can act on — something stalls, periodically, and it does not care about frame sizes — where "the FIFO, the ring or the driver" is three teams. The shape is the finding; the candidate list is its consequence.

And it teaches that best_possible is the third instance of a pattern this module has now used three times. Chapter 21.1 §15 computed it from which counters exist; Chapter 21.4 §15 from whether a partner can be asked; this chapter from whether the four optional counters are presentand in all three the answer is available before any measurement. Telling an operator the ceiling at the start changes the plan; telling them at the end changes the mood.

Deliberately simplified: shape has four values where the two axes give four quadrants, and the selective-and-clustered quadrant is folded into shape = 3 — Section 7 showed it has no member in class G, so the fold hides a contradiction. The 970 threshold hardcodes Section 3's tolerance rather than reading it. And best_possible returns 1 or 3 with nothing between, so a platform with two optional counters is reported as if it had none.

Production implication: the intermediate case is the common one and deserves the arithmetic. A platform with c_filtered and c_vlan_discards but not the FIFO or descriptor counters — which is a very ordinary combination, because the first two are cheap switch-side counters and the last two live in the datapath and the driver — has a ceiling of three, not one, and the three are the FIFO, the ring and the driver. That is exactly class C, which the free ratios reach anyway — so on such a platform the optional counters add nothing at all, and knowing that before the investigation is worth the two comparisons.


16. RTL 8 — The Drop Conformance Monitor

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// dropdiag_conformance_monitor -- six verdicts, and three of them say
// the traffic cannot support the measurement.
// ---------------------------------------------------------------------
module dropdiag_conformance_monitor
  import dropdiag_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [31:0] frames_in,
  input  logic [15:0] loss_ppt,
  input  logic [15:0] mean_in,
  input  logic [15:0] size_variance_ppt,
  input  logic        fcs_correction_applied,
  input  logic        fcs_stripped_on_delivery,
  input  logic [3:0]  optional_present,
  input  logic [3:0]  optional_proven,
  input  logic        clustering_valid,
  input  logic        outside_class_g,

  output logic        single_size_traffic,
  output logic        loss_below_floor,
  output logic        correction_missing,
  output logic        probe_skipped,
  output logic        window_too_short,
  output logic        model_wrong,
  output logic        diagnosis_sound
);
  // Section 6: a link carrying one frame size has an index that is
  // 1.000 by construction rather than by evidence.
  assign single_size_traffic = (size_variance_ppt < 16'd50);

  // Section 6's sensitivity: below about 2% total loss the index shift
  // is inside the tolerance.
  assign loss_below_floor = (loss_ppt < 16'd20);

  // Section 5 and Section 14's row two.
  assign correction_missing = fcs_stripped_on_delivery && !fcs_correction_applied;

  // Chapter 21.1 Section 10, inherited whole.
  assign probe_skipped = (optional_present != optional_proven);

  assign window_too_short = !clustering_valid;

  // Section 5: nothing in class G removes small frames preferentially.
  assign model_wrong = outside_class_g;

  assign diagnosis_sound = !correction_missing && !probe_skipped && !model_wrong;

  always_ff @(posedge clk) begin
    if (rst_n && single_size_traffic && (frames_in > 32'd1000000))
      $display("[dropdiag] one frame size: the selectivity index cannot distinguish anything");
  end
endmodule

Classification: an auditor whose three loudest verdicts are about the traffic and are deliberately not faults.

What it teaches: that single_size_traffic and loss_below_floor are excluded from diagnosis_sound for the reason this module has excluded such things three times now. A diagnosis run on single-size traffic is correctly executed and cannot distinguish anything — the index is 1.000 by construction. Calling it unsound would blame the engineer for the link's traffic, which Chapter 21.1 §16, Chapter 21.2 §16 and Chapter 21.5 §16 all declined to do for their own equivalents.

And it teaches that correction_missing is a term of soundness, unlike the others. Applying the check-value correction is entirely within the investigator's control and its absence produces a false positivedrops_large_frames on a healthy link — rather than a blind spot. The distinction the monitor draws is between what the traffic denies you and what you forgot to do, and only the second makes a diagnosis unsound.

Deliberately simplified: size_variance_ppt is an input the block cannot compute from a mean, so the single-size test depends on somebody else measuring a second moment — which Chapter 19.7 §2's histogram supports and the two octet counters do not. model_wrong is outside_class_g renamed. And probe_skipped fires whenever any optional counter is unproven, including ones this diagnosis does not need.

Production implication: the size_variance_ppt dependency is the one gap between this chapter's claim of zero added hardware and its implementation. The selectivity index needs four counters that exist; knowing whether the index is meaningful needs a second moment of the size distribution, which they do not give. The cheap substitute is the RMON histogram's bucket occupancyalready present, receive side, and enough to say whether more than one bucket is populated — which is Chapter 21.3 §3's cross_populated doing the same job in a different chapter.


17. Zero Flops Against 297: What Each Buys

The direction of this chapter was to find what can be done without the four optional counters. The answer is three classes instead of one, and this section is the comparison that decides whether it is enough.

Instrument setFlopsClassesLargestExpected candidates
the RMON six alone0155.00
plus the selectivity index0254.33
plus the clustering test0332.33
plus the four optional counters~297511.00
plus a delivered-side histogram~990511.00

Row three is free and row four is 297 flops, and the gap between them is 1.33 candidates.

Which is worth it depends on a number this chapter can compute: what a candidate costs.

Cost of one extra candidate
a site the same team ownsa register read
a site another team ownsa conversation
class C's three sitesthe datapath team, the driver team, and the memory system
the expected cost at 2.33 candidatesusually two teams

Class C is the expensive class and the free method does not break it. The FIFO, an empty descriptor ring and an unreaped driver buffer are three different owners — and the free ratios put all three in one bucket, so a class C result routes a ticket to nobody in particular.

The four optional counters break exactly that class.

CounterSplits offFlops
c_fifo_dropsthe FIFO~99
c_desc_errorsthe ring~99
c_filteredthe filter~99
c_vlan_discardsVLAN membership~99

The first two are the ones that matter after this chapter's free method, and they are about 198 flops — 1.4% of Chapter 19.7 §19's 14 166-flop datapath. c_filtered and c_vlan_discards split class B, which the free method has already reduced to two sites that are both configuration and both the same team's.

After the free ratios, two of the four optional counters are worth having and two are almost redundant. That is the chapter's most actionable result and it halves Chapter 21.3 §17's bill.

FlopsClassesLargest
free ratios only033
+ c_fifo_drops and c_desc_errors~19852
+ all four~29751

Row two gets to five classes for two thirds of the cost, because the free method has already separated the filter and VLAN pair from everything else by their steadiness. The last 99 flops buy the split within class B — the filter against VLAN membership — which is one configuration table against another, both on the same switch, both readable by the same person.

And the three-bit alternative, for completeness.

FlopsClasses
a three-bit drop-reason field~3 plus an encoder6 — every mechanism
the four optional counters~2975
the free ratios03

Row one is the cheapest and most complete option in the table by two orders of magnitude and nobody builds it. Section 13 derived why it is not there rather than why it should be: a drop-reason field is a per-frame record, and Chapter 21.3 §19's rule — count what has no frame, log what has onesays a drop has a frame and should be logged. The reason it is not is that the frame is being discarded, and a discard path is the last place anybody adds a field.


18. What the Diagnosis Assumes

Nine assumptions. Three are about the index, three about the traffic and three about the platform — and the first is the one that produces a false positive.

AssumptionFromIf false
1the delivered octet count includes the check valuethe DMA enginea 6.25% bias on minimum-size traffic — Section 5
2a flat drop leaves the mean unchangedarithmeticit is an identity, not an assumption
3the traffic has more than one frame sizenothingthe index is 1.000 by construction
4the drop's rate is stationary over the windowconvenienceSection 10 — bursty traffic blurs the time axis
5only one mechanism is activeconveniencetwo mechanisms give a mixed shape and no class
6the optional counters, if present, are implementedChapter 21.1 §11an absent counter reads zero
7the DMA does not chain descriptorsthe driverSection 8's step disappears entirely
8the delivered count is of the same framesthe DMAa coalescing engine breaks the pairing
9nothing in class G removes small framesSection 8's tablethe index above 1.030 is unexplained

Row seven is the assumption that decides whether Section 8's one positive result exists at all. A driver that chains descriptors — scatter-gather, which most modern drivers do — can deliver a frame larger than any single buffer, so the step at the buffer size does not exist and G_DMA_SIZE has no signature. The selectivity index then fires for nothing in class G, and its only remaining value is outside_class_g.

Descriptors chainedNot chained
a frame larger than one bufferdelivered across severaldropped
G_DMA_SIZE existsnoyes
the index's positive resultnoneone site named
the index's negative resultstill rules out nothingrules out one site

Row three is the cost and it is worth knowing before the measurement. On a platform with scatter-gather receive, the selectivity index is a test for a fault that cannot happen — and it still has value as outside_class_g, which is a test for something that is not in the fault space at all.

Row one is the assumption that is false on most platforms and produces a false positive rather than a blind spot. Most receive paths strip the four-octet check value before delivery, because the host has no use for it. At a mean of 645.6 octets that is 0.62% and inside the tolerance; at 64 octets it is 6.25% and twice outside it — so an uncorrected index on a control-traffic link reads 0.938 and reports a size-selective drop on a healthy port.

And three things deliberately not assumed:

Not assumedWhy not
that a size histogram exists on the delivered sideSection 4 — it does not, and it is not worth building
that the loss is an errorSection 2 — four of the five are legal
that the free method reaches one siteSection 12 — three classes, largest three

Row three is the chapter's honest position and it differs from the direction it was given. The question was what can be done without the optional counters; the answer is three classes of five, not five of fiveand Section 17 then finds that two of the four counters are enough to finish, which is the useful half of the result.

And there is a tenth assumption that is not in the table because it is about the measurement's window rather than about the link.

Both free ratios are computed over a window, and neither block chooses one.

Since resetOver a fixed window
the index's denominatora week of traffic mixesone mix
a fault that began an hour agodiluted by a weekvisible
a traffic-mix change overnightmoves the indexdoes not
what it costs0 — it is the defaulta shadow copy of four counters

Row three is the false positive the windowing gap produces and Section 22's seventh complaint is about it: an index computed since reset mixes populations, so a change in what the link carries reads as a change in how it drops. The fix is a shadow copy and a subtraction — about 160 flops for the four countersand it is the same fix Chapter 21.3 §3 needed for its size cross and Chapter 19.7 §15 needed for its telemetry. Three chapters, one gap, one answer.


19. The Cost, Accounted

A drop diagnosis is two ratios and a variance test, and the ratios are free.

BlockFlopsNature
dropdiag_pkg0six mechanisms, two axes
mean_size_tracker0combinational over existing counters
size_selectivity_index0one division
drop_shape_classifier0a mask intersection
drop_clustering_probe — 64 windows~128the time axis, and it must be free-running
optional_counter_gate0combinational
reason_field_absence~38one counter and two constants
dropdiag_telemetry0combinational
dropdiag_conformance_monitor0combinational
total~166 flops

Seven of the nine blocks are pure combinational logic and the total is the second-smallest in Module 21 — just above Chapter 21.4 §19's 168 and far below Chapter 21.3's 4 856. The reason is that this chapter's instruments are ratios over counters somebody else already pays for.

And the addition to a design is a choice between three options with wildly different costs.

OptionFlopsClasses of the five
nothing — the free ratios03
c_fifo_drops and c_desc_errors~1985, largest 2
all four optional counters~2975, largest 1
a three-bit drop-reason field~3 plus an encoder6 — every mechanism

Row four is a hundredth of row three's cost and strictly better, and Section 13 explained why it does not exist: it is a field on a discard path, and a discard path is where fields go to be omitted.

Module 21's running bill, six 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~7925.6%
Chapter 21.4 §19~710.5%
Chapter 21.5 §19~4553.2%
this chapter — the free route00.0%
total~2 04114.4%

This chapter adds nothing to the bill and removes something from it: Section 17 showed that after the free ratios, two of Chapter 21.1 §19's four optional counters are nearly redundant — the filter and VLAN split is one configuration table against another, on the same switch, for the same person. The module's total falls to about 1 942 flops, 13.7%, and the chapter that spends nothing is the one that finds the saving.


20. Properties Worth Asserting, and One Worth Refusing

The frame validity chapter says a frame is counted once and the scoreboard chapter's conservation identity says every missing frame is accounted for, so the natural property asserts that every dropped frame has exactly one reason and that the reasons partition the drops. The trouble is that the drop reason field does not exist. Six mechanisms need three bits to name and the design carries zero: the receive path has a drop signal and no companion field at all. So the property cannot be bound as written, and there are exactly two ways to make it bindable, both of which destroy it. Add the reason to the testbench as a model, and the property compares two evaluations of the same rule, an address comparison or an occupancy threshold written twice, so it passes whenever both are written the same way and fails only when the testbench's fidelity is poor. It has become a check of the model. Add the reason to the design as a field, and asserting one hot over it is a tautology: a three bit encoded field is one hot after decoding whatever value it holds, so the property holds on a design that labels every drop as filtered regardless of why. What can be asserted instead is the conservation identity over the counters that do exist, the observable consequence that a silent drop moves no error counter, and the absence itself as a static fact a reviewer will encounter.One reason perdropthe tempting property6 mechanisms = 3bitsthe design carries 0Model it in thetestbenchchecks the modelAdd a field tothe designa tautologyLeave it outdoes not elaborateAssertconservationover counters thatexistAssert theconsequenceno error counter movedAssert theabsencea decision, writtendown12
Figure 4 — a property whose domain is a field with no producer, and both repairs destroy it.

Thirty-three properties and eight covers, in four groups: the index's arithmetic, the two axes, the optional counters, and the absence the chapter is built around.

Group one — the index, and the identity it rests on.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Section 6: a flat drop leaves the mean exactly unchanged, because
// removing a random share of frames removes the same share of octets.
// It is an identity, so it is assertable.
p_flat_is_exact:    assert property (@(posedge clk) disable iff (!rst_n)
                      (drop_is_uniform && both_sides_valid) |->
                        (s_index_ppt == 16'(S_FLAT_PPT)));

p_index_bounded:    assert property (@(posedge clk) disable iff (!rst_n)
                      s_valid |-> (s_index_ppt <= 16'd4000));

p_index_needs_pop:  assert property (@(posedge clk) disable iff (!rst_n)
                      s_valid |-> both_sides_valid);

p_correction_applied:assert property (@(posedge clk) disable iff (!rst_n)
                      fcs_stripped_on_delivery |->
                        (mean_corrected == mean_delivered + 16'd4));

p_three_outcomes:   assert property (@(posedge clk) disable iff (!rst_n)
                      s_valid |-> ($countones({drop_is_flat, drops_large_frames,
                                               drops_small_frames}) == 1));

p_large_is_below:   assert property (@(posedge clk) disable iff (!rst_n)
                      drops_large_frames |->
                        (s_index_ppt <= (16'(S_FLAT_PPT) - 16'(S_TOLERANCE_PPT))));

p_mean_from_ratio:  assert property (@(posedge clk) disable iff (!rst_n)
                      (frames_in > 32'd0) |-> (mean_in == 16'(octets_in / 48'(frames_in))));

p_loss_consistent:  assert property (@(posedge clk) disable iff (!rst_n)
                      (frames_in >= frames_delivered) |->
                        (frames_lost == (frames_in - frames_delivered)));

Group two — the two axes and their intersection.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
p_axes_independent: assert property (@(posedge clk) disable iff (!rst_n)
                      ((SIZE_SELECTIVE | SIZE_FLAT) == ALL_G) &&
                      ((CONFIG_SITES  | STATE_SITES) == ALL_G));

p_size_partition:   assert property (@(posedge clk) disable iff (!rst_n)
                      ((SIZE_SELECTIVE & SIZE_FLAT) == 6'd0));

p_time_partition:   assert property (@(posedge clk) disable iff (!rst_n)
                      ((CONFIG_SITES & STATE_SITES) == 6'd0));

p_mask_intersect:   assert property (@(posedge clk) disable iff (!rst_n)
                      classified |-> (candidates == (by_size & by_time)));

p_blind_is_all:     assert property (@(posedge clk) disable iff (!rst_n)
                      instrument_blind |-> (candidates == ALL_G) || !classified);

p_selective_is_one: assert property (@(posedge clk) disable iff (!rst_n)
                      (drops_large_frames && clustering_valid && !drop_is_clustered)
                        |-> (n_candidates == 3'd1));

p_clustered_is_three:assert property (@(posedge clk) disable iff (!rst_n)
                      (drop_is_flat && drop_is_clustered) |-> (n_candidates == 3'd3));

p_steady_is_two:    assert property (@(posedge clk) disable iff (!rst_n)
                      (drop_is_flat && !drop_is_clustered && clustering_valid)
                        |-> (n_candidates == 3'd2));

p_small_is_outside: assert property (@(posedge clk) disable iff (!rst_n)
                      drops_small_frames |-> outside_class_g);

Group three — the optional counters, and the probe that must precede them.

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

p_gate_intersects:  assert property (@(posedge clk) disable iff (!rst_n)
                      used_optional |->
                        ((best_candidates & free_candidates) == best_candidates));

p_ceiling_from_set: assert property (@(posedge clk) disable iff (!rst_n)
                      (optional_present == 4'hF) |-> (ceiling == 3'd1));

p_free_ceiling:     assert property (@(posedge clk) disable iff (!rst_n)
                      (optional_present == 4'd0) |-> (ceiling == 3'd3));

p_dma_split:        assert property (@(posedge clk) disable iff (!rst_n)
                      ((c_desc_errors > 32'd0) && drops_large_frames) |->
                        ((best_candidates & (6'd1 << G_DMA_SIZE)) != 6'd0));

p_no_optional_no_direct:assert property (@(posedge clk) disable iff (!rst_n)
                      free_method_only |-> (best_candidates == free_candidates));

p_zero_is_not_proof:assert property (@(posedge clk) disable iff (!rst_n)
                      (!optional_proven[2] && (c_fifo_drops == 32'd0)) |->
                        ((best_candidates & (6'd1 << G_FIFO)) != 6'd0));

p_ceiling_static:   assert property (@(posedge clk) disable iff (!rst_n)
                      $stable(optional_present) |=> $stable(ceiling));

Group four — the absence, which is Section 13's subject and Section 20's.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
p_no_reason_carried:assert property (@(posedge clk) disable iff (!rst_n)
                      (reason_bits_carried == 3'd0));

p_reason_needs_3:   assert property (@(posedge clk) disable iff (!rst_n)
                      (reason_bits_needed == 3'd3));

p_model_is_tb:      assert property (@(posedge clk) disable iff (!rst_n)
                      model_is_the_only_source |->
                        (reason_is_modelled && (reason_bits_carried == 3'd0)));

p_drops_counted:    assert property (@(posedge clk) disable iff (!rst_n)
                      (frame_dropped && drop_is_silent) |=>
                        (c_drops == $past(c_drops) + 32'd1));

p_silent_no_error:  assert property (@(posedge clk) disable iff (!rst_n)
                      drop_is_silent |->
                        (!fcs_error && !alignment_error && !undersize && !oversize));

p_g_is_legal:       assert property (@(posedge clk) disable iff (!rst_n)
                      drop_is_silent |-> frame_was_valid);

p_sound_excludes:   assert property (@(posedge clk) disable iff (!rst_n)
                      diagnosis_sound |->
                        (!correction_missing && !probe_skipped && !model_wrong));

p_blind_not_unsound:assert property (@(posedge clk) disable iff (!rst_n)
                      (single_size_traffic || loss_below_floor) |->
                        (diagnosis_sound || correction_missing || probe_skipped));

p_single_size_flat: assert property (@(posedge clk) disable iff (!rst_n)
                      (single_size_traffic && s_valid) |-> drop_is_flat);

And eight covers, because six of these need a traffic mix and a fault a default regression produces neither of.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
c_flat_drop:       cover property (@(posedge clk) drop_is_flat && (loss_ppt > 16'd20));
c_selective_drop:  cover property (@(posedge clk) drops_large_frames);
c_small_selective: cover property (@(posedge clk) drops_small_frames);
c_clustered:       cover property (@(posedge clk) drop_is_clustered);
c_steady:          cover property (@(posedge clk) clustering_valid && !drop_is_clustered);
c_one_candidate:   cover property (@(posedge clk) single_site);
c_single_size:     cover property (@(posedge clk) single_size_traffic);
c_both_methods:    cover property (@(posedge clk) used_optional && s_valid);

21. Verification Scenarios

Fifty-eight scenarios, plus a five-run directed test whose variable is which of five legal discards is active — none of which any frame can cause.

The index's arithmetic — 11 scenarios.

#ScenarioExpected
140% of frames dropped at randomindex exactly 1.000
2the same at 5% lossstill 1.000
3the same at 90% lossstill 1.000
4every 1 518-octet frame droppedindex 0.099
5half the 1 518-octet frames0.662
6a quarter of them0.850
710% of them0.944 — 4% total loss
85% of them0.972 — at the tolerance
92% of them0.989 — below the floor
10every 64-octet frame dropped2.351 — outside_class_g
11fewer than 1 000 delivered framesboth_sides_valid low

The check-value correction — 8 scenarios.

#ScenarioExpected
12FCS stripped, correction applied, mixed trafficindex 1.000
13FCS stripped, correction NOT applied, mixed0.994 — inside tolerance
14the same on 64-octet-only traffic0.938 — a false positive
15drops_large_frames on scenario 14asserts wrongly
16correction_missing on itasserts — and it is a soundness term
17FCS delivered, correction applied anywayindex 1.006 — the opposite bias
18the bias at a 645.6-octet mean0.62%
19at a 64-octet mean6.25%

The time axis — 9 scenarios.

#ScenarioExpected
205% loss in every windowsteady
21100% loss in two windows of sixty-fourclustered
22the mean loss in bothabout the same
23max_loss_in_window in both50 ppt against 1 000 ppt
24fewer than 64 windowsclustering_valid low
25bursty foreign traffic, filter droplooks clustered — Section 10's limit
26a consumer stalling every windowlooks steady
27the axis's information3 sites against 3 — 1.000 bits
28windows measured in frames, varying ratedurations vary; a stall correlates with time

The three classes — 10 scenarios.

#ScenarioExpected
29selective and steady1 candidate — the descriptor buffer size
30flat and steady2 — the filter, VLAN membership
31flat and clustered3 — the FIFO, the ring, the driver
32selective and clusteredno member; the model is wrong
33index blind, time axis valid3 or 3 — no size split
34time axis blind, index valid1 or 5
35both blind5 — where Chapter 21.1 §4 started
36expected candidates, both axes2.33
37with the RMON six alone5.00
38with the four optional counters1.00

The optional counters — 10 scenarios.

#ScenarioExpected
39c_fifo_drops moves1 candidate — the FIFO
40c_desc_errors moves, index flatthe ring
41c_desc_errors moves, index 0.94the buffer size — the split only the index makes
42c_fifo_drops reads zero, unproventhe FIFO stays a candidate
43the same, proven presentthe FIFO is eliminated
44two of the four presentceiling 3, not 1
45c_filtered and c_vlan_discards onlyclass B split; class C untouched
46c_fifo_drops and c_desc_errors onlyclass C split — the useful pair
47the flops for scenario 46~198, and it reaches 5 classes
48all four~297, largest class 1

The absence, and the platform — 10 scenarios.

#ScenarioExpected
49reason_bits_carried0, always
50reason_bits_needed3
51a reason modelled in the testbenchmodel_is_the_only_source
52p_one_reason bound against that modelchecks the model, not the design
53a three-bit reason field added to the design$onehot becomes a tautology
54the same field, read instead of inferred6 classes for ~3 flops
55a driver that chains descriptorsG_DMA_SIZE has no signature at all
56the index on that platformonly outside_class_g remains useful
57single-size trafficindex 1.000 by construction
58the $display after a million framesfires once, and says the instrument is blind

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

The case: five legal discards, activated one at a time, on a link where nothing is wrong with any frame.

Chapter 20.5 §10 divided injections into what a wire can produce and what needs a fault inside the design. None of this chapter's five is in either category. They are not faults at all: a filter table, a VLAN membership list, a consumer that stalls, a descriptor ring, a driver's scheduler. Reaching them needs the environment's configuration to change, and no field of any frame touches any of it.

RunWhat is configuredWhere it lives
Aan address filter that excludes most traffica table in the MAC
Ba port removed from the VLAN most traffic carriesa port-mode register
Ca consumer that stalls for 3 µs every 10 msthe memory model
Da descriptor ring the driver stops refillingthe bus functional model
Edescriptor buffers of 1 518 octets, traffic tagged at 1 522the ring's configuration

The oracle is four-part and no part of it looks at a frame.

PartABCDE
selectivity index1.0001.0001.0001.000below 0.97
time axissteadysteadyclusteredclusteredsteady
candidates22331
every error counterzerozerozerozerozero

Row four is the control and it is the reason class G exists. Five completely different configurations, five sets of frames that never reach the host, and not a single error counter moves in any of them — because in all five the frames were valid and the receiver was correct to discard them.

Run E is the chapter's one positive result and it is four octets wide. Chapter 21.2 §18 showed the MTU boundary moves from 1 518 to 1 522 with a single VLAN tag; a descriptor buffer sized for the untagged MTU drops exactly the tagged frames — and the selectivity index is the only free instrument that sees it. Runs A and B are indistinguishable from each other and runs C and D are indistinguishable from each other and from the driver, which is the honest limit.

And run C is the one that cannot be produced from the wire at all. Chapter 20.5 §12 proved it: the arrival rate is the line rate and Chapter 19.5 §4's drain rate exceeds it, so no sequence of frames overflows a correctly sized FIFO. The consumer has to stop, which is a memory-system action — and that is the fault Chapter 21.7 takes as its subject rather than as its stimulus.


22. Debugging a Silent Drop

Six complaints.

Complaint 1 — "frames are disappearing and every counter is zero."

CheckIf yesMeaning
is link_up high?yesthis chapter, not Chapter 21.4
is frames_in moving?yesthe port is receiving
is frames_delivered short?yesclass G
what is the selectivity index?compute itfour counters you already have

Row four is the step nobody takes. The octet and frame counters on both sides are already collected by every monitoring system on the planet, and dividing them gives a number that separates a size-selective drop from a flat one. The reason it is not computed is that a mean frame size reads as a traffic statistic rather than as a diagnostic.

Complaint 2 — "the index says 0.94 and the DMA counters are clean."

CheckIf yesMeaning
is the check value stripped on delivery?usuallySection 5
was the correction applied?nothe false positive
what is the mean received size?64four octets is 6.25% of it
apply the correctionindex 1.000there was no selective drop

A control-traffic link with an uncorrected index reads 0.938 and asserts drops_large_frames on a perfectly healthy port. The bias is exactly four octets per frame; it is negligible on mixed traffic and dominant on minimum-size traffic, and correction_missing is a soundness term for precisely that reason.

Complaint 3 — "the index says 1.000 so there is no drop."

CheckIf yesMeaning
is loss_ppt non-zero?yesthere is certainly a drop
what does 1.000 mean?it is flatfive of the six mechanisms
is the traffic single-size?check the histogramthen 1.000 is by construction
what does the time axis say?it is the other halfsteady or clustered

The index is a shape measurement and not a magnitude one, which Section 6 stated as a rule and which is the commonest misreading of it. 1.000 with a 40% loss means forty per cent of the frames are gone and the drop does not care about their size — which eliminates one mechanism of six and leaves five.

Complaint 4 — "we added the four optional counters and the answer did not improve."

CheckIf yesMeaning
which four?c_filtered, c_vlan_discards and two otherscheck which
were they probed?noChapter 21.1 §11 — a zero may be an absence
what class was the fault in?C — flat and clusteredthe FIFO, the ring, the driver
do c_filtered and c_vlan_discards split class C?nothey split class B, which was already two

Row four is Section 17's finding arriving as a complaint. After the free ratios, c_filtered and c_vlan_discards are nearly redundant — they separate the filter from VLAN membership, which are two configuration tables on the same switch, owned by the same person. The counters worth having are c_fifo_drops and c_desc_errors, which split the three-site class, and they are two thirds of the cost.

Complaint 5 — "the drop looks clustered but nothing stalls."

CheckIf yesMeaning
is the foreign traffic bursty?yesSection 10's limit
is this an address filter drop?possiblyand it will look clustered
does the index help?it says flat, which both areno
is c_filtered available?that is the answer~99 flops

The time axis measures the traffic as well as the fault, which the size axis does not — a frame's length is a property of the frame and a drop's timing is a property of the arrival process. On a link whose foreign traffic arrives in bursts the two branches of the time axis blur, and the free method degrades to two classes.

Complaint 6 — "our driver uses scatter-gather so the index found nothing."

CheckIf yesMeaning
does the driver chain descriptors?yesSection 18's row seven
can a frame exceed one buffer?it is delivered across severalno step exists
does G_DMA_SIZE have a signature?nothe mechanism cannot occur
is the index still worth computing?yes — outside_class_git tests for faults outside the five

On a scatter-gather platform the index's one positive result is testing for a mechanism that cannot happen. What remains is its negative value: an index above 1.030 means small frames are being removed preferentially, which no member of class G does — so the fault is a policer, a queue discipline or an upstream device, and that is worth one division.

Complaint 7 — "the index moved from 1.000 to 0.96 overnight and nothing changed."

CheckIf yesMeaning
did the traffic mix change?check the received histogramthe index's denominator moved
is mean_in the same as yesterday?nothat is the whole finding
is the loss rate the same?yesso the drop did not change
is the index computed since reset?yesan hour of new traffic against a week of old

The index is a ratio of two means and both of them move with the traffic. A link whose overnight backup shifts the mix towards maximum-size frames changes mean_in and, if any drop is even slightly size-selective, changes the ratiowithout anything about the fault changing at all. The windowing gap Section 3 flagged is what makes this severe: an index since reset mixes a week of one traffic mix with an hour of another, and the fix is a delta over a fixed window.

Complaint 8 — "the free method says class C and the DMA counter is clean."

CheckIf yesMeaning
is c_desc_errors implemented?check the probeChapter 21.1 §11
was it proven present?noa zero may be an absence
is c_fifo_drops implemented?also nothen class C stands at three
what is left?the driverand it has no counter at all

Class C's third member is the host driver and nothing in the MAC can see it. c_fifo_drops and c_desc_errors split off two of the three; the driver is named by elimination, which is the weakest form of naming and the only one available — because a buffer that the driver failed to reap is a fact about software, and a MAC has no register for it.

And the three symptoms this chapter is systematically blamed for:

SymptomBlamed onUsually is
"every counter is zero"the instrumentationfour existing counters nobody divided
a selective index on control trafficthe DMAfour octets of check value
optional counters that did not helpthe methodthe wrong two of the four

23. Misconceptions

Misconception 1 — "every counter is zero, so there is no evidence."

The wrong model: the RMON error counters are the instrument, and they read zero, so nothing can be said.

What it costs: the evidence is in the octet counters, not the error ones. octets_in / frames_in and octets_delivered / frames_delivered are four counters every platform already collects, and their ratio separates a size-selective drop from a flat one — a factor of ten between two runs with identical loss. The reason it is not computed is that a mean frame size looks like a traffic statistic.

The corrected model: class G is silent in the error counters by design — Chapter 21.2 §10 showed why — and not silent in the octet counters at all. Two divisions and a variance test take five candidates to at most three, for no hardware.

Misconception 2 — "a selectivity index of 1.000 means nothing is wrong."

The wrong model: the index is a health measure, so 1.000 is healthy.

What it costs: the index is a shape measurement. 1.000 with a 40% loss means forty per cent of the frames are gone and the drop is indifferent to their size — which is five of the six mechanisms, including every one in the expensive class C. Reading a shape as a magnitude discards the loss figure, which is the other half of the report.

The corrected model: report the shape and the magnitude as two numbers. The index says which mechanism; the loss says how much. Neither implies the other, and Section 6 states it as a rule for exactly this reason.

Misconception 3 — "add a size histogram on the delivered side."

The wrong model: the diagnosis is size-conditioned, so build the size-conditioned instrument.

What it costs: about 693 flops, and it separates nothing the four optional counters do not. A delivered-side histogram would locate the step at a descriptor buffer's size — useful — and it would not split class C at all, because the FIFO, the ring and the driver are all size-blind. The size-conditioned route is more expensive than the direct one and reaches fewer sites.

The corrected model: project the distribution onto its mean, which costs nothing because both operands exist. The mean detects the one size-selective mechanism and cannot locate it — and locating it is a bisection with the traffic rather than a register.

Misconception 4 — "the DMA is one site."

The wrong model: class G has five members and the DMA is one of them.

What it costs: the DMA path has two mechanisms with opposite signatures — an empty ring, which is flat and clustered, and a buffer too small, which is selective and steady. They share one counter and they are two different bugs in two different pieces of software. A diagnosis that reports "the DMA" has named a block and not a question.

The corrected model: six mechanisms, five sites. c_desc_errors moving with a flat index is an empty ring; the same counter with an index below 0.97 is a buffer-size mismatch — which is the one split the optional counters cannot make and the free index can.

Misconception 5 — "a drop is a drop."

The wrong model: frames are being lost, so something is broken.

What it costs: four of the five sites are legal discards. A port on a shared segment filters most of what it hears; a port outside a VLAN discards that VLAN's traffic; both are Chapter 7.4 and Chapter 13.2 working exactly as specified. Reporting them in an "errors" figure makes a healthy busy port look like a failing one, which is Chapter 21.2 §15's discards_exceed_errors argument.

The corrected model: a class G drop is a frame the receiver judged valid and then did not deliver. The question is not "why is it broken" but "which of five correct behaviours removed it" — and only two of the five are faults at all.

Misconception 6 — "we need a drop counter."

The wrong model: the problem is that drops are not counted.

What it costs: drops are counted — frames_in minus frames_delivered is the count. What is missing is the reason, which is three bits and which the design carries none of. A sixth aggregate drop counter would add a number that is already computable and no information at all.

The corrected model: the missing thing is a three-bit reason field on the discard path — about three flops and a small encoder — which would give six classes where 297 flops of optional counters give five. Section 13 derived why it is not there: it is a field on a path whose purpose is to throw the frame away, and a discard path is where fields are omitted.


24. Interview Questions

Question 1 — "Frames vanish and every error counter is zero. What do you do?"

What the answer should establish: that the error counters are the wrong instrument and the octet counters are the right one. A strong answer computes the selectivity index: mean delivered size over mean received size, from four counters every platform has, and explains what 1.000 means — a drop indifferent to size, which is five of six mechanisms. The strongest answer mentions the check-value correction, because without it a control-traffic link reads 0.938 and reports a fault that is not there.

Question 2 — "Two runs lose 40% of frames. How do you tell them apart?"

What the answer should establish: the mean delivered size. A flat drop leaves the mean exactly unchanged — removing a random share of frames removes the same share of octets — so the index reads 1.000 precisely. A drop that removes every maximum-size frame from a bimodal mix pulls the mean from 645.6 to 64 and the index to 0.099. A strong answer notes that every other aggregate figure is identical in the two runs.

Question 3 — "Which of class G's five sites does a size-conditioned instrument reach?"

What the answer should establish: one, and only in one of its two mechanisms. Every other decision — the address filter, VLAN membership, the FIFO at start-of-frame, an empty descriptor ring, the driver — is taken before the frame's length is known, so it cannot depend on it. Only a descriptor buffer's size is a comparison against a length. A strong answer adds the corollary: firing eliminates five of six, which is 2.58 bits from counters that already exist.

Question 4 — "Is a delivered-side size histogram worth building?"

What the answer should establish: no. About 693 flops, more than twice the four optional counters' 297, and it separates nothing further — because the sites it would distinguish are already distinguished and the sites it cannot help with are size-blind. A strong answer contrasts it with the free projection: a mean is one moment of the distribution, it costs nothing, and it detects the one selective mechanism without locating it.

Question 5 — "You can add two counters. Which two?"

What the answer should establish: c_fifo_drops and c_desc_errors, not c_filtered and c_vlan_discards. The free time axis already separates the configuration sites from the system-state ones; what it cannot do is split the three system-state sites from each other, and those are three different owners. The two configuration sites are one switch and one person. A strong answer prices it: ~198 flops reaches five classes where ~297 reaches five with a smaller largest class.

Question 6 — "What would make this whole chapter unnecessary?"

What the answer should establish: a three-bit reason field on the drop path. Six mechanisms need ceil(log₂ 6) = 3 bits; the design carries zero. About three flops and a small encoder gives six classes where 297 flops of counters give five. A strong answer explains why it does not exist: it is a field on a path whose purpose is to discard the frame, and Chapter 21.3 §19's rule — count what has no frame, log what has one — says a drop has a frame and should carry a reason.


25. Questions and Answers


26. What's Next

Module 21 has three chapters left, and this one has handed two of them their subject directly.

ChapterTakesFrom here
Chapter 21.7the descriptor pathclass C's ring and buffer mechanisms, in detail
Chapter 21.8a link with no drops and no errorsthe case where even frames_delivered is healthy
Chapter 21.9the captureChapter 21.1 §12's step 6

Chapter 21.7 takes class C apart and it starts from the one fault no frame can produce. Chapter 20.5 §12 proved that the arrival rate is the line rate and Chapter 19.5 §4's drain rate exceeds it, so no sequence of frames overflows a correctly sized FIFO — the consumer has to stop. In Chapter 20.5 that was a limit on what could be injected; in the next chapter it is the thing being diagnosed, and Chapter 19.6's outstanding count is the instrument.

Chapter 21.8 is the inversion this chapter makes possible. Everything here rests on frames_in exceeding frames_delivereda difference that can be counted. A link that is slow and correct has no difference at all: every frame arrives, every frame is delivered, every counter is where it should be, and the complaint is a number that is smaller than the line rate. Chapter 8.3's efficiency arithmetic replaces the counters entirely, which is a different instrument set for the same ticket queue.

And the series is now ninety-nine classes long. The last three have been about who controls a property's evaluation: Chapter 21.4's class 97, where the fault silenced the antecedent; Chapter 21.5's class 98, where the generator did; and class 99, where nothing silences it because the field it quantifies over does not exist. The third is not a member of that family — it is a property with an empty domain rather than an unvisited one — which puts it back with Chapter 19.2 §19's class 82 and Chapter 20.5 §20's class 92, the family about a property's relationship to the design's own representations. Three families now have three members each, and Chapter 21.8 will make a hundred.


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.