このページは、マルチギガビット・トランシーバ(MGT)を紹介する一連のページの 3 ページ目です。
注記:このページを、Xillyp2p の物理リンクを設定する一環として読んでいるなら、このページは関係ありません。この場合、すべてのエンコーディング機能をオフにする必要があります。Xillyp2p IP コア(IP core)が内部で全部を実装しており、アプリケーションデータのエンドツーエンドのストリームをユーザーに提供するからです。
はじめに
アプリケーションロジック(application logic)のデータストリームが、そのまま物理チャネル上で伝送されることはほぼありません。そのようにすると、おそらく MGT は誤動作します。その理由は前のページで示したとおりです。ほぼすべてのアプリケーションでは、物理チャネルが正しく動作するよう、MGT またはアプリケーションロジックがデータストリームにエンコーディングを施します。このエンコーディングは、送信側と受信側の同期も助けます。
ただし例外もあります。この完全なサンプルデザインでは、MGT はエンコーディングを一切有効にせず、単なる SERDES として使われています。これは、アプリケーションロジックがスクランブラ(scrambler)やその他の必要な機能を実装しているから可能です。
このページでは、最もよく使われるエンコーディング方式の基本を説明します。前のページのプロトコル一覧が、これらのエンコーディングと、FPGA 間で使われるプロトコルとの対応関係を示しています。
8b/10b エンコーディング
8b/10b エンコーディングは、いくつかのプロトコルで使われています。例えば、PCIe の一部のバージョン、Gigabit Ethernet、SATA、DisplayPort、SuperSpeed USB などです。このエンコーダはロジックファブリック(logic fabric)にも実装できますが、どの FPGA MGT にも 8b/10b エンコーダとデコーダが内蔵されています。
このエンコーディングは、各バイト(8 ビット)を 10 ビットのワードに変換します。この変換の主な目的は、'0' と '1' の数が平均的に等しいビット列を作ることです。言い換えると、エンコードされたデータストリームのビットは DC バランスが取れています。もう 1 つの利点は、データストリーム内に '0' と '1' の間の遷移が十分に確保されるため、CDR(Clock Data Recovery、クロックデータリカバリ)のメカニズムが正しく動作することです。
ただし、8b/10b エンコーディングはデータストリームをランダム化しません。特に、イコライザ(equalizer)を使い、そのイコライザがデータストリームの統計的なランダム性を要求する場合、8b/10b エンコーディングだけでは不十分です。
DC バランスという目標を達成するため、一部の 8 ビットワードは 2 通りの候補にエンコードできます。例えば、8 ビットワード 0x20(00100000、D0.1 と呼ばれる)は、1001111001 または 0110001001 のどちらかにエンコードできます。どちらの選択肢も 0x20 にデコードされます。最初の選択肢には '0' が 4 ビット、'1' が 6 ビット含まれることに注意してください。2 番目の選択肢には '0' が 6 ビット、'1' が 4 ビット含まれます。これが 8b/10b エンコーディングの基本的な考え方です。エンコーダには 2 つの選択肢があり、一方は '1' より '0' が多く、もう一方はその逆になっています。
エンコーダはこの機能を使って、長期的に '0' と '1' のバランスを保ちます。これまでにデータストリーム中で '0' が多すぎるか、'1' が多すぎるかを記憶しているのです。この不均衡はランニングディスパリティ(Running Disparity)と呼ばれます。エンコーダは、この不均衡を減らす方向の 10 ビットワードを選びます。
すべての 8 ビットワードに 2 つの 10 ビット候補があるわけではありません。例えば、8 ビットワード 0x23(00100011、D3.1 と呼ばれる)は常に 1100011001 にエンコードされます。このエンコード後のワードは '0' と '1' の数が同じなので、ランニングディスパリティには影響しません。
このエンコーディングは 1983 年に最初に発表され、およそ 2010 年までに登場したプロトコルで非常によく使われました。最近発表されたプロトコルではあまり使われていません。主な理由は、スクランブラもしばしばプロトコルの一部になっているためです。スクランブラを使えばデータストリームの DC バランスが保証されるので、この目的のために 8b/10b エンコーディングは不要です。また、スクランブラは '0' と '1' の間の遷移も十分な頻度で保証します。その一方で、8b/10b エンコーディングは物理チャネルに送信するビットを 25% 増やします。この余分なビットは、有用なデータの送信に使えたはずです。
とはいえ、スクランブラを使う成功したプロトコルの中にも、8b/10b も使うものがあります。例えば、PCIe の全バージョンはスクランブラの使用を要求していますが、8b/10b エンコーディングも PCIe 3.0 より前のバージョンで使われています。したがって、8b/10b エンコーディングには明らかに別の利点もあります。そして、ここから次のトピック、K シンボルに入ります。
K シンボル
8b/10b エンコーダがエンコードする 8 ビットごとに 10 ビットを生成するという事実は、エンコード後のワードが、元のワードの 256 通りに対して 1024 通りあることを意味します。仮にすべての元のワードに 2 通りのエンコード後ワードがあるとしても、512 通りしかカバーしません。前述のように、一部の 8 ビットワードには 10 ビットへの変換候補が 1 つしかないため、有効な 10 ビットワードは 512 通りよりも少なくなります。したがって、少なくとも 512 通りの 10 ビットワードには、対応する 8 ビットワードがないことになります。
したがって、8b/10b エンコーディングは、不正な 10 ビットワードを検出することで、物理リンク上のビット誤りを検出できます。FPGA MGT には、不正な 10 ビットワードを検出したときにアプリケーションロジックへ知らせるための出力ポートがあります。しかし、このエラー検出メカニズムはすべてのエラーを検出するわけではないため、あまり価値がありません。
8b/10b エンコーディングの本当に価値のある機能は、K シンボル(K-symbol)です。K シンボルは、8 ビットワードの代わりにエンコードされて送信されます。デコーダは通常のデータワードと K シンボルを区別でき、K シンボルが到着したときには常にそれをアプリケーションロジックへ知らせる方法があります。
つまり、8b/10b エンコーディングを使うと、通常のデータと混同されることなく、送信側がデータチャネル上で追加の情報を送ることができます。この機能は、受信側が送信側のデータストリームに同期するのを助けるために、プロトコルでよく使われます。
K シンボルの意味はプロトコルによって異なります。しかし、多くのプロトコルが同じ意味で使う K シンボルが 1 つあります。K28.5 です。K28.5 はしばしばコンマ(Comma、COM)と呼ばれ、データストリームの同期に使われます。詳細は後述します。
FPGA MGT で 8b/10b を有効にすると、アプリケーションロジックとのインターフェースには、データのバイトごとに専用の配線があります。この配線は、そのデータが通常のデータバイトであるか K シンボルであるかを示します。言い換えれば、データ送信用インターフェースでは、送信する各ワードを通常データとするか K シンボルとするかを選べます。ただし、データワードを K シンボルとしてマークする場合、8 ビットのデータワードとして使えるのは次の選択肢だけです。
| バイト値(16 進) | K シンボル |
|---|---|
| 1C | K28.0 |
| 3C | K28.1 |
| 5C | K28.2 |
| 7C | K28.3 |
| 9C | K28.4 |
| BC | K28.5 |
| DC | K28.6 |
| FC | K28.7 |
| F7 | K23.7 |
| FB | K27.7 |
| FD | K29.7 |
| FE | K30.7 |
MGT の受信側についても同様に、アプリケーションロジックとのインターフェースには、受信したバイトごとに専用の配線があります。この配線の値は、該当するバイトを通常データとして解釈すべきか、K シンボルとして解釈すべきかを示します。また、受信側には K28.5(コンマシンボル、Comma Symbol、COM)を特別に扱う機能もあります。この K シンボルについては次に説明します。
コンマシンボル(Comma Symbol、K28.5)
K28.5 を 10 ビットで表すと、0011111010 または 1100000101 になります。このワードが特に有用なのは、このビット列が K28.5 の送信によってのみ物理チャネルに現れるからです。受信側は K28.5 を検出するために送信側と同期している必要はありません。最後に受信した 10 ビットが、この 2 つのワードのどちらかに一致すれば十分です。
このため K28.5 は、受信側を同期させる優れたツールになります。この K シンボルがいったん検出されれば、他の 10 ビットワードの境界もわかります。
FPGA MGT には、K28.5 シンボルが到着したのに応じて、到着するデータストリームを自動的にアライメントする機能があります。通常は、より大きな境界に合わせてアライメントするよう要求することもできます。例えば、MGT は、到着した K28.5 を 32 ビットワードの先頭に合わせるよう設定できます。
受信側のアライメントのほかにも、K28.5 シンボルは、同期を必要とする他の機能ユニットをアライメントするためにも使えます。例えば、プロトコルが、この K シンボルの到着に応じてスクランブラをリセットするよう要求することもできます。
これらの可能性があるため、プロトコルは受信側を同期させる目的で、K28.5 を定期的に送信することを要求することがよくあります。ハンドシェイクで接続を確立するプロトコルも、リンク確立の一部として K28.5 を使うことがよくあります。いずれにせよ、K28.5 シンボルはプロトコルの設計を大幅に簡素化できるため、物理チャネル上で送信される 25% の余分なビットを正当化できます。
スキップシンボル(K28.0 と K28.1)
多くの実用的な状況では、送信側と受信側のクロック周波数の間に差があります。これは問題を引き起こす可能性があります。多くの場合、MGT とアプリケーションロジックのインターフェースは、受信側自身のローカルクロックに同期しています。つまり、データは送信側のクロックに従って到着しますが、アプリケーションロジックへは受信側のクロックに従って渡されます。
言い換えれば、MGT が受信するデータは、相手側によって決まるペースで到着します。しかし、データがどのくらいの速さで消費されるかはローカルクロックが決めます。
送信側のクロック周波数が高い場合、アプリケーションロジックが MGT からデータを取り出すのが遅すぎることになります。余分なデータはやがて蓄積され、MGT 内のどこかでオーバーフロー(overflow)が発生します。逆に、送信側のクロック周波数が低い場合、アプリケーションロジックはデータが到着するよりも速く取り出そうとします。これも問題です。
この問題に対する単純な解決策は、「スキップシンボル(skip symbol)」を追加することです。例えば、SuperSpeed USB プロトコルは、「SKP Ordered Set」を 2 つの連続する K28.1 シンボルとして定義しています。プロトコルは、この 2 つの K28.1 シンボルを、通常のデータワード 354 個ごとに 1 回送信することを要求します。受信側の MGT は、これらの K28.1 シンボルをアプリケーションロジックに渡さずに破棄することが許されています。これにより、送信側のクロックが受信側のクロックより速い場合の余分なデータ問題が解決します。受信側の MGT は、クロック周波数差のためにデータが蓄積し始めると、到着する K28.1 シンボルをスキップするのです。
このメカニズムにより、送信側が 356 個のワードを送信するのと同じ時間に、受信側のアプリケーションロジックが 354 個のワードしか取り出さない場合を吸収できます。356 / 354 ≈ 1.00565 という計算から、このメカニズムは 2 つのクロック間の周波数差を最大約 0.565% まで補償できることになります。もちろん、これはプロトコルの仕様が許す範囲を上回っています。
受信側の MGT は、既存の「SKP Ordered Set」に K28.1 シンボルを追加することも許されています。これは、送信側のクロックが遅い場合に役立ちます。つまり、受信側のアプリケーションロジックがデータを到着するより速く取り出そうとしていることを意味します。そこで MGT は、欠落したデータスロットを K28.1 シンボルで埋めてよいのです。アプリケーションロジックは、いずれにせよすべての K28.1 シンボルを無視することになっています。
PCIe プロトコルも同様の方法でスキップシンボルを使います。PCIe の SKP Ordered Set のフォーマットは異なり、4 つの K シンボルで構成されます。最初に K28.5(Comma)、その後に 3 つの K28.0 シンボルです。しかし、スキップシンボルを使う原理は同じです。
USB プロトコルも PCIe プロトコルも、オーダードセット(ordered set)に関連して SKP という省略形を使います。SuperSpeed USB プロトコルの中で出てくる SKP は K28.1 を意味しますが、PCIe では K28.0 を意味することに注意してください。ここには混乱の余地があります。
64b/66b エンコーディング
既に述べたように、8b/10b エンコーディングは物理チャネルの使い方が非効率的であり、このエンコーディングの主な目的(DC バランスと '0' と '1' の間の遷移の保証)は、スクランブラを使えば必要ありません。そのため、最近のプロトコルは 64b/66b エンコーディングや同様の方式に依存しています。ただし、64b/66b は厳密にはエンコーディング方式ではないことに注意が重要です。むしろ、データストリームと制御ワードを整理するための方法です。データが別の表現にエンコードされるわけではありません。起こるのは、データをセグメントに分割し、同期と制御情報の送信を可能にするために余分なビットを挿入することだけです。
K シンボルは 8b/10b エンコーディングにだけ存在し、他のどのコーディング方式にもないことに注意してください。
64b/66b エンコーディングは、いくつかのプロトコルで使われています。例えば、10G/100G Ethernet です。PCIe と USB の高度なバージョンは、後述するように他の方式に基づいていることは注目に値します。
64b/66b エンコーディングは、データストリームを 64 ビットのセグメントに分割し、各セグメントの先頭に 2 ビットを追加します。したがって、物理チャネル上では各セグメントは 66 ビットになります。追加される 2 ビットは、"01" または "10" の 2 通りの値のいずれかをとります。この 2 ビットが "01" の場合、後続の 64 ビットワードには 8 バイトのデータが含まれます。このビットが "10" の場合、次のバイトには、残りの 56 ビットが何を含むかを定義するコードが入ります。すなわち、データワードがいくつで、制御ワードがいくつかということです。
制御ワードは、特にフレーム(パケット)の開始と終了を示すために使われますが、クロック周波数の差を補償する目的でアイドルワードを挿入するためにも使われます(8b/10b のスキップシンボルと同様)。プロトコル固有の制御ワードも定義できます。
既に述べたように、最初の 2 ビットが "10" の場合、残りの 64 ビットは 2 つの部分に分けられます。すなわち、8 ビットのコードワードと、データと制御ワードの組み合わせからなる 56 ビットです。56 ビット部分の中でのデータワードと制御ワードの配置はかなり複雑です。主な理由は、各制御ワードが 7 ビット長であるためです。この変則的な構成は、残り 56 ビットに最大 8 個の制御ワードを挿入できるようにするために必要です。
さらに、このエンコーディングを使うプロトコルは、データの DC バランスとランダム性を確保するために、データに対してスクランブラも使います。このランダム性は、イコライザのためだけに必要なのではありません。受信側は、到着するデータストリームの中で 66 ビットのセグメントの先頭を見つけるためにもこれが必要です。これは、66 ビットの各セグメントの最初の 2 ビットを調べることで行われます。この 2 ビットが "01" または "10" だけを繰り返していれば、受信側は同期しています。そうでなければ、別の位置を試す必要があります。スクランブラは他のビットをランダムにするため、受信側のアライメントがずれていれば、正しい組み合わせの代わりに "00" または "11" がすぐに現れます。
総合すると、64b/66b は基盤となる物理チャネルをより有効に活用できますが、この方式を使うプロトコルは実装がより困難です。特に、各セグメントを(最初の 2 ビット、場合によっては後続の 8 ビットにも応じて)異なる方法で処理する必要があることが、実装を複雑にします。FPGA MGT によって、この点での支援のレベルは異なります。特に、一部の MGT には、到着するデータを 66 ビットのセグメントに自動的にアライメントするメカニズムが内蔵されています。しかし、データと制御ワードの組み合わせを含む 66 ビットのセグメントを展開するというより難しい作業は、依然としてアプリケーションロジックの責任です。
FPGA MGT には、66 ビットのセグメントのストリームから 64 ビットのワードを取り出すためのギアボックス(gearbox)が内蔵されていることがよくあります。ギアボックスについては、この一連のページの次のページでさらに説明します。
64b/67b、128b/130b、128b/132b
64b/66b は物理チャネルをより有効に活用できますが、この方式は実装が複雑です。PCIe と SuperSpeed USB の両プロトコルが、8b/10b から離れるときに別の道を選んだのは、おそらくこのためです。
これらのプロトコルはどちらも、データストリームをセグメントに分割するという考え方を維持しました。これらのプロトコルは、64 ビットのセグメントではなく、128 ビットに基づいています。
PCIe 3.0 以降は 128b/130b に基づいています。64b/66b エンコーディングと同様に、このプロトコルの各 128 ビットセグメントは、データコードと制御コードを区別するために "01" または "10" で始まります。SuperSpeed USB Gen 2 は 128b/132b に基づいています。その各 128 ビットセグメントは、同じ目的で "0011" または "1100" で始まります。唯一の違いは、USB プロトコルがビット誤りに対する保護を強化するために、2 ビットではなく 4 ビットを割り当てていることです。
また、64b/66b エンコーディングと同様に、各セグメントの 128 ビット部分には、DC バランスの確保とデータストリームのランダム化のためにスクランブラが使われます。しかし、64b/66b との類似点はここまでです。どちらのプロトコルも、128 ビット部分の内容の意味を、それぞれのプロトコル固有の構造に基づいて定義しています。したがって、128b/130b と 128b/132b は、データストリームをセグメントに分割し、データを含む部分にどれだけのビットを追加するかを表すにすぎません。残りは各プロトコル固有です。
64b/67b エンコーディングも同様の方法で動作します。違いは、同じ目的のために 64 ビットの各セグメントに 3 ビットが追加されることです。このエンコーディングは、主に Interlaken プロトコルで使われます。
エンコーディングなし
前述のエンコーディング方式を一切使わずに通信リンクを実装することも可能です。そのようなプロトコルの例が Xillyp2p です。Xillyp2p は、受信側を送信側にアライメントして同期させる目的で、223 ビットごとに同期ワードを使います。このプロトコルにとって MGT は単なる SERDES にすぎません。この戦略の主な利点は、プロトコルが MGT の他の機能にまったく依存しないことです。これにより、幅広い MGT 上でのプロトコル実装が簡単になります。もう 1 つの利点は、このサンプルデザインに示すように、MGT のインスタンシエーション(instantiation)がはるかに単純になることです。
欠点は、おそらく MGT 内部で処理できたはずのことを、FPGA のロジックリソースを使って行うことです。
この手法が適切なのは、プロトコルが、エンコーディングが助けになり得るすべてのニーズをカバーしている場合です。すなわち、DC バランス、ランダム化(必要な場合)、同期、ワードアライメント(word alignment)、そしてデータと制御情報の区別です。
まとめ
上記のように、アプリケーションロジックのデータストリームをエンコードする方法にはさまざまな選択肢があり、エンコーディングをまったく使わないことも可能です。ほとんどのアプリケーションでは、8b/10b エンコーディングが最も扱いやすいのですが、物理チャネルのデータストリームの観点からは無駄が多い方式です。そのため、最近のプロトコルでは、より効率的だがかなり扱いにくい他のエンコーディング方式が採用されています。
以上で、MGT に関するこの一連のページの 3 ページ目を終わります。次のページでは、PCS の一部、特にここで述べたエンコーディングを実装する部分を紹介します。