Moore型状态机和Mealy型状态机


  一、状态机的定义

    状态机就是能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定动作的控制中心。状态机简写为 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仿真部分仿真截图: