実装メモ

あんまり進める気はなかったんだが、発注した基板でミスがあって到着が遅れまくっているので仕方なく進む m72 project.

DRAM の配置

DRAM はアクセスするために複雑なインタフェースを組まねばならないが、大きい容量を得られる。ここで大きなサイズを使用する下記のデータを1つにまとめる。

  • tile0, tile1, sprite の各キャラクタROM
  • tile0, tile1 の attribute table (tilemap とか nametable とか方言多々)

tilemap はキャラクタと比較すると少ないが、FPGA 内部RAMとしては容量が大きいのとキャラクタと切り換えやすいので DRAM に配置する。tile map のサイズは固定、tile char のサイズは各最大512KB, sprite char のサイズは最大8MB ということになっているらしい。
最大ということでそこまで使っているかは別なので、 DRAM を無駄がないように配置するとこうなった。

DRAM memory map   CPU           assignment   page
                                                                                                  • -
0x000000-0x373fff (N/A) sprite.char 0x000-0x1bd 0x37c000-0x37dfff d0000h-d3fffh tile0.map 0x1be 0x37e000-0x37ffff d8000h-dbfffh tile1.map 0x1bf 0x380000-0x3bffff (N/A) tile0.char 0x1c0-0x1df 0x3c0000-0x3fffff (N/A) tile1.char 0x1e0-0x1ff

page というのは、キャラクタ ROM を CPU から DRAM に転送するために思いついた仕組み。tile1.map のエリアを bank として、 空いている IO map に page レジスタを設ける。sprite ののキャラクタデータを転送する場合は page を 0 から 0x1bd にして順次、 bank に書き込んでいく。転送が終わり次第、 page は 0x1bf とすれば通常の tile1.map としても機能する。

DRAM のアクセス方法をハードから考えるとこれが一番単純だったのでこれにした。ソフト的には bank と segment の両方を考えながらやらねばならぬ。

メモリインターフェース関連

VRAM は上記の DRAM と内蔵RAMの sprite map, color RAM の3つが大きなメモリであとはスクロールレジスタとか小規模な物が混ざる。

これらの配線はごちゃごちゃしてシミュレートしにくいので Video 回路内部で CPU との共有RAMとレジスタをまとめて配線するモジュールを作ってみた。

declare maincpu_video_interface{
	//cpu pins
	input cpu_rd, cpu_wr; input cpu_d[16];

	//CPU side memory assignements
	input cpu_address[14:1], cpu_bytemask[2]; 
	input cpu_sprite_map_select, cpu_color_select[3], cpu_dram_select;
	input cpu_dram_address_high[9];
	output cpu_q[16], cpu_wait;

	//SDRAM pins
	output sdram_ba[2], sdram_a[12]; 
	output sdram_dq_dir; output sdram_dq_out[16];
	output sdram_cke, sdram_cs, sdram_ras, sdram_cas, sdram_we, sdram_dqm[2];

	//video control signal
	output vblank_int, scanline_int; 
	input sprite_dma_trigger, scanline_config_select, tile_scroll_select; //write port enable

	//video side memory assingments
	input scanline_num[8];
	input video_color_a[9]; output video_color_d[15];
	input video_vram_a[22]; input video_vram_select, video_vram_rd;
	output video_vram_d[32], video_vram_wait[2];
	input video_sprite_a[7]; output video_sprite_d[45];

	output tile0_scroll_x[9], tile0_scroll_y[8];
	output tile1_scroll_x[9], tile1_scroll_y[8];
}

これだけ出しておくと CPU 側から read/write を送ってちゃんと動くかとする場合に CPU 側からちゃんとうごく入力をして、 Video 側は適当に固定値入力で干渉がないようにする。逆のこともできるのでこれ経由で 1 frame の画像を出すこともできそうだ。

あとはこの中にCPU用に内蔵RAMをいれたり、Video用にROMをいれられれば結構進んだ気になれる。