14 |
BSVによるSpace Invadersの変更 (2) |
アルゴリズム説明
アルゴリズムの中心部分を説明します。一度に変換すると、bscによるデータサイズの推定がうまく行かなかったため、ステップに分解してデータタイプのヒントを与えています。ステップに分解しても結局組み合わせ回路が合成されるため、回路オーバヘッドはありません。
Bit#(8) xa = a[15:8];
横方向アドレスであるxaは縦方向アドレス(上位8bit)をそのまま使用します。
Int#(10) yax = 256 - signExtend(unpack(a[7:0]));
一方、縦方向アドレスyaは横方向アドレス(下位8bit)をunpackにより整数化し、符号拡張した上で256から引きます。
Bit#(8) ya = truncate(pack(yax));
その後unpackによりビットベクターとし、最後にtruncateで8bitベクターに戻します。データタイプ変換関数はここに掲載されています。
if (sel) return b;
else if (sw) return {ya, xa};
else return a; // normal state
最後にselがtrueならb(メモリダンプFSMによるアドレス)、falseでswがtrueならxとyの入れ替え&yの反転(90°回転)、falseならオリジナルのa(ゲームFSMによるアドレス)を選択します。
実行結果
図508.1に実行結果を示します。首を左に90度傾けた上で正しく実行できました。
変更後のソース
変更したMux.bsv:
typedef Bit#(16) Addr_t;
interface Mux_ifc;
(* prefix="" *)
method Addr_t outp(Bool sw, Bool sel, Addr_t a, Addr_t b);
endinterface
(* synthesize, always_ready = "outp", no_default_clock, no_default_reset *)
module mkMux(Mux_ifc);
method Addr_t outp(Bool sw, Bool sel, Addr_t a, Addr_t b);
Bit#(8) xa = a[15:8];
Int#(10) yax = 256 - signExtend(unpack(a[7:0]));
Bit#(8) ya = truncate(pack(yax));
if (sel) return b;
else if (sw) return {ya, xa};
else return a; // normal state
endmethod
endmodule
変更箇所はこのアドレスの縦横入れ替えと、VRAM初期値のデータの縦横入れ替えの2点となります。後者はプログラムでも可能ですが、csvに変換した上でexcelのコピーのオプションの行列の入れ替え機能で実施しました。
追記:改良版の記事はここ