【 FPGA 】序列检测器 11010 (mealy状态机,moore状态机)

1.mealy状态机和moore状态机me

        状态机是硬件电路设计的常用的描述工具,也是电路设计的重要思想。很早之前我就知道mealy状态机和moore状态机,但是对两者的差别不是非常的清楚,最近在学习系列检测器的设计时对这两种状态机和一段式、三段式状态机有了更深刻的了解,在这里分享自己的见解给大家。有什么理解不准确的地方也希望大家指正。

1.1序列检测器

        在介绍两种状态机之前首先先介绍一下序列检测器。

        序列检测器:从一串数据流中找到需要检测的序列号。例如如下一串数据流,需要检测的序列为11010,则每一次检测到11010时序列检测器需要输出一次使能。

9ab5e22aae8540ccbbd6a57138f57c58.png        设计该电路就可以使用状态机来实现。接下来讲解两种状态机区别和用这两种状态机实现该电路的状态图。

1.2.mealy状态机和moore状态机区别

        mealy状态机:输出由当前状态机状态和控制信号共同决定。

        moore状态机:输出仅仅取决于当前的状态机状态。

        下图时两种状态机的状态转移图 

3a785cd07e4f4685bdb6e76b7ba33563.png

7038a8a3363b477ca34409c71717da56.png

        首先解释两种状态机的工作:

        1.mealy状态机:s0状态表示一个最初状态,该状态检测到1表示序列11010的第一个1被检测到,跳转到s1,此时需要检测11010的第二个1,当在检测到第二个1时,跳转到s2,一次类推到跳转到s4,此时如果下一时刻检测到0,则表示检测到了所需要的序列,输出正确。

具体状态解释:s0:等待检测第一个需要的序列

                        s1:已经检测到1,等待检测到第二位1

                        s2:已经检测到11,等待检测第三位0    

                        s3:已经检测到110, 等待检测第四位1

                        s4:已经检测到1101,等待检测第五位0

        检测成功条件:状态机处于s4状态,并且下一个时刻输入的检测信号是0

        2.moore状态机:s0表示一个空闲状态,该状态等待第一位1的到来,当检测到第一个1后,跳转到s1,等待检测第二位1,一次类推直到跳转到s5。

具体状态解释:s0:等待检测第一个需要的序列

                        s1:已经检测到1,等待检测到第二位1

                        s2:已经检测到11,等待检测第三位0    

                        s3:已经检测到110, 等待检测第四位1

                        s4:已经检测到1101,等待检测第五位0

                        s5:已经检测到11010

        检测成功条件:状态机处于s5状态。

        在该电路中,两种状态机本质上,moore状态机是比mealy多一个s5状态,moore状态机就是通过判定是否处于该状态来判定条件是否正确,而mealy状态机则时通过s4状态以及下一个时刻的条件信号是否有效来判定条件是否正确。

2.序列检测器的verilog代码实现

2.1.mealy状态机verilog实现ssf

module sequence_11010_chack (
	input 					clk							,
	input					rst_p						,

    input                   sequence_num                ,

    output                  num_en                      
);

localparam s0   =   5'd0    ;
localparam s1   =   5'd1    ;
localparam s2   =   5'd2    ;
localparam s3   =   5'd4    ;
localparam s4   =   5'd8    ;
localparam s5   =   5'd16   ;  

reg [ 4   : 0 ] cur_state   ;
reg             chack_right ;

reg [ 4   : 0 ] next_state ;

//-----------------------------------------------------------------------
//-----mealy状态机
//---三段式实现
//--序列11010检测
//-----------------------------------------------------------------------

//第一段
always @(posedge clk) begin
    if(rst_p)
        cur_state <= 5'd0 ;
    else 
        cur_state <= next_state ;
end

//第二段
always @( *) begin
    case(cur_state)
        s0 : next_state = (sequence_num) ? s1 : s0 ;
        s1 : next_state = (sequence_num) ? s2 : s0 ;
        s2 : next_state = (sequence_num) ? s2 : s3 ;
        s3 : next_state = (sequence_num) ? s4 : s0 ;
        s4 : next_state = (sequence_num) ? s1 : s0 ;
        default : next_state = s0 ;
    endcase
end

//第三段
always @(posedge clk) begin
    if(rst_p)
        chack_right <= 1'b0 ;
    else begin
        case(cur_state)
            s4 :  chack_right <= (sequence_num) ? 1'b0 : 1'b1 ;
            default : chack_right <= 1'b0 ;
        endcase           
    end
end

assign num_en = chack_right ;

         mealy状态机输出与当前状态以及输入信号有关 可以看到代码中chack_right信号是由cur_state和sequence_num共同决定的。

2.2.moore状态机的Verilog代码实现

module sequence_11010_chack (
	input 					clk							,
	input					rst_p						,

    input                   sequence_num                ,

    output                  num_en                      
);

localparam s0   =   5'd0    ;
localparam s1   =   5'd1    ;
localparam s2   =   5'd2    ;
localparam s3   =   5'd4    ;
localparam s4   =   5'd8    ;
localparam s5   =   5'd16   ;  

reg [ 4   : 0 ] cur_state   ;
reg             chack_right ;

//-----------------------------------------------------------------------------
//----------Moore状态机
//---三段式
//--序列11010检测
//-----------------------------------------------------------------------------
reg [ 4   : 0 ] next_state ;

//第一段
always @(posedge clk) begin
    if(rst_p)
        cur_state <= 5'd0 ;
    else 
        cur_state <= next_state ;
end

//第二段
always @( *) begin
    case(cur_state)
        s0 : next_state = (sequence_num) ? s1 : s0 ;
        s1 : next_state = (sequence_num) ? s2 : s0 ;
        s2 : next_state = (sequence_num) ? s2 : s3 ;
        s3 : next_state = (sequence_num) ? s4 : s0 ;
        s4 : next_state = (sequence_num) ? s2 : s5 ;
        s5 : next_state = (sequence_num) ? s1 : s0 ;
        default : next_state = s0 ;
    endcase
end

//第三段
always @(*) begin
    case(cur_state)
        s5 :  chack_right = 1'b1 ;
        default : chack_right = 1'b0 ;
    endcase           
end

assign num_en = chack_right ;

        moore状态机输出只与当前状态有关,从代码中表示就是输出chack_right信号只要当cur_state处于s5就输出1,反之就输出0。

2.3.仿真代码

`timescale 1ns/1ps

module sequence_11010_chack_tb;

  // Parameters

  //Ports
  reg  clk=0;
  reg  rst_p=1;
  reg  sequence_num=0;
  reg [4:0] tb_data = 5'b11010;
  wire  num_en;

  sequence_11010_chack  sequence_11010_chack_inst (
    .clk(clk),
    .rst_p(rst_p),
    .sequence_num(sequence_num),
    .num_en(num_en)
  );

always #5  clk = ! clk ;

initial begin
    #201;
    rst_p = 1'b0 ;

    //1
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[3:0],tb_data[4]};
    end

    //2
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[3:0],tb_data[4]};
    end

    //3
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[3:0],tb_data[4]};
    end
    
    //4
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[3:0],tb_data[4]};
    end

    //5
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[3:0],tb_data[4]};
    end

    //6
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[3:0],tb_data[4]};
    end

    //7
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[3:0],tb_data[4]};
    end

    //移位方向改变

    //1
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[0],tb_data[4:1]};
    end

    //2
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[0],tb_data[4:1]};
    end

    //3
    @(posedge clk)begin
        sequence_num <= tb_data[4]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[3]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[2]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[1]  ;
    end
    @(posedge clk)begin
        sequence_num <= tb_data[0]  ;
        tb_data <= {tb_data[0],tb_data[4:1]};
    end

    #100; 
    $stop;
end

endmodule

仿真结果如下:

811e7a1ca5b94302b34ff5fad50a0af7.png

 3.Reference

本文参考了csdn、知乎上相关文章。如果存在什么问题请指正!!!

完成工程和仿真代码如下链接免费下载:【免费】verilog序列检测器,序列11010,(mealy状态机和moore状态机)资源-CSDN文库

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月7日
下一篇 2023年12月7日

相关推荐