新規プロジェクト作成 VHDLファイル作成 ピン配置固定 コンパイル 書込み(iMPACT) 書込み(NAXJP) 戻る

WebPACKによるFPGAのコンパイル方法

 WebPACKを使った場合の一般的なコンパイル方法も解説します。NP1003を使う場合以外にもお役に立てば幸いです。

ソースファイルテンプレート

 FPGAの各ピンは、USBチップなどの各ピンとあらかじめ接続されています。ユーザ回路を新たに設計する際には、下記のソースファイルテンプレートを使用すると便利です。右クリックで保存し、WebPACKでのプロジェクトのフォルダに入れてください。

テンプレートVHDLファイル

 NP1003 FPGAの最上位階層のVHDLファイルです。各入出力ピンが宣言されています。内部での接続はされていません。

テンプレートUCFファイル

 NP1003の各入出力ピンとピン番号が定義されています。

WebPACK 新規プロジェクトの作成

 まず、XILINX WebPACKを起動します。

 起動したら、メインメニューで「File→NewProject」を選びます。
 次の図のようなダイアログが現れたら、各種項目を入力します。

 Project Nameは、これから作ろうとしているFPGAのデザイン名、Project Locationはそのプロジェクトファイルのパスです。Device FamilyにはSpartan2を選択し、Deviceには使用したデバイスを入力します。NP1003は、ピン互換性のあるXC2S15〜XC2S100までのTQ144パッケージのFPGAが乗ります。
 最後のDesign FlowはVHDLにしておきます。

VHDLファイルの作成

 プロジェクトを作成した状態では、何もない状態ですので、とりあえずメインのVHDLファイルを作ります。左上の白いボックスで、「xc2s30・・・」の上で右クリックし、New Sourceを選びます。

 前の手順で「New Source」を選ぶと、下の図のようなダイアログが現れますので、左のボックスで「VHDL Module」を選択し、適当なファイル名をつけます。ここで、ファイル名をmainとしています。
 ここで設定するファイル名は、VHDLファイルのエンティティーの名前にもなり、また、コンパイルしてできた最終的なROM書き込みファイルの名前にも使われます。じっくり考えて決めたいものです。なお、「xproject」というディレクトリ名にも意味はありません。皆さんがいつも開発するディレクトリの名前で結構です。

 次に現れる下の図のダイアログは、FPGAの入出力ピンをグラフィカルに入力できるものですが、今回は使いません。

 とりあえず、WebPACKが作ってくれたVHDLファイルを全部消して、下のVHDLテンプレートソースファイルを、コピーアンドペーストしてください。ダウンロードはこちら

----------------------------------------------
-- NP1003 SDRAM & USB template source file
-- (C) Copyright 2003 Nahitafu Nahitech
-- http://www.nahitech.com
----------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity main is
    Port (      CLK0      : in std_logic;
                CLK1      : in std_logic;
                CLK2      : in std_logic;
                CLK3      : in std_logic;
                USER      : inout std_logic_vector(36 downto 0);
                SD_D      : inout std_logic_vector(15 downto 0);
                SD_A      : out std_logic_vector(12 downto 0);
                SD_BS1    : out std_logic;
                SD_BS0    : out std_logic;
                SD_LDQM   : out std_logic;
                SD_UDQM   : out std_logic;
                SD_WEN    : out std_logic;
                SD_RAS    : out std_logic;
                SD_CAS    : out std_logic;
                SD_CLK    : out std_logic;
                SD_CKE    : out std_logic;
                SD_CS     : out std_logic;
                USB_D     : inout std_logic_vector(7 downto 0);
                USB_WR    : out std_logic;
                USB_RD    : out std_logic;
                USB_TXE   : in std_logic;
                USB_RXF   : in std_logic;
                USB_PWREN : in std_logic;
                USB_RSTO  : in std_logic
        );
end main;

architecture Behavioral of main is
    signal CLK          : std_logic;
    signal logicH       : std_logic;
    signal logicL       : std_logic;

    signal USB_STATE        : integer range 0 to 15;
    signal USB_RXF_node     : std_logic;
    signal USB_TXE_node     : std_logic;
    signal USB_RX_Ready     : std_logic;
    signal USB_TX_Ready     : std_logic;
    signal USB_Received     : std_logic;
    signal USB_Transmitted  : std_logic;
    signal USB_Tx_DATA      : std_logic_vector(7 downto 0);
    signal USB_Rx_DATA      : std_logic_vector(7 downto 0);
    signal USB_WR_node      : std_logic;
    signal USB_RD_node      : std_logic;

begin
    CLK <= CLK0;
    logicH <= '1';
    logicL <= '0';
--  SDRAM default pin condition
    SD_CLK    <= not CLK;
    SD_CS     <= '1';
    SD_RAS    <= '1';
    SD_CAS    <= '1';
    SD_CKE    <= '0';
    SD_WEN    <= '1';
    SD_D      <= (others=>'Z');
    SD_A      <= (others=>'0');
    SD_BS1    <= '0';
    SD_BS0    <= '0';
    SD_LDQM   <= '0';
    SD_UDQM   <= '0';

--  USB default pin condition
    USB_RD_node <= logicH;
    USB_WR_node <= logicL;
    USB_RD      <= USB_RD_node;
    USB_WR      <= USB_WR_node;
    USB_D       <= (others=>'Z');

--  USER I/O default pin condition
    USER(35 downto 0)  <= (others=>'0');
    -- USER(36) is used to avoid implementation error. see below

--  CLK processes
    process(CLK) begin
      if(CLK'event and CLK='1') then
        USER(36)           <= usb_txe and usb_rxf;
      end if;
    end process;

end Behavioral;

 上のVHDLファイルで、赤で書いた部分は、VHDLのファイル名に合わせてください。コピー&ペーストした際の画面は、次の図のようになります。

 これで、とりあえずソースファイルは準備ができました。

ピン配置の固定

 VHDLファイルをFPGAにコンパイル(synthesis + imprement)させると、デフォルトでは適当にピン配置を決められてしまいます。NP1003ではFPGAのピンはすでに基板上で配線されていますので、ピン配置を固定しなければなりません。
 先ほどのVHDLテンプレートをうまくコンパイルし、指定されたピンを指定された場所に配置するためのUCFファイルは次のとおりです。ダウンロードはこちら

NET "user<0>"   LOC = "P83";
NET "user<1>"   LOC = "P84";
NET "user<2>"   LOC = "P85";
NET "user<3>"   LOC = "P86";
NET "user<4>"   LOC = "P87";
NET "user<5>"   LOC = "P93";
NET "user<6>"   LOC = "P94";
NET "user<7>"   LOC = "P95";
NET "user<8>"   LOC = "P96";
NET "user<9>"   LOC = "P99";
NET "user<10>"  LOC = "P100";
NET "user<11>"  LOC = "P101";
NET "user<12>"  LOC = "P102";
NET "user<13>"  LOC = "P103";
NET "user<14>"  LOC = "P112";
NET "user<15>"  LOC = "P113";
NET "user<16>"  LOC = "P132";
NET "user<17>"  LOC = "P133";
NET "user<18>"  LOC = "P134";
NET "user<19>"  LOC = "P136";
NET "user<20>"  LOC = "P137";
NET "user<21>"  LOC = "P138";
NET "user<22>"  LOC = "P139";
NET "user<23>"  LOC = "P140";
NET "user<24>"  LOC = "P141";
NET "user<25>"  LOC = "P3";
NET "user<26>"  LOC = "P4";
NET "user<27>"  LOC = "P5";
NET "user<28>"  LOC = "P6";
NET "user<29>"  LOC = "P7";
NET "user<30>"  LOC = "P10";
NET "user<31>"  LOC = "P11";
NET "usb_d<0>"  LOC = "P114";
NET "usb_d<1>"  LOC = "P115";
NET "usb_d<2>"  LOC = "P116";
NET "usb_d<3>"  LOC = "P117";
NET "usb_d<4>"  LOC = "P118";
NET "usb_d<5>"  LOC = "P120";
NET "usb_d<6>"  LOC = "P121";
NET "usb_d<7>"  LOC = "P122";
NET "usb_rd"    LOC = "P123";
NET "usb_wr"    LOC = "P124";
NET "usb_txe"   LOC = "P126";
NET "usb_rxf"   LOC = "P129";

NET "sd_d<0>"   LOC = "P64";
NET "sd_d<1>"   LOC = "P63";
NET "sd_d<2>"   LOC = "P62";
NET "sd_d<3>"   LOC = "P60";
NET "sd_d<4>"   LOC = "P59";
NET "sd_d<5>"   LOC = "P58";
NET "sd_d<6>"   LOC = "P57";
NET "sd_d<7>"   LOC = "P56";
NET "sd_d<8>"   LOC = "P67";
NET "sd_d<9>"   LOC = "P74";
NET "sd_d<10>"  LOC = "P75";
NET "sd_d<11>"  LOC = "P76";
NET "sd_d<12>"  LOC = "P77";
NET "sd_d<13>"  LOC = "P78";
NET "sd_d<14>"  LOC = "P79";
NET "sd_d<15>"  LOC = "P80";
NET "sd_a<0>"   LOC = "P43";
NET "sd_a<1>"   LOC = "P42";
NET "sd_a<2>"   LOC = "P41";
NET "sd_a<3>"   LOC = "P40";
NET "sd_a<4>"   LOC = "P22";
NET "sd_a<5>"   LOC = "P23";
NET "sd_a<6>"   LOC = "P26";
NET "sd_a<7>"   LOC = "P27";
NET "sd_a<8>"   LOC = "P28";
NET "sd_a<9>"   LOC = "P29";
NET "sd_a<10>"  LOC = "P44";
NET "sd_a<11>"  LOC = "P30";
NET "sd_a<12>"  LOC = "P31";
NET "sd_cs"     LOC = "P48";
NET "sd_ras"    LOC = "P49";
NET "sd_cas"    LOC = "P50";
NET "sd_wen"    LOC = "P51";
NET "sd_bs1"    LOC = "P46";
NET "sd_bs0"    LOC = "P47";
NET "sd_udqm"   LOC = "P66";
NET "sd_ldqm"   LOC = "P54";
NET "sd_clk"    LOC = "P65";
NET "sd_cke"    LOC = "P38";

#NET    "usb_pwren" LOC = "P130";
#NET    "usb_rsto"  LOC = "P131";
NET "clk0"  LOC = "P88";
    
#PINLOCK_END

 なお、UCFファイルはピン配置の固定だけでなく、FPGA内部のコンポーネントの配置指定、メモリ(ブロックRAM)の初期値、タイミングの制約なども指定できます。

 このファイルをダウンロードして、プロジェクトのディレクトリに入れます。WebPACKでコンパイルする際には、Imprementのプロパティを開き、このUCFファイルを指定します。そうして、再度Synthesisから実行することで、指定したピンに指定した信号を割り当てることができます。
 Imprementのプロパティは、右の図のように「Process for Current Source:」の「Implement Design」にカーソルを合わせ、右クリックで開きます。


 UCFファイルを指定するには、下の図のダイアログでAの場所にファイル名を入力します。
 パスを指定するのが面倒な場合は、@の無地のボタンを押すと、ファイルオープンダイアログが開くのでそこで選択してもいいでしょう。

いざコンパイル

 ソースファイルが準備できたら、いざコンパイルです。
 コンパイルと呼んでいるのは、正確には論理合成(Synthesize)とデバイスへの実装(Implement)です。コンパイルが終わると、ピン配置のレポートや使用率のレポートなど様々なレポートが作成されます。
 その後、「Generate Programming File」というプロセスを実行するとbitファイルが生成されます。BITファイルは最終的にFPGAが受け取るデータです。BITファイルをコンフィグROM(XC18Vxx)に書き込むためには、BITファイルをMCSファイルに変換しなければなりません。そこで、PROM File Formatter」というツールを起動し、MCSファイルを作成します。

 実際にコンパイルするためには、まず、最上位のVHDLソースを選択します。今回は1個しかVHDLソースがないのですが、階層化設計でいろんなコンポーネント(部品)を使うときには、最上位のファイルを指定しないとImplementでエラーになるか、滅茶苦茶なものが生成されるでしょう。
 次に、「Generate PROM File」をダブルクリックします。「Synthesize」や「Implement Design」は自動で実行されます。もちろん、「Synthesize」や「Implement Design」を順番に実行していっても構いません。

 コンパイルがうまくいくと、BITファイルが生成され(ログを良く見るとbitgenというのが起動していますね)、その後、「PROM File Formatter」が自動で起動します。これはBITファイルをMCSファイルに変換してくれるツールなのですが、単純な変換だけではありません。例えば800kByteになったBITファイルを512kByteのROM2個に分割したり、そのような分割や結合ができます。
 とりあえず、そんな複雑な機能は使わないので、まずはSAVEボタンを押してください。次にファイル名を聞かれますが、それも「はい」と答えてください。

 デフォルトでは、BITファイルを、ワンタイムのコンフィグROMであるXC17V512に書き込むようになっています。これでも問題ないのですが、PROMのプロパティを開いて、XC18V01に変えましょう。

 これでもう一度SAVEすれば、完了です。

書込み方法

iMpactによる書き込み

 iMpactを使って書き込みを行う方法を解説します。
 WebPACKには「Generate PROM File」の下にConfigure Device(iMPACT)」とありますが、これは押さないほうがいいでしょう。これはJTAGチェーンに唯一のデバイスがぶら下がっていることを想定しているためです。
 ちょっと面倒かもしれませんが、StartメニューからiMPACTを起動してください。

 その前に、NP1003とPCとをJTAGケーブルで接続します。JTAGケーブルは自作してもいいですし、購入することもできます。下の写真は、私が愛用している自作JTAGケーブルです。

 JTAGケーブルの回路図は、下のURLにあります。
www.xilinx.com/support/programr/jtag_cable.pdf
 上の回路を自作してもいいですし、キットや完成品を購入してもいいでしょう。JTAGケーブルのキット・完成品は、ヒューマンデータさんやStrawberry-linuxさんで購入できます。もちろん純正品をXILINXの代理店からも購入できますが、高価です。

 iMpactを起動し、いくつかのダイアログで「はい」と答えると、自動でXC18V01とXC2S100が接続されていることを認識します。XC18V01のコンフィグレーションファイル指定で、コンパイル時に生成された「main.mcs」を選択します。(mainの名前はデザインによって変わる)
 XC2S30の方は、「指定なし」です。

 XC18V01の絵の上で右クリックし、Programを実行します。

 次のダイアログでは、書き込み時オプションを選択できます。「書き込み前の消去」と「ベリファイ」がONになっていることを確認してください。
 特に、ベリファイは大事です。XC18VシリーズはCPLDと違い、書き込み途中でベリファイが行われないため、書き込み後にベリファイをしなければなりません。

 Programming Succeededと出れば、成功です。
 新しく書き込んだデザインはすぐにはFPGAに反映されません。一度、USBコネクタを抜き、再度挿せば、次回の起動時にFPGAはコンフィグROMからコンフィグされます。

NAXJPによる書き込み

 NAXJPを使えば、次のような特徴のある書込みができます。

  1. JTAGケーブルの簡略化
  2. 書込み後に自動的にFPGAをリブートし、コンフィグ即反映
  3. 高速起動、簡単操作。コマンド一発で書込み
  4. Linuxマシンを遠隔操作し、書込み
  5. USB経由での書込み
 只今、NAXJPの次期バージョンを準備中です。今しばらくお待ちください。