1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UltraZed 向け Debian GNU/Linux (v2017.3版) で FPGA をコンフィギュレーション

Last updated at Posted at 2017-12-31

はじめに

次の記事で UltraZed 向け Debian GNU/Linux (v2017.3版) の構築をしました。

また、次の記事で、上の記事で構築したシステムのイメージを紹介しました。

この記事では、上の記事で構築したシステムを使って、Linux から FPGA をコンフィギュレーションする例を示します。この記事で紹介する FPGA のデザインやプログラムは次の URL に公開しています。

Sample FPGA Design

今回 FPGA にコンフィギュレーションする回路は、次の記事で説明したものを使用します。

デザインのブロック図は次のようになっています。

Fig.1 ZynqMP Sample Design

Fig.1 ZynqMP Sample Design

準備

UltraZed の準備

次の記事を参考に UltraZed に Debian GNU/Linux (v2017.3版) をインストールしてください。

fpga でログイン

Linux が起動したら ユーザー名 fpga でログインします。パスワードは fpga になっています。

debian-fpga login: fpga
Password:
fpga@debian-fpga:~$

リポジトリのダウンロード

サンプルとなる FPGA デザインやプログラムを下記の URL よりダウンロードします。

ここでは v2017.3 版 を examples/gpio としてダウンロードします。

fpga@debian-fpga:~$ mkdir examples
fpga@debian-fpga:~$ cd examples
fpga@debian-fpga:~/examples$ git clone -b v2017.3 https://github.com/ikwzm/ZynqMP-FPGA-Linux-Example-0-UltraZed gpio
fpga@debian-fpga:~/examples$ cd gpio
fpga@debian-fpga:~/examples/gpio$ git checkout v2017.3

FPGA のコンフィギュレーション

Binary File への変換

今回構築した Debian GNU/Linux には FPGA Reagion が組み込まれています。残念ながら、次の記事のとおり FPGA Regsion と FPGA Manager の組み合わせでは Xilinx のビットストリームを直接読めません。したがって、まずはビットストリームファイルを変換する必要があります。

fpga@debian-fpga:~/examples/gpio$ python3 fpga-bit-to-bin.py -f design_1_wrapper.bit design_1_wrapper.bin
Design name: b'design_1_wrapper;UserID=0XFFFFFFFF;Version=2017.2.1\x00'
Full bitstream
Partname b'xczu3eg-sfva625-1-i\x00'
Date b'2017/12/24\x00'
Time b'10:39:58\x00'
Found binary data: 5568668
Flipping data...
Writing data...

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 用のソースファイルを用意します。

fpga-load.dts
/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 のコンフィギュレーションを行います。

  1. Device Tree Overlay 用ソースファイル(ここでは fpga-load.dts)を dtc(Device Tree Compiler) を使って dtb (ここでは fpga-load.dtb) に変換する。
  2. /config/device-tree/overlays 下に Device Tree Overlay 用のディレクトリ(ここでは fpga) を作る。
  3. 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 用のソースファイルを用意します。

fclk0-zynqmp.dts
/dts-v1/;/plugin/;
/ {
	fragment@0 {
		target-path = "/amba";
		__overlay__ {
			fclk0 {
				compatible    = "ikwzm,fclkcfg-0.10.a";
				clocks        = <&clkc 0x47>;
				insert-rate   = "100000000";
				insert-enable = <1>;
				remove-rate   = "1000000";
				remove-enable = <0>;
			};
		};
	};
};

ここでは clocks で ZynqMP の PL CLOCK[0] を指定しています。&clkc はクロック制御ドライバのシンボル名、0x47 は PL CLOCK[0] のインデックス番号です。また、この Device Tree が挿入されたとき PL CLOCK[0] は 周波数 100MHz のクロックを出力するように設定しています。

次の手順で Device Tree Overlay を使ってクロックを設定します。

  1. Device Tree Overlay 用ソースファイル(ここでは fclk0-zynqmp.dts)を dtc(Device Tree Compiler) を使って dtb (ここでは fclk0-zynqmp.dtb) に変換する。
  2. /config/device-tree/overlays 下に Device Tree Overlay 用のディレクトリ(ここでは fclk0) を作る。
  3. 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 用のソースファイルを用意します。

uio.dts
/dts-v1/;
/ {
	fragment@0 {
		target-path = "/amba_pl@0";
		#address-cells = <2>;
		#size-cells = <2>;

		__overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;

			uio0: uio@80000000 {
				compatible = "generic-uio";
				reg = <0x0 0x80000000 0x0 0x10000>;
	                };
			uio1: uio@80010000 {
				compatible = "generic-uio";
				reg = <0x0 0x80010000 0x0 0x10000>;
	                };
			uio2: uio@80020000 {
				compatible = "generic-uio";
				reg = <0x0 0x80020000 0x0 0x10000>;
	                };
                };
	} ;
} ;

Zynq の場合と異なり、注意点があります。

  1. target-path に "/amba_pl@0" を指定します。
  2. address-cells と size-cells がともに 2 であること。これは ZynqMp のアドレスのビット幅が 64bit であるためです。従って reg には <アドレスの上位32bit アドレスの下位32bit サイズの上位32bit サイズの下位32bit> という形で指定します。

次の手順で Device Tree Overlay を使って Uio を設定します。

  1. Device Tree Overlay 用ソースファイル(ここでは uio.dts)を dtc(Device Tree Compiler) を使って dtb (ここでは uio.dtb) に変換する。
  2. /config/device-tree/overlays 下に Device Tree Overlay 用のディレクトリ(ここでは uio) を作る。
  3. 2.で作ったディレクトリ下の dtbo に 1. で作った dtb を書き込む。

これで次のように /dev/uio0、/dev/uio1、/dev/uio2 が出来れば成功です。

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

LED を点滅させてみる

次のような Python のプログラムを用意しました。

led_on.py
from uio     import Uio
import numpy as np
import time
import signal

class  LED:
    def __init__(self):
        self.uio  = Uio('uio1')
        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 は次の記事で紹介したものです。

上のプログラムを走らせてみて数秒 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

参考

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?