三段式狀態機
下圖分別為時鍾同步的Moore狀態機(左)和時鍾同步的Mearly狀態機(右),二者都由產生下一狀態的組合邏輯、當前狀態寄存器和產生輸出的組合邏輯三個部分組成。
三段式狀態機正如其名字一樣,每個部分采用一個always過程塊進行描述,可以清晰地顯示出狀態機的結構。
在調試多輸出狀態機時,還可以根據輸出的數量把產生輸出的組合邏輯按輸出寫成彼此獨立的always組合塊,以方便調試,在設計復雜的多輸出狀態機時推薦采用這種風格。
別人的總結:
- 使用三段式狀態機需要聲明內部信號,一般需要定義state和nextstate;
- 三個always語句塊分別代表:
- 當前狀態轉換到下一狀態的時序邏輯;
- 在當前狀態在當前輸出下轉換為下一狀態的組合邏輯;
- 當前狀態(和當前輸入)產生當前輸出的組合邏輯;
樣例:
下圖為樣例的狀態轉移圖,並使用三段式狀態機對其進行描述。由於該狀態機包含兩個輸出G、F,所以代碼中包含兩個輸出組合邏輯。
// 三段式狀態機
module fsm_mult_out( output reg K2, K1, input clk, Reset, A ); reg [1:0] state, nextstate;
parameter Idle = 2'b00,
Start = 2'b01,
Stop = 2'b10,
Clear = 2'b11;
// -----------------當前狀態寄存器-------------------------
always @(posedge clk) // 為什么這里要用非阻塞賦值,后面用阻塞賦值? if(!Reset) state <= Idle; else state <= nextstate; // ----------------產生下一狀態的組合邏輯-------------------- always @(state, A) case(state) Idle: if(A) nextstate = Start; else nextstate = state; Start: if(!A) nextstate = Stop; else nextstate = state; Stop: if(A) nextstate = Clear; else nextstate = state; Clear: if(!A) nextstate = Idle; else nextstate = Clear; default: nextstate = 2'bxx;
endcase
// --------------產生輸出的組合邏輯--------------------------
// assignment for K1
always @(state, Reset, A) if(!Reset) K1 = 0; else
if(state==Clear && !A) K1 = 1; else K1 = 0; // assginment for K2
always @(state, Reset, A) if(!Reset) K2 = 0; else
if(state==Stop && A) K2 = 1; else K2 = 0; endmodule
相應的testbench
// testbench
module t_fsm(); reg a; reg clk, rst; wire k1, k2; // reg [1:0] state;
fsm_mult_out m(.K2(k2), .K1(k1), .A(a), .clk(clk), .Reset(rst)); initial
begin
// state = 2'b00;
a = 0; rst = 1; clk = 0; #22 rst = 0; #133 rst = 1; end
always #50 clk = ~clk; always @(posedge clk) begin #30 a = {$random}%2; #(3*50 + 12); end
initial
begin #100000 $stop; end
endmodule