一、狀態機的定義
狀態機就是能夠根據控制信號按照預先設定的狀態進行狀態轉移,是協調相關信號動作、完成特定動作的控制中心。狀態機簡寫為 FSM (Finite State Machine),分為兩類:
1:輸出只和當前狀態有關而與輸入無關,則稱為摩爾(Moore)狀態機;
2:輸出不僅和當前狀態有關而且和輸入有關,則稱為米利(Mealy)狀態機;
二、兩種狀態機的區別
1:在波形上區別:以一個序列檢測器為例,檢測到輸入信號11時輸出z為1,其他時候為0。用摩爾型FSM實現需要用到三個狀態(A,B,C)。而用米利型FSM實現則需要兩個狀態(A,B)。摩爾型FSM輸出函數的輸入只由狀態變量決定,要想輸出z=1,必須C狀態形成,即寄存器中的兩個1都打進去后才可以。輸出z=1會在下一個有效沿到來的時候被賦值。而米利型FSM輸出函數是由輸入和狀態變量共同決定的。狀態在B的時候如果輸入為1,則直接以組合電路輸出z=1,不需要等到下個有效沿到來。從而也就不需要第三個狀態C。
2:摩爾狀態機更安全:輸出在時鍾邊沿變化(總是在一個周期后)。在Mealy機器中,輸入更改可能會在邏輯完成后立即導致輸出更改, 當兩台機器互連時出現大問題 ,如果不小心,可能會發生異步反饋。
3:Mealy狀態機對輸入的反應更快:在相同的周期內反應 - 不需要等待時鍾。在Moore機器中,可能需要更多邏輯來將狀態解碼為輸出 - 在時鍾邊沿之后更多的門延遲。並非所有時序電路都可以使用Mealy模型實現。 一些時序電路只能作為摩爾機器實現。
三、經典三段式狀態機模板
1 reg [:] current_state ; 2 reg [:] next_state ; 3 4 wire [:0] IDLE ; 5 wire [:0] S0 ; 6 wire [:0] S1 ; 7 wire [:0] S2 ; 8 9 //=============================================================================\ 10 //**************************** State Machine ******************************* 11 //=============================================================================\ 12 13 always @(posedge sclk or negedge s_rst_n) begin 14 if(!s_rst_n) 15 current_state <= IDLE; 16 else 17 current_state <= next_state; 18 end 19 20 always @(*) begin 21 next_state = IDLE; 22 case(current_state) 23 IDLE:begin 24 if(idle2s0 == 1'b1) 25 next_state = S0; 26 else 27 next_state = current_state; 28 end 29 30 S0:begin 31 if(s02s1 == 1'b1) 32 next_state = S1; 33 else 34 next_state =current_state; 35 end 36 37 S1:begin 38 if(s12s2 == 1'b1) 39 next_state = S2; 40 else 41 next_state = current_state; 42 end 43 44 S2:begin 45 if(s22idle == 1'b1) 46 next_state = IDLE; 47 else 48 next_state = current_state; 49 end 50 51 default:begin 52 next_state = IDLE; 53 end 54 endcase 55 end 56 57 assign idle2s0 = current_state == IDLE && 58 assign s02s1 = current_state == S0 && 59 assign s12s2 = current_state == S1 && 60 assign s22idle = current_state == S2 && 61 62 always @(posedge sclk or negedge s_rst_n) begin 63 if(!s_rst_n) begin 64 65 end 66 else begin 67 case(next_state) 68 69 end 70 end
四、摩爾型狀態機
1、舉例說明摩爾型狀態機,非重疊檢測 1101 1101
(1)狀態轉移圖

(2)Moore代碼
1 // ********************************************************************************* 2 // Project Name : state_test 3 // Email : 4 // Create Time : 2020/06/25 20:20 5 // Module Name : state_test 6 // editor : qing 7 // Version : Rev1.0.0 8 // Description : 非重疊檢測的Mooer狀態機 1101 9 // ********************************************************************************* 10 11 module state_test( 12 input sclk , 13 input s_rst_n , 14 15 input din , 16 output reg dout 17 ); 18 19 //========================================================================\ 20 // =========== Define Parameter and Internal signals =========== 21 //========================================================================/ 22 23 reg [4:0] current_state ; 24 reg [4:0] next_state ; 25 26 parameter S0 = 5'b00001 ; 27 parameter S1 = 5'b00010 ; 28 parameter S2 = 5'b00100 ; 29 parameter S3 = 5'b01000 ; 30 parameter S4 = 5'b10000 ; 31 32 //============================================================================= 33 //**************************** Main Code ******************************* 34 //============================================================================= 35 36 always @(posedge sclk or negedge s_rst_n) begin 37 if(!s_rst_n) 38 current_state <= S0; 39 else 40 current_state <= next_state; 41 end 42 43 always @(*) begin 44 next_state = S0; 45 case(current_state) 46 S0:begin 47 if(din == 1'b1) // 1 48 next_state = S1; 49 else 50 next_state = current_state; // 0 51 end 52 53 S1:begin 54 if(din == 1'b1) 55 next_state = S2; // 11 56 else 57 next_state = S0; // 10 58 end 59 60 S2:begin 61 if(din == 1'b0) // 110 62 next_state = S3; 63 else 64 next_state = current_state; // 111 65 end 66 67 S3:begin 68 if(din == 1'b1) 69 next_state = S4; // 1101 70 else 71 next_state = S0; // 1100 72 end 73 74 S4:begin 75 if(din == 1'b1) // 1101 1 76 next_state = S1; 77 else 78 next_state = S0; // 1101 0 79 end 80 81 default:begin 82 next_state = S0; 83 end 84 endcase 85 end 86 87 always @(posedge sclk or negedge s_rst_n) begin 88 if(!s_rst_n) begin 89 dout <= 0; 90 end 91 else if(current_state == S4) 92 dout <= 1; 93 else 94 dout <= 0; 95 end 96 endmodule
testbench
1 // ********************************************************************************* 2 // Project Name : state_test 3 // Email : 4 // Create Time : 2020/06/25 06:25 5 // Module Name : state_test_tb 6 // editor : qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 `timescale 1ns/1ps 11 module state_test_tb; 12 reg sclk ; 13 reg s_rst_n ; 14 reg din ; 15 wire dout ; 16 17 state_test state_test_inst( 18 .sclk (sclk ) , 19 .s_rst_n (s_rst_n ) , 20 .din (din ) , 21 .dout (dout ) 22 ); 23 24 initial 25 sclk = 1'b0; 26 always #10 sclk = ~sclk; 27 28 initial 29 begin 30 #1; 31 din = 0; 32 s_rst_n = 1'b0; 33 #21; 34 s_rst_n = 1'b1; 35 36 #51; 37 38 din = 1; 39 #20; 40 din = 0; 41 #20; 42 din = 1; 43 #20; 44 din = 1; 45 #20; 46 din = 0; 47 #20; 48 din = 1; 49 #20; 50 din = 0; 51 #30; 52 53 din = 1; 54 #20; 55 din = 0; 56 #20; 57 din = 1; 58 #20; 59 din = 1; 60 #20; 61 din = 0; 62 #20; 63 din = 1; 64 #20; 65 din = 0; 66 #30; 67 end 68 69 endmodule 70
2、舉例說明摩爾型狀態機,重疊檢測 1101001
(1)狀態轉移圖

(2)Moore代碼
1 // ********************************************************************************* 2 // Project Name : state_test 3 // Email : 4 // Create Time : 2020/06/25 20:20 5 // Module Name : state_test 6 // editor : qing 7 // Version : Rev1.0.0 8 // Description : 重疊檢測的Mooer狀態機 1101 9 // ********************************************************************************* 10 11 module state_test( 12 input sclk , 13 input s_rst_n , 14 15 input din , 16 output reg dout 17 ); 18 19 //========================================================================\ 20 // =========== Define Parameter and Internal signals =========== 21 //========================================================================/ 22 23 reg [4:0] current_state ; 24 reg [4:0] next_state ; 25 26 parameter S0 = 5'b00001 ; 27 parameter S1 = 5'b00010 ; 28 parameter S2 = 5'b00100 ; 29 parameter S3 = 5'b01000 ; 30 parameter S4 = 5'b10000 ; 31 32 //============================================================================= 33 //**************************** Main Code ******************************* 34 //============================================================================= 35 36 always @(posedge sclk or negedge s_rst_n) begin 37 if(!s_rst_n) 38 current_state <= S0; 39 else 40 current_state <= next_state; 41 end 42 43 always @(*) begin 44 next_state = S0; 45 case(current_state) 46 S0:begin 47 if(din == 1'b1) // 1 48 next_state = S1; 49 else 50 next_state = current_state; // 0 51 end 52 53 S1:begin 54 if(din == 1'b1) 55 next_state = S2; // 11 56 else 57 next_state = S0; // 10 58 end 59 60 S2:begin 61 if(din == 1'b0) // 110 62 next_state = S3; 63 else 64 next_state = current_state; // 111 65 end 66 67 S3:begin 68 if(din == 1'b1) 69 next_state = S4; // 1101 70 else 71 next_state = S0; // 1100 72 end 73 74 S4:begin 75 if(din == 1'b1) // 1101 1 76 next_state = S2; 77 else 78 next_state = S0; // 1101 0 79 end 80 81 default:begin 82 next_state = S0; 83 end 84 endcase 85 end 86 87 always @(posedge sclk or negedge s_rst_n) begin 88 if(!s_rst_n) begin 89 dout <= 0; 90 end 91 else if(current_state == S4) 92 dout <= 1; 93 else 94 dout <= 0; 95 end 96 endmodule
testbench
1 // ********************************************************************************* 2 // Project Name : state_test 3 // Email : 4 // Create Time : 2020/06/25 06:25 5 // Module Name : state_test_tb 6 // editor : qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 `timescale 1ns/1ps 11 module state_test_tb; 12 reg sclk ; 13 reg s_rst_n ; 14 reg din ; 15 wire dout ; 16 17 state_test state_test_inst( 18 .sclk (sclk ) , 19 .s_rst_n (s_rst_n ) , 20 .din (din ) , 21 .dout (dout ) 22 ); 23 24 initial 25 sclk = 1'b0; 26 always #10 sclk = ~sclk; 27 28 initial 29 begin 30 #1; 31 din = 0; 32 s_rst_n = 1'b0; 33 #21; 34 s_rst_n = 1'b1; 35 36 #51; 37 38 din = 1; 39 #20; 40 din = 0; 41 #20; 42 din = 1; 43 #20; 44 din = 1; 45 #20; 46 din = 0; 47 #20; 48 din = 1; 49 #20; 50 din = 0; 51 #30; 52 53 din = 1; 54 #20; 55 din = 0; 56 #20; 57 din = 1; 58 #20; 59 din = 1; 60 #20; 61 din = 0; 62 #20; 63 din = 1; 64 #20; 65 din = 0; 66 #30; 67 end 68 69 endmodule
五、米利型狀態機 1101序列檢測
1、狀態轉移圖

2、Mealy 代碼
1 // ********************************************************************************* 2 // Project Name : mealy_state 3 // Email : 4 // Create Time : 2020/06/29 22:28 5 // Module Name : 6 // editor : Qing 7 // Version : Rev1.0.0 8 // Description : 米利型狀態機 1101序列檢測 9 // ********************************************************************************* 10 11 module mealy_state( 12 input sclk , 13 input s_rst_n , 14 15 input din , 16 output reg dout 17 ); 18 19 //========================================================================\ 20 // =========== Define Parameter and Internal signals =========== 21 //========================================================================/ 22 23 24 reg [3:0] current_state ; 25 reg [3:0] next_state ; 26 27 parameter IDLE = 4'b0001 ; 28 parameter S0 = 4'b0010 ; 29 parameter S1 = 4'b0100 ; 30 parameter S2 = 4'b1000 ; 31 32 //=============================================================================\ 33 //**************************** State Machine ******************************* 34 //=============================================================================\ 35 36 always @(posedge sclk or negedge s_rst_n) begin 37 if(!s_rst_n) 38 current_state <= IDLE; 39 else 40 current_state <= next_state; 41 end 42 43 always @(*) begin 44 next_state = IDLE; 45 case(current_state) 46 IDLE:begin 47 if(din == 1'b1) 48 next_state = S0; 49 else 50 next_state = current_state; 51 end 52 53 S0:begin 54 if(din == 1'b1) 55 next_state = S1; 56 else 57 next_state = IDLE; 58 end 59 60 S1:begin 61 if(din == 1'b0) 62 next_state = S2; 63 else 64 next_state = current_state; 65 end 66 67 S2:begin 68 if(din == 1'b1) 69 next_state = IDLE; 70 else 71 next_state = IDLE; 72 end 73 74 default:begin 75 next_state = IDLE; 76 end 77 endcase 78 end 79 80 always @(posedge sclk or negedge s_rst_n) begin 81 if(!s_rst_n) 82 dout <= 1'b0; 83 else if(current_state == S2 && din == 1'b1) 84 dout <= 1'b1; 85 else 86 dout <= 1'b0; 87 end 88 89 endmodule
testbench:
1 // ********************************************************************************* 2 // Project Name : mealy_state 3 // Email : 4 // Create Time : 2020/06/29 23:06 5 // Module Name : mealy_state_tb 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module mealy_state_tb; 11 reg sclk ; 12 reg s_rst_n ; 13 reg din ; 14 wire dout ; 15 16 mealy_state mealy_state_inst( 17 .sclk (sclk ), 18 .s_rst_n (s_rst_n ), 19 .din (din ), 20 .dout (dout ) 21 ); 22 23 initial 24 sclk = 1'b0; 25 always #10 sclk = ~sclk; 26 27 initial 28 begin 29 #1; 30 din =1'b0; 31 s_rst_n = 1'b0; 32 #21; 33 s_rst_n = 1'b1; 34 #20; 35 36 xulie; 37 #100; 38 xulie; 39 #100; 40 xulie; 41 end 42 43 task xulie; 44 repeat(2) 45 begin 46 din = 1'b1; 47 #40; 48 din = 1'b0; 49 #20; 50 din = 1'b1; 51 #80; 52 din = 1'b1; 53 #30; 54 din = 1'b0; 55 #30; 56 din = 1'b1; 57 #100; 58 end 59 60 endtask 61 62 endmodule
六、總結
1、Moore狀態機的輸出是與時鍾同步,Mealy狀態機的輸出是異步的,當輸入發生變化時,輸出就發生變化。
2、Mealy狀態機的輸出比Moore狀態機狀態的輸出提前一個周期;
3、序列檢測器可以用於檢測一組或多組由二進制碼組成的脈沖序列信號,當序列檢測器連續收到一組串行二進制碼后,如果這組碼與檢測器中預先設置的碼相同,則輸出 1 ,否則輸出 0 。由於這種檢測的關鍵在於正確碼的接收是連續的,這就要求檢測器必須記住前一次的正確碼及正確序列,直到在連續檢測中所收到的每一位碼都與預置數的對應碼相同。在檢測過程中,任何一位不相等都將回到初始狀態重新開始檢測。
七、參考
1:《搭建你的數字積木數字電路與邏輯設計》(Verilog HDL & Vivado版);
2:https://blog.csdn.net/CrazyUncle/article/details/88830654
八、附錄
1:米利型狀態機 檢測 1001
1 // ********************************************************************************* 2 // Project Name : mealy_state 3 // Email : 4 // Create Time : 2020/06/30 09:35 5 // Module Name : 6 // editor : Qing 7 // Version : Rev1.0.0 8 // Description : 米利型狀態機 1001序列檢測 9 // ********************************************************************************* 10 11 module mealy_state( 12 input sclk , 13 input s_rst_n , 14 15 input din , 16 output reg dout 17 ); 18 19 //========================================================================\ 20 // =========== Define Parameter and Internal signals =========== 21 //========================================================================/ 22 23 24 reg [3:0] current_state ; 25 reg [3:0] next_state ; 26 27 parameter IDLE = 4'd0 ; 28 parameter S0 = 4'd1 ; 29 parameter S1 = 4'd2 ; 30 parameter S2 = 4'd3 ; 31 32 //=============================================================================\ 33 //**************************** State Machine ******************************* 34 //=============================================================================\ 35 36 always @(posedge sclk or negedge s_rst_n) begin 37 if(!s_rst_n) 38 current_state <= IDLE; 39 else 40 current_state <= next_state; 41 end 42 43 always @(*) begin 44 next_state = IDLE; 45 case(current_state) 46 IDLE:begin 47 if(din == 1'b1) 48 next_state = S0; // 1 49 else 50 next_state = current_state; // 0 51 end 52 53 S0:begin 54 if(din == 1'b0) // 10 55 next_state = S1; 56 else 57 next_state = current_state; // 11 58 end 59 60 S1:begin 61 if(din == 1'b0) 62 next_state = S2; // 100 63 else 64 next_state = S0; // 101 65 end 66 67 S2:begin 68 if(din == 1'b1) 69 next_state = S0; // 1001 70 else 71 next_state = IDLE; // 1000 72 73 end 74 75 default:begin 76 next_state = IDLE; 77 end 78 endcase 79 end 80 81 always @(posedge sclk or negedge s_rst_n) begin 82 if(!s_rst_n) 83 dout <= 1'b0; 84 else if(current_state == S2 && din == 1'b1) 85 dout <= 1'b1; 86 else 87 dout <= 1'b0; 88 end 89 90 endmodule
testbench:
1 // ********************************************************************************* 2 // Project Name : mealy_state 3 // Email : 4 // Create Time : 2020/06/29 23:06 5 // Module Name : mealy_state_tb 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module mealy_state_tb; 11 reg sclk ; 12 reg s_rst_n ; 13 reg din ; 14 wire dout ; 15 16 mealy_state mealy_state_inst( 17 .sclk (sclk ), 18 .s_rst_n (s_rst_n ), 19 .din (din ), 20 .dout (dout ) 21 ); 22 23 initial 24 sclk = 1'b0; 25 always #10 sclk = ~sclk; 26 27 initial 28 begin 29 #1; 30 din =1'b0; 31 s_rst_n = 1'b0; 32 #21; 33 s_rst_n = 1'b1; 34 #20; 35 36 xulie; 37 #100; 38 xulie; 39 #100; 40 xulie; 41 end 42 43 task xulie; 44 repeat(2) 45 begin 46 din = 1'b1; 47 #40; 48 din = 1'b0; 49 #50; 50 din = 1'b1; 51 #50; 52 din = 1'b0; 53 #30; 54 din = 1'b1; 55 #100; 56 end 57 58 endtask 59 60 endmodule

2:摩爾型狀態機 無重疊檢測 0110

閱讀不同的人寫的代碼,發現不同的描述方式都可以實現同一個功能,沒有統一的解答過程,這讓我感到迷惑。
如有疏漏或不當之處,還望各位道友不吝指出~
// ===============================================
// ======================= 更新 ===================
時間:2020/12/22 22:22
今晚看到一個關於狀態機的說法,覺得蠻好的,與諸位道友分享~
一段式、二段式、三段式其實都是之前經典的老寫法,也是一些老工程師仍然習慣用的寫法,老方法是根據狀態機理論建立的模型抽象后設計的,其實要嚴格按照固定的格式來寫代碼,否則綜合器將無法識別出你寫的代碼是個狀態機,因為早期的開發工具只能識別出固定的狀態機格式,如果不按照標准格式寫代碼綜合器最后無法綜合成為狀態機的樣子。這樣往往增加了設計的難度,很多人學習的時候還要去了解理論模型,反復學習理解很久才能夠設計好的狀態機,所以需要改進。
老的一段式、二段式、三段式各有優缺點,其中一段式在描述大型狀態機時會比較困難,會使整個系統顯得十分臃腫,不夠清晰;二段式狀態機的好處是其結構和理想的理論模型完全吻合,即不會有附加的結構存在,比較精簡,但是由於二段狀態機的第二段是組合邏輯描述數據的輸出,所以有一些情況是無法描述的,比如輸出時需要類似計數的累加情況,這種情況在組合邏輯中會產生自迭代,自迭代在組合邏輯電路中是嚴格禁止的,而且第二段狀態機主要是描述數據的輸出,輸出時使用組合邏輯往往會產生更多的毛刺,所以並不推薦。所以衍生出三段式狀態機,三段狀態機的輸出就可是時序邏輯了,但是其結構並不是最精簡的了。三段式狀態機的第一段狀態機是用時序邏輯描述當前狀態, 第二段狀態機是用組合邏輯描述下一狀態, 第三狀態描述狀態輸出。
新的狀態機使用兩個均采用時序邏輯的 always 塊,第一個 always 塊描述狀態的轉移為第一段狀態機,第二個 always 塊描述數據的輸出為第二段狀態機(如果我們遵循一個 always 塊只描述一個變量的原則,如果有多個輸出時第二段狀態機就可以分為多個always 塊來表達,但理論上仍屬於新二段狀態機,所以幾段式狀態機並不是由 always 塊的數量簡單決定的)
1 reg [3:0] state ; 2 3 always @ (posedge sclk or negedge s_rst_n) begin // 描述狀態轉移條件 4 if(s_rst_n == 1'b0) 5 state <= IDLE; 6 else begin 7 case(state) 8 IDLE:begin 9 if(start_init_pre == 1'b1) 10 state <= INIT_PRE; 11 else 12 state <= state; 13 end 14 15 INIT_PRE:begin 16 if(start_init_aref == 1'b1) 17 state <= INIT_AREF1; 18 else 19 state <= state; 20 end 21 22 default:begin 23 state <= IDLE; 24 end 25 endcase 26 end 27 end 28 29 always @ (posedge sclk or negedge s_rst_n) begin // 描述狀態輸出,不拘泥於一個always塊 30 if(s_rst_n == 1'b0) 31 32 else begin 33 case(state) 34 IDLE:begin 35 36 end 37 38 INIT_PRE:begin 39 40 end 41 42 43 default:begin 44 45 end 46 endcase 47 end 48 end
注:上述文字出自 野火 的論壇,侵刪~
// =============================================================
// *************************************** 更新 ********************************************************
// ==============================================================
// 2021/09/06
一種狀態機的例程
該例程簡單的驗證了 野火 論壇中的狀態機的實現方式,簡單好用(未考慮時序方面)
源碼:
1 // ********************************************************************************* 2 // Project Name : state_test 3 // Email : 4 // Create Time : 2021/09/06 17:08 5 // Module Name : 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module state_test( 11 input clk , 12 input rst_n , 13 14 output reg[2:0] dout 15 ); 16 17 //========================================================================\ 18 // =========== Define Parameter and Internal signals =========== 19 //========================================================================/ 20 21 parameter T_1 = 3 ; 22 parameter T_2 = 4 ; 23 parameter T_3 = 5 ; 24 parameter T_4 = 6 ; 25 parameter T_5 = 7 ; 26 27 parameter IDLE = 4'd0 ; 28 parameter FIRST = 4'd1 ; 29 parameter SECOND = 4'd2 ; 30 parameter THREE = 4'd3 ; 31 parameter FOUR = 4'd4 ; 32 33 reg [3:0] state ; 34 35 reg [7:0] cnt_clk ; 36 reg cnt_clk_rst ; 37 38 wire idle_2_first_flag ; 39 wire first_2_second_flag ; 40 wire second_2_three_flag ; 41 wire three_2_four_flag ; 42 wire four_2_idle_flag ; 43 //============================================================================= 44 //**************************** Main Code ******************************* 45 //============================================================================= 46 47 always @(posedge clk or negedge rst_n) begin 48 if(!rst_n) 49 cnt_clk <= 4'd0; 50 else if(cnt_clk_rst == 1'b1) 51 cnt_clk <= 4'd0; 52 else 53 cnt_clk <= cnt_clk + 1'b1; 54 end 55 56 assign idle_2_first_flag = (state == IDLE ) && (cnt_clk == T_1) ; 57 assign first_2_second_flag = (state == FIRST ) && (cnt_clk == T_2) ; 58 assign second_2_three_flag = (state == SECOND) && (cnt_clk == T_3) ; 59 assign three_2_four_flag = (state == THREE ) && (cnt_clk == T_4) ; 60 assign four_2_idle_flag = (state == FOUR ) && (cnt_clk == T_5) ; 61 62 always @(posedge clk or negedge rst_n) begin 63 if(!rst_n) 64 state <= IDLE; 65 else begin 66 case(state) 67 IDLE:begin 68 if(idle_2_first_flag == 1'b1) 69 state <= FIRST; 70 else 71 state <= state; 72 end 73 74 FIRST:begin 75 if(first_2_second_flag == 1'b1) 76 state <= SECOND; 77 else 78 state <= state; 79 end 80 81 SECOND:begin 82 if(second_2_three_flag == 1'b1) 83 state <= THREE; 84 else 85 state <= state; 86 end 87 88 THREE:begin 89 if(three_2_four_flag == 1'b1) 90 state <= FOUR; 91 else 92 state <= state; 93 end 94 95 FOUR:begin 96 if(four_2_idle_flag == 1'b1) 97 state <= IDLE; 98 else 99 state <= state; 100 end 101 102 default:state <= IDLE; 103 endcase 104 end 105 end 106 107 always @(*) begin 108 case(state) 109 IDLE:cnt_clk_rst = (idle_2_first_flag == 1'b1) ? 1'b1 : 1'b0; 110 FIRST:cnt_clk_rst = (first_2_second_flag == 1'b1) ? 1'b1 : 1'b0; 111 SECOND:cnt_clk_rst = (second_2_three_flag == 1'b1) ? 1'b1 : 1'b0; 112 THREE:cnt_clk_rst = (three_2_four_flag == 1'b1) ? 1'b1 : 1'b0; 113 FOUR:cnt_clk_rst = (four_2_idle_flag == 1'b1) ? 1'b1 : 1'b0; 114 default:cnt_clk_rst = 1'b0; 115 endcase 116 end 117 118 always @(posedge clk or negedge rst_n) begin 119 if(!rst_n) 120 dout <= 3'd0; 121 else begin 122 case(state) 123 IDLE: dout <= 3'd1; 124 FIRST: dout <= 3'd2; 125 SECOND: dout <= 3'd3; 126 THREE: dout <= 3'd4; 127 FOUR: dout <= 3'd5; 128 default: dout <= 3'd0; 129 endcase 130 end 131 end 132 133 endmodule
testbench:
1 `timescale 1ns/1ps 2 3 module state_test_tb; 4 reg clk ; 5 reg rst_n ; 6 7 wire [2:0] dout ; 8 9 state_test inst( 10 .clk ( clk ), 11 .rst_n ( rst_n ), 12 .dout ( dout ) 13 ); 14 15 initial 16 begin 17 $dumpfile("wave.vcd"); 18 $dumpvars(0,inst); 19 end 20 21 initial 22 clk = 1'b0; 23 always #10 clk = ~clk; 24 25 initial 26 begin 27 #1; 28 rst_n = 1'b0; 29 #51; 30 rst_n = 1'b1; 31 end 32 33 endmodule
gtkwave仿真部分仿真截圖:

