« FPGAカンファレンス2018に出展しました | トップページ | 1Gsps ADCボードの新基板設計 »

2018.01.20

FPGAをLinuxからコンフィグするxdevcfgの使い方

ZYNQ用に作ったLinuxでは、/dev/xdevcfgというデバイスドライバがあります。このデバイスドライバを使うとLinuxのコンソールからFPGAを再コンフィギュレーションできます。この使い方を調べました。

基本的な使い方はXILINXのAnswer Record 46913に書かれているのですが、

cat ビットファイル > /dev/xdevcfg

で、単純に流し込めばFPGAがコンフィグされるようなのですが、バイトオーダーをスワップしなければならない(?)らしく、単純にbitファイルをcatで流し込んでもうまくいかないようです。

一番簡単なやり方としては、bootgenを-process_bitstreamオプションを付けて使うのがよさそうですが、その設定ファイルをいちいち作るのが面倒なので以下のようなバッチファイルで処理します。

@if "%1"=="" goto ERR
@echo all:{%1} > all.bif
D:\Xilinx\SDK\2017.2\bin\unwrapped\win64.o\bootgen.exe -image all.bif -w -process_bitstream bin
move %1.bin %~dp0
pause -1
exit /b
:ERR
@echo "ビットストリームファイル名が必要です"
@echo "Usage: bootgen.bat <bit_file_name>"
pause -1

これをbit2bin.batなどというファイル名で保存し、

bit2bin.bat ファイル名.bit

とすると、ファイル名.bit.binが出来ます。

Bit2bin_1

出来上がった.binファイルをLinuxに転送してcatで流し込めばコンフィグできます。

さて、このバッチファイルはBIFファイルを生成して、bootgen.exeを呼び出して、できあがったbinファイルを移動させるという動作を行っていますが、これだけでは中で何をやっているかわからないので、bitファイルとbinファイルを比較してみました。

まずはオリジナルのBitファイルの先頭部分です。ファイル名やデバイス名、生成時刻のあとにFFFFFFFFで続く領域があったあと、AA995566の同期ワードが見えます。

Orig

次は、bootgenで変換したBinファイルの先頭部分です。

Swap_2

ヘッダ部分がざっくり削られた後、同期ワードが665599AAにスワップされているほか、4バイト単位で入れ替わっています。スワップというのは4バイト単位で[b0 b1 b2 b3]を[b3 b2 b1 b0]に入れ替えればよいということです。

これを、Windows上で変換するのではなく、BitファイルをLinuxに転送して、Linux上で変換しつつxdevcfgに流せば使い勝手はよいはずです。

そこで、こんなプログラムを作りました。

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main() { unsigned long val = 0; const int FILESIZE = 1048576*16; // とりあえず16MBとする while(!feof(stdin)) { // FFFFFFFFが見つかるまで読み飛ばし unsigned char uc = fgetc(stdin); val = (val << 8) | uc; if(val == 0xffffffff) break; } unsigned long *buf = new unsigned long [FILESIZE]; int bssize = fread(buf,1,FILESIZE,stdin); printf("Bit stream size = %d\n",bssize); for(int i=0;i<bssize/4;i++) { val = buf[i]; buf[i] = ((val & 0xff) << 24) | ((val & 0xff00) << 8) | ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); if((i < 20) && (val == 0x665599aa)) printf("Found magic word %lx\n",val); } int xdevcfg = open("/dev/xdevcfg",O_RDWR); if(!xdevcfg) { printf("Can not open /dev/xdevcfg.\n"); return 1; } write(xdevcfg,buf,bssize); close(xdevcfg); printf("Bit stream send\n"); }

これをfpgacfg.cppというファイル名で保存し、ZYNQ Linux上で

# g++ fpgacfg.cpp -o fpgacfg.elf

でコンパイルできます。

使い方は、

# fpgacfg.elf < ファイル名.bit

です。

このプログラムは最大16MBまでのビットストリームのバイトオーダーをスワップして、/dev/xdevcfgに流し込んでくれます。本当はビットファイルのヘッダを解析して本体を抽出するべきなのですが、このプログラムでも十分です。

Xdevcfg

XC7Z030のコンフィギュレーションに1秒かからないので、JTAGよりもはるかに高速です。その上、LinuxをリブートせずにFPGAだけ再起動できます。boot.binを作り直さなくていいのも楽ですね。

仮のビットストリームで起動しておいて、状況に合わせてFPGAを再コンフィギュレーションしたり、パーシャルリコンフィギュレーションとかできるとすごく便利かもしれませんね。

|

« FPGAカンファレンス2018に出展しました | トップページ | 1Gsps ADCボードの新基板設計 »

コメント

いつも素敵な情報をありがとうございます。

(ところで)
Bit stream send は
Bit stream sent
の方が良いのでは、と思いました :-)

投稿: 藤原 誠 | 2018.01.22 13:27

コメントを書く



(ウェブ上には掲載しません)




« FPGAカンファレンス2018に出展しました | トップページ | 1Gsps ADCボードの新基板設計 »