Tang-Nano-9Kを使い倒して、ワンチップで(今更)ＮＥＳを動かす

# 目的
　Tang-Nano-9Kの上位機種としてTang-Primer-20Kなるものが売られている事を聞きつけ、入手手配を行った。
　GithubではTP20(Tang-Primer-20KをTP20、Tang-Nano-9KをTN9と以下略す)によるfpganesの動作例が掲示されている。
　　※fpganes　fpga上でnesを動かすソフト。
　　※nes　　　ファミコン(通称)の米国内での略称。
　TP20クラスで無ければfpganesは無理だろうかな、いや、そんな事は無いだろう。
　TN9だってできる子じゃ無いのかな。
　◆◆◆　そうだ、Tang-Nano-9Kでfpganesを動かすぞ　◆◆◆
　marioを動かすことでも目標にするかな。
　TN9の内蔵RAM容量が心もとないが、気合で何とかなるだろう。


# 方針
　FC(以下ファミコンをFCと略す)は、言わずと知れた日本発祥のゲーム機。
　エミュレータも多数出ており、fpganesはその一種でFPGAで構成する。
　FCは本体外のカートリッジに、プログラムROMとキャラクターROMを収めている。
　一世を風靡したmarioの場合、プログラム32KB、キャラクター8KBで構成されている。
　元ネタであるfpganesは、Nexys4の16MBの大容量疑似SRAMを、時分割で振り分けて動かしている。
　　※お値段もTN9の２０倍ぐらいですが。
　TN9の内蔵RAM容量は52KB(8bit換算)、これならいけると思うかもしれないが、ワークとして4KB、カラーテーブル等の内部処理に10KB必要であり、計54KB無いと動かせない。
　　※コンパイルしてエラーが発生してから気が付いた、お粗末な話ですが。
　　※プログラム16KB、キャラクター8KBの初期カートリッジなら内蔵RAMだけで動かせる。
　そこで、プログラムエリアにはDDRAMを割り当て、RAM(32KB)をキャラクターに全振りする作戦に変更。
　これは何とかうまく行った。marioがTN9単体で(一応)動作可能となっている。
　　※勿論、カートリッジデータは各自で用意が必要です。

　下記に仕様を示す。
　　◇表示はHDMIポートに出力、VGAモニタは必要無し。
　　◇音声は疑似アナログ信号として出力、イヤーホン等で聴取可能。
　　◇プログラム(カートリッジデータ)は、起動時にPCよりダウンロード。※fpganesの基本仕様
　　◇コントローラーはPCのキーボードで代用。※fpganesではゲームコントローラーが前提

　ご参考
　「[fpganes Tang-Nano-9K バージョン](https://github.com/hi631/tang-nano-9K/tree/master/NES/fpganes)」
　「[fpganes Tang-Nano-9K ローダー](https://github.com/hi631/tang-nano-9K/tree/master/NES/loader)」
　「[fpganes Tang-Nano-9K モニター](https://github.com/hi631/tang-nano-9K/tree/master/NES/mon)」
![Image7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/fff4e403-c93f-8817-026e-524b03160482.jpeg)


# 必要な開発環境とLicense
　□Tang-Nano-9K　　2K円ちょいで入手可能(シ〇ゾーンは入荷待ち、秋〇は販売中)。
　□開発ライセンス　「[Tang Nano、Nano9KのIDEであるGowin EDAをインストール(Winのみ)](https://qiita.com/yosiaki/items/2e635e115ecedabecc35)」に詳しく書かれています。
　□HDMIディスプレィ及びケーブル


# 動作クロック
　FCを動作させるマスタークロックとして21.477MHzが必要だが、PLLで分周できないので21.6MHZで動作。
　FCのCPU(6502)は之を12分周した1,8MHzで動作している。
　HDMIには126MHzを与える事により、640x400のVGA信号相当がHDMIに表示可能になる。
　DDRメモリには166MHZが欲しい所だが、TN9にはPLLが2個しか無いので、HDMIと兼用して126MHzを与えている。


# プログラム用メモリ
　PSRAM(内蔵DDRAM)を割り当て居ると言ったが、アクセスタイムの確保が悩みの種。
　PSRAMはバースト(連続)アクセスにのみ対応で有り、1byteの読み込みにも32byteの読出しが必要となる。
　バースト一回(BurstMode:16)には24cycl必要であり、インターフェースを83MHz(メモリは166MHz動作)で動作したとしたメモリ単体でのアクセスタイムは289nsと計算される。
　　※実機ではPLLの都合により83MHz(メモリ128MHz)で動作させており、アクセスは380nsと計算される。
　　※PSRAM自体はもう少し早く動くが、IPを使う限りはこうなる。
　FCのCPUはシステムクロック21.6MHz(本来は21.477MHz)を12分周して1.8MHz(本来は1.789MHz)で動作、アクセスは555nsとなるのでこれならマージンが有る事になるが、制御の都合だろうがfpganesでは、8分周と16分周によるアクセスを交互に行っている。
　8分周の場合アクセスは370nsとなり、PSRAMのアクセスタイムでは僅かに不足する。
　これを補うために、回路の途中より制御信号を取り出し、DDRAMは常時12分周相当で動作させている。
　　※全体の動きを把握していないので、この取り出しが正解の自信は無い。

# ＨＤＭＩ
　画像はHDMIポートより出力している。
　fpganesがVGAに準拠した信号を発生させていたので、多少の調整でHDMI表示が可能であった。
　　※sync信号を反転させ、blnk信号の追加により表示が出て来た。
　但し、調整して無いので4:3の画像が9:6の画面に表示されている。
　　※marioがでぶっちょになっているが、別に問題は無いだろう。


# 音声出力
　fpganesは16bitデジタル信号をシリアライズして、ステレオ信号として送出している。
　　※同一データをサンプルしており実質モノラル。
　TN9はDACを持っていないので、これではこの音を変換する機器が別途必要となる。
　そこで、16bitデジタル信号をでDeltaSigma処理でアナログ化しており、イヤーホン等での聴取が可能。
　アナログ信号はTN9の30ピン(TN9背面に記載の数字)に出力している。
　　※聞くに堪えるレベルかどうかは疑わしいが。
　　※イヤーホン直接接続でも壊れなかったが、1KΩ程度の直列抵抗を入れるべきだろう。
　　※HDMIへの出力も技術的には可能と思うが、かなりの追加ロジックが必要のようだ。

# ローダー
　実行プログラムはPCのloader(DOSプログラム)からシリアル経由でダウンロードする。
　　※loaderはVS2017でコンパイルした。
　　　VSでDOSのテンプレートを作成して、cppの中身を移し替えればコンパイル出来るだろう。(多分)
　プログラムはカートリッジから吸い出した後、予めiNES形式のヘッダーを付けてファイル化しておく。
　loaderの起動コマンドを下記に示す。
　　loader xxxx.nes COMx kb
　　　xxxx.nes　ロードするプログラム
　　　COMx　　通信に使うポート(ディフォはCOM4)
　　　kb　　　　PCのkbをコントローラーとして使用する
　TN9を起動させるとLEDが点滅を始める。
　この状態では、HDMIは細い白縁のみが表示されている。
　　※何も出ない場合は、信号が出ていない可能性が高い。
　loaderを起動し通信が始まると、点滅が早くなる。
　　※通信速度は115200bpsだが、もっと早くても良いかも。
　完了するとLEDは点灯状態となり、HDMIへの表示が始まる(はず)。
　　※エラー又はkbを使用しない場合、DOS窓は即座に終了。
![Image5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/334eda69-6d01-073d-c185-494508dfb716.jpeg)


# コントローラー
　loaderでkb指定をしていた場合、PCはコントローラーの役目を担う。
　　※原本はxbox用のコントローラーがディフォらしいが、この時点では所持して無かったので。
　ボタン設定は下記となっている。
　　'1'又は','が'A'釦
　　'2'又は'.'が'B'釦
　　'3'又は'SHIFT'が'SELECT'釦
　　'4'又は'ENTER'が'START'釦
　　カーソルキーで上下左右移動
　'ESC'でloaderは終了する。


# iNES形式
　カセットからコピーしたデータは、動作の識別の為にヘッダーが必要になる。
　16byteのiNESヘッダーを作成し、プログラム、キャラクターデータを繋げばファイルは完成。
　ヘッダーの作りは、「[TNESヘッダをiNESヘッダに変換](https://qiita.com/ringo1231/items/7da27f9c8ff2e7a2e32c)」等に書かれています。
　理解できなかった場合は、「[NES研究室のサンプル](http://hp.vector.co.jp/authors/VA042397/nes/sample.html)」等を見れば判ると思います。
　marioはプログラムが32KB、キャラクターが8KBなので、ヘッダーとして下記を設定。
　　4E 45 53 1A 02 01 00 00 00 00 00 00 00 00 00
　ここで'02'はプログラムサイズ(16KBx02=32KB)、'01'はキャラクターサイズ(8KBx01=8KB)となり、合計で40,976byteのファイルとなります。


# モニター
　一応モニターも作りました。
　mon.nesをロードすると、mango1(6502モニタ)が起動します。
　　※NES研究室のHello, World!に、mango1モニタを追加したものです。
　　※アセンブルにはNESASM3.exeが必要、
　　　「[nespowerpak.com/nesasm](http://nespowerpak.com/nesasm/)」の物を使ったが、ご使用は自己責任で。
　　※mango1はapple1モニタのもじりらしいが、今となっては何処から持って来たのか定かでない。
　通信速度は115200bps、loaderを終了させてターミナル(teraterm等)の起動が必要。
　起動時にターミナルに'#'が表示されます。FC画面はHello, World!が表示されます。
　mango1モニタのコマンド
　　Rxxxx　xxxx番地を読み込む。
　　Wxxxx　xxxx番地に書き込む。
　DDRAMのデバックには重宝したが、IOとして変な番地(4020)を使っているので邪魔なら外して下さい。
　　※2040-204f番地に定位している、動作に支障が出て無い事は一応確認している。
　　※nes.vの223行当たり。sarcsに'0'を代入すれば見えなくなる。
　モニターを拡張する前にFCとして動いてしまったので、ショボいまま放置となった。


# 未解決事項
　キャラクターエリアを32KBとし、CPU側のメモリを全てDDRAMにすると、marioが有り得ないワールドに行くと言う珍現象が発生。
　　※Ｘ－１とか、'　'(キャラクターでは無い)－１とか。
　ワークエリアの初期クリアとか、タイミング調整等を試みたが改善しなかった。
　キャラクターエリアを16KBにし、CPUのワークをSRAMにすると、１－１ワールドからスタートするようになったので、そのまま放置。
　　※キャラクターエリアを32KBにすれば、dorakue1は起動するのだけど。
　　※nestang(fpganesのTP20への移植)でも同様の現象を確認、marioがミラーRAMを利用して居るのかも。
　キャラクターエリアを32KBにしたい場合は、NES_TN9.vの先頭に記載の、//`define Use32Kのコメントを外せば32KBになるので、必要なら試されたい。


# NESTang
　TP20(Tang-Primer-20K)の入手に時間がかかると思っていたが、意外に早く入手できたので、ついでに味見
　NESTangはfpganesのTP20へのインプリ。
　元ネタのNexys4の疑似SRAMを、DDR3メモリで置き換えているとか。
　　※SRAMのアクセス速度を、DDR3で出すことがキモ。
　　※画面も4:3で表示されている。
　　※HDMIからの音声は確認できていない。
　完動品なので追試の必要は無い筈だが、当方環境では多少の手入れが必要だった。

　NESTangのプロジェクトでは初期のピンアサインはnestang.cstで指定している。
　なので、ドックを使用している場合は、nestang_dock.cstを有効ににしないと画面が出ない。
　初期画面の「colorful NES palette」とは、下記のパレット表示画面の事だろう。

　XBOX用のUSB接続のコントローラーを入手したが認識せず。
　これは、コントローラーがID=1と認識されており、ID=0が無いと判断されたもの。
　　※当方の環境の問題とも思われるが。
　ID=1でも動作するutil(TP20).cppを添付しておく、必要なら差し替えてください。
　　※コントローラー無しでPCから操作する方が良かったかも。
![Image14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/0da2f317-a077-2528-554f-24ef8fe51829.jpeg)

# 感想
　TP20到着までの繋ぎのつもりで着手したが、意外と早く動いてくれた。※TP20も意外と早く到着したが。
　FPGAによるFCエミュは6年前にも手を付けており、この時は出来合いのソフト動かすだけであった。
　今回はFPGAも異なる別ボードへの移植を行い、コア部分には手を付けて無いが、多少の改造も行った。
　大した事無いと言われればそれまでだが、多少は技術が進歩していると言う事だろう。
　FCのカートリッジは物によっては二束三文であり、fpgaのステップターゲットとしてfpganesは良い材料かも知れない。
　なお、上記記載内容は全て無保証であり、各自の責任においてご利用願います。