DE0でFPGAのチップ内蔵RAMをVRAMに使おうとしたら上手く行かなかった日記

手順としてはこちらに書かれている通り「DE0でFPGAのチップ内蔵RAMにアクセスする - きしだのはてな

「RAM: 2-PORT」を選んで、1ポートずつread/writeに割り当て。モノクロ640x480ピクセルのVRAMを作りたかったので、How many bits for memoryに307200bitと指定した。Resource Usageは48 lut + 40 M9K + 6 reg。僕が使っているDE0はマニュアルによれば「56 M9K Embedded Memory Blocks」と書いてあるので、40個のM9Kブロックを使うことはおかしくないはずだ。

しかしこれをVRAMに使って絵を描いてみると、なぜか5箇所ぐらいに同じ絵が出たり、絵の表示されないゾーンが出来たり、とおかしな挙動をする。

試しにメモリの先頭から1024bitずつ0と1で埋めてみた。画面の横幅が640pxなので、1024bitずつ交互に塗れば「太さが1または2の横縞模様」ができるはず。しかし縞模様が10本描かれた(つまり20480bit)後、残りがベタ塗りになってしまった。下の写真で縞模様になっているゾーンが5つあるけど、頭から埋めていく過程で5箇所同時に縞模様が書かれて、青いゾーンには一瞬で青くなった。つまり限界ギリギリの場所にあるおそらく1bitのメモリを埋めるとこの青いゾーンが全部青になってしまうってことか。何が起きているのやらさっぱり。

M9Kメモリブロックはパリティを含んで9216bitのメモリなので、有効に使えるのは8192bit。20480bitとの関連性もさっぱりわからない。

しかたがないので使えそうな前半の20480bitに収まるように、4x4ピクセルで1bitににして160x120の解像度にしたものがこちら。160 * 120は19200だ。メモリがおかしくさえなければちゃんと期待通りに動くんだから、やっぱ問題はRAMの側かなぁ。307200bitも確保することが予想されておらずアドレスの指定に関する回路がおかしくなっているとかなのかなぁ。なにぶんFPGAは素人なのでどう解決したらいいかがわからない。

ところで160x120のモノクロでも楽しめそうなものはなにかないか考えた結果、ライフゲームを実装しようと思っているのだけど、ダブルバッファリングはどうするのが一般的なのかなぁ。普通に同じサイズのRAMを2つ作って、1bitのフラグでどっちから読んでどっちに書くかをif文で分岐するのでいいのかなぁ。

ルール部分は512bitのROMでテーブル引きにしたらいいと思っている。

とりあえずシンプルに実装すると9クロック掛けて9箇所のピクセルデータを読んで、その値でテーブル引きして書き込む、という形になるかと思うけど、せっかくFPGAなのに1ピクセルに9クロックも掛けるのがもったいないと思うのでもっと並列化したい。どうしたらいいのだろうか。RAMのreadポートを9本にしたりできたらいいんだけどウィザードでは2ポートまでしか作れない。それとも323bitのシフトレジスタを用意して2行+3px分のデータをそこに溜めながらスライドしていく?