TinyFPGA BX が来たので動かしてみた

投稿者: | 2019/11/27

Received my own TinyFPGA BX yesterday so ran it in anyway!  Also dived into underlying software (Yosys, Arachne-pnr etc.) very shallowly...

昨日、TinyFPGA BX が届きました。早速、公式サイトを見ながらいじってみたのですが、いくつかトラブルに遭遇。備忘録としてまとめてみました。同じような問題に遭遇する方もあるかも知れないので、御参考になれば幸いです。

TinyFPGA BX に乗っている FPGA は Lattice 社の iCE40LP8K で、logic cell が 7,680個乗っています。ちなみにこのシリーズの logic cell は、4入力 1出力の LUT が 1つと D-FF が 1つで構成されています。

FPGA 内ブートローダーのアップデート

TinyFPGA BX に搭載されている FPGA(Lattice iCE40)のコンフィグレーション(ビットストリームの読み込み)には、外付けの SPI Flash メモリを利用します。しかし、この TinyFPGA ボードはコンパクトに実装することを目標としているため、SPI Flash メモリのライタ(書込み機能)を外付けチップ(FTDI FT232H など)として搭載せず、FPGA 自身で実装するブートローダーハードウェアでライタを実現しています。つまり、まさにミュンヒハウゼン男爵の話どおり、最初のブートローダーはどうやって SPI Flash に書き込むんだ!?  ということになりますが、答えは簡単で、基板裏には SPI Flash メモリへのアクセスパッドが出ており、出荷時に SPI ライタ(おそらく FTDI のチップ)で書き込んでいるようです。

余談ですが、そんな訳でブートローダーを壊してしまうと面倒です。こちらに、その時の解決法に関する記事がありました。

公式サイトに従って、私の Mac OS (El Capitan) に apio をインストールしてみましたが、こんなエラーが出て、デバイスにアクセスできません。

$ tinyprog --update-bootloader

TinyProg CLI
------------
Using device id 1d50:6130
No port was specified and no active bootloaders found.
Activate bootloader by pressing the reset button.

どうも、Mac OS から TinyFPGA の USB CDC(仮想シリアル)にアクセスできていないようです。いろいろと調べると、新しい Mac OS では OK ぽいので、私の Mac OS が古いのでしょう。しようがないので、VMware 上のゲスト OS である Ubuntu 16.04.6 を使うことにしました。Ubuntu Linux では無事に tinyprog が動作しました。

なお、リリース版の tinyprog は Python 3 であまりテストされていないらしく、問題に遭遇することがあります。そのときは、こちらを御参考ください。なお、GitHub 上の master ブランチでは問題が修正されているようです。

説明に従い Atom エディタとプラグインをインストール

続いて、Atom エディタをインストールします。結論としては、別に Atom は要らないようですが、いきなり apio コマンドを使うのは不安があった(というか分からなかった)のでインストールしました。

しかしドキュメント通りにやっても、問題が生じます。Atom の apio 拡張から FPGA にビットストリームを upload をしようとすると、

Error: board TinyFPGA-BX not connected

というエラーになってしまうのです。これもネットを探すと、作者の方が「ああしろ」「こうしろ」と手引きをしてますが、私の環境では結局動きませんでした。

後述: いま、これを書いていて原因が分かりました。usermod コマンドで自分を dialout グループに割り当てたあと、Ubuntu デスクトップに再ログインするのを忘れてました。後述のコマンドラインでは、ssh で再ログインしていたので、うまく行っていたのです。とほほ。失礼しました。

apio のコマンドラインでやってみよう

次に、apio のコマンドラインでやってみます。ビルドするサンプルは、上記公式サイトの GitHub リポジトリにある apio_template です。公式サイトの設定通りにインストールした後、apio_template ディレクトリの中で(公式サイト説明通り blink_project にコピーしておいたほうがベター)、

$ apio build
[Wed Nov 27 12:32:58 2019] Processing TinyFPGA-BX
--------------------------------------------------------------------------------
yosys -p "synth_ice40 -blif hardware.blif" -q top.v
arachne-pnr -d 8k -P cm81 -p pins.pcf -o hardware.asc -q hardware.blif
(たくさんの警告)
icepack hardware.asc hardware.bin
========================= [SUCCESS] Took 2.21 seconds =========================
$

うまく行きました。これを TinyFPGA(の SPI Flash)にアップロードするには、

$ apio upload
[Wed Nov 27 12:34:46 2019] Processing TinyFPGA-BX
--------------------------------------------------------------------------------
tinyprog --pyserial -c /dev/ttyACM0 --program hardware.bin
Erasing:  97%|█████████▋| 131k/135k [00:00<00:00, 163kB/s]
Erasing: 100%|██████████| 135k/135k [00:00<00:00, 158kB/s]
Writing:  99%|█████████▉| 134k/135k [00:02<00:00, 56.1kB/s]
Writing: 100%|██████████| 135k/135k [00:02<00:00, 65.7kB/s]
Reading:  96%|█████████▌| 130k/135k [00:00<00:00, 215kB/s]

TinyProg CLI
------------
Using device id 1d50:6130
Programming /dev/ttyACM0 with hardware.bin
Programming at addr 028000
Waking up SPI flash
135100 bytes to program
Success!

Reading: 100%|██████████| 135k/135k [00:00<00:00, 215kB/s]
========================= [SUCCESS] Took 4.27 seconds =========================
$

これもうまく行きました。USB コネクタから見て右手の LED(Boot LED)がモールス信号で SOS(・・・ ——— ・・・)を打っていれば成功です。

各コマンドの使い方をもう少し調べてみる

これだけではあまりにも簡単すぎますし、ネット上にも情報が溢れていますので、もう少しコマンドの使い方を理解しておきましょう。

apio というのは結局ラッパーツールであり、背後の次のようなコマンドを動かしているのだということが分かります。

余談ですが、arachne-pnr は apache-pnr ではありません。 🙂  arachne というのは、日本語だとアラクネと読むそうで、ギリシャ神話の登場人物だそうです。pnr というのは placing and routing の略ですね。あるウェビナーを見ていたら、pnr を「ピナー」と発音しているように聞こえました。つまり、アラクネ・ピナーですが、日本人的にはピーエヌアールでも良さそうです。

各ツールを実行してみる前に、まず最初の疑問です。apio ツールはターゲットの FPGA 種別をどうやって認識しているのでしょう。実は簡単で、apio コマンドは apio.ini というファイルを読み取って FPGA 種別を決めているのです。では、そのファイルの書き方は!?  こちらに説明がありました。

$ apio boards --list

Supported boards:

--------------------------------------------------------------------------------
Board            FPGA                 Type  Size  Pack      
--------------------------------------------------------------------------------
Cat-board        iCE40-HX8K-CT256     hx    8k    ct256     
TinyFPGA-B2      iCE40-LP8K-CM81      lp    8k    cm81      
TinyFPGA-BX      iCE40-LP8K-CM81      lp    8k    cm81      
alhambra-ii      iCE40-HX4K-TQ144     hx    8k    tq144:4k  
blackice         iCE40-HX4K-TQ144     hx    8k    tq144:4k  
blackice-ii      iCE40-HX4K-TQ144     hx    8k    tq144:4k  
fpga101          iCE40-UP5K-SG48      up    5k    sg48      
go-board         iCE40-HX1K-VQ100     hx    1k    vq100     
iCE40-HX8K       iCE40-HX8K-CT256     hx    8k    ct256     
iCE40-UP5K       iCE40-UP5K-SG48      up    5k    sg48      
iCEBreaker       iCE40-UP5K-SG48      up    5k    sg48      
iCEBreaker-bitsy iCE40-UP5K-SG48      up    5k    sg48      
iceblink40-hx1k  iCE40-HX1K-VQ100     hx    1k    vq100     
icestick         iCE40-HX1K-TQ144     hx    1k    tq144     
icezum           iCE40-HX1K-TQ144     hx    1k    tq144     
icoboard         iCE40-HX8K-CT256     hx    8k    ct256     
kefir            iCE40-HX4K-TQ144     hx    8k    tq144:4k  
upduino          iCE40-UP5K-SG48      up    5k    sg48      
upduino2         iCE40-UP5K-SG48      up    5k    sg48  

Use `apio init --board <boardname>` to create a new apio project for that board
$ apio init --board TinyFPGA-BX
Creating apio.ini file ...
File 'apio.ini' has been successfully created!
$

これで apio.ini ファイルができました。

それではここからは、apio コマンドを使わずに直接、下層ツールを動かしてみましょう。まずは PATH を設定しておきます。

$ export PATH=$HOME/.apio/packages/toolchain-icestorm/bin:$PATH

Yosys

上記 apio の出力を見ると、yosys に次のようなコマンドライン引数を与えているのが分かります。

-p "synth_ice40 -blif hardware.blif" -q top.v

ヘルプ等を見て調べると、-p に与えている引数(ダブルクオートで囲まれていることに注意)は、yosys へのコマンドだそうです。yosys は実は対話的に実行することが可能で、その時のコマンドなのです。-blif というのは、合成結果を BLIF(Berkeley Logic Interchange Format)で出力しなさい、という意味のようです。-q は quiet で、最後に与えているのが Verilog ソースファイルです。

それでは yosys を対話的に実行してみましょう。

$ yosys
(略)
yosys> read -sv top.v
1. Executing Verilog-2005 frontend.
Parsing SystemVerilog input from `top.v' to AST representation.
Generating RTLIL representation for module `\top'.
Successfully finished Verilog frontend.

yosys> synth_ice40 -blif hardware.blif
(略)
2.29. Executing BLIF backend.

yosys> exit
$ ls *blif
hardware.blif

うまく行きましたでしょうか?  (-sv というのはよく分かりませんが、与えるファイルの形式(Verilog のバージョンとか)のようです。デフォルトが -sv で、しかし対話モードでは省略できないようなので指定しています。)

arachne-pnr

次に、place and route です。arachne-pnr  のコマンドラインオプションは

-d 8k -P cm81 -p pins.pcf -o hardware.asc -q hardware.blif

でした。-d と-P に与えるオプションは、こちらを調べると分かります。TinyFPGA BX の搭載 FPGA は iCE40LP8K-CM81 なので、こうなる訳ですね。-p は PCF(Physical Constraints File)というもので、つまり FPGA 屋さんの言葉で言う「コンストレイント」を定義しているファイルです。簡単に言えば、HDL ファイルから参照される信号名と物理的な FPGA のピン名を結びつける定義をしています。-o は出力ファイル(テキスト形式のビットストリーム)の指定ですね。-q  は quiet で、最後の引数が入力の BLIF ファイルです。

icepack

最後に、生成されたビットストリームをバイナリ形式に変換します。

$ icepack hardware.asc hardware.bin

あとは、FPGA ボードの SPI Flash にアップロードするだけです。

tinyprog

次のように実行します。本当はいろいろオプションがありますが、デフォルトで実行しています。あ、まずは TinyFPGA BX のリセットボタンを押し、Boot LED がフワフワ明滅している状態(ブートローダー動作)にします。

$ tinyprog -p hardware.bin

書き込めましたね。apio で実行したのと同様、SOS を打っていれば OK です。

おまけ

TinyFPGA BX を PC の USB コネクタに繋ぐとブートローダーモードになってしまいます。別途 USB 電源等を持っていれば良いのですが、そうでないときに TinyFPGA BX で実装した回路をデモしたいときにはどうしたら良いのでしょう?

正式なやり方としては、tinyprog コマンドを使います。

tinyprog -b

もし、手持ちの PC に tinyprog が入っていなかったら?  次のコマンドで 0x00 のバイトを USB CDC(仮想シリアル)に送ってあげれば OK です。参考: GitHub - tinyfpga/TinyFPGA-Bootloader

$ echo -ne '\0' > /dev/ttyACM0

まとめ

私は以前に、Xilinx の Artix-7 を載せた Cmod-A7 を Vivado で動かしたことがあります。その時は、チュートリアルに従って操作しているだけで(実際には、仕事で MicroBlaze を動かしたりしましたが)、背後で何が動いているかは、あまり理解していませんでした。

今回も、Yosys や arachne-pnr、また Project IceStorm の皆様が多大な苦労をなさって提供したリバースエンジニアリングドキュメントの詳細はまったく理解できていませんが、このようなフリーのツールで、コマンドラインで Verilog HDL を合成、配置、ルーティングを実行し、実際に FPGA 上で動かすことができることに感激しました。もう少し Verilog を勉強して、実務に役立てれば、と思っています。

今日はここまで。

2019/11/27 カテゴリー: FPGA