【FPGA】Tile GraphicsのサンプルをZybo向けに変更して動かす(FPGA + Verilogでゲーム機をつくろう日記5日目)

投稿日:2021年1月3日
最終更新日:2021年5月24日

今回はTile Graphicsのサンプルを動かす

以下の本を読みつつ進めているFPGAでゲーム機をつくろう日記。前回はmoving ballというサンプルを実装して動かしてみて、だんだんゲームっぽくなってきた。今回は本の15章「Tile Graphics」の内容をZybo向けにカスタマイズして動かしてみた。

Designing Video Game Hardware in Verilog (English Edition)

以下が実際に動かしてみた動画。

今回のサンプルのプロジェクトは以下で公開している。ただ、LFSRの疑似乱数を発生するRTLはネット上のものを使わせてもらったが、ライセンスが不明でそのままGitHubに上げるわけにもいかない。そのため、今回はGitHubにはLFSRのコードのダミーファイルを置いておいたので、このプロジェクトを使う場合はReadmeに記載したコードの掲載先URLのコードで、ダミーファイルの中身を上書きしてください。もちろん自分で作るか、別のLFSRのコードを使ってもOK。

https://github.com/WakkyFree/FpgaGameConsole/tree/master/TileGraphics

tclファイルからプロジェクトを生成する方法はこちら。

Vivadoのプロジェクトをtclから生成する

いつものごとく、日記ではポイントだけ絞ってメモしていきます。

 

開発環境

Windows 10
Vivado 2020.1
Zybo(Zynq-7000)

 

hvsync_generator.v、detect_edge.v、MMCM IP、ピンアサインは前回と同じ

前回のMoving Ballのプロジェクトとhvsync_generator.v、detect_edge.v、mmcmのIP(clk_vga_25m)、ピンアサイン情報が記述された制約ファイル(game_console.xdc)は前回と同じ。今回変更&追加したのは

  • zybo_top.v
  • digit10_case.v
  • lfsr.v(こちらはリンク先のVerilogコードを使用させて頂きましたm(_ _)m)
  • RAM_sync.v
  • test_ram1_top.v

の5つのVerilogコード。ball_absolute_top.vのベースはこの本のサンプルコード。例のごとくこのまま移植してもうまく動かなかったので、test_ram1_top.v(サンプルだとファイル名がchardisplay.vとなっていたがmodule名の定義はtest_ram1_topだったので、VivadoのSynthesis通すためにファイ名を変更)とdigit10_case.vを変更した以下では変更のポイントを書いていく。

 

zybo_top.vの変更箇所

こちらは前回のball_absolute_topをtest_ram1_topのモジュールに変更しただけ。そのほかは変更なし。

 

test_ram1_topのポイント

ベースになっているのはエミュレータのchardisplay.vというソースコードの中のtest_ram1_topのモジュール。細かい部分の解説は省くが、ポイントは2つある。

ソースコードの上から順番に見ていく。まず1点目は、以下のようなカウンターを用意し、87行目でカウンターが15になったタイミングで文字が切り替わるようにしていること。

  always @ (posedge clk) begin
    if (reset)
      counter <= 4'd0;
    else if (v_rise)
      counter <= counter + 4'd1;
  end

画面上の数字は、RAMへの書き込みタイミングを変えて切り替えているが、カウンターを入れないと文字が高速で切り替わりすぎて、綺麗に文字が見えなかったためこのようにした。15というのは適当に決めた数値なので、もっと早く切り替えたければ15より小さい値を、もっと遅く切り替えたければ15より大きい値(ただしこの場合はcounterのビット数を大きする必要があるので注意)にすればよい。

2点目は、画面上の表示をランダムっぽく切り替えるためにLFSR(線形帰還シフトレジスタ)のRTLを使用して疑似乱数を発生させて、数字を切り替えていること。

  lfsr #(.NUM_BITS(8)) lfsr_inst
         (.i_Clk(clk),
          .i_Enable(1'b1),
          .i_Seed_DV(1'b0),
          .i_Seed_Data({8{1'b0}}), // Replication
          .o_LFSR_Data(lfsr_adrs),
          .o_LFSR_Done()
          );

もともとのコードだとあまりきれいに数字がバラけて表示されなかったため、今回は疑似乱数を発生させてRAMにwriteするデータを変えている。LSFRについてはググって頂きたいが、今回はRTLは自作せずに冒頭でも紹介したこちらのコードを使用させて頂いた。

 

digit10_case.vのポイント

digit10.case.vも元々のコードから少しだけ変えている。このコードの中では、モニターに表示される0~9の各数字のビットマップが定義されているのだが、サンプルコードのままだと、モニターに表示したときに隣の数字とくっついて表示されてしまって何が表示されているのかわからない状態になっていた。

どのように変えたかはサンプルコードとGitHubに上げているコードを見比べればわかると思うが、各数字でのbitsのLSBとMSBを0にして、モニターに表示した時に隣の数字と必ず間隔があくようにしている。

 

動かしてみた

プロジェクトをsynthesisとimplementationしてGenerate bitstream後にFPGAに書き込んで動かすと、最初にのせた動画のように数字が画面上で良い感じに入れ替わるように表示できた。

次回だが、例のごとく16~18章はあまり動きが無いので実機での実装はやらずに読み流して、19章のRacing Gameを実装してみたいと思う。これができれば一応日記の目的であるFPGAでゲーム機をつくるという目的は果たせるかな。

 

FPGAでゲーム機をつくろう日記まとめ

この日記は以下でまとめています。

【FPGA/HDL】FPGAでゲーム機をつくろう日記まとめ


投稿者: wakky

映画と旅行が大好きなエンジニア。お酒、ゲーム、読書も好き。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください