はじめに
次の記事で UltraZed 向け Debian GNU/Linux (v2018.2版) の構築をしました。
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(イントロ編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(Boot Loader編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(Linux Kernel編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(Debian9 Root File System編)」@Qiita
また、次の記事で、上の記事で構築したシステムのイメージを紹介しました。
この記事では、上の記事で構築したシステムを使って、Linux から FPGA をコンフィギュレーションする例を示します。この記事で紹介する FPGA のデザインやプログラムは次の URL に公開しています。
Sample FPGA Design
今回 FPGA にコンフィギュレーションする回路は、次の記事で説明したものを使用します。
デザインのブロック図は次のようになっています。
Fig.1 ZynqMP Sample Design
UltraZed 向け Debian GNU/Linux (v2018.2版) で FPGA にロードするためには、Bitstream File を Binary File に変換する必要があります。Binary File への変換は、次のような bif file を用意して、Vivado-SDK v2018.2 の bootgen コマンドを使います。
all:
{
[destination_device = pl] design_1_wrapper.bit
}
vivado% bootgen -image design_1_wrapper.bif -arch zynqmp -w -o design_1_wrapper.bin
Binary File の作り方の詳細は以下の URL を参照してください。
準備
UltraZed の準備
次の記事を参考に UltraZed に Debian GNU/Linux (v2018.2版) をインストールしてください。
fpga でログイン
Linux が起動したら ユーザー名 fpga でログインします。パスワードは fpga になっています。
debian-fpga login: fpga
Password:
fpga@debian-fpga:~$
リポジトリのダウンロード
サンプルとなる FPGA デザインやプログラムを下記の URL よりダウンロードします。
ここでは v2018.2 版 を examples/gpio としてダウンロードします。
fpga@debian-fpga:~$ mkdir examples
fpga@debian-fpga:~$ cd examples
fpga@debian-fpga:~/examples$ git clone https://github.com/ikwzm/ZynqMP-FPGA-Linux-Example-0-UltraZed gpio
fpga@debian-fpga:~/examples$ cd gpio
fpga@debian-fpga:~/examples/gpio$ git checkout v2018.2
FPGA のコンフィギュレーション
Binary File を /lib/firmware へコピー
FPGA Region では /lib/firmware にコンフィギュレーションするファイルを置いておく必要があります。
fpga@debian-fpga:~/examples/gpio$ sudo cp design_1_wrapper.bin /lib/firmware
Device Tree Overlay による FPGA のコンフィギュレーション
FPGA Region では Device Tree を使って FPGA をコンフィギュレーションします。そこで次のような Device Tree Overlay 用のソースファイルを用意します。
/dts-v1/;
/ {
fragment@0 {
target-path = "/fpga-full";
__overlay__ {
firmware-name = "design_1_wrapper.bin";
};
};
};
target-path が "/fpga-full" であることに注意してください。これは Linux 起動時に読み込んだ Device Tree で指定した fpga-region のシンボル名です。
次の手順で Device Tree Overlay による FPGA のコンフィギュレーションを行います。
- Device Tree Overlay 用ソースファイル(ここでは fpga-load.dts)を dtc(Device Tree Compiler) を使って dtb (ここでは fpga-load.dtb) に変換します。
- /config/device-tree/overlays 下に Device Tree Overlay 用のディレクトリ(ここでは fpga) を作ります。
- 2.で作ったディレクトリ下の dtbo に 1. で作った dtb を書き込みます。
これで次のようなカーネルメッセージが出れば、FPGA のコンフィギュレーションは成功です。
fpga@debian-fpga:~/examples/gpio$ dtc -I dts -O dtb -o fpga-load.dtb fpga-load.dts
fpga@debian-fpga:~/examples/gpio$ sudo mkdir /config/device-tree/overlays/fpga
fpga@debian-fpga:~/examples/gpio$ sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
[ 1462.560122] fpga_manager fpga0: writing design_1_wrapper.bin to Xilinx ZynqMP FPGA Manager
FPGA のクロックの設定
FPGA をコンフィギュレーションするだけでは FPGA 側の回路は動きません。なぜなら FPGA へ供給するクロックの設定が終わっていないからです。
ここでは fclkcfg を使ってクロックを設定します。fclkcfg は筆者が作ったデバイスドライバで、次の URL に公開しています。
「UltraZed 向け Debian GNU/Linux ブートイメージの提供」をインストールしてあれば、すでに fclkcfg が組み込まれています。
クロックを設定するには、次のような Device Tree Overlay 用のソースファイルを用意します。
/dts-v1/;/plugin/;
/ {
fragment@0 {
target-path = "/amba";
__overlay__ {
fclk0 {
compatible = "ikwzm,fclkcfg-0.10.a";
clocks = <&clk 0x47>;
insert-rate = "100000000";
insert-enable = <1>;
remove-rate = "1000000";
remove-enable = <0>;
};
};
};
};
ここでは clocks で ZynqMP の PL CLOCK[0] を指定しています。&clk
はクロック制御ドライバのシンボル名、0x47 は PL CLOCK[0] のインデックス番号です。また、この Device Tree が挿入されたとき PL CLOCK[0] は 周波数 100MHz のクロックを出力するように設定しています。
なお、「UltraZed 向け Debian GNU/Linux (v2017.3版) で FPGA をコンフィギュレーション」 で説明した fclk0-zynqmp.dts とは clocks の記述が違うことに注意してください。v2017.3版では <&clkc 0x47>
でしたが、v2018.3版では <&clk 0x47>
となっています。
次の手順で Device Tree Overlay を使ってクロックを設定します。
- Device Tree Overlay 用ソースファイル(ここでは fclk0-zynqmp.dts)を dtc(Device Tree Compiler) を使って dtb (ここでは fclk0-zynqmp.dtb) に変換します。
- /config/device-tree/overlays 下に Device Tree Overlay 用のディレクトリ(ここでは fclk0) を作ります。
- 2.で作ったディレクトリ下の dtbo に 1. で作った dtb を書き込みます。
これで次のようなカーネルメッセージが出れば、FPGA クロックの設定は成功です。
fpga@debian-fpga:~/examples/gpio$ dtc -I dts -O dtb -o fclk0-zynqmp.dtb fclk0-zynqmp.dts
fpga@debian-fpga:~/examples/gpio$ sudo mkdir /config/device-tree/overlays/fclk0
fpga@debian-fpga:~/examples/gpio$ sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
[ 1830.238976] fclkcfg amba:fclk0: driver installed.
[ 1830.243617] fclkcfg amba:fclk0: device name : fclk0
[ 1830.248737] fclkcfg amba:fclk0: clock name : pl0
[ 1830.253678] fclkcfg amba:fclk0: clock rate : 99999999
[ 1830.259085] fclkcfg amba:fclk0: clock enabled : 1
[ 1830.263833] fclkcfg amba:fclk0: remove rate : 1000000
[ 1830.269125] fclkcfg amba:fclk0: remove enable : 0
Uio の準備
FPGA にコンフィギュレーションした回路にアクセスするには UIO を使います。UIO を使うために次のような Device Tree Overlay 用のソースファイルを用意します。
/dts-v1/;
/ {
fragment@0 {
target-path = "/amba_pl@0";
#address-cells = <2>;
#size-cells = <2>;
__overlay__ {
#address-cells = <2>;
#size-cells = <2>;
uio1: uio@80000000 {
compatible = "generic-uio";
reg = <0x0 0x80000000 0x0 0x10000>;
};
uio2: uio@80010000 {
compatible = "generic-uio";
reg = <0x0 0x80010000 0x0 0x10000>;
};
uio3: uio@80020000 {
compatible = "generic-uio";
reg = <0x0 0x80020000 0x0 0x10000>;
};
};
} ;
} ;
Zynq の場合と異なり、注意点があります。
- target-path に
"/amba_pl@0"
を指定します。 - address-cells と size-cells がともに 2 であること。これは ZynqMp のアドレスのビット幅が 64bit であるためです。従って reg には <アドレスの上位32bit アドレスの下位32bit サイズの上位32bit サイズの下位32bit> という形で指定します。
次の手順で Device Tree Overlay を使って Uio を設定します。
- Device Tree Overlay 用ソースファイル(ここでは uio.dts)を dtc(Device Tree Compiler) を使って dtb (ここでは uio.dtb) に変換します。
- /config/device-tree/overlays 下に Device Tree Overlay 用のディレクトリ(ここでは uio) を作ります。
- 2.で作ったディレクトリ下の dtbo に 1. で作った dtb を書き込みます。
これで次のように /dev/uio1、/dev/uio2、/dev/uio3 が出来れば成功です。
fpga@debian-fpga:~/examples/gpio$ dtc -I dts -O dtb -o uio.dtb uio.dts
fpga@debian-fpga:~/examples/gpio$ sudo mkdir /config/device-tree/overlays/uio
fpga@debian-fpga:~/examples/gpio$ sudo cp uio.dtb /config/device-tree/overlays/uio/dtbo
fpga@debian-fpga:~/examples/gpio$ ls -la /dev/uio*
crw------- 1 root root 245, 0 Dec 31 10:20 /dev/uio0
crw------- 1 root root 245, 1 Dec 31 10:20 /dev/uio1
crw------- 1 root root 245, 2 Dec 31 10:20 /dev/uio2
crw------- 1 root root 245, 2 Dec 31 10:20 /dev/uio3
LED を点滅させてみる
次のような Python のプログラムを用意しました。
from uio import Uio
import numpy as np
import time
import signal
class LED:
def __init__(self):
self.uio = Uio('uio2')
self.regs = self.uio.regs()
self.regs.write_word(4, 0)
self.pattern = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02]
self.index = 0
def run(self):
self.regs.write_word(0, self.pattern[self.index])
if self.index < len(self.pattern)-1:
self.index = self.index + 1
else:
self.index = 0;
if __name__ == '__main__':
led = LED()
for i in range(100):
led.run()
time.sleep(0.1)
ここで import している uio.py は次の記事で紹介したものです。
なお、「UltraZed 向け Debian GNU/Linux (v2017.3版) で FPGA をコンフィギュレーション」 で説明した led_on.py とは指定した uio のデバイスドライバ名が違うことに注意してください。v2017.3 では Uio('uio1')
でしたが v2018.3 では Uio('uio2')
になっています。
上のプログラムを走らせてみて数秒 LED が左右に点滅すれば成功です。
fpga@debian-fpga:~/examples/gpio$ sudo python3 led_on.py
後始末
遊び終わったら、Device Tree Overlay で追加したデバイスツリーを、後から追加した順に削除します。
fpga@debian-fpga:~/examples/gpio$ sudo rmdir /config/device-tree/overlays/uio
fpga@debian-fpga:~/examples/gpio$ sudo rmdir /config/device-tree/overlays/fclk0
[ 2149.037235] fclkcfg amba:fclk0: change rate : 992064
[ 2149.042497] fclkcfg amba:fclk0: change enable : 0
[ 2149.047353] fclkcfg amba:fclk0: driver unloaded
fpga@debian-fpga:~/examples/gpio$ sudo rmdir /config/device-tree/overlays/fpga
注意
Binary File Format について
次で示す記事で v2017.3版 での方法を示しました。
v2018.2 版では Binary File のフォーマットが異なっていることに注意してください。v2017.3 では fpga-bit-to-bin.py という Python のスクリプトを使って変換した Binary File を使いましたが、v2018.2 からは Vivado-SDK の bootgen で変換した Binary File を使う必要があります。
なお、v2018.2 版で 2017.3 版と同様の fpga-bit-to-bin.py を使って変換した Binary File を扱うには、次のように fpga_manager のフラグに 0x20 を設定します。
fpga@debian-fpga:~/examples/negative$ sudo echo 20 > /sys/class/fpga_manager/fpga0/flags
参考
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(イントロ編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(Boot Loader編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2017.3版) の構築(Sample FPGA Design編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(Linux Kernel編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(Debian9 Root File System編)」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供」@Qiita
- 「UltraZed 向け Debian GNU/Linux (v2017.3版) で Vivado-HLS を使って合成した回路を動かす」 @Qiita
- 「Python と Numpy で UIO を制御」@Qiita
- http://www.wiki.xilinx.com/Solution+ZynqMP+PL+Programming
- https://github.com/ikwzm/ZynqMP-FPGA-Linux-Example-0-UltraZed
- https://github.com/ikwzm/fclkcfg