FT245BMの話 内部構造 信号線 受信タイミング 送信タイミング FIFOの弊害
ステートマシンの話 作成する構造 データ受信時の動作 データ送信時の動作 インタフェースステートマシンを作る 上位モジュールと処理系を作る
戻る FT245BMとUSB内蔵マイコンの比較

はじめに

 NP1003にはFTDI社のFT245BMというUSBチップが使用されています。ここでは、NP1003のメインインタフェースであるUSBを、FPGAから使う方法を説明します。
 このページで解説しているUSBのインタフェースを、下記のリンクからダウンロードすることができます。なお、このコードはSpartanIIのリソースを30スライス(XC2S30の僅か3%)を消費します。

FT245BMとのインタフェース

FT245BMの内部構造

 USBチップのFT245BMは、次の図のようにFIFOを持った構造です。USBから受信したデータ、あるいはUSBへ送信したいデータはすべてFIFOを通過します。


 FPGAからFT245BMに送られたデータは、まず送信FIFOに入ります。その後、USBのスケジューリングに従って自動で送信されます。もし、FT245BMの送信FIFOが満杯なら、次のデータは送信できないので、FT245BMからFPGAに待ったがかかることになります。
 逆に、PC側からデータが送られてくると、FT245BMは受信FIFOにそれを入れます。受信FIFOにデータが溜まっている状態では、FPGAはデータを取り出して処理することができます。受信FIFOが満杯にならないように、FPGAは適宜データを取り出して処理します。
 このように、FPGAはUSBの状態を直接知る必要はなく、送信FIFOが満杯か、あるいは受信FIFOにデータがあるか否かを見て、動作を行います。

信号線

 FT245BMとFPGAは、下記の4本の信号線でハンドシェイクします。

信号名方向極性備考
WRFPGA→USBL→Hの遷移で書き込み要求 
RDFPGA→USBH→Lの遷移で読み込み要求 
RXFFPGA→USBLなら受信バッファが満杯 
TXEFPGA→USBHなら送信バッファが空 

受信タイミング

 これらの信号線でどのようにしてデータを受信するかを解説します。

  1. FT245BMがデータを受信すると、FT245はRXF信号を0にします。
  2. このRXFの遷移をトリガーとして、FPGAはRD信号を0にします。
  3. すると、FT245はデータバス上にデータを出力するので、FPGAはそれを取得します。
  4. FPGAがRD信号を1に戻すと、データバスはハイインピーダンスに戻ります。


タイミング条件意味
T1RDのパルスの幅は50ns以上でなければならない。
T2RDがアクティブでない幅は50ns以上でなければならない。
T3RDをLに遷移させてから30ns以上した後、有効なデータが出力される。
T4RDをHに戻してから、10ns以上経過した後のデータは無効である。
T5RDをHに戻してから、5〜25nsでRXFは戻る。
T6連続してデータを受信する場合、次のRXFは80ns以降にアクティブになる。

 タイミング条件は、最小値が規定されているものと、最大値が規定されているものがあります。
 一般に、最小値が規定されているものは、FPGAなどのユーザ回路が出力する信号が守るべきタイミング条件です。
 最大値が規定されているものは、チップメーカが保証する動作速度です。「〜ns以内に必ず信号を出します」という意味なので、FPGAなどのユーザ回路は、その時間が経過した後に信号をキャプチャするなどの動作を行います。

 これらのタイミング条件も踏まえて、次のような考え方でFPGAの回路を設計します。

  1. RXFがLに遷移したのをトリガーとして、RDをLにする。
  2. RDのパルスの幅は50ns以上にする。(条件T1より)
  3. RDをLに遷移させてから、30ns以上経過した後、データを取得する。(条件T3より)
  4. RDをHに戻した後のデータは取得しない。(条件T4より)
  5. RDをHに戻した後、25ns以上経過してからRXFの遷移を見るべき(条件T5)だが、RDのHの幅は50ns以上なので、次のサンプリングは50ns以上経過後とする。(条件T2)

 ところで、もしFPGAがRD信号を遷移させない(つまり、受信データを取り出さない)まま、次のデータを受信した場合でも、そのデータはFT245内のバッファ(FIFO)に溜まりますので、失われることはありません。もちろんFIFOが満杯になった場合はデータ受け入れができませんので、USBにデータを送ろうとしているPCのプログラムにWAITがかかることになります。

送信タイミング

 FPGAからUSBへデータを送信する方法を解説します。

  1. FPGAは、TXE#(FT245BMが出力)がLであることを確認します。
  2. FPGAはWR信号をHにします。
  3. FPGAはデータバス上にデータを出力し、WRをH→Lへ遷移させます。
  4. FPGAは、TXE#(FT245BMが出力)がL→H→Lへ遷移するのを確認します。


タイミング条件意味
T7WRのパルスの幅は50ns以上でなければならない。
T8WRがアクティブでない幅は50ns以上でなければならない。
T9WRをH→Lに遷移させる20ns前には、データは確定していなければならない。
T10WRをLに戻してから、10ns以上経過しないと、データを変化させてはいけない。
T11WRをHに戻してから、5〜25nsでTXE#はHになる。
T12連続してデータを送信する場合、次のTXE#は80ns以降にアクティブになる。

 タイミング条件も踏まえ、次のような考え方でFPGAの回路を設計します。ただし、これから設計する回路はあくまでもユーザ回路とFT245BMとの橋渡しをする回路です。実際のデータは、この回路の背後にあるユーザ回路から与えられるものとします。

  1. ユーザ回路からの送信要求をトリガーとして、TXE#がLであるのを確認して、WRをLにする。
  2. WRのパルスの幅は50ns以上にする。(条件T7より)
  3. WRをLに遷移させる、20ns以上前にデータを出力する。(条件T9より)
  4. WRをLに遷移させてから、10ns以上経過した後、データバスをHI-Zにする。(条件T10より)
  5. WRをHに戻した後、WRのインアクティブの幅は50ns以上なので、ウェイトする。(条件T8,T11より)

 もし、ホストPCがUSBからデータを受信しないまま、FPGAが次のデータを送信した場合、そのデータはFT245内のバッファ(FIFO)に溜まりますので、失われることはありません。FIFOが満杯になった場合はデータ受け入れができませんので、USBにデータを送ろうとしているFPGAにWAITがかかることになり、FPGA内のユーザ回路が最終的にWAITします。

FIFOの弊害

 FT245BMのFIFOは、RS232CやパラレルポートのFIFOよりもずっと深いFIFOが使用されます。FIFOが使用されるということは、データの送受信タイミングに余裕がでるため、データを失う危険性は少なくなりますが、緊急で送りたいデータがあっても緊急で送信できないという弊害もあります。
 また、信号線の状態を監視するようなアプリケーションをパラレルポートで開発するときには、PCからパラレルポートがHかLかを監視することでとても簡単にでき、周辺機器側で送信動作を行わなくてもできました。しかしながら、USBでは周辺機器が何かしらのデータを送信しないとPCは受信できませんので、一定周期あるいは不定期にUSBにデータを送信してやらねばなりません。

FPGAのステートマシンを設計しよう

作成する構造

 USBとFPGAの理解を深めるために、次の図のような回路を作りましょう。

 今回作成するのは、インタフェースステートマシン(usbif)と、処理系です。今回作る処理系は、受信した文字がアルファベットの小文字ならば大文字に変換してエコーバックするアプリケーションとします。
 このような設計を行うために、まず、ステートマシンへの動作のトリガーとなるイベントと、ステートマシンの行うべき動作を洗い出します。

インタフェース(usbif)の仕様を決める

 FPGA内のUSBインタフェース(usbif)はあくまでも、FT245BMと処理系をつなぐ役割に徹するものとします。複雑なデータ処理からUSBという物理デバイスを分離して、いろいろな処理系と接続しやすいようにします。そして、処理系はFT245BMのことを考えなくてもよく、usbifとの接続を考えればよいようにカプセル化します。カプセル化がうまくいけば、FT245BMのデータシートを見る必要もなくなり、FT245BMかどうかを意識する必要すらなくなります。FT245BMの代わりにUSBN9601やEZ-USBがつなげることだってありえます。
 さて、FT245BMとusbifの接続はRXF#,RD#,WR,TXE#の4線でしたが、処理系とusbifも次の4本の線でハンドシェイクするものとします。

信号名方向動作
USB_RX_Ready処理系→USBインタフェース次のUSBデータを受け入れることができる
USB_RX_ReceivedUSBインタフェース→処理系FT245BMから1バイトのデータを受信した
USB_TX_Ready処理系→USBインタフェースUSBに送信したいデータが用意できた
USB_TX_TransmittedUSBインタフェース→処理系FT245BMへ1バイトのデータを送信した

 FT245BMとFPGAのインタフェースは4本の線で、FPGA内のUSBインタフェースと処理系も4本の線です。これでは信号の線数も減らないし、意味がないと思われるかもしれませんが、このようなインタフェース回路を自前で作っておくと、いろいろと便利なことがあります。
 たとえば、FT245BMとFPGAは別々のクロックで動く非同期回路です。このため、自前の処理系とのインタフェースは工夫が要ります。このインタフェースと自前の処理系は完全同期なので、インタフェースは簡単です。また、USB_RX_Receivedのような信号は、信号を受信した際に1パルスの信号を発するので、その先の処理系でステートマシンの設計がとても楽になります。
 また、FT245BMとFPGAの間のデータバスは8ビットのバスを双方向で使うので、データ方向の切替えを行わなければなりません。タイミングを間違えると、データがぶつかってしまいます。一方、usbifは受信バスと送信バスが分かれているため、処理系の設計は楽になります。
 もちろん、将来的に別のUSBチップを使う際にも、変更が最小で済みますし、回路のクロック周波数を変更する際のwaitの設定も、usbifのパラメータを変更するだけで済み、処理系への変更は不要です。
 ただし、レスポンスは数クロック分遅くなります。

データ受信時の動作

 まず、FT245BMがRXF#をLにし、USBからのデータを受信したことを示します。FPGAはそれをトリガーとして、FT245BMへ読み出しパルス(RD_pin)を送り、データを受信します。受信したデータは、FPGAの中にあるデータ処理系へと送られるわけですが、その前にデータ処理系のUSB_RX_Readyを見て、BUSYでないことを確認する必要があります。そのため、USB_RX_ReadyとRXD_nodeの両方を見て、ステートをS1に遷移させます。

 FPGAのIDLEステートをS0とします。ステートがアイドル状態で、RXF#の立下りを検出すると、ステートを次のS1に進めるものとします。また、ステートがS1の時にはRDの信号をLに下げます。こうして適度なWAITをとりながら、処理を続けます。
 Sn+1のステートも重要です。もし、RDをHに戻した直後にステートをS0に戻してしまうと、戻った直後はまだRXF#がLかもしれませんので、再度S1へ遷移してしまうからです。FT245BMはRDがHになった後、RXF#をHに戻すには5〜25nsかかるので、システムのメインクロックが40MHzを超えるときに問題が生じてしまいます。したがって、RDを戻した後、50ns以上の余裕を持ってステートをS0に戻すものとします。
 ところで、FT245BMの出すRXF#は、FPGAのクロックとは無関係に動いている非同期信号なので、FPGAがそれを利用するためには、一度FPGA内のクロックでラッチして、同期化する必要があります。

データ送信時の動作

 データ処理系から、USBへの送信要求(USB_TX_Ready)を受けます。それをトリガーとして、USBへデータを書き込みたいとします。もし、FT245BMがTXE#をHにしているならば送信FIFOが満杯なので送信できませんので、待つことになります。TXE#がLならば、FT245BMにデータと送信パルスを送り、その完了を処理系に知らせます。

 FPGAのIDLEステートをS0とします。ステートがアイドル状態で、処理系からUSBへの送信要求(USB_TX_Ready)を検出すると、ステートを次のw1に進めるものとします。ステートがw1の時に遷移する際に、WRの信号出力をHにします。その後、適度なWAITをとりながら、処理を続けます。
 wn+1のステートも重要で、もしWRをHに戻した直後にステートをS0に戻してしまうと、戻った直後はまだTXE#がLかもしれませんので、次の送信要求が出されている場合、再度w1へ遷移してしまうからです。FT245BMはWRがHになった後、TXE#をL→Hへと遷移させるには4〜25nsかかるので、システムのメインクロックが40MHzを超えるときに問題が生じてしまいます。したがって、WRを戻した後、50ns以上の余裕を持ってステートをS0に戻すものとします。
 ところで、FT245BMの出すTXE#は、FPGAのクロックとは無関係に動いている非同期信号なので、FPGAがそれを利用するためには、一度FPGA内のクロックでラッチして、同期化する必要があります。

VHDLへの実装

 このようなステートマシンを作成するにあたって、出力信号をどのように生成するかを考えます。できるだけ機敏な動きをするステートマシンを目指します。
 ステートマシンの動作と、出力信号の割り当てにはいくつかの流儀があります。

ステートをデコードする(組み合わせ型)

USB_TX_Transmitted <= '1' when(USB_state = ・・・
          ・
          ・
          ・
USB_WR             <= '1' when(USB_state = ・・・
          ・
          ・
          ・
process (CLK) begin
  if(CLK'event and CLK='1') then
    case USB_state is
      when S0 => ・・・
    end case
  end if;
end process;

 ステートマシンの遷移の記述は、CLKで動くPROCESS文の中に入りますが、FPGAの出力ピンの記述はPROCESS文の外です。ステートを直接デコードしているため出力動作は機敏ですが、ハザードの出る可能性と、記述の変更が面倒であるという欠点があります。

ステートをデコードする(レジスタ型)

process (CLK) begin
  if(CLK'event and CLK='1') then
    if(USB_state = ・・・) then
      USB_TX_Transmitted <= '1'; …ウェイト1でこの信号は遷移する
    elsif(USB_state = ・・・) then
          ・
          ・
          ・
          ・
    end if;
  end if;
end process;

process (CLK) begin
  if(CLK'event and CLK='1') then
    case USB_state is
      when S0 => ・・・
    end case
  end if;
end process;

 ステートマシンの遷移のPROCESS文と、ステートをデコードするPROCESS文を両方用意する方法です。
 ハザードの出る可能性はなくなりますが、動作の機敏性は失われます。ステートがある状態の時、次のクロックのタイミングで出力信号が反映されるためです。
 このタイプと、先の組み合わせ型との記述上利便性の大きな違いは、出力信号の遷移をIF文やCASE文で書けるところです。組み合わせ型では、PROCESS文の外なのでWHEN〜ELSE文で書くことになります。

ステートマシン中に記述する(レジスタ型)

process (CLK) begin
  if(CLK'event and CLK='1') then
    case USB_state is
      when S0 =>
        if(USB_TX_Ready = '1' and USB_TXE_node ='0') then
          USB_State <= w1;    条件分岐
          WR      <= '1'; …ウェイト0でWR信号は遷移するので、
        else                  w1ステートではWR信号は1になっている
          WR      <= '0';
        end if;
      when w1 =>
        USB_State <= w2;
          ・
          ・
          ・
      when w5 =>        
        USB_State <= w6;    …そろそろWRを戻したい。
        WR        <= '0';  でも、次のw6ステートでWR信号は0に遷移する
    end case
  end if;
end process;

 ステートマシンの状態遷移と、出力ピンの遷移を同じ場所に書く方法です。いろいろな無理難題が簡単にかけてしまうので人間は楽ですが、CADは苦労しているはずです。

 このタイプで、いかに機敏なステートマシンを作るかを簡単に書きます。
 出力信号の遷移をif文やcase文の中に書くと、反映されるのは次のステートになります。下の図のようにステートマシンが条件分岐する場合、出力信号をステートをデコードする形で書くならば、条件分岐のために無駄なクロックを1つ使ってしまいます。下の図は、条件分岐後のステートがS1ならばWR=0として、w1ならばWR=1とする例です。

 条件分岐と同時に出力信号を変化させたい場合は、IF文の中でステートの更新と一緒に遷移を書きます。
 ABELではwithオプションとかを使ってもっと簡潔に書くことができたのですが、VHDLではステートマシンの遷移と、出力信号の遷移を一緒に書こうと思うと、上のソースのように書くのが楽なのではないでしょうか?

ウェイト数を決める

 FT245BMとのタイミング規約を守るため、ウェイトが必要になります。例えば、RDのパルス幅は50ns以上です。この規約を守ってパルスを生成するにはどうすればよいでしょう?

 最速でステートマシンを動かすなら、S0でRD<='0'として、S1でRD<='1'とします。 このようにすると、ステートマシンがS1の時にRDはLになって、S2の時にRDはHになります。よって、RDのLのパルス幅は1クロック分です。この場合クロックが20MHz以下でないとパルス幅の規約50nsを満たせません。
 当然ながら、クロックの周波数によって必要なウェイト数は変わってきます。ウェイトとして、余分なステートを1個入れるならクロックは40MHzまで対応できます。余分なステートを2個入れれば、クロックは60MHzまで対応できます。余分なステートが3個ならクロックは80MHzまでで、余分なステートが4個ならクロックは100MHzまで対応できます。
 このようなステートマシン設計を行った場合、必要なウェイト数は次の式で計算できます。

n + 1 > f * Δt / 1000
n:ウェイトの数 , f:周波数[MHz] , Δt:必要なパルス幅[ns]

USBインタフェースステートマシンを作る

 作ろうとしている回路をもう一度載せます。なお、コードはすべてこのページの一番上にあります。どうぞダウンロードしてください。

 さて、USBインタフェースステートマシンを作るわけですが、どうせ作るなら他の回路モジュールからも容易に呼び出せるように、コンポーネント化しましょう。次のコードは、USBIFのピン定義です。

entity USBIF is
    Port (
        CLK                : in std_logic;
        FT245_D            : inout std_logic_vector(7 downto 0);
        FT245_WR           : out std_logic;
        FT245_RD           : out std_logic;
        FT245_TXE          : in std_logic;
        FT245_RXF          : in std_logic;
        FT245_PWREN        : in std_logic;
        FT245_RSTO         : in std_logic;
        USB_Tx_DATA        : in std_logic_vector(7 downto 0);
        USB_Rx_DATA        : out std_logic_vector(7 downto 0);
        USB_RX_Ready       : in std_logic;
        USB_TX_Ready       : in std_logic;
        USB_Received       : out std_logic;
        USB_Transmitted    : out std_logic
    );
end USBIF;

 上のソースコードで、FT245_で始まる信号は、FPGAの外部に出てFT245BMと接続される信号です。
 USB_で始まる信号は、FPGAの中でユーザー処理系との接続に使います。これらの制御信号の使い方を、再度載せます。

信号名方向動作
USB_RX_Ready処理系→USBインタフェース次のUSBデータを受け入れることができる
USB_RX_ReceivedUSBインタフェース→処理系FT245BMから1バイトのデータを受信した
USB_TX_Ready処理系→USBインタフェースUSBに送信したいデータが用意できた
USB_TX_TransmittedUSBインタフェース→処理系FT245BMへ1バイトのデータを送信した

上位モジュールと処理系を作る

 次に上位のメインの回路と、処理系を作ります。上位のメインの回路からUSBIFを呼び出すようにします。そのためには、メインの回路中のentity文の中で、USBIFをcomponentとして定義します。

    component USBIF port (
        CLK                : in std_logic;
        FT245_D            : inout std_logic_vector(7 downto 0);
        FT245_WR           : out std_logic;
        FT245_RD           : out std_logic;
        FT245_TXE          : in std_logic;
        FT245_RXF          : in std_logic;
        FT245_PWREN        : in std_logic;
        FT245_RSTO         : in std_logic;
        USB_Tx_DATA        : in std_logic_vector(7 downto 0);
        USB_Rx_DATA        : out std_logic_vector(7 downto 0);
        USB_RX_Ready       : in std_logic;
        USB_TX_Ready       : in std_logic;
        USB_Received       : out std_logic;
        USB_Transmitted    : out std_logic
    ); 
    end component;

 コンポーネントの定義が終わったら、architecuture文のbeginの中で、USBIFを呼び出します。このUSBIFというのは使用するコンポーネントの名前で、usbif0は個々のコンポーネントの実体の名前です。
 今回は、USBIFを1個しか作らないのでusbif0としていますが、同じコンポーネントを何個も作る場合には、usbif0に相当する部分の名前をひとつひとつ変えます。port mapというのは、下位のコンポーネントと上位の回路を、信号線の名前で接続することを意味します。
 FT245で始まる名前の信号は、上位モジュールの中でUSB_という名前の信号と接続され、そのままFPGAの外に出ます。USB_で始まる名前の信号はFPGAの中でいろいろな役割をします。機能の詳細と使い方は、これから説明します。

    usbif0 : USBIF port map (
        CLK                => CLK,
        FT245_D            => USB_D,
        FT245_WR           => USB_WR,
        FT245_RD           => USB_RD,
        FT245_TXE          => USB_TXE,
        FT245_RXF          => USB_RXF,
        FT245_PWREN        => USB_PWREN,
        FT245_RSTO         => USB_RSTO,
        USB_Tx_DATA        => USB_TX_DATA,
        USB_Rx_DATA        => USB_RX_DATA,
        USB_RX_Ready       => '1', -- always reveive ready
        USB_TX_Ready       => USB_TX_Ready,
        USB_Received       => USB_Received,
        USB_Transmitted    => USB_Transmitted
    );

 次のコードは、データのハンドシェイク部分です。USB_TX_Readyという信号は、ユーザ回路からUSBに送信したいデータを用意できたことを示す信号で、言い換えれば送信要求信号です。この信号を'1'にすると、USBバスにUSB_TX_DATAが出力されます。
 一方、USBからデータを受信すると、1クロックだけUSB_Receivedが'1'になります。USB_ReceivedをトリガーとしてUSB_TX_Readyを'1'にセットすれば、データの受信をトリガとしてデータの送信を行うことができます。エコーバックのように、ホストPCからのイベントによって動く回路を作るときはこのようにします。
 なお、データが出力されたらUSB_Transmittedが1クロックだけ'1'になりますので、送信要求USB_TX_Readyを取り下げます。もし、USB_TX_Readyを下げないといつまでもデータを送信しつづけてしまいます。

    process(CLK) begin
        if(CLK'event and CLK='1') then
            if(USB_Received = '1') then
                USB_TX_Ready <= '1';
            elsif(USB_Transmitted = '1') then
                USB_TX_Ready <= '0';
            end if;
        end if;
    end process;

 次のコードは、データを実際に処理する部分です。受信したデータが、16進数で61〜7Aのとき、すなわちアルファベットの小文字のときには、その値から16進数で20を減じて大文字に変換して、送信データに渡しています。

    process(CLK) begin
        if((USB_RX_DATA >= x"61") and (USB_RX_DATA <= x"7A")) then
            USB_TX_DATA  <= USB_RX_DATA - x"20";
        else
            USB_TX_DATA  <= USB_RX_DATA;
        end if;
    end process;

FT245とUSB機能内蔵ワンチップマイコン

 最後に、NP1003に使われているFT245BMと、代表的なUSB機能内蔵ワンチップマイコンの機能を比較します。両方を使ってみた結果、私の主観を交えながら比較します。

チップFT245BM代表的なワンチップマイコン
基本的特徴USBとユーザ回路のインタフェースUSB機能内蔵ワンチップマイコン
速度
  • USBの速さを十分に発揮できる。
  • ハードウェアロジックは1クロックで複数の処理を実行できる。
  • CPUで、読み出し→処理→出力を行うと、1バイトの処理に5μ秒くらいはかかる。
  • CPUが別の処理をすると、USBはさらに遅くなる。
  • オートポインタを使っても何とか間に合う程度で、他の処理をする余裕はない。
送受信同時処理
  • FTDI社の優れたデバイスドライバのおかげで可能。
  • 受信プロセスが常時バックグラウンドで走っているため、受信用関数をコールしなくても、PC内のバッファには常に最新データが溜まっている。
  • バッファ内のデータの量を知ることも可能。
  • 標準のドライバでは、受信するべきデータの長さをあらかじめ指定しなければならない。
  • 標準のドライバは、受信するデータが満たされるまで次の処理ができない。このため、データを待ち受けながらUSB経由でCPUに次のデータを送る指示がだせない。
 工夫すればできるのかも知れませんが、簡単にはできそうにありませんでした。
データ長 64Bytesの壁がなく、送受信ともに長さを気にせず送ってよい。 大きなブロックのデータを送りたいとき64Byteごとに小分けにする必要があり、CPUと設計者に余計な負担がかかる。
ファームウェア 設計者が本来必要としているUSB→パラレル変換のために、ファームウェアは全く不要。 必ずCPUにはUSB送受信プログラムが必要になり、著作権が発生している。
開発に必要な知識
  • WebPACKとFPGAの最低限の使い方のみ。
  • USBに関する知識はほとんど不要。
  • 特殊なCPUアーキテクチャの理解
  • コンパイルツールの使い方
  • 言語の知識
  • 書き込みツールの知識
  • USBそのものの理解
など新たに覚えなければならないことが多い。

 CPUを内蔵していないFT245BMの方が速度も速く、開発も簡単でした。また、理解すべき知識も少ないのでFT245の方が開発の効率も高いです。一方、マイコンの方は数百ページにおよぶドキュメントがあり、読むべきポイントを掴むまでに苦労しました。
 また、FT245BMではファームウェアが不要で、FPGA内に作りこんだ回路だけで動作します。このため、ファームウェア部分にかかる著作権トラブルを未然に防止できます。
 USBを使って何かをしたいときに、CPUやいろいろなツールの使い方を理解しなければならないというのは、とてもとても時間の無駄な気がします。そもそも、作ろうとしているUSB機器内で、能動的な部分は最低1箇所あればよいわけですから、FPGAだけあればよいわけです。
 ぜひとも、FT245BMとFPGAの組み合わせをお薦めします。

 さて、USBコンポーネントは用意できました。VHDLのコンポーネント文がわかれば、いとも簡単にUSBアプリケーションが作れてしまいます。後はアイデア次第ですばらしいことができるでしょう!!