それでは、前回作成したRTL記述で正しく動作するかどうかシミュレーションをやってみましょう。
たとえターゲットがFPGAであったとしても、この程度の規模のステートマシンであれば
少なくともRTLシミュレーションで全ての状態と全ての遷移条件についてはカバーしておきたいものです。
今回の場合は次の4つのステートを通過すること。
・ST_DoorClose
・ST_Opening
・ST_DoorOpen
・ST_Closing
そして、次の7つの遷移(同じステートにとどまるものも含めるとさらに+4)が行なわれることです。
・ST_DoorClose -> ST_Opening
・ST_Opening -> ST_DoorOpen
・ST_DoorOpen -> ST_Closing (閉ボタン)
・ST_DoorOpen -> ST_Closing (5秒経過)
・ST_Closing -> ST_DoorClose
・ST_Opening -> ST_Closing
・ST_Closing-> ST_Opening
以上の動作を確認するためのテストベンチを作成しました。
主要な部分を次に示します。
initial begin
// Initialize Inputs
reset = 1'b1;
buttonOpen = ~PUSHED;
buttonClose = ~PUSHED;
// Wait 100 us for global reset to finish
#1;
reset <= 1'b0;
// Add stimulus here
#100;
pushOpenButton();
wait(doorPosition==DOOR_POS_MAX);
#100;
pushCloseButton();
wait(doorPosition==DOOR_POS_MIN);
#100;
pushOpenButton();
#20000; // 2.0sec
pushCloseButton();
#10000; // 1.0sec
pushOpenButton();
wait(doorPosition==DOOR_POS_MAX);
wait(doorPosition==DOOR_POS_MIN);
#100;
$finish(2);
end
StateMachineSampleTB.v←完全なコードはこちら。
StateMachine.zip←RTLを含めた検証環境一式のZIPファイル。
タイムユニットは100usです。
ドアが完全に閉まった状態から完全に開いた状態(またはその逆)までには約4秒かかるようにしています。
シミュレーションの流れは次のとおりです。
・シミュレーション開始
↓
・初期状態でドアは閉まっている。
↓
・"開"ボタンを押して、ドアが完全に開くまで待つ。
↓
・ドアが完全に開いたら、"閉"ボタンを押してドアが完全に閉まるまで待つ。
↓(ここまででひとまず全てのステートは通過)
↓
・もう一度"開"ボタンを押す。
↓
・ドアが開いている途中で"閉"ボタンを押す。
↓
・ドアが閉まっている途中で"開"ボタンを押す。
↓
・ドアが完全に開くまで待つ。
↓(5秒経過して自動で閉まりだす)
↓
・ドアが完全に閉まるまで待つ。
↓
・シミュレーション終了
シミュレーションの出力結果は次のようになりました。
# State = ST_DoorClose @ 0
# Open button pushed.
# State = ST_Opening @ 115
# State = ST_DoorOpen @ 40815
# Close button pushed.
# State = ST_Closing @ 40915
# State = ST_DoorClose @ 81615
# Open button pushed.
# State = ST_Opening @ 81715
# Close button pushed.
# State = ST_Closing @ 101725
# Open button pushed.
# State = ST_Opening @ 111735
# State = ST_DoorOpen @ 142575
# State = ST_Closing @ 192585
# State = ST_DoorClose @ 233295
一応、波形も載せておきましょう。
ST_DoorClose -> ST_Opening
ST_Opening -> ST_DoorOpen -> ST_Closing (閉ボタン)
ST_Closing -> ST_DoorClose
ST_Opening -> ST_Closing
ST_Closing-> ST_Opening
ST_DoorOpen -> ST_Closing (5秒経過)
無事動いているようですね。
今回は省略していますが、これに加えて遷移条件が重なった場合に(今回ではST_OpeningやST_Closingから他のステートに遷移する場合)期待したとおりの動作となっているかどうかを確認することも重要です。
この程度のモジュールの単体試験用にちゃんとしたテストベンチを作る必要はあるのか?と聞かれるとなかなか自分もできていない場合が多いので偉そうなことは言えませんが、小さい単位だからこそ少し手間をかけてでも一度ちゃんとしたものを作っておけば、RTLに変更を加えた場合に、論理合成をかける前や後工程に渡す前、または自分が設計するより大きな単位のモジュールに組み込む前に、サッとシミュレーションを流すだけでかなりリスクを抑えることができると思います。
話はそれますが、ソフトのプログラミング言語に比べてHDLの参考になる記述をWebなどで探すのは大変ですよね。さらにテストベンチ用のシミュレーション記述となるとRTL記述に比べてさらに少ない。
結局自分もかなり自己流の記述になっていると思うので、そのあたりを考慮に入れてコードを読んでください。
とりあえず今回でステートマシン記述については終わり。
ステートマシンに関してはもっと書いてみたい事もあるのですがそれはまたの機会に。
0 件のコメント:
コメントを投稿