USB_SIO

FTDI の FT245AM というチップと Xilinx の XC9572XL-VQ64 と いう CPLD で 作る シリアル I/O 装置の紹介です。

FT245AM というチップは、USB インターフェイス を 双方向の 8bit データ通信 に変換するチップで、OS からは シリアルに見える ドライバを通してアクセスします。

XC9572XL-VQ64 という CPLD で、この 双方向の 8bit データ通信を、 さらに、JTAG や SPI といったシリアル I/O に変換します。

2チャネルのシリアル I/O をもっていて、それぞれのチャネルについて


      DI -- シリアルデータ入力
      CK -- クロック出力
      DO -- シリアルデータ出力
      MS -- 出力ポート

を持っています。


なぜ JTAG,SPI なのか

この装置を作った最大の目的は、高速に JTAG の I/O をしたいということ。 XC9500,XC9500XL シリーズのような CPLD を config をしたり、 スパルタンII のような FPGA を config するだけでなく、 FPGA や CPLD 以外の装置の バウンダリスキャンをしたりすることまでしたい と考えました。特に最近の PDA などは、ROM ではなく、Flash ROM を載せている ことが多く、さらにFlash ROM の書き換えは、バウンダリスキャンで書き込む ようになってきているようです。

Flash ROM の書き換えまでできるかどうかわかりませんが、 それができるモノを作ってみたいというのが ひとつの動機になっています。

JTAG で、CPLD や FPGA を config する なら config したデバイス と HOST との通信経路もあった方が嬉しいだろうということから SPI インターフェイスを ついでに付けるのが良いだろうという発想になりました。

SPI を扱えるデバイスもたくさんあります。そういうものを 実験的に扱ってみる ... ということにも利用できそうです。

SPI を扱えるデバイスの例
         * MMC -- Multi Mediea Card
         * AVR マイコン の プログラミング
         * シリアル EEPROM 93C46 など
         * USBN 9603/4 ( USB コントローラ ) など のデバイス 

なぜ USB なのか

パラレルポート経由で使える NAXJP や ianjtag といったソフトもありますが、 パラレルポート経由では、ノイズ対策や高速化が難しそうです。 USB なら、装置の近くまで USB ケーブルをのばせば良いので、 ノイズ対策上有利。しかも Ver 1.1 でも 12Mbps ですから、 普通に使う分には十分高速だ... ということで、USB インターフェイスを採用 しました。

なぜ、FT245AM と XC9572XL-VQ64 の組み合わせなのか

マイクロコントローラ + USB チップのみでは、数 Mbps で JTAG/SPI を扱うのは無理がありそうです。結局ハードウェアサポートが必要になりそうだ。 ハードウェアを CPLD で組む前提だと、 FT245AM + XC9572XL-VQ64 がコスト的にも構造的にも もっとも有利に思えました。


シリアル I/O インターフェイス

写真で、10 pin のピンヘッダが見えますが、右から
         1    2    3    4    5    6    7    8    9    10

シルク   NC   DI   CK   DO   SEL  TDI  TCK  TDO  TMS  GND
VHDL          DI1  CK1  DO1  MS1   DI2  CK2  DO2  MS2 GND  

という風に名前を付けています。XX1 と XX2 は、XX という機能の チャネル番号の意味。以下では、DI,CK,DO,MS の 機能の説明をします。 概要 次のように、CK の ↓↑ とともに 1bit の データを 1 ビット出力し、 CK ↑ で 1bit の データを 取り込むのが基本のシーケンスで、 1 回の操作で、1 - 1016 bit までの bit stream を 出力し、入力できます。

      DO           <    DATA    >

      CK           |______|~~~~~~

      DI                  o
データは、MSB から出力して、MSB から取りこんでいきます。
       DO    ----< O7 >< O6 >< O5 >< O4 >< O3 >< O2 >< O1 >< O0 >---

       CK    ~~~~|__|~~|__|~~|__|~~|__|~~|__|~~|__|~~|__|~~|__|~~~~~

       DI     ----< I7>-< I6>-< I5>-< I4>-< I3>-< I2>-< I1>-< I0>---    

入力データはシフトしているので、最後のバイトのデータが 8 bit に満たない場合 ...たとえば 3 bit の場合は次のように取りこみ、 読みこみデータは 上 5 bit は、出力データを 3 bit シフトした内容 になります。
       DO    ----< O7 >< O6 >< O5 >---

       CK    ~~~~|__|~~|__|~~|__|~~~~~~~   →   | O4 - O0 | I2 - O0 |

       DI     ----< I2>-< I1>-< I0>---    

各機能の捕捉


使い方

内部レジスタ

        7    6    5    4    3    2    1    0
      +---+----------+----+----+----+----+----+
      |   | CLK MODE |CKT |CK2 |CK1 |MS2 |MS1 |
      +---+----------+----+----+----+----+----+

     CLK MODE 0: 1/1 : 6 MHz
              1: 1/2 : 3 MHz
              2:  X
              3:  X

     CKT --- ck1,ck2 timining
              0: slow timing
              1: fast timing

プロトコル

次のように CMD , BYTES, N バイトのデータ を受け取り DO に送信します。 HOST への送信は、CMD, BYTES の エコーバックの後 DI から受け取った N バイトのデータになります。 した後、N 個の受信
       CMD    BYTES              DATA
     +------+-------+------+------+     +------+
     |      |   N   |  1   |  2   |  ...|  N   |
     +------+-------+------+------+     +------+ 

     (BYTES の値の範囲 1 - 127)

     CMD フォーマット

       bit 7   0 
       bit 6   未使用
       bit 5   未使用
       bit 4-3 チャネル
                  0 -> チャネル1
                  1 -> チャネル2
                  2 -> 内部レジスタ
       bit 2-0  N 個目のデータの 有効 bit 数
 

上のような、ひとかたまりのデータを HOST からは シリアル の回線として write し、同じ バイト数を read することになります。

値を連続的に更新したい場合は、送りたいだけの データを write し、 後で、read すれば 良いはずです。OS や FTDI のチップで バッファリングしてくれる量までは、読む必要が出るまで送りつづけられます。 Linux でしか試していませんが、少なくとも 数 KB は バッファリングされる ようです。

データを読んでから、どのように処理するか決めるような場合は、 (たぶん ms オーダの)ディレイがかかります。PC のパラレルポートのように 1 bit づつ処理することも可能ですが、 そのような処理では、(たぶん)気が遠くなるほど遅いということになりそうです。

ModelSYM での タイミング


VHDL ソースコード

メモ

関連 URL


Mail

suz@at.sakura.ne.jp