---
title: "How does a CRC catch bad bits, and what do fast links do when it fails?"
topic: "CRCs on fast links"
answer: "It divides the frame by a fixed polynomial and sends the remainder, and the receiver’s own division has to land on a known constant. Ethernet’s CRC-32 catches any 3 flipped bits in a full 1518-byte frame, and any burst up to 32 bits long. Ethernet drops a bad frame, PCIe and DDR memory send it again, and a cut-through switch that has already sent most of it stomps its CRC so the next box knows."
url: "https://nearfieldnotes.com/notes/crc/"
site: "Near Field Notes"
author: "Michael Walker"
note: 28
family: "Signal integrity"
published: "2026-11-09"
revised: "2026-11-09"
revision: 1
video: "https://nearfieldnotes.com/videos/crc/"
---

Note 28 · [Signal integrity](https://nearfieldnotes.com/families/si/) · Rev 1 · [Watch the video · 3:14](https://nearfieldnotes.com/videos/crc/)

CRCs on fast links

# How does a CRC catch bad bits, and what do fast links do when it fails?

**Short answer:** It divides the frame by a fixed polynomial and sends the remainder, and the receiver’s own division has to land on a known constant. Ethernet’s CRC-32 catches any 3 flipped bits in a full 1518-byte frame, and any burst up to 32 bits long. Ethernet drops a bad frame, PCIe and DDR memory send it again, and a cut-through switch that has already sent most of it stomps its CRC so the next box knows.

In the figure one bit flips at byte 700 on the way into a switch. The switch is sending the frame on before it has all arrived, so when the check fails at the end it marks the frame dead instead.

**Note 28’s opening figure: A bad frame, stomped.** One flipped bit through a cut-through switch

![Note 28’s opening figure: A bad frame, stomped](https://nearfieldnotes.com/notes/crc/fig-opening.png)

*What the figure shows:* A 1518-byte Ethernet frame passing through a cut-through switch, in on port 5 and out on port 27. One bit flips at byte 700 on the way in. The switch is already sending the frame out when its last 4 bytes, the FCS 87 CB 59 48, arrive. Its own CRC of what arrived is AE D4 DF 4D, so the check fails. It writes the inverse, 51 2B 20 B2, as the outgoing FCS, and the next box sees an FCS that is the inverse of its own CRC: a stomped frame.

A 1518-byte Ethernet frame to scale: a 14-byte header in gray, data in blue, the 4-byte FCS at the end. The red tick is the flipped bit. Bytes are written in the order they go on the wire. The out port is drawn 14 bytes behind, once the header is in.

**The numbers**

*Bytes in the order they go on the wire.*

|  | Value |
|---|---|
| Frame | 1518 bytes: 14 of header, 1500 of data, 4 of FCS |
| Flipped on the way in | Byte 700, bit 3 |
| FCS sent | 87 CB 59 48 |
| CRC of what arrived | AE D4 DF 4D |
| FCS written out | 51 2B 20 B2, the inverse of AE D4 DF 4D |
| The next box | Its CRC of the frame is the inverse of the FCS: stomped |

## The frame check sequence

*Four bytes on every Ethernet frame*

A switch like this one takes frames in on one port and sends them out another. The chip under the big heatsink reads each frame’s header to pick the port, and checks its last four bytes on the way through.

At 100 Gb/s a port carries more than 8 million full frames a second. Every one ends in the same kind of check, and every port of every box along the path runs it again.

**Fig. 28: A 32-port switch, cover off.**

![Fig. 28: A 32-port switch, cover off](https://nearfieldnotes.com/notes/crc/fig-28.png)

*What the figure shows:* Figure 28: a 1U, 32-port 100G Ethernet switch with its cover off and two cables plugged in. A frame comes in on port 5, runs over the board's lanes to the switch chip under the large heatsink, and goes back out over other lanes to port 27. The chip checks each frame's CRC as it passes.

A 1U switch with 32 QSFP28 ports, its chassis sized from the Edgecore AS7712-32X datasheet and its board laid out for the picture. The lit lanes carry the opening figure’s frame from port 5 to the switch chip and back out to port 27.

**The numbers**

| Part | Value |
|---|---|
| Ports | 32 QSFP28, 100 Gb/s each |
| In | Port 5 |
| Out | Port 27 |
| Size | 438.4 × 515.0 × 43.5 mm, the Edgecore AS7712-32X’s |
| Board | Schematic: placed for the picture |

Those four bytes are the frame check sequence, the FCS. The sender runs a CRC over everything from the destination address to the last data byte and puts the result at the end.

The receiver runs the same CRC over the same bytes. If its answer doesn’t match, at least one bit changed on the way.

**Fig. 28b: An Ethernet frame.**

![Fig. 28b: An Ethernet frame](https://nearfieldnotes.com/notes/crc/fig-28b.png)

*What the figure shows:* Figure 28b: an Ethernet frame's fields. An 8-byte preamble and start delimiter come first and aren't covered. Then the 6-byte destination (FF FF FF FF FF FF), 6-byte source (02 00 00 00 A1 B2), 2-byte type (08 00) and 46 to 1500 bytes of data, all covered by the CRC. Last comes the 4-byte FCS, the CRC of those fields: 87 CB 59 48 for this frame.

The opening figure’s frame, sent to every port from a locally assigned address. Its 1500 data bytes are random. The preamble lets the receiver lock on and sits outside the CRC.

**The numbers**

*The opening figure’s frame, bytes in wire order.*

| Field | Bytes | This frame | Covered by the CRC |
|---|---|---|---|
| Preamble and start delimiter | 8 | — | No |
| Destination | 6 | FF FF FF FF FF FF | Yes |
| Source | 6 | 02 00 00 00 A1 B2 | Yes |
| Type | 2 | 08 00 | Yes |
| Data | 46 to 1500 | 67 FE … | Yes |
| FCS | 4 | 87 CB 59 48 | Is the CRC |

## Division with XOR

*A 4-bit CRC by hand*

A CRC treats the message as one long binary number and divides it by a fixed divisor, the generator polynomial. The CRC is the remainder.

This page writes a polynomial as its coefficient bits, highest power first, so 10011 is *x*⁴ + *x* + 1. Subtraction is XOR, with no borrows. The sender adds as many zeros as the CRC has bits and divides:

`R(x) = M(x) · x^n mod G(x)`

where R(x): remainder: the CRC, as a polynomial (bits); M(x): the message as a polynomial, its first bit the highest power (bits); x: the polynomial’s variable. Its powers mark bit places, so multiplying by xⁿ shifts left n bits (bit place); n: width of the CRC, the degree of G(x) (bits); G(x): generator polynomial (n + 1 bits).

`= 110101100000 mod 10011 = 0110`

The sender sends 11010110 0110, the message with its remainder. Divide that by 10011 and the remainder is 0000, so a receiver can check by dividing everything it got.

**Fig. 28c: Long division by 10011.**

![Fig. 28c: Long division by 10011](https://nearfieldnotes.com/notes/crc/fig-28c.png)

*What the figure shows:* Figure 28c: long division with XOR. The message 11010110 gets four zeros added, 110101100000. The divisor 10011, x to the 4th plus x plus 1, is XORed under each leading 1, three times, giving 010011100000, 000000100000 and 000000000110. What's left is the remainder 0110, the CRC.

Each row XORs the divisor under the leading 1. Gray bits are already zero. The last four bits are the remainder.

**The numbers**

*Coefficient bits, highest power first.*

| Step | Bits |
|---|---|
| Message and 4 zeros | 110101100000 |
| XOR 10011 at bit 0 | 010011100000 |
| XOR 10011 at bit 1 | 000000100000 |
| XOR 10011 at bit 6 | 000000000110 |
| Remainder | 0110 |

## The register that divides

*One bit a clock*

Hardware does the same division with a shift register and two XOR gates. Each clock one message bit goes in.

The bit falling out of r3 is XORed with the bit coming in. If the result is 1, it XORs the divisor into the register as everything shifts left. That is one step of the long division.

After the eighth bit the register holds 0110, the same remainder as Fig. 28c, and this form of the register needs no zeros added.

**Fig. 28d: The register, clock by clock.**

![Fig. 28d: The register, clock by clock](https://nearfieldnotes.com/notes/crc/fig-28d.png)

*What the figure shows:* Figure 28d: a 4-bit shift register divides by 10011. Each clock one message bit goes in and is XORed with the bit leaving r3; that feedback goes into r0 and is XORed in between r0 and r1. Clock by clock the register holds 0011, 0101, 1010, 0100, 1000, 0000, 0011, 0110. After the 8th bit it holds 0110, the same remainder as the long division.

The message of Fig. 28c, first bit first, into a 4-bit register dividing by 10011. Arrows show where each bit moves on the clock. It rests on clock 8.

**The numbers**

| Clock | Bit in | Feedback | r3 r2 r1 r0 |
|---|---|---|---|
| 0 | — | — | 0000 |
| 1 | 1 | 1 | 0011 |
| 2 | 1 | 1 | 0101 |
| 3 | 0 | 0 | 1010 |
| 4 | 1 | 0 | 0100 |
| 5 | 0 | 0 | 1000 |
| 6 | 1 | 0 | 0000 |
| 7 | 1 | 1 | 0011 |
| 8 | 0 | 0 | 0110 |

## Ethernet’s 32-bit register

*04C11DB7*

Ethernet’s divisor has 33 bits, from *x*³² down to 1. Written in hex with its top bit left off, as specs usually write it, it is 04C11DB7. Its register has 32 cells and 14 taps.

The register starts at all ones, and the sender flips the CRC’s bits before sending it. Because of those two choices, a receiver that runs the whole frame and its FCS through the register doesn’t land on zero.

It lands on C704DD7B for every good frame of every length. One flipped bit in the 1518-byte frame and it ends on 1AF71290 instead.

**Fig. 28e: Where the register ends.**

![Fig. 28e: Where the register ends](https://nearfieldnotes.com/notes/crc/fig-28e.png)

*What the figure shows:* Figure 28e: Ethernet's 32-bit CRC register, with taps at the 14 terms of 04C11DB7 below x to the 32nd. It starts at all ones. Run a 64-byte, a 590-byte or the 1518-byte frame through it together with its FCS and it ends on the same pattern, C704DD7B. With one bit flipped, the 1518-byte frame ends on 1AF71290.

The receiver’s register after each frame and its FCS have gone through, bits in the order they’re sent. A 1 is filled, a 0 left empty, r31 at the left. Each triangle marks a cell the feedback is XORed into. Red frames mark the cells that differ from a good frame’s.

**The numbers**

*Bits go in the order they're sent.*

| Run | Register at the end | r31 … r0 |
|---|---|---|
| Starts at | FFFFFFFF | 11111111111111111111111111111111 |
| 64-byte frame and its FCS | C704DD7B | 11000111000001001101110101111011 |
| 590-byte frame and its FCS | C704DD7B | 11000111000001001101110101111011 |
| The opening figure’s 1518-byte frame | C704DD7B | 11000111000001001101110101111011 |
| The same frame, 1 bit flipped | 1AF71290 | 00011010111101110001001010010000 |

## What it always catches

*By frame length*

Any error is itself a pattern of flipped bits. The CRC misses it only if that pattern divides by the polynomial exactly, and a polynomial can be chosen so that no pattern of a few bits does.

For Ethernet’s, the guarantee depends on length. Any 4 flipped bits are caught in frames up to 375 bytes, and any 3 up to 11,454 bytes, which covers full frames and 9018-byte jumbo frames. Any burst up to 32 bits long is caught at every length.

Past the guarantee, a few patterns slip through. In a full frame they are a tiny share of all 4-bit errors:

`P = W_4/(N (N − 1)(N − 2)(N − 3) ÷ 24)`

where P: share of 4-bit errors that pass the check (share of all 4-bit errors); W_4: 4-bit error patterns the polynomial divides exactly (patterns); N: bits in the frame, FCS included (bits).

`= (223,059)/(905,776,814,103,876) = 1 in 4.06 billion for N = 12,144`

**Fig. 28f: What CRC-32 always catches.**

![Fig. 28f: What CRC-32 always catches](https://nearfieldnotes.com/notes/crc/fig-28f.png)

*What the figure shows:* Figure 28f: how many flipped bits Ethernet's CRC-32 always catches, against frame length. Up to 25 bytes, any 6. Up to 37 bytes, any 5. Up to 375 bytes, any 4, which covers the smallest frame, 64 bytes. Up to 11,454 bytes, any 3, which covers the full 1518-byte frame and 9018-byte jumbo frames. Beyond that, any 2, out to 512 MiB.

The largest number of flipped bits Ethernet’s CRC-32 catches every time, against frame length with its FCS, on a log scale. Each step ends at the length printed under it. Koopman’s breakpoints; the steps from 2 to 5 bits were checked here by search.

**The numbers**

*Koopman’s breakpoints for 04C11DB7, from data bits to bytes with the 4-byte FCS.*

| Flipped bits always caught | Frame length with FCS, bytes | Ethernet frames in that range |
|---|---|---|
| 6 | Up to 25 | None: the smallest is 64 bytes |
| 5 | 26 to 37 | None |
| 4 | 38 to 375 | 64 bytes up to 375 |
| 3 | 376 to 11,454 | 1518-byte frames and 9018-byte jumbos |
| 2 | 11,455 and longer | None |

## One polynomial, five CRC-32s

*Hammond, Brown and Liu, 1975*

The polynomial alone doesn’t pin a CRC down. The start value, the bit order and the final flip all change the answer, and each mix has its own name. Two tools that both say CRC-32 can disagree on every file.

**Fig. 28g: Five CRC-32s of the same input.**

![Fig. 28g: Five CRC-32s of the same input](https://nearfieldnotes.com/notes/crc/fig-28g.png)

*What the figure shows:* Figure 28g: one polynomial, 04C11DB7, run five ways over the nine characters 123456789. ISO-HDLC: zip, Ethernet: start FFFFFFFF, bits reflected, final XOR FFFFFFFF, result CBF43926; BZIP2: start FFFFFFFF, bits not reflected, final XOR FFFFFFFF, result FC891918; MPEG-2: start FFFFFFFF, bits not reflected, final XOR 00000000, result 0376E6E7; CKSUM: start 00000000, bits not reflected, final XOR FFFFFFFF, result 765E7680; JAMCRC: start FFFFFFFF, bits reflected, final XOR 00000000, result 340BC6D9.

Each computed here and checked against the check values in RevEng’s catalog. LSB first means each byte goes in lowest bit first, as Ethernet sends it.

**The numbers**

| Name in RevEng’s catalog | Start | Bit order | Final flip | CRC-32 of “123456789” |
|---|---|---|---|---|
| ISO-HDLC: zip, Ethernet | FFFFFFFF | LSB first | Yes | CBF43926 |
| BZIP2 | FFFFFFFF | MSB first | Yes | FC891918 |
| MPEG-2 | FFFFFFFF | MSB first | No | 0376E6E7 |
| CKSUM | 00000000 | MSB first | Yes | 765E7680 |
| JAMCRC | FFFFFFFF | LSB first | No | 340BC6D9 |

CRC-32

### The Ethernet polynomial

**Field marks.** Polynomial 04C11DB7, start FFFFFFFF, bytes in lowest bit first, final flip. The CRC of “123456789” is CBF43926. A receiver’s register ends on C704DD7B after a good frame. RevEng’s catalog lists it bit-reversed, as DEBB20E3.

**Look-alike.** CRC-32C, polynomial 1EDC6F41, in iSCSI and NVMe over TCP. It catches every odd number of flipped bits at any length. In a full frame it also catches any 3, and it misses 312,496 4-bit patterns where Ethernet’s misses 223,059.

**Range.** Any 3 flipped bits up to 11,454 bytes, any 2 out to 512 MiB, any burst up to 32 bits at any length.

**Habitat.** Ethernet since the 1980 DIX spec. PCIe’s LCRC and ECRC, USB 3’s data, SAS, and SATA, which starts it from 52325032. Hammond, Brown and Liu recommended it in a 1975 study for the US Air Force, and the DIX spec notes the same polynomial in AUTODIN II, a US military network.

## When the check fails

*From each standard’s own documents*

Every link below checks a CRC. They split on what happens next. Ethernet throws the frame away and leaves the resending to TCP. Short links that can’t lose data, like PCIe, SATA and memory, ask for it again on the spot. Every row links the spec, standards body or vendor it comes from. [Note 14](https://nearfieldnotes.com/notes/phy-link/) shows where the check sits above each link’s [PHY](https://nearfieldnotes.com/glossary/#g-phy).

## Errors inside the boxes

*End to end*

A link CRC covers one hop. Each switch checks the frame, holds it in memory, and computes a fresh FCS on the way out. A bit that flips inside the switch, after the check and before the new FCS, leaves with a valid CRC.

Stone and Partridge watched real traffic in 2000. Between 1 packet in 1,100 and 1 in 32,000 failed TCP’s checksum, on links whose CRCs should have missed about 1 error in 4 billion. The errors came from sources a link CRC can’t see, from memory errors to software bugs.

That is why PCIe has an optional end-to-end ECRC that switches pass on unchanged, and why iSCSI and NVMe over TCP put CRC-32C digests on their data.

## Four levels, routine retries

*PCIe 6.0, 2022*

PCIe 6.0 runs four voltage levels at 64 GT/s. Its [eyes](https://nearfieldnotes.com/glossary/#g-eye-diagram) shrink, and bit errors stop being rare. It sends fixed 256-byte flits with error correction built in, and one 8-byte CRC per flit replaces the CRC on each packet. [Note 26](https://nearfieldnotes.com/notes/line-codes/) follows the flit from the [line code](https://nearfieldnotes.com/glossary/#g-line-code) side.

**Fig. 28h: A PCIe 6.0 flit.**

![Fig. 28h: A PCIe 6.0 flit](https://nearfieldnotes.com/notes/crc/fig-28h.png)

*What the figure shows:* Figure 28h: a PCIe 6.0 flit, 256 bytes to scale: 236 bytes of packets, 6 of link data, 8 of CRC and 6 of FEC. The CRC covers the first 242 bytes and the FEC all 256. The receiver corrects with the FEC first, then checks the CRC. A flit that fails gets a NAK and is sent again.

Bytes to scale. The receiver corrects with the FEC first, then checks the CRC to decide whether to accept the flit.

**The numbers**

*From PCI-SIG’s description of the PCIe 6.0 flit.*

| Part of the flit | Bytes |
|---|---|
| Packets | 236 |
| Link | 6 |
| CRC | 8 |
| FEC | 6 |

Flit CRC

### Eight bytes, checked after correction

**Field marks.** 8 bytes over the flit’s first 242. It is built from a Reed-Solomon code over bytes and used only to detect. The FEC after it is 6 bytes, three groups of 2, each able to fix one bad byte.

**Look-alike.** The FEC, which fixes errors where a CRC only finds them. The CRC checks what the FEC leaves, and a flit that fails gets a NAK and is sent again.

**Range.** Up to 8 bad bytes after correction are always caught, and a worse flit slips through with a chance of 2⁻⁶⁴. At PCI-SIG’s design error rate, about 5 flits in a million are retried.

**Habitat.** PCIe 6.0 and 7.0, and CXL 3. CXL’s latency-optimized flit checks a 6-byte CRC on each half first, and runs the FEC only when it fails. Das Sharma, Blankenship and Berger put the CRC at about 10 levels of gates against the FEC’s 50, and the saving at about 2 ns on a x16 link.

## At link speed

*1024 bits a clock*

One bit a clock would need a 400 GHz clock for 400G Ethernet. A MAC takes a wide word each clock instead:

`f = D/w`

where f: clock rate of the MAC (Hz); D: data rate of the port (bit/s); w: bits the MAC takes each clock (bits).

`= (400 Gb/s)/(1024 bits) = 391 MHz`

Intel’s F-tile 400G MAC takes 1024 bits at 415 MHz or more when its error correction is on, a 2.41 ns clock.

Write the register’s next state for a whole word at once and every output bit becomes one big XOR. At 8 bits a clock the busiest bit has 14 inputs. At 1024 it has 554, and only 21 of them come from the register itself.

A 64-byte frame takes 84 bytes of line with its preamble and the gap after it. The smallest frames arrive faster than the clock:

`t = ((64 + 20) bytes × 8)/D`

where t: time between the smallest frames (s); D: data rate of the port (bit/s).

`= (672 bits)/(400 Gb/s) = 1.68 ns`

So one word can hold the end of one frame and the end of the next, and the CRC logic has to finish both in one clock. AMD’s DCMAC is built for up to two frames a clock.

**Fig. 28i: Inputs to one CRC bit.**

![Fig. 28i: Inputs to one CRC bit](https://nearfieldnotes.com/notes/crc/fig-28i.png)

*What the figure shows:* Figure 28i: a CRC-32 that takes w bits per clock, and how many inputs its busiest output bit XORs together, on log scales. 1 bits: 3, 2 bits: 5, 4 bits: 7, 8 bits: 14, 16 bits: 20, 32 bits: 34, 64 bits: 52, 128 bits: 89, 256 bits: 157, 512 bits: 288, 1024 bits: 554. Of those, the inputs from the register itself level off at 21 from 256 bits up. 10G, 100G and 400G MACs take 64, 512 and 1024 bits per clock.

Ethernet’s CRC-32 taking a word of the given width each clock. Each dot is the most inputs any one of the 32 output bits XORs together, on log scales. Lines mark the widths of 10G, 100G and 400G MACs.

**The numbers**

*CRC-32, 04C11DB7, every output bit written out as one XOR.*

| Bits per clock | Inputs to the busiest bit | From the register | From the data | Two-input XORs, no sharing |
|---|---|---|---|---|
| 1 | 3 | 2 | 1 | 27 |
| 2 | 5 | 3 | 2 | 54 |
| 4 | 7 | 4 | 3 | 108 |
| 8 | 14 | 7 | 7 | 220 |
| 16 | 20 | 10 | 10 | 414 |
| 32 | 34 | 17 | 17 | 872 |
| 64 | 52 | 19 | 34 | 1,390 |
| 128 | 89 | 20 | 69 | 2,518 |
| 256 | 157 | 21 | 138 | 4,424 |
| 512 | 288 | 21 | 271 | 8,480 |
| 1,024 | 554 | 21 | 533 | 16,744 |

## Which CRC, and what happens

*From the link you have*

The link sets the CRC, and the CRC’s place in the link sets what a failure does. The key sorts them.

Key to link CRCs

### Which CRC does your link use, and what happens when it fails?

1. 1a The link carries Ethernet frames Go to 2
2. 1b Something else Go to 3
3. 2a Storage over TCP: iSCSI or NVMe/TCP FCS plus CRC-32C digests
4. 2b Any other traffic CRC-32 FCS: dropped or stomped
5. 3a DDR4 or DDR5 memory Write CRC: written again
6. 3b PCIe, USB or SATA Go to 4
7. 4a PCIe Go to 5
8. 4b USB or SATA Go to 6
9. 5a In flit mode, as at 64 GT/s Flit CRC after the FEC: replayed
10. 5b Not in flit mode: PCIe 1.0 to 5.0 LCRC each hop: replayed
11. 6a SATA CRC-32 from 52325032: R_ERR
12. 6b USB Go to 7
13. 7a USB 3, at 5 Gb/s and up CRC-16 and CRC-32: resent
14. 7b USB 2.0 CRC-5 and CRC-16: up to 3 tries

At 2a, bad data is resent on iSCSI and fails its command on NVMe/TCP. At 2b, a stomped FCS is the inverse of the CRC the next box computes, so it counts the frame as damaged upstream. At 5b, the link retrains after the 4th failed replay, and PCIe’s link packets carry a CRC-16 of their own. At 6a, a register FIS may be sent again and a data FIS should never be. At 7a, a bad header is resent hop by hop and bad data is retried end to end.

## Corrupt a frame yourself

*Six errors, one frame*

Pick an error. Each is flipped into the opening figure’s frame as sent, FCS and all, and the whole frame goes through the receiver’s register. A good frame ends on C704DD7B.

The two misses are real. The 4 bits at bytes 393, 610, 1121, 1124 are one of the 223,059 patterns the polynomial divides in a full frame, found by search. The 33-bit burst is the polynomial itself.

**Note 28’s explorer: One frame, one error.**

![Note 28’s explorer: One frame, one error](https://nearfieldnotes.com/notes/crc/fig-explore.png)

*What the figure shows:* Every error pattern flipped into the same 1518-byte frame: where the flipped bits fall, and the receiver's register at the end against C704DD7B, the value every good frame ends on.

The frame as in the opening figure, each red mark a flipped bit or a run of them, with the byte it falls in. Below, the receiver’s register after the frame, cells that differ from a good frame’s framed in red.

**The numbers**

*Each error flipped into the opening figure’s 1518-byte frame as sent, FCS included, then run through the receiver’s register.*

| Error | Bits flipped | First to last, bits | Bytes hit | Register at the end | Check |
|---|---|---|---|---|---|
| 1 bit flipped, at byte 700 | 1 | 1 | 700 | 1AF71290 | Caught |
| 2 bits, 1,300 bytes apart | 2 | 10,406 | 100, 1400 | 7850AF05 | Caught |
| 3 bits across the frame | 3 | 11,756 | 30, 700, 1500 | 3F7C1A8E | Caught |
| A burst 32 bits long | 10 | 32 | 900, 901, 902, 903 | 285CE303 | Caught |
| 4 bits the polynomial misses | 4 | 5,855 | 393, 610, 1121, 1124 | C704DD7B | Missed |
| 33 bits that match the polynomial | 15 | 33 | 1100, 1101, 1102, 1103, 1104 | C704DD7B | Missed |

#### Conditions

- **Frame:** 1518 bytes: broadcast destination, source 02 00 00 00 A1 B2, type 08 00, 1500 bytes of seeded random data, then its FCS. One bit flipped at byte 700, bit 3.
- **CRC-32:** Polynomial 04C11DB7 from FFFFFFFF, bytes in lowest bit first, final flip, checked against zlib. The receiver’s register is the shift-left form of Fig. 28d, run over the frame and its FCS in wire order.
- **Guarantees:** Koopman’s breakpoints for 04C11DB7 and CRC-32C, and the count of 4-bit patterns each misses in a full frame, reproduced by search.
- **Errors:** Flipped into the frame as sent. The 4-bit miss was found by searching for powers of *x* whose sum divides by the polynomial. The 32-bit burst has random bits between its two flipped ends.
- **Parallel CRC:** The register’s next state written out for 1 to 1024 bits a clock, each output bit as one XOR, with no shared terms.
- **Render:** Blender, one camera angle. The switch is generic.

Computed only. No frames were captured from a real link.

#### Limits

- The switch is drawn, not modeled. Real cut-through switches wait for more than the header, and their delay varies.
- The guarantees count flipped bits. Real links make bursts, and a descrambler below the CRC turns one line error into several flipped bits.
- DDR5’s CRC width isn’t given here. The page gives DDR4’s from Micron and says only that DDR5 adds reads.
- The parallel counts assume one XOR per output bit. Synthesis tools share terms and use far fewer gates.
- SAS appears only as a user of the polynomial. Its handling of a failed CRC isn’t covered.

#### Files

- sim/crc.py The frame, its FCS and its stomp, the CRC-4 division and register, the five CRC-32s and the 400G timing
- sim/site.py The receiver’s register for good and bad frames, the explorer’s errors and the inputs per CRC bit
- refs/checks/crc32_breakpoints.py Koopman’s breakpoints and 4-bit counts for 04C11DB7 and CRC-32C
- refs/checks/parallel_crc_matrix.py The parallel CRC equations at each word width
- render/switch.py The switch with its cover off in Fig. 28

#### Sources

- [AMD PG051, the Ethernet FCS](https://docs.amd.com/r/en-US/pg051-tri-mode-eth-mac/FCS)
- [DEC, Intel and Xerox, Ethernet 1.0, 1980, the polynomial and AUTODIN II](http://www.bitsavers.org/pdf/xerox/ethernet/Ethernet_Rev1.0_Sep1980.pdf)
- [Cisco, Nexus 9000 stomped CRCs](https://www.cisco.com/c/en/us/support/docs/switches/nexus-9000-series-switches/216239-nexus-9000-cloud-scale-asic-crc-identifi.html) and [CRC errors on Nexus switches](https://www.cisco.com/c/en/us/support/docs/ios-nx-os-software/nx-os-software/217554-understand-cyclic-redundancy-check-crc.html)
- [RFC 9293, TCP](https://www.rfc-editor.org/rfc/rfc9293.txt)
- [PCI Express Base 2.0, LCRC, ECRC, link packets, nullified packets and replay, archived](https://web.archive.org/web/2022/https://www.cl.cam.ac.uk/~djm202/pdf/specifications/pcie/PCI_Express_Base_Rev_2.0_20Dec06a.pdf)
- [PLX PEX 8604 data book, a PCIe switch’s ECRC](https://docs.broadcom.com/doc/PEX_8604-BA_Data_Book_v1.3_31Mar11.pdf)
- [PCI-SIG, PCIe 6.0’s flit, CRC and retry rate, archived](https://web.archive.org/web/20250120200834/https://pcisig.com/blog/evolution-pci-express-specification-its-sixth-generation-third-decade-and-still-going-strong)
- [Synopsys, PCIe 6.0 FEC then CRC](https://www.synopsys.com/blogs/chip-design/pcie-6-verifaction-fec-crc.html)
- [Das Sharma, Blankenship and Berger, CXL, arXiv 2023](https://arxiv.org/pdf/2306.11227)
- [USB 2.0 specification](https://www.usb.org/sites/default/files/usb_20_20211008.zip) and [USB 3.2 specification](https://usb.org/sites/default/files/usb_32_202206_1.zip)
- [Serial ATA 1.0a, its CRC, start value and retries](https://web.mit.edu/fustflum/etcetera/serialata10a.pdf)
- [T10 07-130r1, SAS’s CRC](https://www.t10.org/ftp/t10/document.07/07-130r1.pdf)
- [Micron 16Gb DDR4 datasheet, write CRC](https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors/231284/1/16Gb_DDR4_SDRAM.pdf) and [Synopsys, DDR5’s read CRC](https://www.synopsys.com/designware-ip/technical-bulletin/ddr5-features.html)
- [RFC 7143, iSCSI digests](https://www.rfc-editor.org/rfc/rfc7143.txt) and [NVMe/TCP 1.1](https://nvmexpress.org/wp-content/uploads/NVM-Express-TCP-Transport-Specification-Revision-1.1-2024.08.05-Ratified.pdf)
- [Stone and Partridge, “When the CRC and TCP Checksum Disagree”, SIGCOMM 2000](https://conferences2.sigcomm.org/sigcomm/2000/conf/abstract/9-1.htm)
- [Koopman, CRCs for Internet applications, DSN 2002](https://users.ece.cmu.edu/~koopman/networks/dsn02/dsn02_koopman.pdf) and [his CRC zoo](https://users.ece.cmu.edu/~koopman/crc/crc32.html)
- [RevEng catalog of CRC models, check values and residues](https://reveng.sourceforge.io/crc-catalogue/all.htm)
- [Hammond, Brown and Liu, RADC-TR-75-138, 1975](https://everyspec.com/USAF/USAF-RADC/RADC-TR-75-138_47950/)
- [Altera F-tile Ethernet guide, the 1024-bit interface](https://docs.altera.com/r/docs/683023/26.1.1/f-tile-ethernet-hard-ip-user-guide/tx-mac-segmented-client-interface?contentId=mQAb9fSWeitZthAFCwFB0w) and [its clocks](https://docs.altera.com/r/docs/683023/26.1.1/f-tile-ethernet-hard-ip-user-guide/clocks?contentId=5LiRsRlqdLOCSHDkYqZPWg)
- [AMD PG369, DCMAC, up to two frames a clock](https://docs.amd.com/r/en-US/pg369-dcmac/AXI4-Stream-Interface)

What should the next note be? [Ask for one](https://nearfieldnotes.com/#ask-for-a-note)

---

Source: https://nearfieldnotes.com/notes/crc/

Cite as: Michael Walker, “CRCs on fast links”, Near Field Notes, Note 28, Rev 1, 9 Nov 2026. https://nearfieldnotes.com/notes/crc/

Figures: free to reuse under CC BY 4.0 (https://nearfieldnotes.com/license/). Each one's image is linked under its name. Credit Michael Walker, Near Field Notes, and link the figure: this address plus #fig- and its number, like https://nearfieldnotes.com/notes/crc/#fig-28.
