1年くらい前、当ブログに「USB2.0の転送速度に関する一考察」というのを書きました。その後、いろいろな考察を行い、USB2.0 HighSpeedの最高速度はどれくらいかということと、USB2.0をちょっとだけ高速化するためのアイデアを得ました。
その後ある会誌に寄稿したのですが、本情報は一般にも公開したほうが良いと思いましたので、今日はそれを少し手直ししてブログに載せます。
------------------------------------------------------------
●はじめに
USB2.0 HighSpeedモード(以下、USB2HSと略す)は非常に高速で手軽なインタフェースです。このインタフェースの速度は480Mbpsと謳われていますが、真の性能は、いったいどのくらいなのでしょうか?
おそらく街で販売されているUSB機器には「理論値480Mbps」などとあいまいな記載しかなく、実効速度についてはっきりとは書いていないでしょう。
本稿では、そんなUSB2.0の速度について考察してみることにします。
●USBの実効速度の測定
図1の構成の装置を作り、通信速度を測定してみました。

図1 USB速度測定のための実験環境
図2はIN方向(ターゲット→パソコン)のデータ転送を行う際の波形です。オシロのCH2はFPGAからUSBへデータを送る際のストローブ信号を、CH3はUSBのD-信号を見ています。D-信号は高速ディジタル信号なので正確に見えてはいませんが、通信が行われたタイミングを知ることはできます。

図2(a) データ転送時の波形

図2(b) データ転送時の波形
今回使用したUSB ICは内部のデータバッファがダブルバッファの構造になっています。USB ICからパソコンにデータが送信されて送信バッファに空きができると、FPGAから次のデータが送られます。大きなデータを連続して送るときには、IC内のバッファにはあらかじめ常に十分な量のデータを溜めておき、USBバスにデータが送信された後、IC内のバッファにFPGAからデータが補充するようにします。
図2(b)の波形を見ると、125μ秒ごとに似たような形が繰り返されているのがわかります。USB2.0ではマイクロフレームといって125μ秒ごとにタイムスロットが区切られています。今回構築した実験装置では、この125μ秒の間に11回のデータ転送が行われたと推測されます。
USBはデータをパケット単位で送受信しますが、1回のデータサイズは最大512バイトです。今回の実験環境では512バイトのデータパケットを125μ秒の間に11回転送できたため、速度は毎秒45Mバイト出たことになります。実際にはOSやデバイスドライバのオーバーヘッドが入るため、実効転送速度はこれより下がることになりますが、数Mバイトの大きなデータを一括で送れば近い値が出ます。
USBのデータパケットの前後には、トークンやハンドシェイクという制御用のパケットが送受信されます。トークンとデータとハンドシェイクを合わせてトランザクションとよびます。
結局のところ、USBの実効速度は、1マイクロフレームにどれだけの数のトランザクションを発行できるかということで決まります。もし、1マイクロフレームが9トランザクションならば、実効レートは512×8×9/125μ秒= 294Mbps。10なら327Mbps。11なら360Mbpsになります。

図3 トランザクション数と実効速度の関係
では、なぜ今回の実験ではトランザクションが11回なのでしょうか。
図2(a)によると、1回のトランザクションには10μ秒強の時間がかかっていることがわかります。
データサイズは512バイトなので、データだけならば8.53μ秒で送れるはずですが、実際にはトークンパケットや、ハンドシェイクパケット、パケット間の待ち時間(ギャップ)などがあるため多少余分に時間がかかってしまいます。また、今回の実験ではIN方向で転送しているので、トークンとハンドシェイクはパソコン側が送信し、データはUSB IC側が送信しています。送受信が交代するためどうしても空き時間が生じてしまいます。
図4 USBパケット間の詳細
こういった理由によってパケットごとに1.3μ秒ほどの追加の時間が生じてしまいます。そのため実際には1トランザクションあたり10μ秒強の時間がかかることになります。待ち時間はパソコンのCPUの処理速度にも影響されるので、速いパソコンのほうが当然速くなります。
さらに、マイクロフレームの先頭を示すSOFパケットから、最初のトランザクションが開始するまでの無駄なアイドル時間も無視できません。この時間は実測で約5~7μ秒ありました。
●送信するデータの種類によって速度が低下することがある
この実験装置にVGAのカメラをつないでUSBカメラを構成してみたところ、明るいシーンを撮影した時に転送レートが低下するという現象が発生しました。

写真1 USBカメラで撮影した通常のシーン

写真2 USBカメラで撮影した極度に明るいシーン
このUSBカメラは、通常のシーンの撮影時には約320Mbpsの速度でデータを転送できるのですが、極度に明るいシーンでは292Mbpsと、約10%も低下してしまいました。オシロで観察したところ、明るいシーンを撮影した際には、1マイクロフレーム間のトランザクション数が10個に減少していることがわかりました。減少した理由は、USBがNRZI符号を採用しているためだと考えられます。
図5 1マイクロフレーム間に10回のトランザクションしか行えていない
NRZI符号とは、図6のように、データ’0’を送りたいときには現在の信号線の状態を反転し、'1'を送りたいときには信号線の状態を反転しないという符号化方式です。

図6 NRZI符号のエンコードと、ビット挿入
NRZI符号では、‘1’が続くと信号が反転しない状態が続いてよくないため、6回続いたら強制的に‘0’が挿入されるようになっています。すると、本来のデータは後ろに1ビットシフトされので、フレーム長が1ビット伸びることになります。‘1’が連続で続くことが多いデータを送信した場合には、フレームが伸びてしまい、その結果トランザクションあたりの通信時間は長くなります。
明るく飽和した画像を送信した場合、NRZIの符号化によってデータ長が伸び、ひとつのマイクロフレームに詰め込むことができるトランザクションの数が減ってしまいます。このようにわずかな時間ロスの増加によって、送信できるトランザクション数の減少し、実効速度が低下するので注意が必要です。
●常に最大速度で通信するための工夫
‘1’が連続するデータを送ると遅くなるので、‘1’が連続しないようにデータにあらかじめスクランブルしてから送り、受信したパソコンでデスクランブルをかけて複合すればよいだろうと、思いつくでしょう。
スクランブルはFPGAで行いますが、デスクランブルはパソコンのCPUで行うので、できるだけ単純な仕組みが良いでしょう。ここでは明るいシーンを撮って飽和してしまった画素(0xFF)を送るのを回避したいので、図7のように送信するデータに0x55でXORしたものを送信するようにしてみました。
図7 通信路上でスクランブルをかけると、速度の低下を防ぐことができる
結果は非常に効果があったといえます。FFに飽和した画像を送信しても遅くなることはなくなりました。逆に、通常の画像を送信した場合にかえって通信が遅くなるということもありませんでした。
改良前はVGA画像1枚(320kバイト)あたり7.7ミリ秒、飽和した画像では8.4ミリ秒と送信時間にばらつきが生じていましたが、この工夫を行うことで、画像の内容に関係なく1枚あたり平均7.7ミリ秒でデータを送信することができるようになりました。
なお、画像1枚あたりのデスクランブルはCPUで処理しているため、0.2ミリ秒を追加で要するようになってしまいましたが、トータルではメリットが生じたといえるでしょう。
●まとめ
表1と、式1~2に、USB2.0の最大実効速度の計算方法を示します。

USB2.0 HighSpeedモードは、マイクロフレームの間隔にトランザクションを詰め込む仕組みになっているため、実効通信速度はホストやターゲットの処理速度によっても変化します。
最近のパソコン(デュアルコアクラス)ではN=10~11となるでしょう。NRZIの符号化によって送信するデータの中身によってはNが1程度減少することがありますが、スクランブルをかけることで回避できるのを確認しました。
理論上のNの最高値は13で、最大実効速度は425.984Mbps(53MBytes/s)です。
この速度は'1'を連続で送信すると達成できないでしょう。
N=13の最高速を目指すには、まず適度なスクランブルをかけてNRZIのビット挿入が起こらないようにしなければなりません。
また、USBターゲット側とホスト側のソフトウェアの処理を十分高速にして、ハンドシェイクや次のトークンを極力早く出し、パケット間のギャップを詰めれば、ぎりぎり達成できる可能性はあります。
スクランブルをかけた方が高速になるか否か、またどのようなスクランブル方式が適切かということは送信するデータの種類によって変わります。そのデータの特徴があらかじめわかっていれば、スクランブルの方式を動的に変更するというのも面白いでしょう。
このレポートが皆様のお役に立てば幸いです。
最近のコメント