はじめに
FPGA へのビットストリーム送信は、通常、グラフィカルユーザーインターフェイス(GUI)を使います。Vivado のハードウェアマネージャー (Hardware Manager) のようなツールはこの機能を提供していますが、この単純な作業にしては、操作手順が複雑に感じられることがよくあります。特に、コンピュータに JTAG ケーブル 1 本で FPGA が 1 つだけ接続されている場合、ユーザーインターフェイス上では不要な操作が多く必要です。FPGA が 1 つしかないのなら、コンピュータがビットストリームファイルをその FPGA に書き込むべきだと自動的に判断してくれてもよさそうなものではありませんか。なぜ、やろうとしていることをツールに毎回明示的に伝える必要があるのでしょうか。実際のところ、選択肢は 1 つしかないのですから。
1 つの解決策は、この作業を 1 ステップで実行する bash スクリプトを使うことです。このスクリプトは、JTAG ケーブル経由でコンピュータに接続されている FPGA を見つけ、その FPGA へビットストリームファイルを送信します。
スクリプト
FPGA へビットストリームファイルを送信するスクリプトは次のとおりです。
#!/bin/bash
set -e
if [ "$#" -ne 1 ]; then
echo "Usage: $0 bitstream-file.bit"
exit 1
fi
if ! which vivado >/dev/null ; then
echo Vivado is not in the execution path. Please run something like
echo source /path/to/..../Vivado/20nn.n/settings64.sh
exit 1
fi
if [ ! -f "$1" ] ; then
echo \"$1\" file doesn''t exist
exit 1
fi
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" <<"EOF"
# Tcl script begins here.
set bitfile [lindex $argv 0]
open_hw
connect_hw_server
open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost*]] 0]
set thefpga [lindex [get_hw_devices] 0]
set_property PROGRAM.FILE "$bitfile" $thefpga
set_property PROBES.FILE {} $thefpga
current_hw_device $thefpga
refresh_hw_device -update_hw_probes false $thefpga
program_hw_devices $thefpga
# Tcl script ends here
EOF
then
echo -e "\nProgramming successful.\n"
else
echo -e "\nProgramming failed.\n"
fi
この bash スクリプトの中に Tcl スクリプトが含まれていることに注意してください。vivado コマンドに与えている引数の 1 つは「-source /dev/stdin」です。これにより、Vivado は Tcl スクリプトを標準入力から読み取ります。「<<」を使ったおなじみのヒアドキュメント (here document) の仕組みが使われています。
スクリプトの使い方
上記のスクリプトを、例えば fpga_program という名前のファイルに保存します。次のようなコマンドで、このファイルを実行可能にします。
$ chmod a+x fpga_program
スクリプトを実行する前に、次のようなコマンドで環境変数を設定します。
$ source /opt/xilinx/Vivado/2023.1/settings64.sh
このコマンドの中の「/opt/xilinx/Vivado/2023.1」の部分は、お使いのコンピュータで Vivado がインストールされている場所に合わせて変更してください。
その後、次のようなコマンドでスクリプトを実行します。
$ ./fpga_program myproj.bit
もちろん、「myproj.bit」はお使いのビットストリームファイル名に置き換えてください。
このスクリプトの実行中、Vivado は大量の出力を生成しますが、最後の行は「Programming successful」または「Programming failed」のどちらかです。
スクリプトに関する補足
このスクリプトは Vivado 2015.2 と Vivado 2023.1 で動作確認済みです。したがって、Vivado の全バージョンで動作する可能性は高いでしょう。ただし、最近のバージョンの Vivado では、ソフトウェアが次のようなワーニングを出力します。
WARNING: 'open_hw' is deprecated, please use 'open_hw_manager' instead.
このワーニングが出ても、スクリプト自体は動作します。とはいえ、将来の Vivado のバージョンでは「open_hw」コマンドが認識されなくなる可能性があります。もしこのコマンドがエラーを引き起こすようになったら、スクリプト内のそのコマンドを「open_hw_manager」に変更してください。
もう 1 つ変更したいかもしれない点は、このスクリプトが生成する出力の量です。これだけ大量のテキスト出力が不要なら、出力を /dev/null に捨てるリダイレクションを追加するとよいでしょう。
そうしたい場合は、スクリプト内の次の行を見つけてください。
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" <<"EOF"
そして、次のように変更します。
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" > /dev/null <<"EOF"
ハードウェアサーバーの停止
同じコンピュータで複数のバージョンの Vivado を使っている場合、JTAG ケーブルへの接続に問題が生じることがあります。この問題の原因は、Vivado がハードウェアとの通信に TCP/IP サーバー(ポート 3121 で待ち受け)を使っていることです。Vivado は、必要に応じてこのサーバーを自動的に起動します。
しかし、あるバージョンの Vivado がサーバーを起動した後に、別のバージョンの Vivado が FPGA への接続を試みると、通信がうまくいかないことがあります。サーバーのバージョンが Vivado のバージョンと同じだからです。この状況は、グラフィカルユーザーインターフェイスのハードウェアマネージャーを使っているときにも発生します。
この問題が発生した場合、次のコマンドでサーバーを停止できます。
$ killall hw_server
なお、サーバーは一定時間使われないと自動的に停止します。