ステートマシンとデータパス
デジタル回路は小さなカウンタからFPGA全体までいろいろあるように見えるが、同期設計されたどんなデジタル回路も1個のステートマシンと等価である。しかし実際の設計では、制御信号を作るステートマシンと制御信号にしたがって処理するデータパスに分けた方が見通しがよくなる。
◇
ステートマシン(Finite State Machineを略してFSMともいう)とは、入力信号(遷移条件)にしたがってステートレジスタ値(状態)を遷移させることにより、意図したシーケンスどおりに出力(制御信号)を作る回路である。
ステートマシンの仕様は状態遷移図で書く。図において、状態をブロックで書き、状態間の矢印の横に遷移条件を書く。遷移条件が成り立たなければその状態にとどまる。
この図はそのままRTL記述に書き下せるので、いきなりRTL記述を書いてもよいが、図の方が一目で理解できるのでよい。
/* FSM */ reg[2:0] state_r; // ステートレジスタ localparam IDLE=3'd0; localparam SA1 =3'd1; localparam SA2 =3'd2; localparam SB1 =3'd3; localparam SB2 =3'd4; localparam SB3 =3'd5; always @(posedge clk or posedge rst) begin if(rst) state_r <= IDLE; else case(state_r) IDLE:if(start_a) state_r <= SA1; else if(start_b) state_r <= SB1; SA1: state_r <= SA2; SA2: if(done) state_r <= IDLE; SB1: state_r <= SB2; SB2: state_r <= SB3; SB3: if(done) state_r <= IDLE; endcase end |
各状態に対応する制御信号は、名前をつけて対応を示す真理値表か論理式を書くが、内部で使う分には制御信号にいちいち名前を付ける必要はなくstate_rをそのまま使ってRTL記述を書けばよい。
|
valid |
... |
IDLE |
0 |
|
SA1 |
0 |
|
SA2 |
1 |
|
SB1 |
0 |
|
SB2 |
0 |
|
SB3 |
1 |
|
// 制御信号に名前をつける場合 assign valid = ((state_r==SA2) | (state_r==SB3));
// 制御信号に名前をつけずに使う場合 always @(posedge clk or posedge rst) begin if(rst) count_r <= 0; else if((state_r==SA2) | (state_r==SB3)) count_r <= dati; else if(state_r!=IDLE) count_r <= count_r + 1'b1; end |
◇◇
上記のRTL記述では状態state_rだけを記述しているが、同じcase文の中に各状態におけるデータパスの動作を記述してもよい。ただし、1つのcase文の中にいろいろなレジスタの代入文を記述すると、読みにくくなってしまうので程度問題である。
例) ある処理をstart信号で開始してN回繰り返し、1回の処理はdone信号が来るまで待つというシーケンスを、状態遷移図に表すと次のようになる。
これのRTL記述は次のとおり。
/* FSM - データパスの動作も書いた場合 */ reg[2:0] state_r; reg[3:0] count_r; localparam IDLE=3'd0; localparam S1 =3'd1; localparam WAIT =3'd2; always @(posedge clk or posedge rst) begin if(rst) begin state_r <= IDLE; count_r <= 4'd0; end else begin case(state_r) IDLE: begin if(start) state_r <= S1; count_r <= 4'd0; end S1: begin state_r <= WAIT; count_r <= count_r + 1'b1; end WAIT: begin if(done) state_r <=(count_r==N)? IDLE:S1; end endcase end end |