有限状态机的理解

有限状态机的理解

1. 一段式有限状态机

  数字电子技术中,时序逻辑电路的描述方法和一段式状态机是非常类似的,并没有引入次态这个变量,而是在clk上升沿到来之时检测现态和输入,判断后,更新现态和输出,也有一些数字电路的输出和时序无关,其是输入和现态的组合逻辑。一段式状态机是当clk上升沿上升沿到来之时检测现态和输入,更新现态和输出,这种状态机输出和现态均只是在clk上升沿到来之后才会更新,而在两个上升沿之间是保持不变的。
  一段式状态机的源文件代码和测试文件代码如下:

//一段式状态机
module Fsm(
    input                 clk,
    input                 rst_n,
    input                 x,
    output reg   [2:0]    state
    );

//parameter define
parameter S0=3'd0;
parameter S1=3'd1;
parameter S2=3'd2;
parameter S3=3'd3;
parameter S4=3'd4;

//*****************************************************
//**                    main code                      
//***************************************************** 
//一段式状态机
always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
        state<=S0;
    else
        begin
            case(state)
                S0:
                    begin
                        if(x==1)
                            state<=S0;
                        else
                            state<=S1;
                    end
                S1:
                    begin
                        if(x==1)
                            state<=S2;
                        else
                            state<=S1;
                    end
                S2:
                    begin
                        if(x==1)
                            state<=S3;
                        else
                            state<=S1;
                    end
                S3:
                    begin
                        if(x==1)
                            state<=S0;
                        else
                            state<=S4;
                    end
                S4:
                    begin
                        if(x==1)
                            state<=S2;
                        else
                            state<=S1;
                    end
                default: state<=S0;          //在state处于未知状态下启动状态机
            endcase
        end
end

endmodule
`timescale 1 ns/ 1 ns
module Fsm_vlg_tst();   //Modelsim是对仿真文件进行仿真
                                               
wire [2:0] state;
reg clk,rst_n,x;

Fsm u0_Fsm(
    .clk(clk),
    .rst_n(rst_n),
    .x(x),
    .state(state)
    );
initial                 //  fork join是并行运行的  begin   end是顺序执行的                                           
fork
    clk=0;
    #10 clk=1;
    #20 clk=0;
    #30 clk=1;
    #40 clk=0;
    #50 clk=1;
    #60 clk=0;
    #70 clk=1;
    #80 clk=0;
    #90 clk=1;
    #100 clk=0;
    #110 clk=1;
    #120 clk=0;
    #130 clk=1;
    #140 clk=0;
    #150 clk=1;
    #160 clk=0;
    
    rst_n=0;
    #15 rst_n=1;
    
    x=0;
    #20 x=1;
    #40 x=0;
    #60 x=1;
    #80 x=0;
    #100 x=1;
    #120 x=0;
    #140 x=1;
    #160 x=0;
    
join      
                                                                    
endmodule

  一段式状态机的仿真时序图如下:
在这里插入图片描述
  仿真结果和代码一致。

2. 二段式状态机

  二段式状态机的特色就是将时序逻辑和组合逻辑分成了两个always块,一个always块用于更新现态,这是时序逻辑,使用非阻塞性赋值,其仅在clk上升沿到来时进行;另一个用于更新次态,这是组合逻辑,使用阻塞性赋值,当输入和现态变化时,次态立刻更新。二段式的状态转移和一段式完全一样,只不过二段式是在当现态和输入变化时就更新次态,所以二段式有可能在一个时钟周期内多次更新次态,但是现态仅在clk上升沿到来时进行更新。但是二段式的输出和一段式不同,二段式的输出和次态一样,是实时更新的,而不是仅在clk上升沿到来时进行更新。
  二段式状态机的源文件代码如下:

// 二段式状态机
module Fsm(
    input                 clk,
    input                 rst_n,
    input                 x,
    output reg   [2:0]    state,
    output reg   [2:0]    next_state
    );

//parameter define
parameter S0=3'd0;
parameter S1=3'd1;
parameter S2=3'd2;
parameter S3=3'd3;
parameter S4=3'd4;

//*****************************************************
//**                    main code                      
//***************************************************** 
//CLK上升沿到来时更新现态(时序逻辑)
always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
        state<=S0;
    else
        state<=next_state;
end

//当现态和输入发生变化时更新次态(组合逻辑)
always @ (state or x)
begin
    if(!rst_n)
        next_state=S0;
    else
        begin
            case(state)
                S0:
                    begin
                        if(x==1)
                            next_state=S0;
                        else
                            next_state=S1;
                    end
                S1:
                    begin
                        if(x==1)
                            next_state=S2;
                        else
                            next_state=S1;
                    end
                S2:
                    begin
                        if(x==1)
                            next_state=S3;
                        else
                            next_state=S1;
                    end
                S3:
                    begin
                        if(x==1)
                            next_state=S0;
                        else
                            next_state=S4;
                    end
                S4:
                    begin
                        if(x==1)
                            next_state=S2;
                        else
                            next_state=S1;
                    end
                default:    next_state=S0;          //在state处于未知状态下启动状态机
            endcase
        end
end

endmodule

  二段式状态机的仿真时序图如下:
在这里插入图片描述
  可以发现,二段式状态机中state(现态)的变化和一段式是完全一致的,next_state(次态)是输入和现态的组合逻辑函数,并不是时序逻辑,其在一个时钟周期可能变化多次。

3. 三段式状态机

  三段式状态机和两段式状态机的区别仅仅是将输出量单独拿出来,目前有多种写法,一种是将输出量写成时序逻辑,当clk上升沿到来时,检测现态和输入,更新输出量,这样和一段式状态机其实完全一样;还有一种是将输出量写成组合逻辑,当现态或输入变化时更新输出量,这样和二段式状态机完全一致。此处不再赘述。

4. 选择哪种状态机

  之前教科书一致推荐使用两段式或者三段式,理由大多是便于优化代码,便于布局布线,但是随着技术发展,这个问题日渐消失,而且一段式状态机更加直观,适合初学者。具体比较可以参考一下博客三段式状态机的思维陷阱

反馈与建议

-邮箱:[email protected]

Guess you like

Origin blog.csdn.net/qq_38847810/article/details/105185501