30 |
BSVの設計トライアル (18) |
StmtFSM
前稿ではBSVにより、ステートベースのFSMを設計しました。ステートベースとは、シーケンスを人手でステートに分解し、一つ一つのステートに対してルールを書くもので、基本的にはverilogと同程度の工数がかかります。一方、BSVにはステートマシンを効率的に設計できる、StmtFSMというライブラリが存在します。
検証用FSM
このライブラリの検証用のために検証用FSMを作成します。検証用FSMは2つのコンカレントなFSMを持ち、一方のSenderFSMがFIFOにデータを詰め(エンキュー)、他方のReceiverFSMがFIFOからデータを取り出す(デキュー)ものとします。コンカレントであり、エンキューとデキューは同時に起こります。
package Tb;
import StmtFSM::*;
import FIFOF::*;
(* synthesize *)
module mkTb (Empty);
FIFOF#(Bit#(8)) fifo <- mkFIFOF;
Stmt sender =
seq
$display("senderFSM %4d FSM started", $time);
action
$display("senderFSM %4d Enq 10", $time);
fifo.enq(10);
endaction
action
$display("senderFSM %4d Enq 20", $time);
fifo.enq(20);
endaction
action
$display("senderFSM %4d Enq 30", $time);
fifo.enq(30);
endaction
repeat (8) noAction;
endseq;
FSM senderFSM <- mkFSM(sender);
Stmt receiver =
seq
$display("receiverFSM %4d receiver FSM started", $time);
while(True) seq
action
$display("receiverFSM %4d FIFO popped data", $time, fifo.first());
fifo.deq();
endaction
repeat (2) noAction;
endseq
endseq;
FSM receiverFSM <- mkFSM(receiver);
rule startit;
senderFSM.start();
receiverFSM.start();
endrule
rule finish (senderFSM.done() && !receiverFSM.done());
$finish;
endrule
endmodule
endpackage
コードに示すように、エンキューはレイテンシ1で実行され、デキューはレイテンシ3で実行されます。各々のFSMは、エンキューデータ、デキューデータをそれぞれ表示します。