Ethernet · Module 25
"Full-Duplex Ethernet Uses CSMA/CD"
512 bit times was a 4 752-metre round-trip budget. On a 3-metre link the margin is 1 584 and there is nothing to bound — but the 64-octet frame it chose still sets an eight-wide pipeline.
Chapter 1.5 §2 listed what full duplex removed from the MAC and the list is complete. This chapter asks what the removed mechanism was FOR, and finds that the answer is still in every frame on every link in the world.
The myth, stated as the people who hold it would state it. Ethernet is CSMA/CD. That is what the standard is about, it is what distinguishes Ethernet from other link layers, and a modern switched link is still Ethernet — so it still uses carrier sense, collision detection and backoff.
Every clause of that was true in 1983 and the last one stopped being true in 1997.
| Block from Chapter 1.2 | Fate under full duplex | Why |
|---|---|---|
slot_time_counter | unreachable | nothing else can be acquiring the medium |
collision_classifier | unreachable | there are no collisions to classify |
jam_generator | unreachable | nothing to make unambiguous to stations that do not exist |
backoff_engine | unreachable | nothing to separate in time |
Chapter 1.5 §2's table, and this chapter does not repeat its argument. It asks a different question: 512 bit times was chosen to bound something, and what it bounded was a distance.
| Rate | 512 bit times | Round trip, less the 32-bit jam | Metres of cable, at Chapter 8.2 §3's 5.05 ns/m |
|---|---|---|---|
| 10 Mb/s | 51 200 ns | 48 000 ns | 4 752 m |
| 100 Mb/s | 5 120 ns | 4 800 ns | 475 m |
| 1 Gb/s | 512 ns | 480 ns | 47.5 m |
| 1 Gb/s with carrier extension | 4 096 ns | 4 064 ns | 402 m |
Slot time is a distance wearing a frame-format costume, and every factor of ten in rate divides the distance by ten.
On a point-to-point link the bound is not merely satisfied. A 3-metre link's round trip is 30.3 ns against a 51 200 ns budget — a margin of 1 690 — and there is no second transmitter for the bound to bound.
And the cost that survived is the minimum frame. 512 bits had to be a frame, so the frame's minimum is 64 octets — 45.24% of the wire at minimum size, per Chapter 24.3 §1 — and, more expensively, the packet rate that sets Chapter 23.3 §2's eight-wide pipeline in 2026.
1. Scope — A Timing Constant and the Frame It Left Behind
This chapter owns four derivations.
| What is derived | |
|---|---|
| Sections 2 to 5 | what 512 bit times bounded, as a distance, at four rates |
| Sections 6 to 7 | why the bound is vacuous on a point-to-point link, quantified |
| Sections 8 to 11 | the vestige: a 64-octet minimum frame, at 45.24% of the wire and 595.24 Mpps at 400 Gb/s |
| Sections 12 to 13 | the pipeline width it sets in a 2026 switch ASIC, and what a 128-octet minimum would have bought |
What this chapter does not own. Chapter 1.2 owns the slot time's three roles and the collision-domain budget; Chapter 1.5 owns the deletion and what full duplex broke; Chapter 5.6 owns padding. This chapter uses all three and re-derives none of them — it converts Chapter 1.2's timing budget into a distance and follows the minimum frame forward to Chapter 23.3's silicon.
2. What 512 Bit Times Actually Bounded
Chapter 1.2 §3 gave slot time three roles: an upper bound on medium acquisition, an upper bound on a collision fragment's length, and the quantum for backoff. All three rest on one requirement.
slotTime > round-trip propagation of the collision domain + maximum jam timeAnd that inequality is a statement about DISTANCE, because propagation is a distance divided by a velocity.
Rearrange it.
round trip available = slotTime − jamTime
one-way budget = (slotTime − jamTime) ÷ 2
maximum diameter = one-way budget ÷ propagation delay per metreAt 10 Mb/s with Chapter 1.2 §3's normative 32-bit jam and Chapter 8.2 §3's 5.05 ns per metre of copper.
| Term | Value |
|---|---|
| slot time, 512 bit times at 100 ns | 51 200 ns |
| jam time, 32 bit times | 3 200 ns |
| round-trip budget | 48 000 ns |
| one-way budget | 24 000 ns |
| diameter, pure cable | 4 752 m |
Chapter 1.2 §3's illustrative topology spent 8.8 µs of the 51.2 on round trip and 3.2 on jam, leaving substantial margin — and the margin is the point: the parameter was fixed once, generously, for the worst topology the standard intended to support.
Now take the same arithmetic up the rates, because a bit time is the reciprocal of the signalling rate.
| Rate | Bit time | Slot time | Round-trip budget | Pure-cable diameter |
|---|---|---|---|---|
| 10 Mb/s | 100 ns | 51 200 ns | 48 000 ns | 4 752 m |
| 100 Mb/s | 10 ns | 5 120 ns | 4 800 ns | 475 m |
| 1 Gb/s | 1 ns | 512 ns | 480 ns | 47.5 m |
| 1 Gb/s, extended to 4 096 | 1 ns | 4 096 ns | 4 064 ns | 402 m |
Chapter 1.2 §2's callout said the rate-independence of the MAC is paid for by the rate-dependence of the topology. This is that sentence as a table: ten times the rate buys one tenth the physical extent for the same slot time.
Row three is why gigabit half duplex needed carrier extension, and row four is what extension bought: 4 096 bit times restores the diameter to roughly a fast-Ethernet segment, at the cost of padding every short frame to 512 octets on the wire.
And row three is also why the industry stopped. Forty-seven metres of pure cable, before repeaters and detection latency are charged against it, is not a network — and the alternative was a switch, which has no collision domain at all.
3. RTL 1 — The Slot Package and the Diameter Model
// ---------------------------------------------------------------------
// slotmyth_pkg -- the constants for converting a timing parameter into
// a distance, and for following the minimum frame forward into silicon.
//
// Unit: Chapter 23.3 Section 2's bitcell equivalent.
// 1 BCE = 0.35 GE = one bit of usable on-die SRAM
// 1 flip-flop = 20 BCE
// Chapter 19.7 Section 19's MAC receive datapath = 283 320 BCE
// ---------------------------------------------------------------------
package slotmyth_pkg;
localparam int unsigned DATAPATH_BCE = 283_320;
localparam int unsigned BCE_PER_FLOP = 20;
// ---- Chapter 1.2's normative parameters ------------------------------
localparam int unsigned SLOT_TIME_BITS = 512;
localparam int unsigned SLOT_TIME_BITS_EXT = 4_096; // carrier extension
localparam int unsigned JAM_SIZE_BITS = 32;
localparam int unsigned MIN_FRAME_OCTETS = 64; // 512 bits
localparam int unsigned ATTEMPT_LIMIT = 16;
// ---- Chapter 24.3 Section 1's framing ---------------------------------
localparam int unsigned OCT_PREAMBLE = 8;
localparam int unsigned OCT_IFG = 12;
localparam int unsigned OCT_FIXED = 38;
// ---- Chapter 8.2 Section 3's velocity, hundredths of ns per metre -----
localparam int unsigned NS_PER_M_CU_X100 = 505;
localparam int unsigned NS_PER_M_FI_X100 = 490;
// ---- Chapter 23.3 Section 2's part ------------------------------------
localparam int unsigned SWITCH_PORTS = 64;
localparam int unsigned CORE_MHZ = 1_200;
typedef enum logic [1:0] {
LINK_SHARED_HALF = 2'd0, // a collision domain exists
LINK_P2P_HALF = 2'd1, // two stations, one cable
LINK_P2P_FULL = 2'd2 // Chapter 1.5's deletion applies
} linkmode_e;
// ---- derived: a slot time is a distance -------------------------------
// bit_time_ps: picoseconds per bit at a given rate in Mb/s.
function automatic int unsigned bit_time_ps(int unsigned mbps);
return 1_000_000 / mbps;
endfunction
function automatic int unsigned slot_ps(int unsigned mbps,
int unsigned slot_bits);
return slot_bits * bit_time_ps(mbps);
endfunction
function automatic int unsigned round_trip_ps(int unsigned mbps,
int unsigned slot_bits);
// Chapter 1.2 Section 3: the budget is the slot less the jam.
return slot_ps(mbps, slot_bits) - (JAM_SIZE_BITS * bit_time_ps(mbps));
endfunction
function automatic int unsigned diameter_cm(int unsigned mbps,
int unsigned slot_bits);
// one-way picoseconds / (ns per metre x 100) gives centimetres x 10,
// so divide once more by 10.
return (round_trip_ps(mbps, slot_bits) / 2) * 100
/ (NS_PER_M_CU_X100 * 10);
endfunction
// ---- derived: the minimum frame's wire cost ---------------------------
function automatic int unsigned min_wire_slot();
return MIN_FRAME_OCTETS + OCT_PREAMBLE + OCT_IFG; // 84
endfunction
function automatic int unsigned framing_tax_ppm(int unsigned payload);
return (OCT_FIXED * 1_000_000) / (payload + OCT_FIXED);
endfunction
// ---- derived: the packet rate the minimum frame sets ------------------
function automatic int unsigned pps_k(int unsigned gbps,
int unsigned slot_oct);
return (gbps * 1_000_000) / (slot_oct * 8);
endfunction
function automatic int unsigned datapaths_milli(int unsigned bce);
return (bce * 1000) / DATAPATH_BCE;
endfunction
endpackage// ---------------------------------------------------------------------
// slot_diameter_model -- a bit-time budget expressed as the distance
// it was chosen to bound.
//
// The output that matters is diameter_cm_o, because it makes visible
// what no design reports: the parameter is a length, and it divides by
// ten every time the rate multiplies by ten.
// ---------------------------------------------------------------------
module slot_diameter_model
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic [31:0] rate_mbps,
input logic [15:0] slot_bits,
input logic [15:0] link_metres,
input logic [1:0] link_mode, // linkmode_e
output logic [31:0] slot_ps_o,
output logic [31:0] round_trip_ps_o,
output logic [31:0] diameter_cm_o,
output logic [31:0] link_round_trip_ps,
output logic [31:0] margin_x10,
output logic bound_is_satisfied,
output logic bound_is_meaningful,
output logic mechanism_is_reachable,
output logic [31:0] c_evaluations
);
always_comb begin
slot_ps_o = 32'(slot_ps(int'(rate_mbps), int'(slot_bits)));
round_trip_ps_o = 32'(round_trip_ps(int'(rate_mbps), int'(slot_bits)));
diameter_cm_o = 32'(diameter_cm(int'(rate_mbps), int'(slot_bits)));
// This link's actual round trip.
link_round_trip_ps = (32'(link_metres) * 32'(NS_PER_M_CU_X100) * 32'd2)
/ 32'd100 * 32'd1000;
margin_x10 = (link_round_trip_ps == 0) ? 32'hFFFF_FFFF
: ((round_trip_ps_o * 32'd10) / link_round_trip_ps);
bound_is_satisfied = (link_round_trip_ps <= round_trip_ps_o);
// THE distinction. A bound on medium acquisition is meaningful only
// where a medium is acquired -- which needs a second transmitter.
bound_is_meaningful = (link_mode == 2'(LINK_SHARED_HALF));
// Chapter 1.5 Section 2: five of six blocks become unreachable.
mechanism_is_reachable = (link_mode != 2'(LINK_P2P_FULL));
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) c_evaluations <= '0;
else c_evaluations <= c_evaluations + 32'd1;
end
endmoduleClassification: a unit conversion, and two booleans that say whether the converted quantity means anything.
What it teaches: that diameter_cm_o falls by a factor of ten for every factor of ten in rate — 475 247 cm at 10 Mb/s, 47 524 at 100, 4 752 at 1 Gb/s — and that this is Chapter 1.2 §2's callout rendered as an output. The MAC's parameters are rate-independent in bit times and the topology's reach is not, and only the second of those appears anywhere a network designer looks.
And it teaches that bound_is_satisfied and bound_is_meaningful are different questions. On a 3-metre full-duplex link the bound is satisfied with a margin of 1 584 — and it is meaningless, because bound_is_meaningful requires a shared medium and there is not one. A design that reports only the first has told an operator that a vacuous constraint is being met.
Deliberately simplified: the diameter is pure cable, where Chapter 1.2 §3's table shows repeaters and collision-detection latency consuming most of the budget in any real topology — 8.8 µs of the 51.2 in that chapter's illustrative case, of which only 5.0 was cable. The model uses copper's velocity throughout. And link_round_trip_ps assumes a direct cable, where a half-duplex segment's round trip includes every repeater on the path.
Production implication: the repeater term is the one that made half-duplex topologies fail in a way that looked like a cabling problem. Chapter 1.2 §3's budget is spent by longer cable, more repeaters and slower collision detection from one pool, and when the sum exceeds the slot time the network does not degrade gracefully — it produces late collisions, which that chapter §6 established are not collisions in the ordinary sense at all. A design computing diameter_cm_o at elaboration and comparing it against a configured topology would have caught the whole class at installation, and the reason nobody did is that the parameter was presented as a frame-format constant rather than as a distance.
4. The Bound Is Vacuous Point to Point, and by How Much
Section 2 gave the diameter. This section applies it to the links that exist and finds the margin is four orders of magnitude.
A point-to-point link has two stations and one cable. Its round trip is 2 × length × velocity and nothing else — no repeaters, no shared segment, no third party.
| Link | Round trip | Against the 10 Mb/s budget of 48 000 ns | Margin |
|---|---|---|---|
| 1 m DAC | 10.1 ns | — | 4 752× |
| 3 m DAC | 30.3 ns | — | 1 584× |
| 30 m | 303 ns | — | 158× |
| 100 m | 1 010 ns | — | 47.5× |
| 2 km fibre | 19 600 ns | — | 2.4× |
Even a two-kilometre link satisfies a bound designed for a 1980 coaxial segment, and every link anybody deploys inside a building satisfies it by two to four orders of magnitude.
And that is the less interesting half. The bound is not merely satisfied — it has nothing to bound.
| What the bound is about | On a point-to-point full-duplex link | |
|---|---|---|
| medium acquisition | how long a station may wait to seize a shared medium | there is no medium to seize; the transmitter owns its pair |
| collision-fragment length | the longest runt a collision can produce | there are no collisions |
| backoff quantum | the unit in which retransmissions are separated | nothing is retransmitted at this layer |
A margin of 1 584 is a statement that the constraint is comfortably met. The row above it is the statement that matters: there is no second transmitter, so the quantity the constraint bounds does not exist.
Chapter 1.5 §2 called the four blocks unreachable and this is the arithmetic behind the word. slot_time_counter counts bit times since a transmission began, to answer a question — has the acquisition window closed — that has no meaning when nothing else can transmit.
5. RTL 2 — The Point-to-Point Bound
// ---------------------------------------------------------------------
// point_to_point_bound -- whether a link's slot-time constraint is
// satisfied, and whether it constrains anything.
//
// The two outputs are deliberately separate. A design that reports
// only the first has told an operator that a vacuous constraint is
// being met, which is Section 20's rejected property.
// ---------------------------------------------------------------------
module point_to_point_bound
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic [15:0] link_metres,
input logic [31:0] rate_mbps,
input logic [15:0] slot_bits,
input logic separate_tx_rx_pairs,
input logic [15:0] stations_on_segment,
output logic [31:0] link_round_trip_ns_x10,
output logic [31:0] budget_ns_x10,
output logic [31:0] margin_x10,
output logic bound_satisfied,
output logic collisions_possible,
output logic bound_constrains_anything,
output logic slot_counter_reachable,
output logic backoff_reachable,
output logic [1:0] mode,
output logic [31:0] c_vacuous_evaluations
);
always_comb begin
link_round_trip_ns_x10 = (32'(link_metres) * 32'(NS_PER_M_CU_X100) * 32'd2)
/ 32'd10;
budget_ns_x10 = 32'(round_trip_ps(int'(rate_mbps), int'(slot_bits)))
/ 32'd100;
margin_x10 = (link_round_trip_ns_x10 == 0) ? 32'hFFFF_FFFF
: ((budget_ns_x10 * 32'd10) / link_round_trip_ns_x10);
bound_satisfied = (link_round_trip_ns_x10 <= budget_ns_x10);
// THE question the margin does not answer. Two transmitters that
// can be active at once is what makes a collision possible, and
// separate pairs remove it regardless of the station count.
collisions_possible = !separate_tx_rx_pairs && (stations_on_segment >= 16'd2);
bound_constrains_anything = collisions_possible;
mode = separate_tx_rx_pairs ? 2'(LINK_P2P_FULL)
: (stations_on_segment <= 16'd2) ? 2'(LINK_P2P_HALF)
: 2'(LINK_SHARED_HALF);
// Chapter 1.5 Section 2's deletion, as reachability.
slot_counter_reachable = collisions_possible;
backoff_reachable = collisions_possible;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) c_vacuous_evaluations <= '0;
else if (bound_satisfied && !bound_constrains_anything)
c_vacuous_evaluations <= c_vacuous_evaluations + 32'd1;
end
endmoduleClassification: a comparison and a reachability test, kept deliberately apart.
What it teaches: that bound_satisfied and bound_constrains_anything can both be computed and only their conjunction means anything. On a 3-metre full-duplex link the first is high with a margin of 1 584 and the second is low — so c_vacuous_evaluations counts every cycle the design spent confirming a constraint with no subject.
And it teaches that collisions_possible depends on separate_tx_rx_pairs and NOT on the station count. Section 4's callout: a two-station half-duplex link has collisions and a two-station full-duplex link does not, and the difference is the cabling. The station count enters only to distinguish a point-to-point half-duplex link from a shared segment, which changes the diameter and not the reachability.
Deliberately simplified: separate_tx_rx_pairs is a configuration input standing in for Chapter 1.5 §9's mode register, which that chapter established must not move while the link is up. stations_on_segment is not knowable to a MAC — a station cannot count its neighbours — so it is a topology fact supplied from outside. And the round trip is pure cable.
Production implication: the mode register's immovability is the detail that makes a real bug, and Chapter 1.5 §9 named it. A link that negotiates full duplex and a partner that falls back to half produces the duplex mismatch Chapter 11.4 is about: the full-duplex end transmits whenever it wishes, the half-duplex end sees carrier and defers, and every frame the full-duplex end sends during the other's transmission is a collision the full-duplex end does not detect. The symptom is late collisions at one end and CRC errors at the other, on a link that passes a ping test — and collisions_possible being computed from a locally-configured bit rather than from a negotiated agreement is exactly how the two ends come to disagree. The check is Chapter 11.4's and the arithmetic is this module's: a late collision on a link whose diameter budget is satisfied 1 584 times over is not a distance problem, it is a mode disagreement.
6. The Vestige: 64 Octets, and What It Costs on the Wire
Four blocks became unreachable and one number survived. This section prices it.
The minimum frame size is 64 octets because the slot time is 512 bits. Chapter 1.2 §2's table: slotTime and minFrameSize are the same 512 bits in different units, and the reason a frame must be at least that long is that a transmitter must still be transmitting when the furthest station's collision signal returns.
A shorter frame would finish before the collision was detectable, and the transmitter would move on believing it had succeeded — which is exactly what a late collision is, and Chapter 1.2 §6 established that it is a different fault class.
So the minimum frame is a timing parameter wearing a frame-format costume, and it outlived the timing.
| Value | Where it comes from | |
|---|---|---|
| minimum frame | 64 octets | 512 bits = slot time |
| plus preamble and SFD | 8 octets | Chapter 5.2 |
| plus interframe gap | 12 octets | Chapter 5.9 |
| wire slot | 84 octets | — |
| payload in it | 46 octets | Chapter 5.6 |
| framing tax | 45.24% | Chapter 24.3 §1 |
And the padding, which is the vestige's most visible cost. Chapter 5.6 established that a frame carrying fewer than 46 payload octets is padded to 46. A one-octet payload therefore occupies an 84-octet wire slot.
| Payload | Padded to | Wire slot | Useful fraction of the wire |
|---|---|---|---|
| 1 octet | 46 | 84 | 1.19% |
| 10 octets | 46 | 84 | 11.90% |
| 46 octets | 46 | 84 | 54.76% |
| 100 octets | — | 138 | 72.46% |
A one-octet payload uses 1.19% of the wire it occupies, and the reason is a round-trip budget for a coaxial segment nobody has run since the 1990s.
This is Chapter 8.3 §2's observation with its cause named. That chapter derived the efficiency hyperbola and noted that a one-octet frame's efficiency is 1.2% rather than 54.8%, because 45 of those 46 octets are pad rather than payload. The padding exists to make the frame long enough to detect a collision that cannot occur.
7. RTL 3 — The Minimum-Frame Cost Model
// ---------------------------------------------------------------------
// min_frame_cost -- what the 64-octet minimum costs on the wire, and
// what its timing justification is worth on this link.
//
// The output that matters is justification_still_applies, which is
// low on every link anybody deploys -- and the constant is there
// anyway, because Chapter 5.10's runt check is in every MAC.
// ---------------------------------------------------------------------
module min_frame_cost
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic [15:0] payload_octets,
input logic [15:0] min_frame_octets,
input logic collisions_possible_i,
input logic [15:0] rate_gbps,
output logic [15:0] padded_payload,
output logic [15:0] frame_octets,
output logic [31:0] wire_slot,
output logic [31:0] useful_ppm,
output logic [31:0] pad_octets,
output logic [31:0] framing_tax_ppm_o,
output logic [31:0] pps_k_o,
output logic [31:0] ns_per_frame_x100,
output logic justification_still_applies,
output logic constant_is_frozen,
output logic [31:0] c_padded_frames
);
always_comb begin
// Chapter 5.6: short payloads are padded, not shortened.
padded_payload = (payload_octets < (min_frame_octets - 16'd18))
? (min_frame_octets - 16'd18) : payload_octets;
pad_octets = 32'(padded_payload) - 32'(payload_octets);
frame_octets = padded_payload + 16'd18;
wire_slot = 32'(frame_octets) + 32'(OCT_PREAMBLE) + 32'(OCT_IFG);
useful_ppm = (wire_slot == 0) ? 32'd0
: ((32'(payload_octets) * 1_000_000) / wire_slot);
framing_tax_ppm_o = 32'(framing_tax_ppm(int'(padded_payload)));
pps_k_o = 32'(pps_k(int'(rate_gbps), int'(wire_slot)));
ns_per_frame_x100 = (pps_k_o == 0) ? 32'd0
: (100_000_000 / pps_k_o);
// Section 4: the timing reason needs a collision domain.
justification_still_applies = collisions_possible_i;
// And Chapter 5.10's runt check holds it in place regardless.
constant_is_frozen = 1'b1;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) c_padded_frames <= '0;
else if (pad_octets != 0) c_padded_frames <= c_padded_frames + 32'd1;
end
endmoduleClassification: a padding model whose two constants are a dead justification and a live constraint.
What it teaches: that useful_ppm reports 11 904 for a one-octet payload — 1.19% of the wire — and that justification_still_applies is low on the same evaluation. The cost is paid and the reason is gone.
And it teaches that constant_is_frozen is hard-wired high for a reason that is not physics. Chapter 7.3's runt check discards anything below 64 octets in every MAC ever built, so a shorter frame is indistinguishable from a collision fragment to the installed base. The parameter is held by the population rather than by the specification, which is why no amendment has removed it.
Deliberately simplified: the model pads to min_frame_octets − 18, assuming a 14-octet header and a 4-octet FCS, which a VLAN tag changes — Chapter 13.2 §3's tagged minimum is 68 octets and the payload minimum does not move. collisions_possible_i is supplied from Section 5's model. And the model prices the pad in wire octets and not in the buffer it occupies — Chapter 23.3 §9's cell allocation means a 64-octet frame occupies a 256-octet cell, so the internal waste is four times the wire's.
Production implication: the cell-allocation multiplier is where the vestige is most expensive and it is a second-order effect nobody attributes to it. Chapter 23.3 §9 derived that a 64 MB buffer allocated in 256-octet cells holds between 16 and 63 MB of frames depending on the size mix — a 64-octet frame occupies a whole cell and wastes 192 octets of it. So the minimum frame's cost is 45.24% of the wire and 75% of a buffer cell, and the second is invisible in every bandwidth calculation. A switch whose traffic is dominated by minimum-size frames has a quarter of its nominal buffer, which is the same 4× the pad costs on the wire arriving in a different resource.
8. The Packet Rate the Vestige Sets
Section 6 priced the minimum frame on the wire. This section follows it into silicon, where it is more expensive and much less visible.
A line rate and a minimum wire slot give a packet rate, and a packet rate is a pipeline.
packets per second = rate ÷ (wire slot × 8)
at 84 octets: 100 Gb/s → 148.81 Mpps
400 Gb/s → 595.24 Mpps
800 Gb/s → 1 190.48 Mpps| Rate | Frames per second at 64 octets | Nanoseconds per frame |
|---|---|---|
| 100 Gb/s | 148.81 M | 6.720 |
| 400 Gb/s | 595.24 M | 1.680 |
| 800 Gb/s | 1 190.48 M | 0.840 |
And Chapter 23.3 §2 took that to a switch. Sixty-four ports at 100 Gb/s, all at minimum frame size:
64 × 148.81 Mpps = 9.524 Gpps
at a 1.2 GHz core clock: 9.524 ÷ 1.2 = 7.94 packets per cycle
→ an eight-wide pipelineThe pipeline width of a 2026 switch ASIC is eight because a round-trip budget for a 2.5-kilometre coaxial segment was set at 512 bit times in 1980.
And the counterfactual is worth computing, because it says how much.
| Minimum frame | Wire slot | 64 ports at 100 Gb/s | Packets per cycle at 1.2 GHz | Pipeline width |
|---|---|---|---|---|
| 64 octets | 84 | 9.524 Gpps | 7.94 | 8 |
| 128 octets | 148 | 5.405 Gpps | 4.50 | 5 |
| 256 octets | 276 | 2.899 Gpps | 2.42 | 3 |
| 512 octets | 532 | 1.504 Gpps | 1.25 | 2 |
Doubling the minimum frame would have made the pipeline five wide instead of eight — a 37.5% reduction in the widest, most timing-critical structure in the design.
And the pipeline's width is not a small thing. Chapter 23.3 §2 established that an eight-wide pipeline at 36 stages is what produces the 30 ns lookup term Chapter 23.1 §4 assumed; every stage is replicated eight times, every arbiter resolves eight candidates, and every hazard check is eight-way.
9. RTL 4 — The Pipeline Width Model
// ---------------------------------------------------------------------
// pipeline_width_model -- the chain from a 1980 timing parameter to a
// 2026 pipeline width, with every step visible.
//
// The output that matters is width_traceable_to_slot_time, which is
// high: every term between the two is a division.
// ---------------------------------------------------------------------
module pipeline_width_model
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic [15:0] min_frame_octets,
input logic [15:0] ports,
input logic [15:0] port_gbps,
input logic [15:0] core_mhz,
output logic [31:0] wire_slot_o,
output logic [31:0] port_pps_k,
output logic [31:0] aggregate_pps_k,
output logic [31:0] packets_per_cycle_x100,
output logic [15:0] pipeline_width,
output logic [31:0] width_if_128,
output logic [31:0] width_if_256,
output logic width_traceable_to_slot_time,
output logic [31:0] c_evaluations
);
logic [31:0] slot_128, slot_256, pps_128, pps_256;
always_comb begin
wire_slot_o = 32'(min_frame_octets) + 32'(OCT_PREAMBLE) + 32'(OCT_IFG);
port_pps_k = 32'(pps_k(int'(port_gbps), int'(wire_slot_o)));
aggregate_pps_k = port_pps_k * 32'(ports);
packets_per_cycle_x100 = (core_mhz == 0) ? 32'd0
: ((aggregate_pps_k * 32'd100)
/ (32'(core_mhz) * 32'd1000));
pipeline_width = 16'((packets_per_cycle_x100 + 32'd99) / 32'd100);
// The counterfactuals, computed rather than asserted.
slot_128 = 32'd128 + 32'(OCT_PREAMBLE) + 32'(OCT_IFG);
slot_256 = 32'd256 + 32'(OCT_PREAMBLE) + 32'(OCT_IFG);
pps_128 = 32'(pps_k(int'(port_gbps), int'(slot_128))) * 32'(ports);
pps_256 = 32'(pps_k(int'(port_gbps), int'(slot_256))) * 32'(ports);
width_if_128 = ((pps_128 * 32'd100) / (32'(core_mhz) * 32'd1000)
+ 32'd99) / 32'd100;
width_if_256 = ((pps_256 * 32'd100) / (32'(core_mhz) * 32'd1000)
+ 32'd99) / 32'd100;
// Every term between the slot time and the width is a division.
width_traceable_to_slot_time = 1'b1;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) c_evaluations <= '0;
else c_evaluations <= c_evaluations + 32'd1;
end
endmoduleClassification: four divisions and a ceiling, with the counterfactuals computed alongside so the cost is a difference rather than an absolute.
What it teaches: that pipeline_width is 8 at a 64-octet minimum and width_if_128 is 5, so the parameter's silicon cost is three pipeline lanes — 37.5% of the widest structure in the design. Reporting both is what makes it a cost rather than a fact.
And it teaches that width_traceable_to_slot_time is a hard-wired one and that the traceability is the module's content. Chapter 23.3 §2 derived the width from the packet rate and stopped; this module carries the chain one step further back, to a number chosen for a coaxial segment.
Deliberately simplified: the width is a ceiling of the packets-per-cycle figure, where a real design adds margin for bursts and for the IFG's variability. All ports are assumed at minimum frame size simultaneously, which is the worst case a pipeline must be sized for and is not the traffic anybody sees. And the core frequency is an input where Chapter 23.6 §8 established that frequency is an output of the implementation flow.
Production implication: the worst-case sizing is correct and it is also the reason the cost is permanent. A pipeline sized for a traffic mix rather than for the minimum frame is a pipeline that drops under an adversarial or merely unusual load — and Chapter 12.4 §3's amplification means a single flooding port can produce minimum-size frames at line rate on 63 egress ports at once. So the eight-wide pipeline is not over-provisioning; it is the only width that survives Chapter 25.5 §2's scenario. The minimum frame's cost is therefore paid in every switch, for a case that arises from a different chapter's failure, and the two are connected by nothing an architect would notice.
10. What Else the Vestige Still Touches
Sections 6 and 8 gave the wire cost and the pipeline width. Four more structures carry the parameter and none of them is obviously about a collision domain.
| Structure | How the minimum frame enters | Chapter |
|---|---|---|
| the runt check | a frame below 64 octets is discarded as invalid | Chapter 7.3 |
| the buffer's cell size | a 64-octet frame occupies a 256-octet cell — 75% waste | Chapter 23.3 §9 |
| the descriptor rate | one descriptor per frame, at the minimum-frame packet rate | Chapter 23.4 §5 |
| the interframe gap's share | 12 octets against an 84-octet slot — 14.29% | Chapter 5.9 |
Row three is the largest and it is Chapter 23.4 §5's result restated. That chapter derived that descriptors consume 38.1 Gb/s of host interface at 100 Gb/s and minimum frame size — 38.1% of the payload rate — and 0.35% at 9 000 octets, a factor of 109. The descriptor rate is the packet rate, and the packet rate is set by the minimum frame.
So the vestige's full bill.
| Cost | Caused by | |
|---|---|---|
| framing tax at minimum size | 45.24% of the wire | 64 octets plus preamble and gap |
| padding, at a 1-octet payload | 1.19% useful | the 46-octet payload minimum |
| buffer cell waste | 75% of a 256-octet cell | a 64-octet frame in a fixed cell |
| pipeline width | 8 lanes instead of 5 | 9.524 Gpps instead of 5.405 |
| descriptor bandwidth | 38.1% of payload at 100 Gb/s | one descriptor per frame |
Five costs, one parameter, and the parameter's justification has not applied to any deployed link since 1997.
And the honest counterweight, because a chapter this one-sided owes it. The minimum frame also does useful work that has nothing to do with collisions.
| What the 64-octet minimum still buys | |
|---|---|
| a bound on the frame rate | a receiver's per-frame work is bounded, which is what Chapter 23.4 §2's 6.72 ns budget is against |
| a floor for Chapter 7.3's validity check | a runt is unambiguously distinguishable from a short frame |
| a fixed-cost amortisation point | Chapter 8.3 §2's curve has to start somewhere |
Row one is the real one and it is worth stating plainly: a smaller minimum frame would raise the packet rate, and every structure in Section 8's chain would get wider rather than narrower. The parameter is a burden at the value it has and it would be a larger burden at a smaller one — so the case for change is for a LARGER minimum, which Section 6's callout established is blocked by the same interoperability that blocks a smaller one.
11. RTL 5 — The Vestige Auditor
// ---------------------------------------------------------------------
// vestige_auditor -- every structure whose size the minimum frame
// sets, and whether the parameter's justification still applies.
//
// The output that matters is cost_is_legacy, which is high on every
// deployed link -- and the costs are real and paid anyway.
// ---------------------------------------------------------------------
module vestige_auditor
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic [15:0] min_frame_octets,
input logic [15:0] cell_octets,
input logic [15:0] descriptor_octets,
input logic [15:0] port_gbps,
input logic collisions_possible_i,
output logic [31:0] wire_tax_ppm,
output logic [31:0] cell_waste_ppm,
output logic [31:0] descriptor_bw_ppm,
output logic [31:0] pps_k_o,
output logic [15:0] structures_affected,
output logic justification_applies,
output logic cost_is_legacy,
output logic smaller_would_be_worse,
output logic [31:0] c_audits
);
logic [31:0] wire_slot;
always_comb begin
wire_slot = 32'(min_frame_octets) + 32'(OCT_PREAMBLE) + 32'(OCT_IFG);
// Chapter 24.3 Section 1's framing tax at the minimum.
wire_tax_ppm = (wire_slot == 0) ? 32'd0
: ((32'(OCT_FIXED) * 1_000_000) / wire_slot);
// Chapter 23.3 Section 9: a frame occupies a whole cell.
cell_waste_ppm = (cell_octets == 0) ? 32'd0
: (((32'(cell_octets) - 32'(min_frame_octets)) * 1_000_000)
/ 32'(cell_octets));
pps_k_o = 32'(pps_k(int'(port_gbps), int'(wire_slot)));
// Chapter 23.4 Section 5: one descriptor per frame, as a share of
// the payload bandwidth.
descriptor_bw_ppm = (min_frame_octets <= 16'd18) ? 32'd0
: ((32'(descriptor_octets) * 1_000_000)
/ (32'(min_frame_octets) - 32'd18));
// Section 10's table.
structures_affected = 16'd5;
justification_applies = collisions_possible_i;
cost_is_legacy = !collisions_possible_i;
// And the direction that would help is the one people do not
// propose: a LARGER minimum lowers every cost above.
smaller_would_be_worse = 1'b1;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) c_audits <= '0;
else c_audits <= c_audits + 32'd1;
end
endmoduleClassification: an inventory of five costs and two booleans that say whose they are.
What it teaches: that cost_is_legacy is high on every link anybody deploys and that the five costs are paid regardless. The module exists so the phrase legacy constraint has a list attached — 452 380 ppm of wire, 750 000 ppm of a buffer cell, 148 810 thousand frames per second, and a descriptor overhead of 347 826 ppm against the payload at minimum frame size — 34.8%, which is Chapter 23.4 §5's 38.1% computed against that chapter's own denominator.
And it teaches that smaller_would_be_worse is a hard-wired one, which is the counterweight the chapter owes. A smaller minimum frame would raise the packet rate and widen every structure in Section 8's chain; the case for change is for a larger minimum, and Section 6's callout established that both directions are blocked by the same runt check.
Deliberately simplified: descriptor_bw_ppm compares a descriptor against the payload rather than against the wire slot, which is Chapter 23.4 §5's convention and makes the figure look larger than a wire-relative one would. cell_octets is a single constant where Chapter 23.3 §9's buffer allocates in cells whose size is a design choice — a 128-octet cell halves the waste and doubles the cell-pointer state. And structures_affected is a literal.
Production implication: the cell size is the one lever a switch designer actually has and it trades against a structure this chapter has not priced. Chapter 23.3 §9's 64 MB buffer in 256-octet cells needs 262 144 cell pointers; in 128-octet cells it needs 524 288, and each pointer is 19 bits — so halving the cell size costs 4 980 736 BCE, 17.6 datapaths, 0.89% of the switch and recovers up to half the waste on minimum-size frames. That is a good trade on a switch whose traffic is small-frame dominated and a bad one otherwise, and the deciding number is the frame-size histogram Chapter 21.6 §4 argued for — which is the same measurement, wanted by a third chapter for a third reason.
12. What a Half-Duplex Claim Must Never Do
Five prohibitions, and three of them are about a mechanism that is correct and unreachable.
| # | Never | Because |
|---|---|---|
| 1 | report a satisfied slot-time bound as evidence of anything | Section 4: a margin of 1 584 on a link with no second transmitter constrains nothing |
| 2 | describe a switched link as CSMA/CD | Chapter 1.5 §2: four blocks unreachable and a fifth collapsed |
| 3 | attribute a late collision to distance on a full-duplex link | Section 5: it is a duplex mismatch — Chapter 11.4 |
| 4 | treat the minimum frame as a frame-format fact | Sections 6 and 8: it is a timing parameter and it sets a pipeline width |
| 5 | propose a smaller minimum frame as an efficiency improvement | Section 10: it raises the packet rate and widens every structure in the chain |
Row three is the one that wastes field time. A late collision means a transmitter finished before a collision became detectable — Chapter 1.2 §6's fault class — and the usual cause is a topology that exceeds the slot-time budget. On a full-duplex link the budget is satisfied by three orders of magnitude, so a late collision there is never about distance and always about one end running half duplex.
13. RTL 6 — The Half-Duplex Detector
// ---------------------------------------------------------------------
// half_duplex_detector -- whether the CSMA/CD machinery is reachable
// in this configuration, and whether the evidence agrees.
//
// The output that matters is evidence_contradicts_mode: a link
// configured full duplex that is reporting collisions is Chapter
// 11.4's duplex mismatch, and the slot-time margin says so.
// ---------------------------------------------------------------------
module half_duplex_detector
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic configured_full_duplex,
input logic peer_full_duplex_advertised,
input logic collision_observed,
input logic late_collision_observed,
input logic [31:0] margin_x10_i,
input logic [31:0] c_fcs_errors,
input logic [31:0] c_late_collisions,
output logic machinery_reachable,
output logic evidence_contradicts_mode,
output logic duplex_mismatch_suspected,
output logic distance_is_the_cause,
output logic mode_disagreement_is_the_cause,
output logic [1:0] recommended_check,
output logic [31:0] c_contradictions
);
// recommended_check: 1 = cable length, 2 = duplex negotiation,
// 3 = neither -- the machinery is unreachable.
always_comb begin
// Chapter 1.5 Section 2: full duplex makes them unreachable.
machinery_reachable = !configured_full_duplex;
// A collision on a link that cannot have one.
evidence_contradicts_mode = configured_full_duplex && collision_observed;
// Chapter 11.4's signature: one end full, the other half.
duplex_mismatch_suspected = evidence_contradicts_mode
|| (configured_full_duplex
&& !peer_full_duplex_advertised);
// Section 4: a margin in the thousands rules distance out.
distance_is_the_cause = late_collision_observed
&& (margin_x10_i < 32'd20); // margin below 2x
mode_disagreement_is_the_cause = late_collision_observed
&& (margin_x10_i >= 32'd20);
recommended_check = distance_is_the_cause ? 2'd1
: mode_disagreement_is_the_cause ? 2'd2
: !machinery_reachable ? 2'd3
: 2'd0;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) c_contradictions <= '0;
else if (evidence_contradicts_mode) c_contradictions <= c_contradictions + 32'd1;
end
endmoduleClassification: a contradiction detector between a configured mode and observed evidence, with the slot-time margin as the tie-breaker.
What it teaches: that margin_x10_i turns a late collision into a diagnosis. Chapter 1.2 §6 established that a late collision means the topology exceeded the slot-time budget; Section 4 established that a point-to-point link satisfies it by 47× at 100 metres and 1 584× at 3. So a late collision with a margin in the thousands is not a distance problem — and the module says which check to run rather than leaving it to a guess.
And it teaches that evidence_contradicts_mode is a single AND that no MAC reports. A link configured full duplex has no collision-detect input that should ever assert; a design that leaves the signal connected and counts it has the duplex-mismatch detector for free, and one that optimises the counter away has removed the only evidence.
Deliberately simplified: peer_full_duplex_advertised comes from Chapter 11.2's ability exchange, which is absent when one end is forced rather than negotiated — and a forced full-duplex end against an auto-negotiating peer is precisely how the mismatch arises. The margin threshold of 2× is arbitrary. And the module cannot see the far end's counters, where Chapter 11.4's signature is late collisions at one end and FCS errors at the other — a relation between two nodes that one node cannot evaluate, which is Chapter 22.2 §20's class 104.
Production implication: the forced-mode case is the one that still happens and the fix is a configuration discipline rather than a design change. A port forced to full duplex does not transmit link-code words, so the peer's auto-negotiation finds no partner, falls back to half duplex by its parallel-detection rule — Chapter 11.1 — and the link comes up with the two ends in different modes and no error anywhere. The evidence is split across the two ends by construction: the full-duplex end sees late collisions and the half-duplex end sees FCS errors, and neither end's counters alone identify the fault. A management system that correlates the two ports' counters finds it in one query, and the counter that makes the correlation possible is c_contradictions — which costs one AND gate and exists in almost no part.
14. What a Slot-Time Claim Must Never Do
Five prohibitions about the parameter rather than about the mechanism.
| # | Never | Because |
|---|---|---|
| 1 | present the slot time as a frame-format constant | Section 2: it is a round-trip distance budget, and every rate divides it by ten |
| 2 | quote a collision-domain diameter without the repeater and detection terms | Chapter 1.2 §3: cable was 5.0 µs of an 8.8 µs round trip in that chapter's example |
| 3 | assert a bound whose subject the configuration removed | Section 20's class 120 — the property passes and its cover is empty |
| 4 | carry a half-duplex property into a full-duplex regression | the same; the suite grows with the standard's history |
| 5 | remove the collision-detect counter on a full-duplex design | Section 13: it is the duplex-mismatch detector, for one AND gate |
Row five is the cheapest thing in this chapter and the easiest to optimise away, because on a correctly configured link the counter reads zero forever — which is exactly the property that makes it valuable.
15. RTL 7 — Slot-Time Telemetry
// ---------------------------------------------------------------------
// slotmyth_telemetry -- what a link should report about a mechanism
// it does not use, and about the constant that mechanism left behind.
//
// Design rule: a counter that should always read zero is worth keeping
// precisely because it should always read zero.
// ---------------------------------------------------------------------
module slotmyth_telemetry
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic clear,
input logic frame_tx,
input logic [15:0] frame_octets,
input logic frame_padded,
input logic [15:0] pad_octets_i,
input logic collision_observed_i,
input logic late_collision_i,
input logic configured_full_duplex_i,
input logic fcs_error_i,
output logic [47:0] c_frames,
output logic [47:0] c_min_size_frames,
output logic [47:0] c_padded,
output logic [47:0] c_pad_octets,
output logic [47:0] c_collisions,
output logic [47:0] c_late_collisions_o,
output logic [47:0] c_fcs_errors_o,
output logic [47:0] c_impossible_collisions,
output logic [31:0] min_size_share_ppm,
output logic [31:0] pad_waste_ppm,
output logic should_always_be_zero,
output logic mismatch_evidence_present
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n || clear) begin
c_frames <= '0; c_min_size_frames <= '0; c_padded <= '0;
c_pad_octets <= '0; c_collisions <= '0; c_late_collisions_o <= '0;
c_fcs_errors_o <= '0; c_impossible_collisions <= '0;
end else begin
if (frame_tx) begin
c_frames <= c_frames + 48'd1;
if (frame_octets <= 16'(MIN_FRAME_OCTETS))
c_min_size_frames <= c_min_size_frames + 48'd1;
if (frame_padded) begin
c_padded <= c_padded + 48'd1;
c_pad_octets <= c_pad_octets + 48'(pad_octets_i);
end
end
if (collision_observed_i) begin
c_collisions <= c_collisions + 48'd1;
// THE counter. On a full-duplex link this cannot happen, and
// that is why it is worth one AND gate to record it.
if (configured_full_duplex_i)
c_impossible_collisions <= c_impossible_collisions + 48'd1;
end
if (late_collision_i) c_late_collisions_o <= c_late_collisions_o + 48'd1;
if (fcs_error_i) c_fcs_errors_o <= c_fcs_errors_o + 48'd1;
end
end
always_comb begin
min_size_share_ppm = (c_frames == 0) ? 32'd0
: 32'((c_min_size_frames * 48'd1_000_000) / c_frames);
// Section 6: the pad is wire the payload did not use.
pad_waste_ppm = (c_frames == 0) ? 32'd0
: 32'((c_pad_octets * 48'd1_000_000)
/ (c_frames * 48'(min_wire_slot())));
should_always_be_zero = configured_full_duplex_i;
// Chapter 11.4's signature, as far as one end can see it.
mismatch_evidence_present = (c_impossible_collisions != 48'd0)
|| (c_late_collisions_o != 48'd0);
end
endmoduleClassification: eight counters, of which one should always read zero and is the most valuable.
What it teaches: that c_impossible_collisions costs one AND gate and is the only local evidence of a duplex mismatch. Chapter 11.4's signature splits across two ends — late collisions at the full-duplex end and FCS errors at the half-duplex end — and a counter that records a collision on a link configured full duplex is the half of it that one end can see.
And it teaches that min_size_share_ppm is the number a design needs before it can price anything in this chapter. Section 10's five costs all scale with the minimum-frame share of the traffic; a link carrying 2% minimum-size frames pays almost none of them and one carrying 60% pays nearly all. The counter exists in Chapter 19.7's RMON size bins and is rarely read.
Deliberately simplified: pad_waste_ppm normalises against the minimum wire slot for every frame, overstating the waste when large frames dominate — the correct denominator is the observed wire octets, which needs a second accumulator. The module counts a collision without distinguishing Chapter 1.2 §6's early from late. And should_always_be_zero is a restatement of an input rather than a check, which is deliberate: it names the expectation in the register map so that a nonzero c_impossible_collisions is unambiguous.
Production implication: the RMON size bins are the structure that already exists and already answers this, and Chapter 19.7 §4 priced them. A 64-to-127-octet bin's share of total frames is min_size_share_ppm with a better denominator, and it is the single number that decides whether the minimum frame's five costs matter on this deployment. It is present in every managed switch, graphed by almost none, and it is the same measurement Chapter 21.6 §4 wanted for drop classification and Section 11's production note wanted for cell sizing. Three chapters, three reasons, one histogram that is already being maintained.
16. RTL 8 — The Legacy Conformance Monitor
// ---------------------------------------------------------------------
// slotmyth_conformance -- the checks that hold a design's claims about
// CSMA/CD to the configuration it actually runs in.
//
// Note what is absent: there is no check that collisions do not occur,
// because on a full-duplex link the signal is tied low and the check
// would be Section 20's class 120.
// ---------------------------------------------------------------------
module slotmyth_conformance
import slotmyth_pkg::*;
(
input logic clk,
input logic rst_n,
input logic configured_full_duplex_i,
input logic csma_cd_properties_bound,
input logic [31:0] csma_cd_cover_hits,
input logic claims_csma_cd,
input logic [47:0] c_impossible_collisions_i,
input logic [31:0] margin_x10_i,
input logic late_collision_i,
input logic min_frame_reported,
input logic diameter_reported,
output logic v_vacuous_properties,
output logic v_claims_csma_cd,
output logic v_impossible_collision,
output logic v_distance_blamed,
output logic v_min_frame_unreported,
output logic v_diameter_unreported,
output logic [5:0] violations,
output logic conformant
);
always_comb begin
// 1. Section 20's class 120: properties bound in a configuration
// that cannot reach their antecedents, with an empty cover.
v_vacuous_properties = configured_full_duplex_i
&& csma_cd_properties_bound
&& (csma_cd_cover_hits == 32'd0);
// 2. Prohibition 2 -- Chapter 1.5 Section 2's deletion.
v_claims_csma_cd = configured_full_duplex_i && claims_csma_cd;
// 3. A collision on a link that cannot have one.
v_impossible_collision = (c_impossible_collisions_i != 48'd0);
// 4. Prohibition 3 -- a margin in the thousands rules distance out.
v_distance_blamed = late_collision_i && (margin_x10_i >= 32'd20);
// 5 and 6. The two quantities a design should expose so the
// parameter's cost is auditable rather than folklore.
v_min_frame_unreported = !min_frame_reported;
v_diameter_unreported = !diameter_reported;
violations = { v_diameter_unreported, v_min_frame_unreported,
v_distance_blamed, v_impossible_collision,
v_claims_csma_cd, v_vacuous_properties };
conformant = (violations == 6'b000000);
end
endmoduleClassification: six checks, of which the first is about a verification suite rather than about a design.
What it teaches: that v_vacuous_properties needs three inputs and the third is a cover count. A property bound in a configuration that cannot reach its antecedent passes and contributes to a pass rate; the only signal that distinguishes it from a property doing work is its cover being empty, which is a number every tool produces and almost no report surfaces.
And it teaches that v_diameter_unreported asks for a quantity no design exposes. Section 3's diameter_cm_o is an elaboration-time constant — 4 752 metres at 10 Mb/s, 47.5 at 1 Gb/s — and a design that reported it would make Chapter 1.2 §3's whole budget argument checkable at installation instead of discoverable as late collisions.
Deliberately simplified: csma_cd_cover_hits must be supplied from a coverage database, so the check belongs in a regression report rather than in silicon — it is written as RTL because the argument is the same one and the shape is easier to see as a signal. claims_csma_cd is a documentation fact. And margin_x10_i's threshold of 2× is arbitrary, chosen so that a genuinely marginal topology is not misdiagnosed.
Production implication: the coverage-database dependency is the honest limit and it points at where this check really belongs. A regression report that lists pass counts without cover counts cannot distinguish a suite that verified a design from one that confirmed a configuration is unreachable — and Section 20's class 120 is exactly that confusion. The fix is a report column, not a design change: properties passed, properties covered, and the difference. A suite where the difference is large is a suite carrying a standard's history, and on a full-duplex-only design every CSMA/CD property is in that difference.
17. The Mechanism and the Vestige, Priced Side by Side
Everything this chapter derived, in one table.
| The mechanism | The vestige | |
|---|---|---|
| what it is | CSMA/CD — carrier sense, collision detect, backoff | a 64-octet minimum frame |
| what fixed it | a round-trip budget of 512 bit times | the same 512 bits, as a length |
| reachable on a deployed link? | NO — Chapter 1.5 §2's four unreachable blocks | yes, in every MAC and every switch |
| cost in silicon today | zero, and it is optimised away | an eight-wide pipeline instead of five |
| cost on the wire today | zero | 45.24% at minimum frame size |
| cost in a buffer | zero | 75% of a 256-octet cell |
| cost at a host interface | zero | 34.8% of payload in descriptors |
| who removed it | full duplex, in 1997 | nobody, and nobody can |
The mechanism vanished and the constant it chose did not, and the constant is the expensive half.
And the diameters, which are what the parameter was about.
| Rate | Round-trip budget | Pure-cable diameter | What was deployed |
|---|---|---|---|
| 10 Mb/s | 48 000 ns | 4 752 m | shared coaxial segments |
| 100 Mb/s | 4 800 ns | 475 m | shared segments, briefly |
| 1 Gb/s | 480 ns | 47.5 m | essentially nothing — the switch won |
| 1 Gb/s, extended | 4 064 ns | 402 m | a standard option nobody used |
| 10 Gb/s | 48 ns | 4.75 m | no half-duplex mode exists |
| 100 Gb/s | 4.8 ns | 0.475 m | shorter than the equipment |
Row three is where the mechanism stopped being viable and row five is where the standard stopped offering it, and the two are two rate generations apart — which is how long it took for a geometric impossibility to become an editorial decision.
18. What the Correction Assumes
Eight assumptions.
| # | Assumption | If it is false |
|---|---|---|
| 1 | 512 bit times and a 32-bit jam | Chapter 1.2 §2's normative values |
| 2 | 5.05 ns per metre of copper | Chapter 8.2 §3; every medium is within 5% and the diameters move by that |
| 3 | pure cable, no repeaters or detection latency | Chapter 1.2 §3: those consumed 3.8 µs of an 8.8 µs round trip in that chapter's example, so the real diameters are smaller |
| 4 | a 64-octet minimum and a 46-octet payload floor | Chapter 5.6; a VLAN tag raises the frame minimum to 68 and not the payload's |
| 5 | Chapter 23.3's 64 ports at 1.2 GHz | the pipeline width scales with the port count and inversely with the clock |
| 6 | 256-octet buffer cells | Section 11's production note: 128-octet cells halve the waste and double the pointer state |
| 7 | a 16-octet descriptor | Chapter 23.4 §5's size; the share scales linearly |
| 8 | BCE prices what this chapter counts | Section 19 examines it and the answer is the most interesting in the batch |
Assumption 3 is the one that makes every diameter in this chapter an overestimate, and Chapter 1.2 §3's callout said so about its own table: the per-repeater and per-segment figures a network designer uses come from the standard's system-considerations clauses, and the point that transfers is the method rather than the values. A real 10 Mb/s segment's diameter was a few hundred metres, not 4 752 — and the argument is unaffected, because the ratio between rates is what this chapter is about.
19. The Cost, Accounted — in BCE
This chapter's blocks.
| Block | Flops | BCE | × the datapath |
|---|---|---|---|
slot_diameter_model | 32 | 640 | 0.002 |
point_to_point_bound | 32 | 640 | 0.002 |
min_frame_cost | 32 | 640 | 0.002 |
pipeline_width_model | 32 | 640 | 0.002 |
vestige_auditor | 32 | 640 | 0.002 |
half_duplex_detector | 32 | 640 | 0.002 |
slotmyth_telemetry | 384 | 7 680 | 0.027 |
slotmyth_conformance | 0 — combinational | 0 | 0 |
| this chapter's additions | 576 | 11 520 | 0.041 |
Seven of the eight blocks are models, which is what a chapter about a parameter rather than about a mechanism produces.
And the structures the parameter sets.
| Quantity | Its unit | |
|---|---|---|
| the minimum frame | 64 octets | octets |
| the wire slot | 84 octets — 45.24% tax | octets |
| the packet rate at 100 Gb/s | 148.81 Mpps | frames per second |
| the aggregate at 64 ports | 9.524 Gpps | frames per second |
| the pipeline | 8 lanes at 1.2 GHz | LANES |
| buffer cell waste | 75% of 256 octets | octets |
| cell pointers at 128-octet cells | +4 980 736 BCE — 17.6 datapaths | BCE |
20. Properties Worth Asserting, and One Worth Refusing
Fifty-one properties in six groups, and the refused one is correct, inherited, and has never once been evaluated on a real frame.
Group A — the slot time as a distance (9).
// A1. A bit time is the reciprocal of the rate.
p_sd_bit_time: assert property (@(posedge clk) disable iff (!rst_n)
(rate_mbps != 32'd0) |-> (slot_ps_o == 32'(slot_bits) * (32'd1_000_000 / rate_mbps)));
// A2. The round-trip budget is the slot less the jam.
p_sd_budget: assert property (@(posedge clk) disable iff (!rst_n)
(round_trip_ps_o == slot_ps_o - (32'(JAM_SIZE_BITS)
* (32'd1_000_000 / rate_mbps))));
// A3. The diameter falls by ten for every factor of ten in rate.
p_sd_scales: assert property (@(posedge clk) disable iff (!rst_n)
(rate_mbps == 32'd10 * $past(rate_mbps)) |->
(diameter_cm_o <= $past(diameter_cm_o) / 32'd9));
// A4. At 10 Mb/s with 512 bit times the diameter is about 4 752 m.
p_sd_10m: assert property (@(posedge clk) disable iff (!rst_n)
((rate_mbps == 32'd10) && (slot_bits == 16'd512))
|-> ((diameter_cm_o > 32'd470_000) && (diameter_cm_o < 32'd480_000)));
// A5. Carrier extension restores roughly eight times the diameter.
p_sd_extension: assert property (@(posedge clk) disable iff (!rst_n)
((rate_mbps == 32'd1000) && (slot_bits == 16'd4096))
|-> (diameter_cm_o > 32'd40_000));
// A6. A full-duplex link cannot reach the mechanism.
p_sd_unreachable: assert property (@(posedge clk) disable iff (!rst_n)
(link_mode == 2'(LINK_P2P_FULL)) |-> !mechanism_is_reachable);
// A7. And the bound means nothing there.
p_sd_meaningless: assert property (@(posedge clk) disable iff (!rst_n)
(link_mode != 2'(LINK_SHARED_HALF)) |-> !bound_is_meaningful);
// A8. A shorter link has a larger margin.
p_sd_margin: assert property (@(posedge clk) disable iff (!rst_n)
(link_metres < $past(link_metres)) |-> (margin_x10 >= $past(margin_x10)));
// A9. The slot time is always larger than the jam.
p_sd_jam_fits: assert property (@(posedge clk) disable iff (!rst_n)
(slot_ps_o > 32'(JAM_SIZE_BITS) * (32'd1_000_000 / rate_mbps)));Group B — the point-to-point bound (8).
// B1. A 3 m link satisfies the 10 Mb/s budget by over a thousand.
p_pp_margin: assert property (@(posedge clk) disable iff (!rst_n)
((link_metres == 16'd3) && (rate_mbps == 32'd10) && (slot_bits == 16'd512))
|-> (margin_x10 > 32'd15_000));
// B2. Collisions need two transmitters sharing a medium.
p_pp_collisions: assert property (@(posedge clk) disable iff (!rst_n)
separate_tx_rx_pairs |-> !collisions_possible);
// B3. And the station count alone does not create them.
p_pp_stations: assert property (@(posedge clk) disable iff (!rst_n)
(separate_tx_rx_pairs && (stations_on_segment >= 16'd2))
|-> !collisions_possible);
// B4. A two-station half-duplex link DOES have them.
p_pp_p2p_half: assert property (@(posedge clk) disable iff (!rst_n)
(!separate_tx_rx_pairs && (stations_on_segment == 16'd2))
|-> collisions_possible);
// B5. The bound constrains something only when collisions are possible.
p_pp_constrains: assert property (@(posedge clk) disable iff (!rst_n)
(bound_constrains_anything == collisions_possible));
// B6. Both counters follow the same condition.
p_pp_reachable: assert property (@(posedge clk) disable iff (!rst_n)
(slot_counter_reachable == backoff_reachable));
// B7. A satisfied and vacuous bound is counted.
p_pp_vacuous: assert property (@(posedge clk) disable iff (!rst_n)
(bound_satisfied && !bound_constrains_anything)
|=> (c_vacuous_evaluations == $past(c_vacuous_evaluations) + 32'd1));
// B8. The mode follows the two inputs.
p_pp_mode: assert property (@(posedge clk) disable iff (!rst_n)
separate_tx_rx_pairs |-> (mode == 2'(LINK_P2P_FULL)));Group C — the minimum frame (9).
// C1. A short payload is padded, never shortened.
p_mf_padded: assert property (@(posedge clk) disable iff (!rst_n)
(payload_octets < (min_frame_octets - 16'd18))
|-> (padded_payload == min_frame_octets - 16'd18));
// C2. A long payload is untouched.
p_mf_untouched: assert property (@(posedge clk) disable iff (!rst_n)
(payload_octets >= (min_frame_octets - 16'd18))
|-> (padded_payload == payload_octets));
// C3. The wire slot adds preamble and gap.
p_mf_slot: assert property (@(posedge clk) disable iff (!rst_n)
(wire_slot == 32'(frame_octets) + 32'(OCT_PREAMBLE) + 32'(OCT_IFG)));
// C4. A one-octet payload uses 1.19% of its wire.
p_mf_one_octet: assert property (@(posedge clk) disable iff (!rst_n)
((payload_octets == 16'd1) && (min_frame_octets == 16'd64))
|-> (useful_ppm == 32'd11_904));
// C5. The framing tax at minimum size is 45.24%.
p_mf_tax: assert property (@(posedge clk) disable iff (!rst_n)
((padded_payload == 16'd46)) |-> (framing_tax_ppm_o == 32'd452_380));
// C6. The justification needs a collision domain.
p_mf_justification: assert property (@(posedge clk) disable iff (!rst_n)
(justification_still_applies == collisions_possible_i));
// C7. And the constant is frozen regardless.
p_mf_frozen: assert property (@(posedge clk) disable iff (!rst_n)
constant_is_frozen);
// C8. Pad octets are the difference.
p_mf_pad: assert property (@(posedge clk) disable iff (!rst_n)
(pad_octets == 32'(padded_payload) - 32'(payload_octets)));
// C9. Padded frames are counted.
p_mf_counted: assert property (@(posedge clk) disable iff (!rst_n)
(pad_octets != 32'd0) |=> (c_padded_frames == $past(c_padded_frames) + 32'd1));Group D — the pipeline width (8).
// D1. The packet rate is the line rate over the wire slot.
p_pw_rate: assert property (@(posedge clk) disable iff (!rst_n)
(wire_slot_o != 32'd0) |->
(port_pps_k == 32'(pps_k(int'(port_gbps), int'(wire_slot_o)))));
// D2. The aggregate is the per-port rate times the ports.
p_pw_aggregate: assert property (@(posedge clk) disable iff (!rst_n)
(aggregate_pps_k == port_pps_k * 32'(ports)));
// D3. At 64 ports, 100 Gb/s and 64 octets, eight lanes.
p_pw_eight: assert property (@(posedge clk) disable iff (!rst_n)
((ports == 16'd64) && (port_gbps == 16'd100) &&
(min_frame_octets == 16'd64) && (core_mhz == 16'd1200))
|-> (pipeline_width == 16'd8));
// D4. A 128-octet minimum would give five.
p_pw_five: assert property (@(posedge clk) disable iff (!rst_n)
((ports == 16'd64) && (port_gbps == 16'd100) && (core_mhz == 16'd1200))
|-> (width_if_128 == 32'd5));
// D5. The width never falls as the rate rises.
p_pw_monotone: assert property (@(posedge clk) disable iff (!rst_n)
(port_gbps > $past(port_gbps)) |-> (pipeline_width >= $past(pipeline_width)));
// D6. A larger minimum frame narrows the pipeline.
p_pw_larger_narrower: assert property (@(posedge clk) disable iff (!rst_n)
(width_if_256 <= width_if_128));
// D7. The chain is traceable to the slot time.
p_pw_traceable: assert property (@(posedge clk) disable iff (!rst_n)
width_traceable_to_slot_time);
// D8. The width is a ceiling, never a floor.
p_pw_ceiling: assert property (@(posedge clk) disable iff (!rst_n)
((32'(pipeline_width) * 32'd100) >= packets_per_cycle_x100));Group E — the vestige and the detector (9).
// E1. Five structures carry the parameter.
p_va_five: assert property (@(posedge clk) disable iff (!rst_n)
(structures_affected == 16'd5));
// E2. The cost is legacy on a full-duplex link.
p_va_legacy: assert property (@(posedge clk) disable iff (!rst_n)
!collisions_possible_i |-> cost_is_legacy);
// E3. A smaller minimum would be worse.
p_va_smaller_worse: assert property (@(posedge clk) disable iff (!rst_n)
smaller_would_be_worse);
// E4. Cell waste is the cell less the frame.
p_va_cell: assert property (@(posedge clk) disable iff (!rst_n)
((cell_octets == 16'd256) && (min_frame_octets == 16'd64))
|-> (cell_waste_ppm == 32'd750_000));
// E5. The machinery is reachable only in half duplex.
p_hd_reachable: assert property (@(posedge clk) disable iff (!rst_n)
(machinery_reachable == !configured_full_duplex));
// E6. A collision on a full-duplex link contradicts the mode.
p_hd_contradiction: assert property (@(posedge clk) disable iff (!rst_n)
(configured_full_duplex && collision_observed) |-> evidence_contradicts_mode);
// E7. And suggests a duplex mismatch.
p_hd_mismatch: assert property (@(posedge clk) disable iff (!rst_n)
evidence_contradicts_mode |-> duplex_mismatch_suspected);
// E8. A large margin rules distance out.
p_hd_not_distance: assert property (@(posedge clk) disable iff (!rst_n)
(late_collision_observed && (margin_x10_i >= 32'd20))
|-> mode_disagreement_is_the_cause);
// E9. A recommendation is always produced.
p_hd_recommend: assert property (@(posedge clk) disable iff (!rst_n)
(late_collision_observed || !machinery_reachable)
|-> (recommended_check != 2'd0));Group F — telemetry and conformance (8).
// F1. The impossible-collision counter is the mismatch detector.
p_tl_impossible: assert property (@(posedge clk) disable iff (!rst_n)
(collision_observed_i && configured_full_duplex_i) |=>
(c_impossible_collisions == $past(c_impossible_collisions) + 48'd1));
// F2. And on a correct full-duplex link it stays zero.
p_tl_zero: assert property (@(posedge clk) disable iff (!rst_n)
should_always_be_zero && !mismatch_evidence_present
|-> (c_impossible_collisions == 48'd0));
// F3. Minimum-size frames are a subset of frames.
p_tl_subset: assert property (@(posedge clk) disable iff (!rst_n)
(c_min_size_frames <= c_frames));
// F4. Pad octets accumulate with padded frames.
p_tl_pad: assert property (@(posedge clk) disable iff (!rst_n)
(frame_tx && frame_padded) |=>
(c_pad_octets == $past(c_pad_octets) + 48'($past(pad_octets_i))));
// F5. Bound-but-uncovered properties are a violation.
p_cf_vacuous: assert property (@(posedge clk) disable iff (!rst_n)
(configured_full_duplex_i && csma_cd_properties_bound &&
(csma_cd_cover_hits == 32'd0)) |-> v_vacuous_properties);
// F6. A CSMA/CD claim on a full-duplex link is a violation.
p_cf_claim: assert property (@(posedge clk) disable iff (!rst_n)
(configured_full_duplex_i && claims_csma_cd) |-> v_claims_csma_cd);
// F7. Blaming distance with a large margin is a violation.
p_cf_distance: assert property (@(posedge clk) disable iff (!rst_n)
(late_collision_i && (margin_x10_i >= 32'd20)) |-> v_distance_blamed);
// F8. Conformance is the disjunction of its six checks.
p_cf_vector: assert property (@(posedge clk) disable iff (!rst_n)
conformant |-> (violations == 6'b000000));Coverage — and the point of this group is which of them are empty.
c_sd_10mbps: cover property (@(posedge clk) rate_mbps == 32'd10);
c_sd_1gbps: cover property (@(posedge clk) rate_mbps == 32'd1000);
c_sd_extended: cover property (@(posedge clk) slot_bits == 16'd4096);
c_pp_shared: cover property (@(posedge clk) mode == 2'(LINK_SHARED_HALF));
c_pp_p2p_half: cover property (@(posedge clk) mode == 2'(LINK_P2P_HALF));
c_pp_vacuous: cover property (@(posedge clk) bound_satisfied && !bound_constrains_anything);
c_mf_one_octet: cover property (@(posedge clk) payload_octets == 16'd1);
c_mf_no_pad: cover property (@(posedge clk) pad_octets == 32'd0);
c_pw_eight: cover property (@(posedge clk) pipeline_width == 16'd8);
c_pw_five: cover property (@(posedge clk) width_if_128 == 32'd5);
c_hd_collision: cover property (@(posedge clk) collision_observed);
c_hd_impossible: cover property (@(posedge clk) evidence_contradicts_mode);
c_hd_late: cover property (@(posedge clk) late_collision_observed);
c_cf_vacuous: cover property (@(posedge clk) v_vacuous_properties);21. Verification Scenarios
Fifty-eight scenarios in six groups, plus one directed test random stimulus will not produce.
Group 1 — the slot time as a distance (10).
| # | Scenario | Expect |
|---|---|---|
| 1 | 10 Mb/s, 512 bit times | slot 51 200 ns; budget 48 000; diameter 4 752 m |
| 2 | 100 Mb/s, 512 | 5 120 ns; 4 800; 475 m |
| 3 | 1 Gb/s, 512 | 512 ns; 480; 47.5 m |
| 4 | 1 Gb/s, 4 096 — carrier extension | 4 096 ns; 4 064; 402 m |
| 5 | 10 Gb/s, 512, hypothetically | 51.2 ns; 48; 4.75 m |
| 6 | 100 Gb/s, 512, hypothetically | 5.12 ns; 4.8; 0.475 m — shorter than the equipment |
| 7 | a rate increase of 10× | diameter falls by 10× — p_sd_scales |
| 8 | LINK_P2P_FULL | mechanism_is_reachable low |
| 9 | LINK_P2P_HALF | bound_is_meaningful LOW, and collisions are possible |
| 10 | LINK_SHARED_HALF | bound_is_meaningful high |
Group 2 — the point-to-point bound (9).
| # | Scenario | Expect |
|---|---|---|
| 11 | 1 m link at 10 Mb/s | round trip 10.1 ns; margin 4 752× |
| 12 | 3 m | 30.3 ns; 1 584× |
| 13 | 30 m | 303 ns; 158× |
| 14 | 100 m | 1 010 ns; 47.5× |
| 15 | 2 km fibre | 19 600 ns; 2.4× — still satisfied |
| 16 | separate pairs, 2 stations | no collisions possible |
| 17 | shared pair, 2 stations | collisions POSSIBLE — the middle case |
| 18 | shared pair, 30 stations | LINK_SHARED_HALF |
| 19 | satisfied and vacuous | c_vacuous_evaluations increments |
Group 3 — the minimum frame (10).
| # | Scenario | Expect |
|---|---|---|
| 20 | 1-octet payload | padded to 46; slot 84; 11 904 ppm useful |
| 21 | 10-octet payload | padded to 46; 119 047 ppm |
| 22 | 46-octet payload | no pad; 547 619 ppm |
| 23 | 100-octet payload | no pad; slot 138; 724 637 ppm |
| 24 | the framing tax at minimum size | 452 380 ppm — 45.24% |
| 25 | a 64-octet frame in a 256-octet cell | 750 000 ppm wasted |
| 26 | justification_still_applies on a full-duplex link | low |
| 27 | constant_is_frozen | 1, at every setting |
| 28 | a VLAN-tagged minimum frame | 68 octets; the payload floor does not move |
| 29 | 1 000 short frames | c_padded_frames = 1 000 |
Group 4 — the pipeline (9).
| # | Scenario | Expect |
|---|---|---|
| 30 | 100 Gb/s, 64 octets | 148.81 Mpps; 6.720 ns per frame |
| 31 | 400 Gb/s, 64 octets | 595.24 Mpps; 1.680 ns |
| 32 | 800 Gb/s, 64 octets | 1 190.48 Mpps; 0.840 ns |
| 33 | 64 ports at 100 Gb/s | 9.524 Gpps; 7.94 per cycle at 1.2 GHz; width 8 |
| 34 | a 128-octet minimum | 5.405 Gpps; 4.50 per cycle; width 5 |
| 35 | a 256-octet minimum | 2.899 Gpps; 2.42; width 3 |
| 36 | a 512-octet minimum | 1.504 Gpps; 1.25; width 2 |
| 37 | width_traceable_to_slot_time | 1 |
| 38 | 2.4 GHz core instead of 1.2 | 3.97 per cycle; width 4 |
Group 5 — the vestige and the detector (10).
| # | Scenario | Expect |
|---|---|---|
| 39 | structures_affected | 5 |
| 40 | a full-duplex link | cost_is_legacy high |
| 41 | smaller_would_be_worse | 1, at every setting |
| 42 | 128-octet cells instead of 256 | cell waste 500 000 ppm; +4 980 736 BCE of pointers |
| 43 | full duplex, collision observed | evidence_contradicts_mode; c_impossible_collisions moves |
| 44 | full duplex, peer advertises half | duplex_mismatch_suspected |
| 45 | a late collision with margin 1 584× | mode_disagreement_is_the_cause; check 2 |
| 46 | a late collision with margin 1.5× | distance_is_the_cause; check 1 |
| 47 | a full-duplex link with no anomaly | check 3 — the machinery is unreachable |
| 48 | half duplex configured | machinery_reachable high |
Group 6 — telemetry and conformance (10).
| # | Scenario | Expect |
|---|---|---|
| 49 | a correct full-duplex link, 10⁹ frames | c_impossible_collisions = 0 |
| 50 | 40% minimum-size frames | min_size_share_ppm = 400 000 |
| 51 | CSMA/CD properties bound, cover 0, full duplex | v_vacuous_properties |
| 52 | the same with cover nonzero | clean — the mode is reachable |
| 53 | a CSMA/CD claim on a full-duplex design | v_claims_csma_cd |
| 54 | distance blamed with a large margin | v_distance_blamed |
| 55 | the minimum frame not exposed | v_min_frame_unreported |
| 56 | the diameter not exposed | v_diameter_unreported |
| 57 | should_always_be_zero on a full-duplex link | high |
| 58 | all six checks clear | conformant high |
22. Debugging a Link That Cannot Collide
Six symptoms, and the first three are about a mechanism that is not running.
| Symptom | First question | Where to look |
|---|---|---|
| late collisions on a switched link | is one end running half duplex? | Section 13 — a margin of 1 584 rules distance out |
| FCS errors at one end, late collisions at the other | was either end forced rather than negotiated? | Chapter 11.4 — the classic mismatch signature |
| a collision counter incrementing on a full-duplex port | has it been reported? | Section 15 — c_impossible_collisions, one AND gate |
| a switch pipeline wider than expected | what is the minimum frame? | Section 8 — eight lanes instead of five |
| buffer occupancy far above the byte count | what is the frame-size mix? | Section 11 — a 64-octet frame in a 256-octet cell |
| a regression at 100% with low confidence | how many properties have an empty cover? | Section 21's directed test — bound minus covered |
Row two is the signature worth memorising, because neither end's counters identify it alone: the full-duplex end sees late collisions and the half-duplex end sees FCS errors, and a management system that correlates two ports finds it in one query.
23. Misconceptions
Misconception 1 — "Ethernet is CSMA/CD."
The wrong model: carrier sense, collision detection and backoff are what Ethernet is, so every Ethernet link uses them.
What it costs: a mental model that predicts the wrong failures. Chapter 1.5 §2: four of Chapter 1.2's six blocks become unreachable under full duplex and a fifth collapses from five states to two. Section 4: a full-duplex link has no shared medium, so there is nothing for the mechanism to arbitrate.
The corrected model: a link with separate transmit and receive paths has no collision domain, and every such link has been the norm since 1997. The mechanism is still in the standard, still correct, and reachable on configurations nobody deploys.
Misconception 2 — "switching removed CSMA/CD."
The wrong model: the switch is what killed the collision domain.
What it costs: missing the middle case. Section 4's callout: a half-duplex switch port has a collision domain of two stations and needs every one of Chapter 1.2's blocks — the domain is tiny, the slot time is satisfied enormously, and the mechanism is still reachable and still correct.
The corrected model: full duplex removed it, and full duplex is a property of the cabling and the PHY — Chapter 1.5 §1's separate transmit and receive paths — rather than of the switch.
Misconception 3 — "slot time is a frame-format constant."
The wrong model: 512 bits is a number in the standard, like the preamble's eight octets.
What it costs: never noticing that it is a distance. Section 2: 512 bit times less the 32-bit jam is a round-trip budget, which at Chapter 8.2 §3's 5.05 ns per metre is 4 752 metres at 10 Mb/s, 475 at 100 and 47.5 at 1 Gb/s. Chapter 1.2 §2 called it a timing constant wearing a frame-format costume.
The corrected model: every factor of ten in rate divides the reach by ten — which is why gigabit half duplex needed carrier extension to 4 096 bit times, and why at 100 Gb/s the bound would be 47 centimetres, shorter than the transceivers.
Misconception 4 — "the minimum frame is a frame-format fact."
The wrong model: 64 octets is just how Ethernet frames are.
What it costs: attributing five silicon costs to the wrong cause. Section 10: 45.24% of the wire at minimum size, 75% of a 256-octet buffer cell, 34.8% of payload in descriptors, an eight-wide pipeline instead of five, and 14.29% of the wire slot in interframe gap.
The corrected model: the minimum frame is the slot time in octets — 512 bits either way — and it exists so a transmitter is still transmitting when a collision signal returns. It outlived that requirement and no structure that depends on it noticed.
Misconception 5 — "a late collision means the cable is too long."
The wrong model: late collisions are a topology problem, so measure the cable.
What it costs: a day spent measuring a 3-metre link. Section 4: a 3-metre link satisfies the 10 Mb/s round-trip budget 1 584 times over, and Section 13: a late collision with a margin in the thousands is a duplex mismatch, not a distance problem.
The corrected model: check the mode before the cable. Chapter 11.4's signature is late collisions at the full-duplex end and FCS errors at the half-duplex end, and neither end's counters identify it alone.
Misconception 6 — "our regression passes 100%, so the MAC is verified."
The wrong model: a pass rate is a coverage statement.
What it costs: Section 20's class 120. A full-duplex-only design inheriting a both-modes suite binds 48 CSMA/CD properties whose antecedent is tied low — they pass on every run, their covers are zero, and the report reads 200/200.
The corrected model: compare bound against covered and report the difference. Section 21's directed test: the two suites have identical pass rates and differ by 48 in a column no report prints.
24. Interview Questions
Six, with what a strong answer contains.
1. Does a modern Ethernet link use CSMA/CD?
No, and the reason is the cabling rather than the switch. A strong answer names Chapter 1.5 §2's deletion — the slot-time counter, the collision classifier, the jam generator and the backoff engine all become unreachable — and then makes the sharper point: full duplex removed it, not switching, because a half-duplex switch port still has a collision domain of two stations and still needs every one of those blocks.
2. What was the slot time for?
It is a round-trip distance budget. 512 bit times less a 32-bit jam is the time available for a collision signal to traverse the domain and return, and at Chapter 8.2 §3's 5.05 ns per metre that is 4 752 metres of pure cable at 10 Mb/s. A strong answer scales it: 475 metres at 100 Mb/s, 47.5 at 1 Gb/s — which is why gigabit half duplex needed carrier extension — and 47 centimetres at 100 Gb/s, which is shorter than the transceivers.
3. How vacuous is the bound on a modern link?
A 3-metre link's round trip is 30.3 nanoseconds against a 48 000-nanosecond budget — a margin of 1 584. A strong answer says why the margin is the less interesting half: there is no second transmitter, so the quantity the bound constrains does not exist. The best answers separate the two questions — is the bound satisfied, and does it constrain anything — and note that a design reporting only the first has confirmed a vacuous constraint.
4. Why is a switch ASIC's pipeline eight lanes wide?
Because the minimum frame is 64 octets. The chain: 84-octet wire slot → 148.81 Mpps per port → 9.524 Gpps at 64 ports → 7.94 packets per cycle at 1.2 GHz → eight lanes. A strong answer gives the counterfactual — a 128-octet minimum would give five lanes, a 37.5% reduction in the widest structure in the design — and names the chain's first term: 512 bit times, chosen in 1980 for a coaxial segment.
5. Why has nobody changed the minimum frame?
Because both directions are blocked by the same check. Chapter 7.3's runt discard rejects anything below 64 octets in every MAC ever built, so a shorter frame is indistinguishable from a collision fragment to the installed base; and a longer one breaks every application that sends small messages. A strong answer notes that the value is locally optimal and globally arbitrary — held by compatibility rather than by any argument about what it should be — and that this is the same state as Chapter 12.5's 300-second ageing and Chapter 14.2's 75% watermark.
6. Your full-duplex MAC's regression passes 200 of 200. What do you ask?
How many of the 200 have a nonzero cover. A strong answer explains the mechanism: a suite inherited from a both-modes design binds CSMA/CD properties whose antecedent is tied low by the configuration, so they pass vacuously and contribute to the total. That is Section 20's class 120 — a property inherited from a mode the design never enters — and it belongs to the group where something other than the design controls a property's evaluation count. The repair is if (SUPPORTS_HALF_DUPLEX) around the bind, and a report column for bound minus covered.
25. Questions and Answers
26. What's Next
Module 25 is complete. Six myths, six derivations, and six numbers that each cost real silicon.
| Chapter | The number |
|---|---|
| Chapter 25.1 | 18 octets parsed; 66.2% of a NIC to cross the boundary |
| Chapter 25.2 | a factor of 1 335 907; 0.84% of a switch to detect duplicates |
| Chapter 25.3 | a residual of 1 against 2⁻³²; 6.92× the gates for integrity |
| Chapter 25.4 | zero bandwidth gain; 4.76% of a trunk's wire |
| Chapter 25.5 | 25 607 addresses refused; 98.4% of a frame budget |
| this chapter | a margin of 1 584 on a vacuous bound; three pipeline lanes |
Module 26 turns from what is believed to what is signed off. Four chapters of design review and interview readiness, and the first of them is the sign-off pass for an Ethernet subsystem architecture.
Chapter 26.1 is a different kind of chapter and it has one rule: every item on the review must be a NUMBER SOMEBODY HAS TO PRODUCE, with the chapter that derives it named. A checklist of adjectives — the buffer is adequately sized, the interfaces are correctly specified — cannot fail, because a quality has no failing value, and a review that cannot fail is Chapter 24.3 §20's class 114 at the level of a programme.
So it builds the review as RTL: a readiness model that counts how many items have a produced number, a budget reconciler that adds the claimed areas and latencies against the die and the end-to-end budget, and a claims auditor that asks of each item whether it has a number, a threshold, and a witness who is not its author.
Continue learning
Related tutorials
- Related topic
CSMA/CD, Collision Domains and Slot Time
Slot time is the parameter the whole half-duplex MAC hangs on: it bounds medium acquisition, bounds a collision fragment, and is the retransmission quantum. Deriving it from round-trip propagation plus jam is what fixes Ethernet's minimum frame size — a timing constant wearing a frame-format costume.
- Related topic
Full Duplex and What It Removed from the MAC
Full duplex makes five of the half-duplex MAC's six blocks unreachable and collapses the transmit state machine from five states to two. It also removes a constraint that had been throttling senders by accident, which is why link-level flow control had to be invented to replace it.
- Related topic
Payload, Padding and Minimum Frame Size
The 64-octet minimum is a round-trip propagation time across a shared segment, converted to bits — a constraint whose mechanism full duplex removed and whose cost every frame still pays, in padding that only the length field distinguishes from data.
- Related topic
10 Mbps — The Original Shared-Medium MAC
Manchester cost 100% overhead and bought a clock a 1980 receiver could recover; the shared coax made CSMA/CD necessary and slot time sized the frame. Every constant later modules called inherited was rational here.
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.
