状态机三种写法(下)附代码和状态转移图

以下用10010序列检测为例子,写的三种状态机的写法。

module fsm_10010(      //运行时,只留一种方法。

    input  wire clk       ,
    input  wire rst_n     ,
    input  wire data_in ,  //数据流
    output reg  flag       //检测成功标志
    );
    //状态编码
    parameter  idle  = 4'd0;  //初始状态
    parameter  s0    = 4'd1; //5'b1
    parameter  s1    = 4'd2; //5'b10
    parameter  s2    = 4'd3; //5'b100
    parameter  s3    = 4'd4; //5'b1001
    parameter  s4    = 4'd5; //5'b10010
    
    reg [3:0]  state    ; //状态机 /位
    
    //状态机描述  三种描述方式
    //一段式、二段式、三段式
    
    //一段式:一个always语句块,用时序逻辑既描述状态转移,又描述输出。
    /* always@ (posedge clk ,negedge rst_n)
begin
    if(~rst_n)
        begin
            flag    <= 1'b0;  //达到10010就输出1
            state    <= idle; //赋初值
        end
    else case(state)
    idle:begin
            flag <= 0;
            if(data_in == 1'b1)
                state <= s0 ;
            else
                state <= idle;
        end
    s0: begin
            flag <= 0;
        if(data_in == 0)
            state <= s1;
        else 
            state <=s0;
        end
    s1:begin
        flag <= 0;
            if(data_in == 0)
                state <= s2;
            else
            state <= s0;
        end
    s2:begin 
        flag <= 0;
            if(data_in == 1)
                state <= s3  ;
            else
                state <= idle;
        end
    s3:begin    
            flag <= 0;    
            if(data_in == 1'b0)
                state <= s4;
            else
                state <= s0; 
        end
    s4:begin    //10010
        flag <= 1;
            if(data_in == 1)
                state <= s0;
            else
                state <= s2;
        end
        
        default :begin 
            state    <= idle;  //
            flag <= 1'b0;
        end
    endcase
end
     */
                               


    
   二段式状态机

// 第一段:一个always语块,时序逻辑描述状态转移
// 第二段:一个always语块,组合逻辑描述输出(时序允许的情况下用时序逻辑)


always@ (posedge clk,negedge rst_n)    //时序逻辑
    begin
        if(~rst_n)
        begin
            state    <= idle;
        end
    else case(state)
    idle:begin
            
            if(data_in == 1'b1)
                state <= s0 ;
            else
                state <= idle;
            
        end
    s0: begin
            if(data_in == 0)
                state <= s1;
            else 
                state <=s0;
        end
    s1:begin
    
            if(data_in == 0)
                state <= s2;
            else
            state <= s0;
        end
    s2:begin 
        
            if(data_in == 1)
                state <= s3  ;
            else
                state <= idle;
        end
    s3:begin    
            
            if(data_in == 1'b0)
                state <= s4;
            else
                state <= s0; 
        end
    s4:begin 
        
            if(data_in == 1)
                state <= s0;
            else
                state <= s2;
        end
        
        default :begin 
            state    <= idle;  //
            
        end
    endcase
end


//第二段组合逻辑
always@(*)

begin                //判断状态等于s4时,标志位为0;
    if(~rst_n)      
        flag = 0;
    else if(state == s4)
        flag = 1;
    else 
        flag  = 0;
end

//三段式

/*
    第一段:时序逻辑描述状态更新,把次态(下一状态)赋值到现态
    第二段:一个always语块  组合逻辑描述状态判断,根据现态及输入判断次态
    第三段:一个always语块,时序逻辑描述输出。

*/

/*一个*/
reg [3:0] now_state  ;   //现态
reg [3:0] next_state ;     //次态
always@(posedge clk,negedge rst_n)
begin
    if(~rst_n)
        now_state <= idle;
    else
        now_state <= next_state;

end

  /*二个*/
always@(*)
begin                   //判断状态
    if(~rst_n)
        begin
            next_state = idle;  //复位时就是空闲
        end
    else case(now_state)
    idle:begin
        if(data_in == 1)
            next_state  = s0 ;
        else
            next_state = idle;
            
        end
    s0: begin
        if(data_in == 0)
            next_state = s1;
        else 
            next_state = s0;
        end
    s1:begin
        if(data_in==1)
            next_state = idle;
        else
            next_state = s0;
        end
    s2:begin 
        
            if(data_in ==1)
                next_state = s3 ;
            else
                next_state = idle;
    end
    s3: begin
        if (data_in == 1'b0)
            next_state = s4;
         else 
            next_state = s0;            
        end 
    s4:begin 
        if (data_in == 1'b0)
            next_state = s2;
        else 
            next_state = s0;    
        end
        
        default :begin 
            next_state    = idle;
            end
        endcase 
end

 /*  三个   */

/* always@(posedge clk,negedge rst_n) //带延时
begin
    if(~rst_n)
        flag <= 1'b0;
    else if (now_state == s4)
        flag <= 1'b1;
    else 
        flag <= 1'b0;
end */
    
    endmodule

以下为状态转移图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值