Fomu 事始め

USBスロットに収まるサイズののFPGAバイスで6000円ぐらいでCrowd supplyで購入できる。

自分の場合はストックがあったので、発注してからUPSで3日ぐらいで届いた。

搭載しているFPGAはLatticeのiCE40UP5kというものを積んでいるらしい。 全然わかっていないのでどの程度の回路が組めるかわからないが、LUTが5000個あって、RISC-Vを組み込んでいる。 その上で DFU のソフトウェア実装が動いている。

ソフトコアとブートローダfobootというリポジトリで管理されている。 ソフトコアは hw ディレクトリに収められていて、Migen という python による HDL ツールでビルドされるらしい。 とはいえ、メインの RISC-V の実装は、VexRISC-Vによるものを使うらしく、hw/rtlverilog ファイルが収まっている。 VexRISC-Vは SpinalHDLという高レベルHDLで実装されている。 SpinalHDL は Scala で実装されており、Chiselといい、この分野は Scala が流行っているのかもしれない。

Getting Started として workshopがあるのでこれに沿って初めてみる。

手元の環境は arch linux を使っている。

workshop は Foboot として v2.0.3 以上を要求している。

$ sudo pacman -S dfu-util
$ sudo dfu-util -l
...
Found DFU: [1209:5bf0] ver=0101, devnum=5, cfg=1, intf=0, path="1-9", alt=0, name="Fomu PVT running DFU Bootloader v1.9.1", serial="UNKNOWN"

確認すると残念ながらバージョンが古いのでまずはアップデートが必要になる。

Bootloaderのページを参考にアップデートを行う。

ファームウェアの種類としては PVT (Production Validation and Testing)を選べば良い。

$ curl -OL https://github.com/im-tomu/foboot/releases/download/v2.0.3/pvt-updater-v2.0.3.dfu
$ sudo dfu-util -D pvt-updater-v2.0.3.dfu
$ sudo dfu-util -l
...
Found DFU: [1209:5bf0] ver=0101, devnum=6, cfg=1, intf=0, path="1-9", alt=0, name="Fomu PVT running DFU Bootloader v2.0.3", serial="UNKNOWN"

workshop リポジトリを clone する。 400MB 程度をダウンロードするので少し時間がかかる。

$ git clone --recurs https://github.com/im-tomu/fomu-workshop.git

次にツールチェインをインストールする。 手順ではビルド済みバイナリを利用するが、OS 標準リポジトリと AUR を使ってみる。

nextpnr の依存で必要な trellis ビルドがコケるので trellis-git を選択する。

$ yay -S nextpnr-git
$ sudo pacman -S yosys
$ sudo pacman -S wishbone-utils
$ yay -S riscv64-unknown-elf-gcc riscv64-unknown-elf-newlib

udev を設定して dfu-util を sudo なしで動かすのが公式手順だが、今回はスキップ。

workshop リポジトリに micropython のバイナリがあるのでロードして動かしてみる。

$ sudo dfu-util -D micropython-fomu.dfu

これで fomu がシリアルデバイスに化けるので、screen などでつなぐ。

$ sudo screen /dev/ttyACM1
MicroPython v1.10-308-g421dcd2 on 2020-01-03; fomu with vexriscv

>>>

サンプルはエルチカさせるものだが micropython が拡張されているので簡単。

>>> import fomu
>>> rgb = fomu.rgb()
>>> rgb.mode("idle")
>>> rgb.mode("done")
>>> rgb.mode("writing")
>>> rgb.mode("error")

LED 点滅は Lattice のハードウェアブロックで実装されていて、レジスタをメモリーにマップしているらしい。 この辺でやっているっぽいが、migen を勉強しないと読めないですね。

コンポーネントは、wishbone bus というバスでつながっている。 fomu の場合は bridge が wishbone bus につながっていて、USB 経由でバスをいじることができる。 そのため USB 経由で直接メモリをいじったりできる。 これを利用して gdb でリモートデバッグすることもできる。

あとは、verilog で Lチカしたり、Migen で wishbone bus につながる USB デバイスを作ったりという感じ。