BCH-Code
Zyklischer Blockcode mit frei wählbarer Fehlerkorrekturstärke — überwindet die feste Ein-Bit-Korrektur und die 31-Bit-Obergrenze des Hamming-Codes.
Der BCH-Code (nach seinen Erfindern Bose, Ray-Chaudhuri und Hocquenghem) ist ein zyklischer, fehlerkorrigierender Blockcode, der den Hamming-Code in zwei zentralen Punkten verallgemeinert: Die Anzahl der korrigierbaren Bitfehler $t$ pro Codewort ist frei wählbar (statt fest bei $t=1$), und die Codewortlänge ist nicht auf $n \le 31$ begrenzt. Der Preis dafür: eine deutlich abstraktere Konstruktion und ein komplexeres Dekodierverfahren.
1. Warum Hamming nicht immer reicht
Hamming-Codes haben unabhängig von der gewählten Blockgröße stets eine Minimaldistanz $d_{\min}=3$ — sie korrigieren also immer nur einen Bitfehler pro Codewort, egal wie viele Redundanzbits investiert werden. Für Anwendungen mit höherer Fehlerdichte (z. B. NAND-Flash-Speicher mit zunehmender Zellendichte, oder stark gestörte Funkkanäle) reicht das nicht aus — hier wird eine wählbare Korrekturstärke $t=2,3,4,\dots$ benötigt. Genau das leistet die BCH-Konstruktion, ohne die grundlegende Idee der Polynomdivision aus dem CRC-Code zu verlassen.
2. Konstruktionsprinzip
Die Kodierung eines BCH-Codeworts ist nichts Neues: Sie funktioniert exakt wie beim CRC-Code — Nachricht mit Nullen auffüllen, durch ein Generatorpolynom $G(x)$ teilen, den Rest anhängen (siehe dort Abschnitt 1 für die anschauliche Rest-beim-Teilen-Erklärung). Der gesamte Unterschied zwischen einem "gewöhnlichen" zyklischen Code und einem BCH-Code steckt allein in der Wahl von $G(x)$: BCH verwendet ein Generatorpolynom, das nach einer festen Konstruktionsvorschrift so zusammengesetzt ist, dass es eine garantierte Fehlerkorrekturfähigkeit von $t$ Bits mit sich bringt — statt eines beliebigen oder nur auf Fehlererkennung optimierten Polynoms.
Man kann sich diese Konstruktionsvorschrift wie ein Baukasten-Rezept vorstellen: Für eine gewünschte Codewortlänge $n$ und Korrekturstärke $t$ liefert eine vorgefertigte Tabelle ("Zutatenliste") eine Handvoll kleiner Bausteinpolynome. $G(x)$ entsteht einfach durch Multiplikation dieser Bausteine — man muss die Tabelle also nur ablesen und die Bausteine miteinander malnehmen, nicht von Grund auf herleiten:
- Codewortlänge und Feldgröße festlegen: $n = 2^m - 1$ für ein gewähltes $m$.
- Gewünschte Korrekturstärke $t$ wählen; die Entwurfsdistanz ist $d = 2t+1$.
- Für die Wahl $t$ liefert die Bausteintabelle (fachsprachlich: Tabelle minimaler Polynome für die gewählte Feldgröße $m$) die passenden Bausteine.
- $G(x)$ ist das Produkt dieser Bausteine — dadurch entsteht automatisch ein Generatorpolynom, das eine $t$-Bit-Fehlerkorrektur garantiert.
Exkurs: Was ist $\text{GF}(2^m)$?
Für unser Beispiel mit $m=4$ hat $\text{GF}(16)$ 16 Elemente: die Null und 15 weitere, die sich alle als Potenzen eines einzigen Erzeugerelements $\alpha$ schreiben lassen — $\alpha^0, \alpha^1, \alpha^2, \dots, \alpha^{14}$. Danach schließt sich der Kreis: $\alpha^{15} = \alpha^0 = 1$. Das ist auch der Grund, warum unser BCH-Beispiel eine Codewortlänge von genau $n=15$ hat — sie entspricht exakt der Zykluslänge des Erzeugers.
Jede Potenz $\alpha^i$ lässt sich zugleich als 4-Bit-Muster schreiben. Die Rechenregel dahinter legt ein festes Grundpolynom fest, z. B. $p(x) = x^4+x+1$, wofür gilt $\alpha^4 = \alpha + 1$ — statt eines Übertrags in eine fünfte Bitstelle wird also immer wieder auf die ersten vier Potenzen zurückgeführt (vergleichbar mit einer Uhr, die nach 15 Stunden wieder bei 0 anfängt):
| Potenz | 4-Bit-Muster | Potenz | 4-Bit-Muster |
|---|---|---|---|
| $\alpha^0$ | 0001 | $\alpha^8$ | 0101 |
| $\alpha^1$ | 0010 | $\alpha^9$ | 1010 |
| $\alpha^2$ | 0100 | $\alpha^{10}$ | 0111 |
| $\alpha^3$ | 1000 | $\alpha^{11}$ | 1110 |
| $\alpha^4$ | 0011 | $\alpha^{12}$ | 1111 |
| $\alpha^5$ | 0110 | $\alpha^{13}$ | 1101 |
| $\alpha^6$ | 1100 | $\alpha^{14}$ | 1001 |
| $\alpha^7$ | 1011 | $\alpha^{15}=\alpha^0$ | 0001 |
Die "minimalen Polynome" aus Schritt 3 oben sind nichts anderes als: das kleinstmögliche Polynom mit 0/1-Koeffizienten, das eine bestimmte Potenz $\alpha^i$ als Nullstelle hat. Für $\alpha^1$ ist das genau unser Grundpolynom $p(x)=x^4+x+1$ — deshalb taucht es in Tabelle 1 des Whitepapers als minimales Polynom für $i=1$ auf. Für die BCH-Konstruktion braucht man die minimalen Polynome mehrerer aufeinanderfolgender ungerader Potenzen ($\alpha^1, \alpha^3, \alpha^5$ für $t=3$); ihr Produkt ergibt $G(x)$ aus Abschnitt 3.
3. Konkretes Beispiel: BCH(15,5), $t=3$
10100110111, Grad 10). Mit $n=15$ und $r=10$ Prüfbits verbleiben $k = n-r = 5$ Nutzdatenbits — man spricht vom BCH(15,5)-Code.
| Größe | Wert |
|---|---|
| $m$ (Feldgröße) | 4 |
| $n$ (Codewortlänge) | 15 |
| $t$ (korrigierbare Bitfehler) | 3 |
| $r$ (Prüfbits) | 10 |
| $k$ (Nutzdatenbits) | 5 |
4. Kodierung: dieselbe Polynomdivision wie CRC
Die Kodierung eines BCH(15,5)-Codeworts läuft exakt wie in CRC-Code, Abschnitt 1 beschrieben: die 5 Nachrichtenbits um 10 Nullen erweitern, durch $G(x)$ teilen, den Rest als 10 Prüfbits anhängen.
10110 ergibt die Division durch $G(x)$ das Codewort 101100100011110 (15 Bit) — eine erneute Division dieses Codeworts durch $G(x)$ liefert exakt den Rest 0.
5. Dekodierung: Syndrom-Tabelle statt direkter Formel
Das Syndrom ist ein Prüfwert, der sich allein aus dem empfangenen Codewort berechnen lässt (beim BCH- wie beim CRC-Code: der Rest bei erneuter Division durch $G(x)$) und anzeigt, ob ein Fehler vorliegt — bei 0 keiner, bei einem Wert ungleich 0 ein erkannter Fehler. Beim Hamming-Code verrät das 3-Bit-Syndrom die Fehlerposition direkt als Binärzahl — ein Trick, der nur bei $t=1$ funktioniert. Bei $t=3$ gibt es dagegen $\binom{15}{1}+\binom{15}{2}+\binom{15}{3} = 15+105+455 = 575$ mögliche Ein-, Zwei- und Dreibit-Fehlermuster (plus den fehlerfreien Fall) — zu viele, um sie noch direkt aus einer kurzen Binärzahl abzulesen. Der allgemeine Ausweg — gültig für jeden linearen Blockcode, nicht nur BCH — ist ein simples Nachschlagewerk, die Syndrom-Tabelle: Statt die Fehlerposition zu berechnen, wird sie einmalig für alle möglichen Fehler vorab bestimmt und danach nur noch nachgeschlagen:
- Für jedes mögliche Fehlermuster mit Gewicht $\le t$ — das Gewicht ist einfach die Anzahl der gekippten Bits, ein Fehler an 3 Positionen hat also Gewicht 3 — wird sein Syndrom vorab berechnet: der Rest der Division des Fehlermusters durch $G(x)$ (dieselbe Rechenoperation wie bei der Kodierung).
- Diese Zuordnung Syndrom → Fehlermuster wird in einer Tabelle abgelegt.
- Beim Empfang wird das Syndrom des empfangenen Worts berechnet und in der Tabelle nachgeschlagen — der Treffer liefert direkt das zu korrigierende Fehlermuster.
6. Simulator: Kodierung, Fehler und Syndrom-Korrektur
BCH(15,5), $t=3$: Codewort, Fehler und Korrektur per Syndrom-Tabelle
5 Nutzdatenbits anklicken, um die Nachricht zu ändern — die 10 Prüfbits werden automatisch neu berechnet. Auf bis zu 3 Bits im 15-Bit-Codewort klicken, um Fehler zu simulieren; die Syndrom-Tabelle (576 vorab berechnete Fehlermuster) lokalisiert und korrigiert sie. Bei mehr als 3 gleichzeitigen Fehlern versagt die Korrektur — wie bei jedem Code mit endlichem $t$.
7. Praktischer Einsatz
Amateurfunksatelliten (AMSAT): Viele Amateurfunksatelliten sichern ihre Telemetrie- und Frame-Rahmen mit Golay-Codes ab — einer mit BCH eng verwandten zyklischen Codefamilie mit fest definierter Fehlerkorrekturstärke, gut geeignet für kurze, feste Rahmenlängen. Ein Beispiel ist das Maveric-Projekt mit Golay-Framing auf einem 9600-bps-GMSK-Downlink. BCH selbst kommt seltener direkt in Amateurfunk-Protokollen zum Einsatz, dafür umso häufiger in der Hardware, mit der SDR-Empfangsketten arbeiten (siehe NAND-Flash unten).
NAND-Flash-Speicher (SSDs): Mit wachsender Zellendichte (MLC, TLC, QLC) steigt die Rohfehlerrate beim Auslesen deutlich — Flash-Controller setzen deshalb BCH-Codes mit $t$ im Bereich von 4 bis weit über 40 ein, weit jenseits dessen, was ein Hamming-Code leisten könnte.
Satellitenkommunikation (DVB-S2): Der DVB-S2-Standard für Satellitenfernsehen nutzt einen BCH-Code als äußeren Code in Verkettung mit einem LDPC-Code als inneren Code, um die geforderte extrem niedrige Restfehlerrate bei begrenzter Sendeleistung zu erreichen.
Weitere ECC-Anwendungen mit hoher Fehlerdichte: Überall dort, wo Hamming-Codes an ihre $t=1$-Grenze stoßen, aber weiterhin Vorwärtsfehlerkorrektur (FEC) ohne Rückkanal benötigt wird — etwa in Speicherzellen mit hoher Bitfehlerrate oder stark gestörten Übertragungskanälen.
8. Grenzen
- Komplexere Dekodierung: Während die Kodierung so einfach ist wie beim CRC-Code, benötigt die Dekodierung für größere $n$ und $t$ in der Praxis effiziente Algorithmen (Berlekamp-Massey, Peterson-Gorenstein-Zierler) statt einer brute-force aufgebauten Syndrom-Tabelle — die hier gezeigte Tabellenmethode wird für große Codes schnell unpraktikabel (Anzahl der Einträge wächst kombinatorisch mit $t$).
- Galois-Feld-Arithmetik nötig: Die eigentliche Konstruktion des Generatorpolynoms (Abschnitt 2, Schritt 3) erfordert Rechnen in einem endlichen Körper — Hardware- oder Software-Aufwand, den einfachere Codes wie Hamming oder CRC nicht benötigen.
- Wie jeder Code mit endlichem $t$: Mehr als $t$ gleichzeitige Fehler in einem Codewort werden entweder gar nicht mehr zuverlässig lokalisiert oder (schlimmer) fälschlich auf ein falsches, aber gültig aussehendes Muster korrigiert — dieselbe grundsätzliche Grenze wie beim Hamming-Code, nur bei höherer Fehlerdichte erreicht.
Hamming-Code
Der Spezialfall $t=1$ — einfachere Konstruktion, aber feste Korrekturstärke und auf 31 Bit begrenzt.
Golay-Code
Kein frei wählbares $t$, dafür ein "perfekter" Code — verschwendet keine einzige Syndromkombination.
CRC-Code
Dieselbe Polynomdivision zur Kodierung, aber mit einem Generatorpolynom nur für Fehlererkennung statt -korrektur.
Codes-Übersicht
Einordnung von BCH neben Leitungscodes und anderen Fehlerkorrekturverfahren.