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 の 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 コントローラ ) など のデバイス
パラレルポート経由で使える NAXJP や ianjtag といったソフトもありますが、 パラレルポート経由では、ノイズ対策や高速化が難しそうです。 USB なら、装置の近くまで USB ケーブルをのばせば良いので、 ノイズ対策上有利。しかも Ver 1.1 でも 12Mbps ですから、 普通に使う分には十分高速だ... ということで、USB インターフェイスを採用 しました。
マイクロコントローラ + USB チップのみでは、数 Mbps で JTAG/SPI を扱うのは無理がありそうです。結局ハードウェアサポートが必要になりそうだ。 ハードウェアを CPLD で組む前提だと、 FT245AM + XC9572XL-VQ64 がコスト的にも構造的にも もっとも有利に思えました。
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>---
また、2 種類のタイミングを撰択できるようにしています。
データ出力 XXXXXXXXXXXXXXX データ入力 ↑ 負論理 タイミング1 -------+ +-------+ | | +------+ 負論理 タイミング2 --------------+ + | | +------+ 正論理 タイミング1 +------+ | | -------+ +-------+ 正論理 タイミング2 +------+ | | --------------+ +------
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 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 づつ処理することも可能ですが、 そのような処理では、(たぶん)気が遠くなるほど遅いということになりそうです。