IEEE1284をFPGAで実現しよう

平成15年1月2日

 IEEE1284は、プリンタポートを使ってホスト(PC)とペリフェラル(周辺機器)でデータをやりとりするための規格です。

 IEEE1284ではプラグアンドプレイ(PnP)に対応した周辺装置を作成することができます。しかも、マニュファクチャコードやベンダーコードの取得が不要であり、誰でも無料でPnPデバイスを堂々と作ることができます。

 IEEE1284を実現するためには、次の機能を実装する必要があります。

  1. オートネゴーシエーション
  2. ニブルモード
  3. 互換モード

 上記の機能が実現できれば、Windowsは周辺機器をIEEE1284対応機器として認識します。

 このWebページは急いで書いたので、ところどころ不親切だったり、変な個所がありますが、VHDLのバージョンアップとともに文章も更新していきますので、ご了承ください。
前のページに戻る

目次

  1. なぜ、いまさらプリンタポートなのか?
  2. 開発するIPの概要
  3. IPのダウンロード
  4. IPの使い方
  5. ECPモードの読みこみ実験結果
  6. 各モードの速度比較
  7. ソフトウェア
  8. デバイスIDについて
  9. これだけは知っておきたい、IEEE1284のモード
  10. これだけは知っておきたい、IEEE1284の信号
  11. 波形的な注意点


なぜ、いまさらプリンタポートなのか?

 高度なFPGAが手軽に使える時代になりました。アマチュアレベルでも、FPGAにデジタル信号処理や画像処理ができる時代になりました。でも、FPGAとPCとのインタフェースは依然として壁が残っています。

 私たちが趣味でマイコンやFPGAを使っていろいろ実験するときに、インタフェースにはRS-232Cやプリンタポート、USBなどの選択肢があります。

ポートの種類 速度 長所 短所
プリンタポート 0.1〜16Mbps プロトコルが任意。外付け部品が少ない。 NT系のOSでは簡単に使えない。
RS-232C 〜115kbps ほとんどのPCで使える 電圧レベルの変換。遅い。
USB1.0 12Mbps,480Mbps 速い。現在のトレンド。 専用チップが必要。ベンダーID取得。

 中でも、プリンタポートは外付け部品も少なく、電圧の変換が不要なので手軽にインタフェースできます。なんと言っても、高価なインタフェースチップが不要で、簡単なロジック回路やマイコンがあれば、誰でも自由にインタフェースを自作できます。
 自作の装置では、プリンタポートの信号線の本来の役割を無視して、独自の規格のパラレルIOポートとして使えば、プロトコルも自分で勝手に決めることができます。

 しかしその反面、遅い、NT系OSで手軽に使えない、信頼性が低いなどの欠点もあります。

 そこでプリンタポートをIEEE規格に準拠させようと思っても、ニブルモードやバイトモードなどのレガシー(旧式)の解説はいくつか見つかりますが、ECPモードやEPPモードなどの高度なものを作ろうとしても資料が無く、実現するのはUSBやRS232Cより難しいでしょう。
 プリンタポートを使って、高速で高機能なインタフェースを手軽に作りたいけど、資料が無くてわからない。そんな労力を低減するのが本企画の目的です。

 この企画では、モルフィー企画様のVirtex300Eボードを使って、IEEE1284に対応した装置を開発することを目的とします。開発に使っている装置を右の写真に載せます。写真のようにVirtex300Eボードを、SRAMと高速ADコンバータのついた万能基板に載せます。

SRAM:HM62W16255HJLP-12(256kword*16bit 12ns)
DAC:TDA8702(ビデオ用8bitDAC)

開発するIPの概要

 今回開発するIPの概要を、右の図に示します。 

 本IPは、IEEE1284機能を実現するコアの部分と、VirtexEのブロックRAMなどを使用する周辺部分から構成されています。

 コアの部分は、使いまわしが効くようにソースを分けてあります。


IPのダウンロード

 使用にあたっては、次の点に注意してください。

  1. このIPは未完成であり、十分に検証されていません。
  2. 現バージョンの商用利用はお断りいたします。商用利用については別途ご相談承ります。
  3. 機能の拡充にともない、予告無く更新します。
  4. 著作権は「なひたふ ナヒテック」が所有します。

 現在、実現されている機能は次のとおりです。

  1. オートネゴーシエーション機能
  2. ニブルモード
  3. 互換モード
  4. バイトモード
  5. ECPモード(読みこみのみ。)

 現在、次の機能がまだ実現されていません。

  1. EPPモード
  2. ECPモードの書きこみ
  3. ECPモードの周辺機器側FIFO
  4. RLE付きECPモード
  5. 拡張リンク

 上記の項目に同意いただければ、次のリンクをクリックしてダウンロードしてください。

●IEEE1284コアのダウンロード(IEEE1284main-ver01.vhd)


IPの使い方

IEEE1284コアの解説

 IEEE1284main.vhdの入出力ピンを説明します。

種別 ピン名 入出力 機能
@クロック等 CLK in クロック入力(25MHzを期待)
RESET in リセット入力(実際には未使用)
Aユーザ側 DataAvail in 周辺装置→PCへ送信すべきデータが用意できて、送信可能状態であることを示すフラグ
DataReq out PCから読み出し用にデータを要求されたことを示す、1クロック長のパルス
DataReceived out PCからデータが書きこまれたことを示す、1クロック長のパルス
DataWr in ユーザのデータが用意できて、PCに送信するための、1クロック長のパルス
Busy in 周辺装置がビジー状態であることを示す
Data_IN[7:0] in PCに送信するデータ
Data_OUT[7:0] out PCから受信したデータ
BIEEE1284側 IEEE1284_DIN[7:0] in IEEE1284ポートからのデータ入力
IEEE1284_DOUT[7:0] out IEEE1284ポートへのデータ出力
IEEE1284_nERROR out IEEE1284ポートのnError信号
IEEE1284_Select out IEEE1284ポートのSelect信号
IEEE1284_PaperEnd out IEEE1284ポートのPaperEnd信号
IEEE1284_nAck out IEEE1284ポートのnAck信号
IEEE1284_Busy out IEEE1284ポートのBusy信号
IEEE1284_nStrobe in IEEE1284ポートのnStrobe信号
IEEE1284_nAutoLF in IEEE1284ポートのnAutoLF信号
IEEE1284_nInit in IEEE1284ポートのnInit信号
IEEE1284_nSelectIn in IEEE1284ポートのnSelectIn信号
CIEEE1284の状態を示す Mode_Compatible out 互換モード
Mode_Byte out バイトモード
Mode_Nibble out ニブルモード
Mode_EPP out EPPモード
Mode_ECP out ECPモード
Mode_AutoNego out ネゴーシエーションモード
ODBuf_En out IEEE1284のデータバスをリバース(周辺装置→PC方向)にする。
Debug_Out[7:0] out デバッグ用

 これらの信号線をどのように使えばよいか、少し詳しく解説します。

@クロック等

 クロックとリセット信号です。

Aユーザ側信号

 ユーザロジックから、IEEE1284へデータを送受信するのに必要な信号です。

 ■データを受信(PC→周辺装置)する場合

 PCからデータを受信すると、Data_OUT[7:0]にそのデータを載せ、DataReceivedに1クロック長の信号を出します。

 ■データを送信(周辺装置→PC)する場合

 周辺装置がビジー状態の時にはBusy信号をHighにします。Busy信号はIEEE1284のハンドシェイク等には無関係です。それを受信したPCがどのように処理するかを任されています。

 PCへ送信したいデータが用意できたときには、DataAvailをHighにします。この信号がLowになると、IEEE1284のハンドシェイクにWaitをかけます。

 PCから送信要求がされると、DataReqに1クロック長の信号が出ますので、Data_IN[7:0]に送信したデータを載せ、DataWrに1クロック長の信号を入れてください。DataReqからDataWrまでは即答する必要はありませんが、あまり長いとPCがタイムアウトするので、数ミリ秒以内には返すようにしましょう。

BIEEE1284側信号

 IEEE1284の対応するピンに接続します。ただし、入力信号には必ず1段以上のD-FFを入れてください。

CIEEE1284の状態を示す信号

 ネゴーシエーションの結果、現在どのモードであるかを示します。ODBuf_ENは、データバスを双方向にするための、出力イネーブル信号です。


ECPモードの読みこみ実験結果

データ読みこみ時の波形

 次の写真は、ECPモードでデバイスIDを読み出した時の波形です。CH1がnAck信号で、CH2がnSelect信号です。

 CH1のnAck信号はデータのストローブに使われる信号で、その立下りエッジで、PCはデータを読み込みます。

 CH2のnSelect信号は周辺装置が送りたいデータがあることを示す信号で、Lowレベルのとき、送信したいデータがあることを示します。つまり、この信号が立ちあがると、送信完了を意味します。

 

 この写真を見ると、最初の20μ秒はnACKが詰まっていて、後は閑散としています。その理由はFIFOです。

FIFOフィル時の波形

 ECPモードで読みこむ最初の20μ秒を拡大した波形を次の写真に載せます。

 ECPモードでは、PCのIOチップは、FIFOを使います。周辺装置からFIFOへの読みこみはハードウェアが自動で行います。そのため、約1μ秒に1回データを読み込んでおり、この状態ではとても高速です。

FIFOフル時の波形

 FIFOがフルになると、PC側のECPのハードウェアは自動読みこみを一時停止します。つまり、ウェイト状態です。

 この状態で、ソフトウェアがFIFOからデータを取り出してやると、FIFOに1バイトの空きができるので、自動的にIEEE1284へデータを要求します。ソフトウェアは、FIFOのステータスを見ることと、FIFOからデータを取り出すことで、2回inp命令を実行します。

 私のPCでは1回のアクセスに約1.5μ秒を要します。これは、Windowsのデバイスドライバを作ったわけではなく、単純なinp命令を使っているため実際の読みこみ動作よりかなり遅いです。ちゃんとデバイスドライバを組めば、もっと速くなるでしょう。

FIFOの容量

 最初の写真から判断すると、私の使っているマザーボードでは、FIFOへの高速読みこみは21回行われています。おそらくFIFOの深さが16バイトです。

 PC側のハードウェアが、16バイトをFIFOに読みこむ時間は約16μ秒ですが、この間にもソフトウェアはFIFOから読み出しを行っています。ソフトウェアがFIFOから5バイト読み出す時間は、およそ3.1×5=15μですから、16バイト読みこんだ後には、FIFOのおよそ5バイト分の余裕が空いているはずです。したがって、FIFOがフルになるまでには、あと5バイト読みこめます。

 それゆえ、21バイト分が高速に読み出されたのでしょう。

 とにかく、ECPモードでは、FIFOが満杯か否かで読み出し速度に差が生じるようです。


各モードの速度比較

 各モードがデータを如何に速く読み出せるかを競います。

1バイトの読みこみ速度

モード IOポートへのアクセス回数 1バイトの転送時間 転送速度
ECPモード(FIFO非満杯時) 2回 0.91μ秒 1.087MByte/s
ECPモード(FIFO非満杯時) 2回 3.2μ秒 0.312MByte/s
ニブルモード 12回 22μ秒 0.045MByte/s
バイトモード 12回 21μ秒 0.047MByte/s

 私の実験環境(Celeron366MHz自作PC)では、Windows98上でinp、outp命令を使うことによるIOポートへのアクセスには1回あたり1.6μ秒要することがわかっています。ニブルモードとバイトモードの場合、12回のIOアクセスでは19μ秒要しますが、その他にもWindowsのメッセージ処理などが2〜3μ秒加わっているため、上記の結果になったものと思われます。

 1回のアクセスに12回というのはいささか多い気がしますが、これはハンドシェイクを厳密に行う上の問題で、プログラミングで頑張れば回数は、もっと減らせるはずです。

82バイトの読みこみに要する時間

 オシロスコープを用いて、デバイスIDを読み出すのに必要な時間を計測しました。

モード 時間 平均転送速度
ECPモード 0.22ms 372kByte/s
ニブルモード 1.82ms 45kByte/s
バイトモード 1.74ms 47kByte/s

 思ったほどECPモードが速くないのは、FIFOが16バイトしかないため、すぐに埋まってしまうからです。また、FIFOからの読み出しにデバイスドライバを作成したわけではなく、inp命令を使用しているため、Windows98のVxDの処理などに要する時間と考えられます。

 デバイスドライバを作成すれば、もっと速くなるはずです。


ソフトウェア

 IEEE1284の実験を行うため、次の図のようなソフトウェアを開発しています。近日公開します。

 


デバイスIDについて

 デバイスIDを設定すると、Windowsの起動時にPnPで認識させることができます。どうやら、Windowsの起動時にネゴーシエーションを行って、ニブルモードでID要求するようです。
 デバイスIDは、可変長のASCII文字列です。最初の2バイトは、文字列の長さを示します。

 その後、キーと値を「:」(コロン)で組み合わせ、「;」(セミコロン)で区切ります。

例) [0x00][0x4a]MFG:Nahitafu;MDL:VIRTEX300E;CLS:Dot4;DES:Nahitafu IEEE1284 FPGA;

 次に、各キー名と意味を簡単に説明します。

キー名(省略形) 内容 サンプル
MFG 周辺機器のメーカを表す Nahitafu
CMD プリンタの対応言語を表す ESCPL2,BDC,D4
MDL 機種名を表す省略名称 VIRTEX300E
CLS デバイスのクラスを表す Dot4 ※後述
DES 詳しい解説(PnP時に表示される) Nahitafu IEEE1284 FPGA

 Windowsのバージョンにもよるのでしょうが、デバイスのクラスはWindows DDKで規定されています。その中から、パラレルポートにつなぐ周辺装置として、意味がありそうなものをいくつか紹介します。

デバイスクラス CLS 対象デバイス
CD-ROM CDROM CD-ROM
ディスクドライブ DiskDrive ハードディスク
フロッピーディスクコントローラ FDC フロッピーディスクコントローラ
フロッピーディスクドライブ FloppyDisk フロッピーディスクドライブ
ハードディスクコントローラ HDC ATA/ATAPIを含むが、SCSIやRAIDは含まない
ヒューマンインターフェースデバイス HIDClass キーボードやマウスなど
IEEE1284.4デバイス Dot4 IEEE1284.4に対応したマルチファンクションデバイス
IEEE1284.4プリンタ Dot4Print IEEE1284.4に対応したプリンタ
イメージングデバイス Image デジカメやスキャナなど
IrDAデバイス Infrared IrDAデバイス
キーボード Keyboard キーボード
メモリテクノロジドライバ MTD フラッシュメモリカードなど
モデム Modem モデム
マウス Mouse マウス、トラックボールなど
マルチファンクションデバイス Multifunction 複合デバイス。特に通信関係を意味するらしい。
マルチメディア Media オーディオデバイスやDVD、ジョイスティック、ビデオキャプチャなど
ネットワークアダプタ Net 高速赤外線以外のNDIS NICデバイス
プリンタ Printers プリンタ
プロセッサ Processor プロセッサ
SCSI、RAIDコントローラ SCSIAdapter SCSI、RAIDコントローラ
スマートカードリーダ SmartCardReader スマートカードリーダ
テープデバイス TapeDrive テープデバイス

※IEEE1284.4とは、複数のデバイスをパラレルポートにつなぐ技術です。USBでは127台までつなげることができますが、そのIEEE1284ポート版です。

 上記のデバイス以外にも、たくさんのデバイスクラスがWindowsで規定されています。しかし、IEEE1284ポート越しに、認識されるかは不明です。特に、マイナーなデバイスほど結果は不明です。

 デバイスドライバを作って、INFファイルを記述すればPnPインストールができるかと思います。


これだけは知っておきたい、IEEE1284のモード

 IEEE1284には、互換モード、バイトモード、ニブルモード、ECPモード、EPPモードの5つのモードがあります。その機能はいろいろと差があります。中でもEPPとECPは高度なモードで、書きこみ(PC→周辺装置)と読みこみ(周辺装置→PC)の両方ができます。また、ECPとEPPはハンドシェイクをハードウェアで行い、高速です。

  読み 書き ハンドシェイク 速度 特徴
互換モード × ソフトウェア 低速  
バイトモード × ソフトウェア 低速 データバスを入力用に切りかえる
ニブルモード × ソフトウェア 低速 ステータス用の4本の信号線を使って、1バイトを2回に分けて読み込む。
EPPモード ハードウェア 高速 同期式
ECPモード ハードウェア 高速 FIFO、ランレングス圧縮、内部モード

これだけは知っておきたい、IEEE1284の信号

 IEEE1284の信号はとても気まぐれです。モードによって信号の機能も名前も変わるからです。しかし、名前や機能は変わっても、信号の持つ機能の本質はあまり変わりません。

ハンドシェイクに使われる信号

 プリンタポートを単純なIOとして使った場合、PCが送ったデータを周辺装置が正しく受け取ったかどうかなどをハンドシェイクして確認することは滅多にありませんでした。いわゆる送りっぱなしの状態でした。

 IEEE1284では、どのモードであれ、ハンドシェイクを行うことになっています。PC→周辺装置へのハンドシェイクはnStrobeかnAutoLFをストローブ信号として使います。(モードによっては、名前がHostClkやHostBusyだったりしますが、機能と目的は一緒です)
 周辺装置→PCへデータを送る際のハンドシェイクは、ほとんどの場合、nAckを使います。

 ハンドシェイクの信号は基本的には負論理ですが、例外もあります。

周辺装置から送りたいデータがあることを示す信号

 nDataAvailは、周辺装置からPCへ送りたいデータが存在することを示す信号です。ECPモードではこの信号はnPeriphReqという名前ですが、機能は一緒です。Lowの時に、周辺装置からPCへ送りたいデータが存在します。

モード変更に関わる信号

 周辺装置がバイトモード、ニブルモード、ECP、EPPモードの時に1284ActiveがLowレベルになると、互換モードへ戻ります。ネゴーシエーション中にLowレベルになると、ネゴーシエーションを強制終了し、互換モードへ戻るでしょう。

 このように、1284Activeは、IEEE1284のモードを終了させる機能を持ちます。

XFlag

 Select信号は、IEEE1284のモードではXFlagとなります。これは、周辺装置が、要求されたモードに対応しているか否かを示す信号です。

その他の信号

 Busy信号の意味は、周辺装置からPCへ、ビジー状態であることを伝えるフラグです。

 nInit信号の意味は、PCが周辺装置に初期化を要求する信号です。

 BusyとnInitは、多くのモードでは、IEEE1284の機能に影響を与えません。ユーザが任意に使用しても問題はなさそうです。

 しかし、ECPではnInitをデータバスの方向切り替えに利用していますので、注意が必要です。また、Busy信号を本来のビジーフラグと時分割で各種制御線として使うこともあります(ニブルとECP)。


波形的な注意点

 プリンタポートから出る信号は、とてもいいかげんな信号です。昔は、オープンコレクタにプルアップ抵抗が基本でした。このため、波形品質はとても低いのが実情です。

 昔のように、プリンタポートの信号をマイコンのIOポートで受ける場合には、応答速度がそれほど速くないから問題にはなりませんでしたが、数十MHzで動くようなハードウェアロジックで受けると、波形の汚さを痛感します。

 STBなどの信号は、出力がオープンコレクタなので、立下りは鋭い波形ですが、立ちあがりはプルアップ抵抗のお世話になっているので、緩慢な立ちあがりになります。そのため、信号がスレッショルド近傍で何回もHとLを往復し、チャタリングのような波形になることもあります。

 それでも数MHzという遅いクロックで、パラレルポートのインタフェースをしていた頃は問題になりませんでした。

 本VHDLソースでは、このような現象に対して耐性を持たせております。0.5μ秒以内であれば、信号がばたついても大丈夫です。


戻る
Copyright(c)1998-2003 Nahitafu All rights reserved