Detecting Errors
Say what parity, a checksum and a CRC each catch, read the measured misses for single, double and burst errors, and tell an acknowledge from a check.
- Lesson
- P5.7
- Time
- 25 min
- Runs on
- Your browser
- Check
- 5 questions
A motor drive accepted a corrupted speed command. Its link carried one parity bit per byte, and a burst of noise flipped two bits in the same byte. Parity counts the 1s, and two flips leave the count even.
Read phases and sample points (transmitter half bit)
- start: columns 2 through 3.
- data 0: columns 4 through 5.
- data 1: columns 6 through 7.
- data 2: columns 8 through 9.
- data 3: columns 10 through 11.
- data 4: columns 12 through 13.
- data 5: columns 14 through 15.
- data 6: columns 16 through 17.
- data 7: columns 18 through 19.
- even parity: columns 20 through 21.
- stop: columns 22 through 23.
- rx sampled at 4.688, 4.813, 4.938, 6.688, 6.813, 6.938, 8.688, 8.813, 8.938, 10.688, 10.813, 10.938, 12.688, 12.813, 12.938, 14.688, 14.813, 14.938, 16.688, 16.813, 16.938, 18.688, 18.813, 18.938, 20.688, 20.813, 20.938, 22.688, 22.813, 22.938.
Generated and decoded back. The sender sent 0xA5; two bits were pulled low on the way. The receiver on the bench logged RX a0 ok: a well-formed frame with the wrong byte in it.
Four Checks and a Fault Injector
- Add a check
Parity adds one bit per byte so each byte holds an even number of 1s. The checksum adds the four bytes and keeps the low 8 bits. CRC-8 divides the payload by x^8 + x^2 + x + 1 (0x07) and sends the remainder.
- Hit it
The injector flips bits anywhere in the frame, check bits included: one bit, two bits, or a burst whose first and last bits flip.
- Check it
The receiver computes the check again. A frame that still matches is accepted, even when it carries an error.
- Answer it
With ACK and NACK the receiver can ask for a rejected frame again. The answer is only as good as the check behind it.
Read the diagram as text
- Payload: four random bytes
- Sender adds a check: parity, checksum or CRC-8
- Fault injector: single, double or burst flips
- Receiver recomputes: match: accept; else reject
- ACK or NACK: NACK asks for the frame again
- Payload → Sender adds a check
- Sender adds a check → Fault injector: frame
- Fault injector → Receiver recomputes: frame, maybe flipped
- Receiver recomputes → ACK or NACK
- ACK or NACK → Sender adds a check: retry on NACK
Every scheme saw the same kinds of hit, 2000 frames per kind, from one fixed seed.
A check is extra bits computed from the payload. A flip that changes the payload but leaves the check consistent is a miss. The fault injector counts exactly that: frames hit once and still accepted.
What Each Check Missed
| Scheme | Single flip | Double flip | Burst of 3 to 8 | Burst of 9 to 16 |
|---|---|---|---|---|
| Even parity per byte | 0 | 434 | 682 | 385 |
| 8-bit checksum | 0 | 125 | 0 | 7 |
| CRC-8 (0x07) | 0 | 0 | 0 | 7 |
| ACK with no check | 2000 | 2000 | 2000 | 2000 |
Frames accepted with an error in them, out of 2000 per cell. Measured by the example program below.
Parity misses every even number of flips inside one byte: 434 of the double flips landed in one byte. The checksum misses flips that cancel in the sum, such as one bit rising in one byte while the same bit falls in another.
CRC-8 caught every single flip, every double flip and every burst of 3 to 8 bits. Longer bursts can slip through: 7 of 2000 did. A wider CRC lowers that fraction; no check makes it zero.
The Flips Parity Cannot See
| 0xA5 sent, even parity | Bits pulled low on the wire | The receiver logs |
|---|---|---|
| clean | none | RX a5 ok |
| one flip | bit 0 | RX a4 PE |
| two flips | bits 0 and 2 | RX a0 ok |
Measured on the UART bench (P6), forcing the line low over the receiver's vote ticks of each chosen bit. PE is the parity error flag.
One flip is caught. Two flips give 0xa0, which still has an even count of 1s with the parity bit, so the frame is accepted. The same rule covers any even number of flips in one byte.
An ACK Is a Receipt
An I2C acknowledge says the receiver took the byte (UM10204 §3.1.6). It checks nothing. On the bench, noise lifts SDA during one data bit of a write.
Clean write of 0x3C to register 10
start; address7(7'h50, W);
write_byte(8'h10); write_byte(8'h3c);
stop;
Measured: I2C S 50 W A 10 A 3c A P, last ACK 1, register 10 holds 3c.
Noise lifts SDA during data bit 7
lift = 1; // force SDA high for one bit
start; address7(7'h50, W);
write_byte(8'h10); write_byte(8'h3c);
stop;
Measured: I2C S 50 W A 10 A bc A P, last ACK 1, register 10 holds bc.
The target acknowledged bc and stored it. I3C adds an odd parity T-bit after each controller-written byte (MIPI I3C Basic §5.1.2.3.3), a check like UART parity.
ACK and NACK become error control only with a check behind them. CRC-8 plus retry delivered 9 wrong frames of 2000 after long bursts: the CRC's misses remain. The resends cost bus time: 1970, 2058, 2134, 1880 across the four columns.
Where This Shows Up
| Idea | Where it returns |
|---|---|
| Even and odd parity on a UART frame | P6.2 the frame; P6.5 which flag means which fault |
| ACK and NACK on every byte | P8.3 the ninth clock belongs to the receiver |
| A parity T-bit on controller writes | P9.2 I3C SDR frames |
| Detecting and leaving an error state | P9.7 HDR exit and error recovery |
SPI itself defines no check. The W25Q128JV flash used in module P7 lists no check field in any of its instruction tables (§8.1), so a read is trusted as clocked.
Try It
Each row is one scheme, each column one kind of hit, and each count is the frames accepted with an error. The last two rows are CRC-8 with NACK and retry: frames delivered wrong, then how many resends it took.
Change seed and run again: the zeros stay zeros, the other counts move a little. Then change the polynomial in crc8 from 8'h07 to 8'h01 and watch which columns stop being zero.
parity | single 0 | double 434 | burst 3-8 682 | burst 9-16 385 | missed of 2000 checksum | single 0 | double 125 | burst 3-8 0 | burst 9-16 7 | missed of 2000 crc-8 | single 0 | double 0 | burst 3-8 0 | burst 9-16 7 | missed of 2000 ack, no check | single 2000 | double 2000 | burst 3-8 2000 | burst 9-16 2000 | missed of 2000 crc-8 + retry | single 0 | double 0 | burst 3-8 0 | burst 9-16 9 | delivered wrong of 2000 its resends | single 1970 | double 2058 | burst 3-8 2134 | burst 9-16 1880 | NACKs and resendsCheck Yourself
Remember
- A check is extra bits computed from the payload; a miss is an error that leaves the check consistent.
- Parity catches any odd number of flips in a byte and misses any even number.
- An 8-bit checksum misses flips that cancel in the sum; CRC-8 (0x07) caught every single, double and short burst error in the run.
- An ACK reports receipt and checks nothing; NACK and retry recover only what a check rejects.