水曜日, 3月 27, 2013JavaでJTAGコンフィギュレーションどうせやるなら徹底的にということで、今度はJTAGによるFPGAのコンフィギュレーション(回路の書き換え)に挑戦してみたいと思います。JTAGコンフィギュレーションはQuartus IIが出力するSVF形式のファイルを利用します。SVFファイルは一種のスクリプト言語になっていて、これに記述される一連のJTAG操作を実行することにより、回路の再構成が可能となります。 まずは、DE0-Nanoを接続した状態で、Jarファイル(jtag_demo.jar)をダウンロードして実行してみてください。今度は一応64ビット環境も対応しているはずですが、こちらでは未確認です。
上の画像は「Reset FPGA」「IDCODE」「Config FPGA」「Start Demo」の4つのコマンドを順次実行した結果の例です。「Reset FPGA」はFPGAのリコンフィギュレーションを強制的に実行するコマンドで、DE0-Nanoの場合はボード上のEPCS64の回路を読み込みます。「IDCODE」はデバイス(EP4CE22)の32ビットIDCODEを読み出すコマンドです。 「Config FPGA」は、SVFファイルを実行してFPGAのコンフィギュレーションを行います。SVFファイルはJarファイル内にリソースとして格納されていて、元々は1Mバイト超の巨大なファイルだったものが、30Kバイト程度に圧縮されています。実際、Jarファイルの容量の大部分は、同梱されているJNAのJarファイルです。SVF実行は必要最低限の機能しか実装していないので、例えばTDOをチェックするといった機能は省略されています。くれぐれも、DE0-Nano以外のデバイスでは実行しないでください。 最後の「Start Demo」は前回と同様のJTAG通信デモンストレーション(ただし、ボタン押下によるスピード変化や停止はなし)で、入出力データを観察することができます。実は、コンフィギュレーション前でも特にエラーもなく実行できてしまいますが、その場合は出力データがLEDに反映されることはありません。 今度はさすがにSVFの実行やGUIといったそれなりに複雑な処理がありますので、全て一本のJavaプログラムにまとめても読みにくいと思います。そこで、比較的汎用的な部分としてJTAGライブラリと基本的なGUI(JTAG.java)およびSVFの実行(SVFPlayer.java)、そしてデモアプリケーション(JTAG_Demo.java)といった構成に分割しました。 ライブラリを分離したおかげで、デモアプリケーション部分は非常にすっきりしています。JTAG.GUIクラスのインスタンスを生成すると、画面上にボタンが追加されます。実行内容はonClickメソッド内に記述しますが、SVF実行用にJTAG状態遷移メソッドstateと、SHIFT_DR/SHIFT_IR用にshiftメソッドを追加したので、生データを直接writeメソッドで書き込む必要はほとんどなくなりました。SVFPlayerクラスはJTAG.GUIの派生クラスで、生成パラメータにボタン名とSVFのリソース名を指定します。
import info.relm.JTAG;
import info.relm.SVFPlayer;
public class JTAG_Demo extends JTAG {
public static void main(String[] args) {
GUI.title("JTAG Demo for DE0-Nano");
new GUI("Reset FPGA") {
public void onClick() {
reset();
state("RESET", "IRSHIFT");
shift(10, 0x1);
state("IREXIT1", "IRUPDATE");
text.append("Reconfiguration done.\n");
}
};
new GUI("IDCODE") {
public void onClick() {
reset();
state("RESET", "IRSHIFT");
shift(10, 0x6);
state("IREXIT1", "DRSHIFT");
readBytes(4, 0);
text.append("IDCODE: " +
Long.toBinaryString(0xffffffff00000000L |
read(4)[0]).substring(32) + '\n');
}
};
new SVFPlayer("Config FPGA", "jtag_led.svf");
new GUI("Start Demo", "Stop Demo") {
public void onClick() {
reset();
state("RESET", "IRSHIFT");
shift(10, 0xe);
state("IREXIT1", "DRSHIFT");
shift(9, 0x100);
state("DREXIT1", "DRSHIFT");
flush();
try {
for (int lfsr = 1; ; Thread.sleep(10)) {
readBytes(1, lfsr);
shift(1, 1);
state("DREXIT1", "DRSHIFT");
text.append("out: " +
Integer.toBinaryString(lfsr | 256).substring(1) +
"\tin: " +
Integer.toBinaryString(read(1)[0] | 256).substring(1) +
'\n');
if (((lfsr <<= 1) & 256) != 0) lfsr ^= 0x171;
}
} catch (InterruptedException e) {}
shift(9, 0x100);
state("DREXIT1", "DRUPDATE");
}
};
}
}
これを使えば、わざわざQuartus IIを立ち上げなくてもFPGAのコンフィギュレーションが可能になります。もし問題が無いようでしたら、今後はこの形態でコンフィギュレーションデータを公開していきたいと思います。 |
