ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

lifegameの生死判定をVerilogで

 西尾さんのFPGAでライフゲームを作りましたに反応しました。
 ライフゲームの生死判定を3通りの方法で書いて、合成、比較してみました。生死判定の前後にレジスタが入っているのは動作速度を比較したかったためです。結論を先に書いておくと、どう書いてもたいした違いは無かったです。好きな書き方を選べば良いと思います。

case 文を並べる。

元のソースの記述方法です。
https://github.com/natsutan/lifegame/blob/master/case/case.v

これを合成するとこのような回路になります。

入力をアドレスとしたテーブル引きになっています。
使用ロジックエレメントは12個です。

ROMを使う

Quartus II でROMを作りました。
https://github.com/natsutan/lifegame/blob/master/rom/rom.v
ROMの中身は上のcase文バージョンと同じ内容をmifファイルに書いています。
https://github.com/natsutan/lifegame/blob/master/rom/arom.mif

 ソースがすっきりするのがメリットですが、mifファイルというVerilogじゃないファイルが管理対象に入ってしまうのがデメリットです。Xilinxへ移植するときは、そのまま持って行くことができません。ライフゲームのルールをいじったりするように、生死判定をいろいろ変えたい時はmifファイルだけ差し替えれば良いのでそこはメリットになります。

合成後の結果はこのような回路になります。

使用ロジックエレメントは0になり、total memory bit(内部メモリの使用bit数)が512になっています。

functionで書く

普通にそのまま書けばどうなるかと思い、functionでロジックを書いてみました。ライフゲームのロジックをそのまま書いています。

 function is_live;
    input [8:0] n;
    integer cnt;
    begin
      cnt = n[0] + n[1] + n[2] + n[3] + n[5] + n[6] + n[7] + n[8];
      if ( n[4] == 1 ) 
	is_live = (cnt == 2) || (cnt == 3);
      else 
	is_live = (cnt == 3);
    end
  endfunction 

全体のソースはこちら
https://github.com/natsutan/lifegame/blob/master/add/add.v

合成後の回路はこうなります。

使用ロジックエレメントは、16まで増えています。これを、case文で書いたときと比べて1.5倍になったと思うか、全体のLE数からみれば誤差と思うかは状況次第です。今回の場合であれば誤差の範囲ですね。

まとめ

 ライフゲームの処理を3つの方法で書きましたが、使用リソースはたいした違いはありませんでした。気になる動作速度(fmax)は、最後のfunctionバージョンが一番速かったです。

実装 LE数 使用メモリ fmax
case文 12 0 326Mhz
rom 0 512 bit 357MHz
function 16 0 612MHz

 私が仕事で使うならcase文か、ROMで実装します。functionはロジックが複雑になってきたときに速度低下の具合が良く読めないのにたいし、テーブル引きならどれだけロジックが複雑になっても一定の処理時間で終わる事が見えるからです。実行速度が読めないのは単に私のスキル不足なので、そこがクリアーできるなら最初からfunctionで書くのも良いです。