4 |
BSVの設計トライアル (20) |
実行結果
次は、ファンクションの中にシーケンスを組み込み、ゲームFSMの設計トライアルを行います。 シーケンスを人手で分解することは、なるべくしたくありません。ファンクションでシーケンスが定義できれば、インベーダ動作、自機動作等のファンクションを作成し、順番にそれらを呼び出せば良いはずです。
import StmtFSM::*;
interface TestFSM_ifc;
method Action inp(UInt#(8) inx);
endinterface
(* synthesize *)
module mkTestFSM(TestFSM_ifc);
Reg#(UInt#(8)) i <- mkRegU;
Reg#(UInt#(8)) x <- mkRegU;
function Stmt test1;
return (seq
$display("%3d 1-1", $time);
delay(5);
$display("%3d 1-2", $time);
endseq);
endfunction
function Stmt test2(UInt#(8) xx);
return (seq
$display("%3d 2-1", $time);
for (i <= 0; i < xx; i <= i + 1)
$display("%3d 2-loop-%1d", $time, i);
$display("%3d 2-2", $time);
endseq);
endfunction
Stmt main =
seq
$display("%3d fsm1.start", $time);
test1;
$display("%3d fsm2.start", $time);
test2(x);
endseq;
mkAutoFSM(main);
method Action inp(UInt#(8) inx);
x <= inx;
endmethod
endmodule: mkTestFSM
このためのテストベンチを示します。あえてモジュール外部からループ回数を入れているのは、ループ回数がダイナミックに(実行時に)決定できるかを確認するためです。ファンクションのループを8回呼び出してみます。
import StmtFSM::*;
import TestFSM::*;
(* synthesize, always_ready, always_enabled *)
module mkTb (Empty);
TestFSM_ifc test <- mkTestFSM();
Reg#(UInt#(8)) count <- mkReg(8);
Stmt main =
seq
test.inp(count);
repeat(40) noAction;
endseq;
mkAutoFSM(main);
endmodule
実行結果を示します。test1の次にtest2が呼び出され、ループが8回回ったことを示しています。
20 fsm1.start
30 1-1
90 1-2
100 fsm2.start
110 2-1
130 2-loop-0
150 2-loop-1
170 2-loop-2
190 2-loop-3
210 2-loop-4
230 2-loop-5
250 2-loop-6
270 2-loop-7
290 2-2