SNES on FPGA



DE2-115 FPGA board (1 chip SNES) DE2-115 FPGA board (1 chip SNES)

ファミコンの時代、当時としては高い性能だったがそれ以上に実現できなかったクリエイターたちの世界が、 スーファミの時代になり少しずつ実現しつつあった（それはもうICが火を噴かんがごとく）。 デザイナー、バトルプログラマ、ドッター、サウンドプログラマ… 彼らの歴史の中で紡がれてきたものはなんだったのか。 スーファミ互換機の製作。それはスーファミにおいて最後のゲームとなる。

▼ 開発環境

ハードウエア記述言語 SFL+、VerilogHDL、VHDL

・開発環境１代目

PC Windows2000、Athlon64 4000+、Mem 1GB ／Cygwin、VC++6.0、sfl2vl、Verilator、Altera QuartusII 6.1

・開発環境２代目

dynabook RX3 WindowsXP、Core i5-520M、Mem 2GB ／Altera QuartusII Free 9.1SP2

・開発環境３代目

dynabook R732 Windows7、Core i5-3320M、Mem 4GB ／Altera QuartusII Free 12.1SP1

・開発環境４代目

dynabook R732 Windows7、Core i5-3320M、Mem 16GB ／Intel QuartusPrime Lite 17.1

使用FPGAボード

Terasic DE1 2005〜

Altera CycloneII 約18,000LEs、内蔵RAM 約30KByte

Terasic DE2-115 2016〜

Altera CycloneIV 約115,000LEs、内蔵RAM 約500KByte

Terasic DE0-CV 2017〜

Altera CycloneV 約49,000LEs、内蔵RAM 約380KByte

▼ 動作デモ

SNES on FPGA (with original sound module)

Chrono Trigger demo. YouTube



SPC Player on FPGA

SDカードのSPCファイルを演奏します。 APUのSPC700とDSPをAltera DE1に実装しました。

YouTube



▼ おとなりさんを覗いて見れば、文明開化の音がする

2006年末、巷ではPS3、Xbox360、Wiiといったスーパー描画性能を持つコンシューマ機が出回り始め、 グラフィックやユーザインタフェースの進化とやらが少し見えてきました。 私の部屋にはそれらの次世代機はおろかテレビさえ無いけど。

これまでのPS2やゲームキューブといったゲーム環境と違うところは、 単にゲームで遊ぶだけでなく、現実とのリンクがより強くなったということでしょうか。 とある職人はカスタムレースマシンをオークションに出品し現金を稼いだり、 またある医師はスポーツゲームで筋肉痛になったり。

別に次世代機を持っていなくても羨ましくもなんともないのですが、 ある方から言われたのが「ゲームに遊ばれるな！」。 酒に呑まれたらおしまいだーとかそんなノリで、 まともにゲームを楽しむことができない体に改造されてしまいました （ここの処理は…という所に目がいってしまう）。ああ…たまにはゲームに遊ばれてぇ。

要は、おもちゃといってもどうやって動いてるか分からないなんてくやしいっ！てことで、 じゃあ作りましょうかっていう流れになったのです。 家庭用ゲーム機としてメジャーなファミコンを！ とは誰の言葉だったか…。理由なんて幾らでもありますがそれはおいときます。

そんなベタなファミコンはいやだ！

という心の叫びを実現したのがNES on FPGAであります。 ディジタル回路の復習とFPGAの練習もかねてかりかり実装したわけですが、 このときは「わあFPGAって便利なんだねぇ」程度にしか考えていなかったのがいまや FPGAに苦しめられる立場に…コンプライアンスってナンダー！

ややもしながら、NES on FPGAは一応の完成を見たわけですが、 私としてはファミコンへの思い出以上に、スーファミへの愛着もあったわけです。 ちょっとアーキテクチャを調べてみると、やはり同じ会社が作ったわけで、 似たような部分もあるし、NES on FPGAの開発環境やノウハウもある。 まだ誰も作っていないのならば、作ってみようスーファミを！ 今後の趣味の一つとしてSNES on FPGAの開発が始まったのでした。

基本的な設計方針としてはNES on FPGAの時同様に、 実機に近いサイクルで動作させるようにします。 これは最終的に実カートリッジを使って動かすことを考えてのことですが、 FPGAボードの50MHzと豊富なリソースがあれば、 ほぼソフトエミュレータをベースにした設計で作ることも可能です。 しかしそれでは考古学的な意味合いがちょっとずれてしまいます。 当時のリソースを想定しながら実機に近いアーキテクチャで設計することで、 スーファミの設計者たちがどんな設計思想を持ち、 どんなところに苦労したのか、そんなことも少しは垣間見えるのではないか、 というところも今回の開発の醍醐味でもあるのですから。

NEXT GENERATION



用語の補足 CPU (Central Processing Unit)：65C816、メインの制御を司る。 PPU (Picture Processing Unit)：画面の描画を行う。 APU (Audio Processing Unit)：サウンドを生成する。SPC700プロセッサとDSPからなる。 WRAM (Work RAM)：CPUが使うメインメモリ。 VRAM (Video RAM)：PPUが使う描画用データが格納されるメモリ。 DMA (Direct Memory Access)：メモリからVRAMへCPUよりも速くデータを転送する。 ROM (Read Only Memory)：ゲームカートリッジにあるソフトデータが格納されている。 PPU2：各機能のタイミングなどを制御する。 HDMA：各ラインでちょっとしたDMAを行い、PPUレジスタを書き換えて画面効果を実現する。

SNES on FPGAの開発環境としては、 開発プロセスをなぞりながら見ていきます。 ベースはNES on FPGAの開発プロセスです。 ただし規模が大きくなるためそれなりに効率的な検証方法を導入する必要があります。

・仕様を把握しろ！

一言でいえば互換機の開発なので、 オリジナルの仕様を理解しなければ子供たち（ゲームソフト）との楽しいおしゃべり （ROMカートリッジアクセス）もままなりません。 絵筆が無いと芸術家は爆発し、楽器が無いと演奏家は旅に出たまま戻ってきません。

すでに20数年前に発売されたゲーム機ということもあり、 資料からエミュまで多く存在しています。 それでもハードウエア実装を目的とした資料はあまりありません。 しかも資料によって情報が異なる場合があるので、 やはりそこは自分で確認するしかない。

・エミュレータ作成

資料を読み解きながらリファレンスモデルとなるエミュを作成します。 開発はVC++6.0で行っています。 基本的にはリセットベクタから順繰りデータをフェッチして処理するCPUとメモリがあれば動く。 イニシャライズルーチンから垂直同期待ち、DMA、背景描画、スプライト描画。 デモのソフトを試しながら順次CPUの命令を追加。 ちゃんと実行しているかは描画して確認。 ちなみにサウンドに関してはエミュ実装が面倒で、 FPGA実装の方が容易だろうと踏んで音はでません。 やっぱり基本はマリオだろうということで、実行したがAPUアクセスで停止したり…。

・ハードウエア記述

一般的にはVHDLとかVerilogHDLを使用する人が多いようですが、 生活環境上SFLを使用する流れに。 結果として機能記述が可能なSFLのおかげで、 仕様変更に柔軟に対応できたわけですが。 さらに、NESの開発環境を活用して開発効率を上げます。 特に独自拡張したSFL+はより大規模なSNESの開発に役に立ちました。

・シミュレーション

SFLでのシミュレーションは行わず、VerilatorにてC++に変換しシミュレーションです。 一般的には波形を目視確認することが多いようですが、波形は見たくない。 しかも仕様が未確定な部分が多いためテストケースが作れず十分なシミュレーションもできません。 まあ、基本SFLって動作記述的なところがあるからシミュレーションしなくても大体動いちゃうんですが。

・SFLからVerilogHDLへの変換

オーバートーン社のNSL Coreに付属するsfl2vlコマンドを使用してVerilogHDLへ変換します、これはいい。 Cygwinを使用しているので、makeコマンドで一発です。 ついでにverilatorも通すので、もしsfl2vlで変換不具合があった場合でもすぐにわかります。 そんな時はNSLの開発者様へ報告して、すぐに対応していただけました。感謝いたします。

・そのFPGAボードおいしいの？

SNESのゲート規模をおおよそNESの4倍と想定してAltera DE1（Cyclone II EP2C20）を購入しました。 値段は$150+送料=約\17,000（2005年当時）でした。 本当はDE2（Cyclone II EP2C35）がほしかったんですが値段が3倍以上したので怖くて手が出ませんでした。

・FPGAでの動作確認

AlteraのQuartusIIで論理合成・配置配線したのち、FPGAへコンフィグして動作確認です。 基本的にエミュで動作したものを検証するので、全く動かないことはまれです。 問題なのは動いてしばらくしてから、画面の描画がおかしいとき。 問題はCPUかDMAかPPUか、はたまたそれ以外の部分か？ 不具合を発見するため問題の切り分けが必要です。

・不具合を見つけ出せ！

問題の切り分けのために基本的にはエミュでCPUの動作ログを取得してにらめっこです。 HDLで記述したCPUのシミュレーションは、限られたデバッグ時間では現実的ではないのでできません。 CPUに問題が無さそうであればPPUを疑います。

エミュで問題個所のスナップショットを取り、VerilatorでPPUのVerilogHDLをC++に変換したものをシミュレーションします。 １フレームの描画には約３秒かかります。 PPUの実装で問題があればここでFPGAでの不具合が再現され、描画に失敗した画像が出てきます。

PPUにも問題が無ければDMAやそのほかの部分など、 仕様外動作が考えられるところに一つずつアサーション回路を埋め込んで、さらにFPGAで検証します。

それでも不具合の原因が特定できなければ、 疑わしい部分をVerilatorでC++に変換してエミュに組み込んで協調検証です。 エミュの動作ログとC++に変換した部分の動作ログを比較することで、 不具合発見に至ります。

厄介なのが、レジスタやメモリなどへの同時アクセスがエミュでは再現できないこと。 これらはHDLで記述する場合、しっかりと排他制御しなければいけません。 それを忘れたり実装をミスっていたりすると不具合原因の切り分けが難しくなります。

・はたして結果は…

不具合発見に至ればあとは修正するだけです。 ただし仕様が不明確な部分は試行錯誤が必要ですが。

SFLを修正したらmakeしてコンパイルして再度FPGAで動作確認です。 問題なのは、シミュレーションしない（できない）ので、果たして正しく修正できているか、 ちゃんとした結果が出るまでドキドキです！ コンパイルしてFPGA検証するまで、心の落ち着きを取り戻すのに数日かかることもあります（単に別の事で忙しいだけ）。 その間はひたすら脳内シミュレーションで確認して心を落ち着かせます。

そしていよいよFPGAボードの電源を入れ、データをコンフィグし、動作確認。 問題なく動いたときはあっさりと動くものです。 動かなかったらただ泣きます。 泣き疲れたら再度原因の調査、修正個所の確認です。

・再現性を上げる！

確かに、ゲームが動いて、音も画像も出て、プレイもできるようにはなりました。 しかし、エミュレータでは再現できない、ハードウェアだからこそ発生する不具合というものがあります。 トリガ発生タイミングの問題、メモリアクセスの問題、各プロセッサ協調動作の問題など、 ほんのちょっとの本来の仕様と実装のズレによって発生する不具合。 それも、ほとんどゲームプレイに影響しないような、描画のちょっとしたゴミ、遅延など。 それらの原因を、FPGAの内部信号をプローブできるSignalTapIIで観測したり、 資料を読み込んで推測したりして、原因を究明し修正して、ひとつひとつ不具合を解消していきます。

また、資料に見つからない仕様に関して。 世にある解析資料はソフトウェア開発者目線のものが多く、 ハードウェアで実現するために必要な仕様が不明な部分があります。 そういったパラメータを決めてやらなければいけない所は、 複数のソフトを使って範囲を絞り込む必要があります。 各ソフトでパラメータを変えながら動作する範囲を確認し、 全ての範囲が重なった部分を仕様として決定するのです。

こうしてSNES on FPGAは完成に近づいてゆくのでした。

▼ 開発履歴