-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b6e8889
commit 9a0e63f
Showing
1 changed file
with
74 additions
and
0 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
70046 - Advanced Digital Systems Design/Error Correction.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
## Fault Sources | ||
- Radiation (alpha particles hitting silicon and inducing enough charge to cause a bit flip) | ||
- Hardware breakage (by manufacturing or over lifetime due to aging) | ||
## Error Detection | ||
### Parity Bits | ||
Adding a single bit to a set of bits that represents the number of `1`s. | ||
- Can detect an odd number of fault events (as this changes the parity bit) | ||
|
||
We can include multiple check parity bits to allow error correction (to deduce which bit was flipped, given a single fault). | ||
```rust | ||
P0 = parity(D0, D1, D3) | ||
P1 = parity(D0, D2, D3) | ||
P2 = parity(D1, D2, D3) | ||
|
||
// If only one of P0, P1, P2 is unchanged, then we can deduce which data bit was changed | ||
``` | ||
Each data bit needs to affect a different combination of check bits to allow us to infer the data bit changed, from the check bit change. | ||
$$2^n -n - 1 \ \text{data bits are covered by} \ n \ \text{ parity bits}$$ | ||
- $n$ bits means $2^n$ combinations | ||
- of the $2^n$ combinations, only $n$ affect a single bit (`...010...`) | ||
- one combination should change no bits (no parity change) | ||
```python | ||
def parity(bits: list[bool]) -> bool: | ||
""" Parity as the number of 1s is odd=True, even=False """ | ||
return bool(sum(bits) % 2) | ||
|
||
def gen_indexes(size: int) -> list[set[int]]: | ||
""" Generate the parity indexes for `size` data bits | ||
[index{parity indices... }, ] | ||
- If all parities chan ge except index, then index was flipped. | ||
- The set contains the bit indicies to calculate parity | ||
""" | ||
return [{j for j in range(size) if j != i} for i in range(size)] | ||
|
||
def gen_parity_bits(data_bits: list[bool]) -> list[bool]: | ||
""" Get the error correction bits """ | ||
return [parity([data_bits[i] for i in s]) for s in gen_indexes(len(data_bits))] | ||
|
||
def check(data_bits: list[bool], parity_bits: list[bool]) -> int | None | str: | ||
""" Compares the parity | ||
single fault => (all except one parity bit are flipped) then | ||
return the data bit index flipped | ||
string => double fault | ||
none => no change | ||
""" | ||
same_index: int | None = None | ||
differing: bool = False | ||
for i, (o, n) in enumerate(zip(parity_bits, gen_parity_bits(data_bits))): | ||
if o == n: | ||
if same_index is not None and differing: | ||
return "Double fault" | ||
same_index = i | ||
else: | ||
differing = True | ||
return same_index | ||
|
||
original_bits = [True, True, False, False, True] | ||
original_parity = gen_parity_bits(original_bits) | ||
new_bits = [True, False, False, False, True] | ||
new_parity = gen_parity_bits(new_bits) | ||
assert check(new_bits, original_parity) == 1 | ||
``` | ||
|
||
We can also add an extra bit fir the parity of the parity bits (to detect double faults) | ||
### Basic Checksum | ||
Add all data words together (ignoring carry) and store result. | ||
- Easy to compute | ||
- Errors can cancel out (no error detected) | ||
### Modified Checksum | ||
On every carry, add a 1 instead, this way carry information is not entirely lost. | ||
- Errors can still cancel out | ||
### Cyclic Redundancy Check | ||
Use polynomial division | ||
[[TODO]] |