RasPi 3B+ から FPGA を簡単にコンフィグレーションする (Xilinx Artix-7編)

#はじめに
RasPi から FPGA に、簡単にコンフィグデータをダウンロードする方法を説明します。
JTAG でやってもいいのですが、手間とピン数が惜しいので、SPI バスでダウンロードを行います。
SPI バスを使うと、JTAG よりも圧倒的に高速にダウンロードできます。
コンフィグ後、SPI バスを RasPi - FPGA 間の通信にも利用すれば、使用ピン数も最小限で済みます。

[激安 FPGA 開発ボード "Wukong" の導入 (Xilinx Artix-7 XC7A100T)](https://qiita.com/kan573/items/0a95a4367da4c0914944)

で解説した Wukong 基板を使って、RasPi からのダウンロード方法を説明します。

#実験環境
FPGA 基板 "Wukong" (Xilinx Artix-7 XC7A100T-2FGG676I 搭載)
RasPi 3B+


#FPGA コンフィグ方法の説明
Artix-7 でサポートされているコンフィグレーション方法を示します (UG470 Table 2-1)
![UG470_Table2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/b94f1aa3-f2c8-4783-566a-07de369ab83a.png)

FPGA が起動時にどのモードで起動するかは、M[2:0] ピンで設定します。

>FPGA が自分でコンフィグデータを読みに行くのが Master Mode で、
>FPGA が外部からコンフィグされるのは Slave Mode です。
>このモード設定を、M[2:0] で決めています。

ちゃんとした評価基板だと、DIP-SW とかショートプラグとかで、起動モードを選択できるようになっています。
残念ながら、Wukong 基板では Master SPI モード( M[2:0]=001 )で固定されていて、起動モードを変更することができません (下記、回路図)
![Wukong_Config_Setting_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/2d6e15fa-94b2-1564-7f13-1652204609b6.png)

この Master SPI モードでは、FPGA 起動時に SPI フラッシュを読みにゆきます。
フラッシュに有効なデータが書き込まれていれば、そのデータを読み込んで FPGA を設定して、起動します。

デバッグでダウンロードケーブルを使用する場合は、JTAG で接続され、M[2:0] の設定によらず、任意でコンフィグを上書きすることができます (強制ダウンロード)


#Wukong 基板のコンフィグ動作
Wukong 基板は、出荷時には SPI フラッシュには何も書かれていません。
電源を投入しただけでは何も起こらず、JTAG からのダウンロードで動作を開始します。

SPI フラッシュに書き込めば、電源投入時に Master SPI モードで読み込んで自動起動します。

#RasPi からコンフィグレーションする方法
RasPi が FPGA のコンフィグレーションデータを保持しておき、FPGA にダウンロードして起動する方法を考えます。

FPGA を外部からコンフィグレーションする方法は、

>(a) Slave Serial Mode
>(b) JTAG Mode
>(c) Slave SelectMAP Mode

の3種類が用意されています(UG470 Figure 1-1)
![slave_mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/fe868d88-ea2f-4732-5966-adec6e2008a4.png)

Vivado でダウンロードするときと同じ JTAG ストリームを RasPi から吐ければ、M[2:0] の設定を無視してダウンロードできます。
しかし、専用のソフトウエアを用意して、JTAG の 4 本の信号線の制御が必要になるため、面倒です。

ここでは、最も簡単な (a) Slave Serial Mode によるコンフィグレーションを実施したいと思います。

Slave Serial で必要な信号は下記4つです。

>PROGRAM_B: FPGA の設定リセットを行う。マイコンのリセットピン相当。
>CCLK: シリアル信号のクロックを入力する。
>DIN: シリアル信号のデータを入力する。立ち上がりでデータ取り込み。
>DONE: コンフィグが完了して FPGA が起動すると、L → H に変化する。

Wukong 基板では、PROGRAM_B は SW1 で入力可能、DONE には LED D1 が接続されています。
RasPi からは、CCLK と DIN の 2 つの信号を与えれば良いです。

Slave Serial Mode と SPI の信号を比較してみると、クロックとデータの波形は同一であることがわかります (UG470 Figure 2-3 と、Wikipedia SPI 波形図)
![UG470_Figure2-3_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/cafce6dd-6fb4-cc67-4a7e-66feb0a526bf.png)

CCLK の最大周波数は、Artix-7 の各スピードグレード共通で 100MHz です (DS181 Table 66)
![DS181_Table66.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/68492655-98c3-9698-1ead-2e608bd886e8.png)

#コンフィグレーションモードの変更
前述の通り、Wukong 基板では、コンフィグレーションモード設定ピン M[2:0] が Master SPI ( M[2:0] = 001 )に固定されています。

>M2_0 (W9) = GND
>M1_0 (Y9) = GND
>M0_0 (AB7) = +3.3V

M2 と M1 を +3.3V 接続に変更してやれば、Slave Serial ( M[2:0] = 111 ) モードで起動します。
![Wukong_Config_Setting_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/ce2a4074-7001-a571-3239-a4d195048f53.png)
Table2-1 によると、M[2:0] は内部でプルアップされているため、M2 と M1 を GND から切り離すだけでもよいはずです。

基板を見た感じでは、BGA パッケージの直下で GND に接続されているらしく、プルダウン抵抗を外して、というわけにはいきません。



#Wukong 基板の改造
さて、通常の BGA 基板の配線でピンを GND へ接続する場合、BGA のパッドの隙間にビアを打って、内層 GND へ接続するのがセオリーです。
(XAPP157 の図2)
![pad-via.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/10869217-7023-6437-18bf-52ee6a3b76a2.png)

このビアのスルーホール内側の銅めっきを剥がしてしまえば、該当ピンと内層 GND の接続を切ることができます。

Wukong 基板の FPGA 下面を調べて、M2, M1, M0 付近で GND/VCC と接続されているビアを探したところ、下図のピンが該当するようです。
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/996f5bf6-1897-94a1-e7f9-0271f383633d.jpeg)

M2, M1 と思われるビアを、ピンバイスとφ0.5 のドリルで広げて、GND との接続を切ります。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/1edc9e95-fc64-dc67-a7d7-d80f3c1f90a3.jpeg)

M2 / M1 と GND との接続が切れたかどうかを確認するには、Master SPI で起動するかしないかを見るのがよいです。
作業前に、SPI フラッシュに正常起動するコンフィグデータを書いておき、電源を入れます。
Master SPI が有効な間はコンフィグ完了の LED = D1 が点灯します。
D1 が点灯しなくなれば、GND との接続が絶てたと思って大丈夫そうです。

何度かドリルを通して、Slave Serial 状態に変更できたらしい基板は下記のようになりました。
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/268bc943-5c79-9d88-52d7-79bbe0bd6bff.jpeg)

#RasPi と Wukong の接続
うまく起動モードが変更できたら、RasPi の 40pin バスから、Slave Serial 信号線  3 本(CCLK, DIN, GND) を Wukong 基板の SPI フラッシュの該当信号ピンに接続します。
下の図と写真を参考にしてください。
![rp2_pinout_gray2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/0b382a88-1409-19ce-651e-8f907a068484.png)
![Slave_Serial.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/94badff7-bd7f-f7eb-3f1b-47238508ba6d.png)
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/55ef9b26-c4a6-0866-1675-e927f37a8ddd.jpeg)


FPGA を壊したくないので、先に Wukong 基板の電源を入れてから、RasPi の電源を入れます。


#Passive Serial 用のコンフィグレーションファイル(.bin)の作成
FPGA にダウンロードするプロジェクトは、
[激安 FPGA 開発ボード "Wukong" の導入 (Xilinx Artix-7 XC7A100T)](https://qiita.com/kan573/items/0a95a4367da4c0914944#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB)
で使用したサンプル Test06_HDMI_OUT を使います。

Vivado で、通常のコンパイルを行うと、JTAG ダウンロード用の top.bit ファイルが生成されます。
このファイルは、ダウンロードケーブルで JTAG ダウンロードするときに使う形式で、ヘッダー情報などが含まれています。

Passive Serial ダウンロードでは、ヘッダー情報などが含まれていない生のコンフィグレーションデータ(top.bin)を使用します (UG570 Table 5-1)
![UG470_Table5-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/1290797f-fcdf-673d-2780-72fbe27ce359.png)


この top.bin ファイルを生成するよう、オプションをオンにします。

Generate Bitstream で右クリックして、BitStream Settings を開きます。
![Bitstream Settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/5c112179-3304-1c33-6c9d-a94ed403e33d.png)

Settings で、-bin_file にチェックを入れて OK します。
![Bitstream Settings_binFile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/ac2eef7b-165b-edf3-4445-45e600a89f3a.png)

ここから、Generate Bitstream すると、top.bit が生成されたのと同じフォルダに、top.bin も生成されます。
デスクトップにサンプルプロジェクトを展開した場合、場所は下記に。
C:/Users/(user)/Desktop/Test06_HDMI_OUT/Test06_HDMI_OUT/Test06_HDMI_OUT.runs/impl_1/top.bin

生成した .bin ファイルの大きさは、3,825,788 バイトになりました。
Table1-1 に、XC7A100T の Configuration Bitstream Length (bits) で示されている数値(30,606,304 bis = 3,825,788 Bytes)と一致します (UG470 Table 1-1)
![UG470_Table1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/a42834e6-381a-0a83-3bc9-59986331b79f.png)



#RasPi からのダウンロード
FPGA への SPI ダウンロードを実行するプログラムは、
[RasPi 3B+ で最新の spidev_test を使う](https://qiita.com/kan573/items/b362b6b9fc493ee2223f)
で用意した最新版の spidev_test を使用します。

コンフィグレーションデータの大きさは 3.64MB ありますので、バッファサイズも最大(4MB)まで拡張しておきます。

samba 経由で RasPi に top.bin をコピーしたら、

```
pi@raspberrypi:~$ ./spidev_test -D /dev/spidev0.0 -i top.bin -s 50000000
```
でダウンロードを開始します。
50MHz の Slave Serial でコンフィグレーションが完了して、D1 が点灯します。
直後に、HDMI からカラーバー出力が出てきます。
ダウンロードにかかる時間は、640ms ほどで、ほぼ一瞬です。

Vivado から JTAG でダウンロードすると 12秒ほどかかります(※)ので、圧倒的に早いです。

※ダウンロードケーブルへの接続を 12MHz に変更すると 7 秒ほど

SW1 を押すと FPGA がリセットされ、再度 Slave Serial のコンフィグ待ちに戻ります。
再度、上記コマンドでダウンロードできます。
何度でも再コンフィグできます。

ダウンロード中の SPI 信号の波形を示します。
RasPi の OS 側の処理の都合で、途中で CLK/DATA が一時停止する期間が生じます。
都度、ランダムな場所に1～3回ほど発生しますが、FPGA へのダウンロードには影響しません。
ダウンロードは100発100中で成功します。
![image9414.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/07ca2827-0e9e-ff23-7d09-db7aebbc7989.png)

100MHz でも試してみます。

```
pi@raspberrypi:~$ ./spidev_test -D /dev/spidev0.0 -i top.bin -s 100000000
```
こちらも、問題無くダウンロードできました。
ダウンロードにかかる時間は、410ms ほどです。
CLK/DATA の停止期間が複数回発生しても、100% 成功します。
単純なシフトレジスタで SRAM に格納されてゆく仕組みで、クロックとデータが同時に停止する分には影響を受けない、ということでしょうか。

#まとめ
RasPi の SPI バスから、Artix-7 FPGA に Slave Serial でのダウンロードが実現できました。
RasPi + FPGA のシステムを構築する際、FPGA のコンフィグを RasPi から行う事ができます。

FPGA を SPI フラッシュから起動する仕組みだと、FPGA の更新やバグ修正の際には、SPI フラッシュの書き換えが必要になります。
FPGA を RasPi からダウンロードして起動できると、RasPi のソフトウェアに FPGA データを抱かせておけばよいので、更新が非常に楽になります。

今回の例では Xilinx FPGA での例を説明しました。
Intel(Altera) FPGA でも Passive Serial がサポートされており、全く同じ仕組みでダウンロードが可能と思います。