
FPGAの専門家ではない私が、AIで作ったGPUの上で、メガデモもFM音源も日本語ADVも動かしてしまった
まさか本当に、ここまで動くとは思わなかった
先日、Tang Nano 9Kという小さなFPGAボードを使って、KAGURA-HDという自作2D GPUを作った話を書きました。
前回記事:FPGAの専門家ではない私が、AI駆動開発でGPUを作ってみた
640×360・16色のフレームバッファを持ち、FILL、BLIT、ダブルバッファ、ハードウェアカーソルを備え、1280×720・60HzのHDMIへ出力する。
GPUと言っても、NVIDIAのような3D GPUではありません。
どちらかというと、昔のPCに搭載されていたグラフィックチップに近いものです。
前回は、そのGPUが何とかTang Nano 9Kに収まって、実機で動くところまで来た、という話でした。
で、その後なのですが……。
150秒のメガデモが動きました。
4オペレータFM音源もリアルタイムで動きました。
さらに、日本語ADVまで動いてしまいました。
しかも全部、RP2040とTang Nano 9Kの組み合わせです。
いや、さすがにここまで来ると、ちょっとおかしいですね(笑)。
前回はGPUが動いた。今回はその上でソフトウェアが動いた
もともとKAGURA-HDは、KAGURA-9という別のプロジェクトから派生しました。
KAGURA-9は、タイルとスプライトを使う、昔のゲーム機のVDPに近い構成です。
ところが開発を進めていくうちに、GUIや日本語表示、日本語入力のようなことまで始めてしまいました。
それなら、もっと普通のパソコンに近いフレームバッファ方式のほうが扱いやすいのでは?
というのがKAGURA-HDの出発点です。
640×360・4bppなら、1画面は115,200バイト。
ダブルバッファにしても230,400バイトです。
表示用のフレームバッファはFPGA側のPSRAMに置き、RP2040から描画コマンドを送る。
あとはFPGAがPSRAMを読み出して、HDMIへ映像を出す。
理屈としては、それほど複雑な話ではありません。
問題は、その理屈をTang Nano 9Kの限られたロジックに収めることだったわけです。
前回の記事では、PSRAMのデータ化けやBlock RAMの部分書込み問題、配置配線とタイミング収束で苦労した話を書きました。
それでも最終的には、Framebuffer GPUとしての主要機能が実機で動くところまで到達しました。
ただ、その段階ではまだ「GPUを作った」という話だったんですよね。
今回はそこから一歩進んでいます。
実際にC言語でプログラムを書いて、GPUの上で作品を動かせるようになりました。
これは個人的には、かなり大きな変化だと思っています。


まず、C言語で150秒のメガデモを作ってみた
せっかく自作GPUを作ったので、まずはグラフィックスの性能を見せるデモが欲しくなりました。
そこで作ったのが、BEYOND 16 COLORSです。
AmigaやX68000、昔のデモシーン文化を意識した、約150秒のメガデモです。
内容としては、
HYPERSPACE:奥行きのあるスターフィールド
RASTER WAVES:波打つロゴとラスタ風の演出
PLASMA ENGINE:パレットとタイル合成によるプラズマ表現
ROTOZOOM:回転・拡大縮小する幾何学模様
BLIT STORM:多数のオブジェクトを移動させる描画デモ
VECTOR WORLD:固定小数点演算によるワイヤーフレーム表現
といったものです。
もちろんオープニングとフィナーレもあります。
これらをRP2040上のネイティブCで実装し、KAGURA-HDへ描画命令を発行して表示しています。
ここで重要なのは、完成した150秒の動画をFPGAへ流しているわけではないことです。
シーンの進行や座標計算はC言語側で行い、KAGURA-HDのFILL、BLIT、パレット制御、ダブルバッファなどを組み合わせて描画しています。
素材の一部は事前にPSRAMへ配置していますが、デモの進行そのものはリアルタイムです。
つまり、ちゃんとGPUのデモになっているわけです。

ただし、60fpsで動くとは限らない
ここは少し正直に書いておきたいところです。
KAGURA-HDのHDMI出力は1280×720・60Hzですが、それはGPUの描画内容が毎秒60回更新されているという意味ではありません。
実際、今回のメガデモではシーンによって更新頻度がかなり違いました。
なお、以下は開発初期の実機測定結果です。その後、描画処理やHost通信の最適化によって更新頻度は大幅に改善しましたが、ここでは当初どこがボトルネックになっていたのかを示すため、初期の数値を掲載しています。

といった結果です。
正直、VECTOR WORLDあたりはだいぶ厳しいですね(笑)。
KAGURA-9はタイル・スプライト方式だったので、オブジェクトの座標を更新するだけで画面を動かせました。
一方、KAGURA-HDはフレームバッファ方式です。
オブジェクトを動かそうとすると、以前の表示を消して、次の位置へ描き直す必要があります。
そのため、見た目以上に大量の描画コマンドが発生します。
実際に調べてみると、BLIT STORMではオブジェクトの描画より背景消去の命令数のほうが多く、VECTOR WORLDでは線分を表現するために膨大なFILL命令を発行していました。
つまり、現状ではGPU内部の描画能力だけでなく、RP2040からGPUへ命令を送り込む処理が、性能上の重要な制約になっています。
とはいえ、これをもってKAGURA-HDの限界だとは思っていません。
背景消去のまとめ描きや不要な描画の削減、通信処理の効率化など、C側にはまだ改善余地があります。
少なくとも、ボトルネックの分析から実際の改善まで進められました。
自作GPUの性能を、自作アプリケーションで測定して、その結果をもとにソフトウェアを最適化する。
なんだか、だいぶ普通のコンピュータ開発みたいなことをしていますね。
ところで、音源はどうするのか
グラフィックスの話ばかりしてきましたが、実はもう一つ重要な問題がありました。
音です。
KAGURA-9ではプログラマブルな音源機能も実装していました。
ただし、KAGURA-HDでは事情が違います。
フレームバッファ、PSRAM制御、HDMI、BLIT、カーソルなどを詰め込んだ結果、FPGAのロジックにはほとんど余裕がありません。
そこへ音源回路をさらに追加するのは、さすがに厳しい。
そこでKAGURA-HDでは、FPGA側にはPCM音声出力を持たせ、音の生成そのものはRP2040側で行える構成にしています。
PCM出力は48kHz・2系統。
左右の音量を制御してHDMIのステレオ音声へ出力できます。
この仕組みがあれば、必ずしもFPGA側に専用のFM音源回路を持つ必要はありません。
RP2040でFM音源を計算して、PCMとして渡せばいいのでは?
というわけです。
で、実際にやってみました。そのためにPCM音声を継続的に供給できるストリーミング機能も追加しました。
もともとのPCM2は、PSRAMに配置した音声データを再生する構成です。これに加えて、A/Bの半バッファを使って音声データを順次供給する方式を実装しています。これなら、あらかじめ長い楽曲をすべてPSRAMへ配置しなくても、RP2040側で生成したPCMを継続的に再生する構成が取れます。
つまり、リアルタイムFM合成との相性がかなり良いわけです。
もちろん、継続的な音声転送にはバッファの管理やタイミングの問題があります。実際、開発中には音声の途切れを疑う現象もあり、かなり苦労しました。それでも、最終的に選定したQSPI版では、実機のメガデモ回帰試験で音声異常を検出することなく、150秒の再生を完走できています。
いや、GPUを作っていたはずなのに、いつの間にかPCMストリーミングまで実装してしまいました(笑)。
4-OPERATOR Demo —— 4オペレータFM音源がリアルタイムで動いた
作ったのが、4-OPERATOR Demoです。
FM音源というのは、複数のオペレータを組み合わせて、周波数変調によって音色を作る方式です。
昔のPC-98やX68000、ゲーム機などで使われていたFM音源を思い浮かべてもらうと、イメージしやすいと思います。
今回は、そのFM合成をRP2040上のソフトウェアで実行しています。
4オペレータの計算をリアルタイムで行い、生成したPCMデータをKAGURA-HDの音声出力系へ渡す。
あとはFPGA側でHDMI音声として出力します。
つまり、事前にWAVファイルを作って再生しているわけではありません。
RP2040が、その場で音を合成しているわけです。
これが普通に動いてしまいました。
いや、これはかなり面白いですね。
専用FM音源チップも不要。
FPGA内部に新しいFM合成回路を追加する必要もありません。
すでに実装しているPCM出力機能を利用するだけで、ソフトウェア側の工夫によってFM音源まで実現できる。
ハードウェアの機能を固定したまま、ソフトウェアでできることが増えていく。
これこそ、汎用的なコンピュータの面白いところだと思います。

これはPCM再生テストとは意味が違う
実は、FM音源風の音楽を事前にPCMへ変換しておいて、それを再生するだけなら、もっと簡単です。
それでもPCM出力回路の検証にはなります。
しかし、今回は違います。
RP2040側でリアルタイムに音を計算しています。
つまり、GPUへの描画命令を発行するCPUが、同時に音声生成の仕事も担当できるわけです。
この構成が成立するなら、今後ソフトウェアを変更することで、音色や演奏内容を自由に変えられます。
専用のハードウェア音源を追加せずに、です。
しかもFPGA側のリソースはそのまま。
これは、KAGURA-HDの設計としてかなり重要な成果でした。
この4オペレータFM合成とPCMストリーミングの構成は、後から別のアプリケーションにも応用できました。
実際、MIDNIGHT TERMINALでは音源を7声構成に拡張し、雨音や効果音などもソフトウェアで合成しています。

そして日本語ADVまで作ってしまった
さて、ここまででグラフィックスと音声の両方が動くようになりました。
だったら、せっかくなので両方を組み合わせたアプリケーションを作ってみたい。
ということで作ったのが、MIDNIGHT TERMINALです。
1990年代のPC-98向けADVなどを意識した、サイバーパンク風の短い日本語アドベンチャーデモです。
雨の夜の街から始まって、バーでの会話があり、端末画面があり、異常演出があり、最後に物語が戻ってくる。
そんな構成です。
絵のほうも最初はだいぶプログラマーズアートだったのですが、後から手を入れて、昔のPCゲームらしい雰囲気に寄せました。
こういう画面を640×360・16色で作るというのは、制約がある一方で結構楽しいんですよね。
使える色が少ないので、配色やディザリング、輪郭の扱いで見た目がかなり変わります。

なにげに、日本語が普通に表示できるのがすごい
このデモで個人的に感心しているのが、日本語表示です。
日本語のテキストが普通に読めて、会話が進んで、背景やキャラクターも切り替わる。
見た目としては当たり前のことなのですが、よく考えると自作GPUの上でこれをやっているんですよね。
日本語は英数字と違って文字種が多く、漢字を扱うにはそれなりの解像度も必要です。
しかも、文字を表示するために細かい描画命令を大量に発行すると、Hostとの通信がボトルネックになります。
今回はそれでも、ADVとして自然に読める形で表示できています。
これが結構うれしい。
というのも、最初にKAGURA-HDを作ろうと思った理由が、もともとGUIや日本語環境を扱いやすくしたかったからなんです。
その意味では、MIDNIGHT TERMINALが動いたことで、最初の構想に対してかなり具体的な答えが出たように感じています。
しかもBGMはリアルタイムFM合成
そして、ここで先ほどの4-OPERATOR Demoが効いてきます。
MIDNIGHT TERMINALでは、RP2040側で4オペレータFM音源をリアルタイム合成し、KAGURA-HDのPCM出力系から音を鳴らしています。
つまり、このADVでは、
C言語によるシーン制御
640×360・16色の画像表示
日本語テキスト描画
背景とキャラクターの表示
GPUへの描画コマンド送信
4オペレータFM音源のリアルタイム合成
HDMI映像とステレオ音声出力
が一つのシステムとして動いているわけです。
これ、ちょっと冷静になると相当なことをやっています。
自作GPUの上で日本語ADVを動かして、さらに自作のソフトウェアFM音源で音楽まで鳴らす。
しかもRP2040とTang Nano 9Kです。
いや、なんというか……。
こんな小さな構成で、ここまで普通のPCゲームみたいなものが動いてしまうのか。
と、作っている本人が一番驚いています(笑)。
ところで、FPGA側のリソースはどうなったのか
ここまでいろいろ動くようになったので、さぞかし余裕のある設計なのだろうと思われるかもしれません。
実際は全然そんなことはありません。
むしろ、前回よりさらに厳しくなっています。
2026年11月8日に選定した、Queue8とPCMストリーミングに対応するQSPI版の配置配線・STA結果は次のとおりです。

CLS使用率98.5%
もうほとんど残っていません。
Setup WNSも+0.177nsなので、タイミング余裕が潤沢というわけではありません。
前回の記事ではCLS使用率95.9%という数字を書きましたが、その後、Queue8とPCMストリーミング構成を含めた開発を進めた結果、さらに厳しい状態になっています。
ちなみに、当初はKAGURA-9で実装していたプログラマブル音源機能も維持したかったのですが、さすがに全部は収まりませんでした。
そこでKAGURA-HDではPCM 2系統に絞り、FM合成のような処理はRP2040側へ持っていく構成にしています。
結果として、それが今回の4-OPERATOR DemoやMIDNIGHT TERMINALにつながりました。
ハードウェアの機能を増やせないなら、ソフトウェアで工夫する。
昔のコンピュータでもよく行われていたことですが、自分でハードウェアから作っていると、その意味がよく分かります。
FPGAの実装は、相変わらずサイコロを振っているようなもの
それにしても、今回の開発では改めてFPGAの難しさを感じました。
RTLが正しくても、配置配線で失敗する。
ロジックを減らしたのに、タイミングが悪化する。
少し構造を変えただけで、それまで問題なかった経路が急にクリティカルパスになる。
本当に、サイコロを振っているような感覚になることがあります。
もちろん、配置配線が完全にランダムだという意味ではありません。
合成ツールや配置配線ツールには最適化の仕組みがありますし、クリティカルパスを解析して設計を改善するのが本来のやり方です。
ただ、CLS使用率98%超という状態では、わずかな変更でも結果が大きく変わります。
実際、追加で検討したSPI構成では、Bitstreamの生成自体はできたものの、あるビルドでSetup WNSが−3.359ns、違反4件となりました。
つまり、Bitstreamが作れることと、タイミング条件を満たしていることは別の話です。
そのため、QSPIの合格済み構成は保護し、SPI対応は別の検証対象として扱っています。
なお、QSPI版についても、内部STAを通過して実機でアプリケーションが動いたことと、あらゆる温度・電圧・個体差での動作が保証されたことは別です。
そこは区別する必要があります。
それでも、ここまで実際のソフトウェアが動いているという事実は、非常に大きいと思っています。
AI駆動開発で、一番変わったのは試行錯誤の回数かもしれない
前回の記事でも触れましたが、私はFPGAの専門家ではありません。
組込みや電子回路の開発経験はあるものの、FPGAのRTL設計やタイミング収束は専門外です。
今回の開発では、RTLの実装、C言語のドライバ、テストコード、デモプログラム、画像素材、音声処理まで、かなり多くの部分でAIを利用しています。
ただし、AIが一発で正しいものを作ってくれるわけではありません。
むしろ逆です。
シミュレーションでは動いても実機では動かない。
配置配線が失敗する。
性能を改善したつもりが悪化する。
普通にそういうことが起きます。
なので、そのたびに原因を調べて、実装を変えて、また試す必要があります。
今回も、単にGPUが動いたというところで終わらず、さらにメガデモを作り、FM音源を作り、日本語ADVまで作ることができました。
これは、AIによって実装と検証の試行錯誤を繰り返すコストが大きく下がったことと無関係ではないと思います。
一方で、人間が何を作りたいのかを決め、どこまでを合格とするか判断することは依然として重要です。
今回のKAGURA-HDでも、RTLに機能を追加し続けるのではなく、ある程度のところで止めるという判断が必要でした。
何でもハードウェアで実装すればよいわけではないんですよね。
実際、FM音源はソフトウェアで実現できました。
そして、それで普通に作品が動いてしまった。
AIによってFPGAの物理的なリソースが増えるわけではありません。
でも、限られたリソースをどう使うかについて、以前よりずっと多くの案を試せるようになった。
今回の開発では、その効果をかなり強く感じています。
もう、GPUを作る段階は終わりにしてもよさそう
さて、ここまで来て、KAGURA-HDの今後についても少し考えています。
少なくともQSPI構成については、主要機能も揃い、実機でC言語のデモが動き、日本語ADVとリアルタイムFM音源まで動いています。
もちろん、描画性能の最適化や長期安定性の検証、リリースに向けた作業などは残っています。
ただ、機能面ではもう十分ではないでしょうか。
SPI対応については、タイミング収束と実機検証を進めています。これが一区切りついたら、RTLの機能追加を凍結し、C SDKとアプリケーションの開発に集中したいと考えています。
KAGURA-9は、タイル・スプライト方式のゲーム向けVDP。
KAGURA-HDは、フレームバッファ方式のGUIや画像表示向けGPU。
それぞれ違った特徴を持つ構成として、使い分けていけそうです。
そして何より、KAGURA-HDにはもう実際に動くアプリケーションがあります。
これから先は、新しいハードウェア機能を足すことより、このGPUの上で何を作るかを考えるほうが面白そうです。
日本語テキストエディタでもいい。
GUIでもいい。
ゲームでもいい。
もっとちゃんとしたADVを作るのも楽しそうです。
自分で作ったGPUの上で、自分で作ったソフトウェアが動く。
考えてみれば、それだけの話なのですが……。
その「それだけ」を実現するのが、なかなか大変だったわけです。

おわりに
前回の記事では、KAGURA-HDが何とかGPUとして動いたという話を書きました。
それから短い期間で、150秒のメガデモ、リアルタイム4オペレータFM音源、そして日本語ADVまで動くようになりました。
特にMIDNIGHT TERMINALを見ていると、もう普通の昔のPCゲームみたいなんですよね。
絵が出て、文字が出て、音楽が鳴る。
場面が切り替わり、会話が進んでいく。
これだけ見ると当たり前なのですが、その裏側はTang Nano 9KとRP2040です。
しかもFPGAのCLS使用率は98.5%。
いや、本当によく動いているな……。
最初はGPUを作るつもりだったのに、気付いたら映像も音声も扱える、小さなレトロコンピュータのようなものになっていました。
FPGAの専門家なら、もっと上手い実装ができるのかもしれません。
それでも、専門外の私がAIを使いながら試行錯誤して、ここまで実機で動かせたというのは、なかなか面白いことだと思っています。
さて、次は何を作ろうかな。
……いや、その前にSPI対応を終わらせないといけませんね(笑)。
関連記事
FPGAの専門家ではない私が、AI駆動開発でGPUを作ってみた
GitHub
KAGURA-HD:https://github.com/siska-tech/kagura-hd
KAGURA-9:https://github.com/siska-tech/kagura
#AI駆動開発 #FPGA #TangNano9K #RP2040 #組込み #KAGURA #自作GPU #レトロPC