はじめに
今更と言うところはあるのですが、FPGAプログラミングを知らない人に説明する機会も増えてきたので少し記事にしておきます。
FPGA とは
昔電子工作したときに撮影した写真が出てきたので張っておきますが、いわゆるこんなやつです。

タイプはいろいろあって、小さいものから大きなものまで。写真のように裏にI/Oピンなどの端子が並んでいるBGAタイプのものもあれば、周りにピンが生えているQFPタイプなどいろいろありますが、まあ見た目はCPUなどと同じで、中に入っている半導体シリコンがパッケージに収まっています。
とはいえ実際に使う時は、例えば私なんかは下記などをよく使うわけですが、パソコンのCPU同様に、冷却機構に隠れて直接は見えなかったりすることもあります(剝き出しで使う事も多いですが)。なのでとにかく電気的が端子がいっぱい出ているものという事だけ知っておいてください。
なぜこんな話をしているかと言うと、CPU/GPUのプログラミングと違ってFPGAプログラミングではデバイスから生えているピンを気にしないといけないからです。
普通に組み込みソフト書いている方はもちろん、Raspberry PI や Arduino や M5Stack などなど、今では親しみやすい IoT デバイスも多いので、そういうものに触れておられる方には I/Oピンと言われるとピンとくるのではないかと思います。
プログラミングで扱う範囲
さてここで、ソフトウェアプログラマがプログラミングで扱う範囲の話をします。
パソコンなどの場合

例えば、Python で何かアプリを書いてみようとなったとき、プログラミング言語はもちろん、例えば Flask や Django などのWebフレームワークであったり、PyTorch や numpy や matplotlib や scipy などのライブラリであったり、いろんなものを勉強しながらプログラミングされるかと思います。
この時、勉強するのが、自分が今から作ろうとする部分と、既に世の中にあり使おうとしているものの境界面のインターフェース仕様ではないかと思います。
これは既にある大変便利な機能の恩恵に預かれる半面、誰かが用意してくれた環境の中で出来る事以上の事ができない という事になりますので、誰もやった事の無い新しい事を研究開発したい とか 今の仕様じゃやりたいことがやれない とか、不都合が出るケースもあります。
組み込みマイコンの場合
これが例えば、ベアメタルのプログラミングになるとこれまたやれることが大きく変わってきます。特殊なスケジューリングをするOSのようなものを自作する事もできますし、割り込みを禁止して全力でADCの値をポーリングする処理を書いてみたり、部分的にキャッシュを無効にして処理するなどもできますし、お作法を無視したアグレッシブな実験がいろいろできます。
また、外部I/Oの制御を自分でプログラムする事も多いです、ちなみに手元にあった RaspberryPI が下記です。

RaspberryPI でマイコンの一部の端子が基板上のピンヘッダに引き出されています。これらのピンはピンごとに役割が決まっており GPIO や SPI や I2C などなど、それぞれのマイコンのハードウェア仕様で許されている範囲でプログラムから設定したり制御したりできます。
一方でこの際には、既存のOSやドライバは何も助けてくれませんので、マイコン上のプロセッサの仕様や外部デバイスの仕様を勉強することになります。プロセッサがどのように命令を実行してくれるのか、使うマイコンはどのような機能を内蔵していて、どこに何が繋がっているのか、よく理解した上で「0xFFFF0100 番地に1を書けばピンヘッダに繋いでいる外部スイッチがONになってモーターが回り始めるはずだ」と言ったプログラミングすることになります(番地は適当です)。
いずれにせよ、プログラマが勉強すべき、インターフェース仕様の界面(図の緑の位置)が変わることがとても重要なファクターだと思っております。
FPGAの場合
そして、FPGA プログラミングはここで、さらに、従来はプロセッサがやっていた部分まで、ソフトウェアプログラマが自由にプログラミングできる世界となります。
もっともCPUの上で動かすことを前提に作られているプログラミング言語は使えなくなるので、SystemVerilog や VHDL など、CPU自体をプログラミングする事すらできるさらにRTL(register transfer level)と呼ばれるようなレベルの言語にも触れていく事になります。
ここで先ほどの I/O の話に繋がるわけですが、FPGA はプログラミングはかなり I/Oピンに近いところまでソフトウェアプログラムの手の内に委ねられます。
FPGAの外部のピンがどういう動きをするか自体をプログラミングする ことが出来てしまうのでかなり何でもできます。
一応、
- 電源やGNDなどのピンは決まっている
- 電圧はI/Oバンクと呼ばれるグループ単位で供給される
- クロックは決まったピンにしか入れられない
- 高速シリアルや SDRAMなどピンが決まっているものもある
など、LSIの仕様で決まっている縛りもあります。
逆に言うと、FPGA で理解すべきインターフェースの界面はこれらのハードウェアデバイスであらかじめ決められた縛りなどであり、これらを駆使して思い通りにプログラマが外部仕様を決めていく事になります。
そして、いわゆるプロセッサが存在しない FPGA ではどのような方式で計算を進めるかの定義自体をソフトウェアプログラマが決めることが出来ます。FPGAのなかにソフトウェアでCPUを作り出すことも出来れば、全く新しい計算アーキテクチャをプログラムすることも出来ます。
FPGAでどんなプログラムが出来るのか?
FPGA の内部構造がどうなっていて、どうして自由にロジックがプログラムできるのかは、検索すればいろいろ出てくると思いますので、ここでは詳しくは触れませんが、どういう時にCPU/GPUを使わずにわざわざプログラマブルロジックを使うと嬉しいのかを少し紹介してみます。
面白い外部インターフェースを作る
インターフェースを自由に弄れるという事は例えばパソコンでは出来ない下記のよう事がいろいろ思いつきます
- 数ナノ秒ずつ位相をずらした信号を出力して特殊計測する
- エンコーダの値をマイクロ秒単位でフィードバックしてモーターの精密制御をする
- イメージセンサの露光制御と照明制御を同期させて特殊撮影を行う
- 全部のピンを通信用にして巨大ネットワークスイッチを作る
などなどいくらでも思いつけそうです。
面白い計算をする
こちらも、char, short, int, float, double などの決まった型の計算機しか持たない CPU などと比べて
- 特殊なサイズの型を定義して演算する
- 四則演算とは違う不思議な演算子を定義して計算を行う
- 論理演算のような小さな演算を数十万並列で実行する
- ものすごく長いパイプラインでバケツリレー的演算をする
- 宛先付きのデータが流れながら演算が行われていく
などなど、これもまた、決まった型の決まった演算以外の事をやろうとすると CPU は極端に性能が落ちる事がありますので、FPGAが役立つケースが多々あります。
どこから手を付けるべきか
それでは実際問題どこから FPGA に手を付けていけばいいのかという話ですが、SystemVerilog や VHDL など、これらを記述する言語の勉強は確かに必要にはなるのですが、
- LEDチカチカから始めてみる
- UART とかを作ってみる
- CPU を作るようなことを考える
などと、手の届くところから始めるのも良い気がします。
過去記事紹介
手前味噌ですが、自分の過去記事とかを幾つかリンクしておきます。
おわりに
CPUやGPUなど既存のプロセッサを使いこなすというのはもちろん非常に価値のある事ですが、世の中の常識から外れた新しい事を試そうとすると、実はFPGAはすごく強い味方になります。
また今の FPGA は、マイコンのように、「プログラムを修正しては、ビルドし直して再実行」というのが比較的簡単に行えますので、基本的にソフトウェア実行媒体として扱う事ができます。
確かに難易度は高く、取っつきにくいという話はよく聞くのですが、あなたのプログラミングの範囲を広げる という観点で、興味を持って頂けると嬉しいなと思った次第です。
最後に少し興味深いブログにリンクを張って終わりにしておきます。