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 というのは結局ラッパーツールであり、背後の次のようなコマンドを動かしているのだということが分かります。
- Yosys(RTL 合成フレームワーク)
- arachne-pnr(Placing/Routing ツール)
- icepack(ビットストリームフォーマット変換ツール)
- tinyprog(TinyFPGA プロジェクトのツール)
余談ですが、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 を勉強して、実務に役立てれば、と思っています。
今日はここまで。