ビット誤り訂正について

パリティビット付きの72ピンSIMMとHXチップセットで誤り訂正が出来たり、 通信やCDなど、 誤り訂正技術はいろんなところで使われています。

1ビット誤り検出

まず、ここに4ビットの情報があるとします。 1ビットの誤りを検出するにはどうしたらいいでしょうか? 1ビットの誤りとは、次のようなものです。

元データ結果データ
11001100誤りなし
0100
1000
1110
1101
1ビット誤り

これは簡単、パリティビットを付け加えればいいですね。 送ったデータのうち1ビットだけ誤りならば、受信側でパリティエラーになります。

元データ結果データ検証
1100.01100.00誤りなし
0100.0
1000.0
1110.0
1101.0
1100.1
1
1
1
1
1
パリティエラー

上の表で注意しなければならないのは、パリティ自体も誤る可能性がある、 ということです。 通常、データもパリティも同じ媒体で記録されたり伝送されたりしますので。

ここでちょっと定義します。 元データを A1、A2、… のように表し、 付加ビットを B1、B2、… のように表します。 元データのビット数は a、付加ビットのビット数は b と表すことにします。 上の例では、次のように表せます。

a=4、b=1 において、
送信側: B1=A1+A2+A3+A4 となるようにパリティを生成
受信側: A1+A2+A3+A4+B1≠ 0 なら誤りあり

ここで + は、XOR演算です。 誤り検出、訂正などすべてこのXOR演算が基本になっています。

1ビット誤り訂正

それでは誤りの訂正です。まず、誤りの状況を見てみましょう。

元データ結果データ
11001100誤りなし
0100
1000
1110
1101
1ビット誤り

誤りの状態として4つ、そして正常な状態の1つ、あわせて5状態が、 誤り訂正用の付加ビットで区別できればいいことがわかります。 5状態なので、3ビットあればよさそうだな、 ということはだいたい想像できると思います。

「え、3ビット付け加えたらそのビットも誤るかもしれないじゃないか」 はい、その通りです。ので、3ビット付け加えたら、 誤りの状態として7つ、正常な状態の1つ、あわせて8状態となり、 …ちょうど3ビットで区別できそうですね。

さて、ここで7ビットの列 X1、X2… X7を 考えてみます。但し、これらの間には次の関係が成り立つものとします。

X1+X3+X5+X7 = 0
X2+X3+X6+X7 = 0
X4+X5+X6+X7 = 0

ちょっとわかりにくいですか? では、下の表を見て下さい。 この表で、* となっているXのビットを全てXORしたものが、 0となっていることにします。

X1*--
X2-*-
X3**-
X4--*
X5*-*
X6-**
X7***
xor→000

これはつまり、受信側での検証を示しています。 X1…X7を受信したら、 上記の式つまりこの表を用いてXOR計算をおこない、 検証結果が 0、0、0、であることを確認します。

さて、ここで、X1〜7のうち、1ビットに誤りが生じたとします。

X1*--
X2-*-
X3**-
X4--*
X5 *-*
X6-**
X7***
xor→10 1

例えば、X5が誤ったとすると、そのビットが反転します。 そして、この誤りの影響が出るのは、上の表で * となっている部分だけであり、 検証結果として、1、0、1、というものが得られます。 表を良く見るとわかりますが、 この検証結果は、誤った X のビット位置によって、値が変わるようになっています。 つまり、検証結果を見ると、どのビットが誤ったかわかるのです。

あとは簡単ですね。このX1〜7を、A1〜4と、 B1〜3に割り当てればよさそうです。 ただ、どこに割り振ってもいいか、というとそうではありません。 例えば、A1〜4を、X4〜7に割り振ってしまうと、

A1+A2+A3+A4 = 0

を強制することになりますが、 これは元データに制約をかけることになってしまいうまくありません。

次のように割り当てると都合良さそうです。

B1*--
B2-*-
A1**-
B3--*
A2*-*
A3-**
A4***
xor→000

式で書いてBを移項するとこんな感じになります。

B1 = A1+A2+A4
B3 = A1+A3+A4
B3 = A2+A3+A4

これで1ビットの誤り訂正ができることになります。 つまり、送信側では上記の式に従ってAからBを作り、 受信側では、表を利用して、どのビットが誤ったのかを検出できます。

2ビット誤り検出+1ビット誤り訂正

上記の誤り訂正方式で、2ビットの誤りがでたらどうなるでしょう?

B1*--
B2-*-
A1 **-
B3--*
A2 *-*
A3-**
A4***
xor→01 1

というわけで、2ビット誤ると、さらに誤って訂正されてしまいます。 上の例では、A1とA2の2ビットが誤ると、 A3が誤っていると認識され、さらに誤って訂正されてしまいます。

これを検出するにはどうすればよいのでしょうか? 簡単には、さらに全体にパリティを設けます。 全体にパリティを適用すると、2ビット誤るとパリティは一致してしまいますので、 2ビット誤っていることがわかります。 つまり、B4をパリティとすると、次のように送信側で構成します。

B1 = A1+A2+A4
B2 = A1+A3+A4
B3 = A2+A3+A4
B4 = A1+A2+A3+A4+B1+B2+B3 (= A1+A2+A3)

受信側では、つぎのような計算を行ないます。

Y1 = A1+A2+A4+B1
Y2 = A1+A3+A4+B2
Y3 = A2+A3+A4+B3
Y4 = A1+A2+A3+A4+B1+B2+B3+B4
(※受信側では Y4 = A1+A2+A3 にはできません)

Y1〜3Y4
00誤りはなし
0以外1A1〜4、B1〜3の1ビット誤り訂正
01B4の1ビット誤り訂正(無視)
0以外02ビット誤り検出

誤り訂正に必要な付加ビット数

以上のことより、元のデータビット数 a に対し、 誤り訂正を行うために必要な付加ビット数 b は、以下のようになります。

誤り訂正能力最低必要なビット数 b
1ビット誤り検出1
1ビット誤り訂正log2(a+b+1)
2ビット誤り検出+1ビット誤り訂正 1+log2(a+b+1) ※上記の構成法の場合

コード間距離

というわけで、1ビット誤り検出、1ビット誤り訂正、 2ビット誤り検出+1ビット誤り訂正、と説明してきましたが、 これはつまりコード間距離がどれだけあるか、を議論していることになります。

コード間距離とは、ある正当なコードからある正当なコードに変化させるのに、 最低何ビット変えなければならないか、ということです。 受信側へ送られてくるコード列 X1…Xnを、 何ビット変化させれば、別の正しいコード列となるか、ということです。

1ビット変化させただけで別のコードになってしまう場合は、誤り検出も訂正もできません。
コード間距離が2ある場合は、1ビット変化させたものは必ず誤りですので、 1ビット誤り検出ができます。
コード間距離が3になると、もし1ビット誤った場合に、 どちらの正しいコードにより近いか、がわかりますので、 1ビット誤り訂正ができます。
コード間距離が4の場合は、 2ビット誤ったコードは正当なコードからどちらも距離2以上ですので、 2ビット誤り検出+1ビット誤り訂正が可能となります。

受信側で、誤りの検出だけ出来れば良くて、誤り訂正が不要な場合はどうでしょう? この場合は、コード間距離-1が、誤り検出できるビット数になります。 上記で議論してきた、1ビット誤り訂正コードも、 訂正ではなく誤り検出としてだけ用いるならば、2ビット誤り検出が可能です。 同様に、1ビット誤り訂正+2ビット誤り検出コードは、 訂正ではなく誤り検出としてだけ用いるならば、任意の3ビット誤り検出が可能です。

実際の例 - 430HX

では、実際の例を見てみます。 Pentiumプロセッサ用のチップセット 430HX は、 パリティ付きの72ピンSIMMを2枚使うと、 64ビット中1ビットの誤り訂正、2ビット誤り検出をすることができます。

64ビットですので、誤っていない状態を含めて65通り、 よって付加が7ビットあれば1ビット誤り訂正が可能であり、 さらにパリティを付けて、付加ビットが8ビットあれば、 1ビット誤り訂正、2ビット誤り検出ができます。 パリティ付きのSIMMは、36ビット構成であり、 2枚で72ビット=64ビット+8ビットとなり、丁度うまくいくことになります。

この誤り訂正回路を実際に設計してみましょう。 まず、2進数で1から71まで71ビット分の表を書きます。 次に、この中で単独ビットのものを付加ビットとして、上からP0、P1、P2、… P6 まで割り当てます。 最後に、空いた部分を、D0〜D63を割り当てます。 こうしてできた表はこちらになります。 この表から、メモリに書き込む時はP0〜P6及びP7を計算して書き込み、 読み出した時にもこの表から誤り位置を計算して訂正することができます。 430HXはこの表に相当する回路が入っているわけですね。

CRC16チェック

伝送路のチェック方式として有名なCRC16チェック、というものがあります。 このCRC16チェック、ハードウェアによる構成が簡単なため、 パケット転送における誤り検出においてほぼ標準的なものになっています。 詳しい回路や動作原理は省略しますが、 このCRC16、実は上の表を作っているのと等価です。 つまり、入力ビット列が430HXの例で言う所のデータ列であり、 CRC16はそれに掛け合わせる16ビットベクトルを順番に作って、 掛け合わせて、XORを取っていることになります。 このCRC16は、16ビット、つまり、65535通りの表を作るとひと廻りし、再び同じ表を作ります。 さらに、CRCには非常に重要な性質として、 連続する16個分のベクトルが常に直交しています。 つまり、任意の16ビット連続部分を、付加ビットとして使用できます。

これらの性質から、任意のビット列65519ビットに対してCRCを生成して、 CRC内容16ビットを出力すると、受信側では、1ビットの誤り訂正を行なうことができます。

さて、CRC16が上記の性質を持つためには、 CRC生成多項式が因数分解できない必要があるのですが、 実際には、X+1で割り切れてしまいます。 X+1というのは実はパリティそのものです。

というわけで、一般に広く用いられているCRC16チェックというのは、 1ビット誤り訂正+2ビット誤り検出のコードであり、 任意のビット列32751ビットに対してCRCを生成して、 CRC内容16ビットを出力すると、受信側では、1ビットの誤り訂正+2ビットの誤り検出が できるようになっています。 現実には誤り訂正に用いられることは少なく誤り検出としてのみ用いられますので、 32751ビット中任意の3ビット誤りを検出することができる、というわけです。

(96-12-22 ここまで)
(98-8-14 修正)

戻る