其他分享
首页 > 其他分享> > 状态机、序列检测器

状态机、序列检测器

作者:互联网

(1)了解状态机:什么是摩尔型状态机,什么是米利型状态机,两者的区别是什么?一段式、二段式、三段式状态机的区别?

状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。有限状态机简写为FSM(Finite State Machine),主要分为2大类:

    Mealy:输出信号不仅取决于当前状态,还取决于输入;

    Moore:输出信号只取决于当前状态;

 实现相同的功能时,Mealy型比Moore型能节省一个状态(大部分情况下能够节省一个触发器资源,其余情况下使用的资源相同,视状态数和状态编码方式决定),Mealy型比Moore型输出超前一个时钟周期

一段式一个always,既描述状态转移,又描述状态的输入输出,当前状态用寄存器输出。一段式写法简单,但是不利于维护,状态扩展麻烦,状态复杂时易出错,不推荐;

二段式两个always,时序逻辑与组合逻辑分开,一个always块采用同步时序描述状态转移;另一个always块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出,当前状态用组合逻辑输出,可能出现竞争冒险,产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计;

三段式三个always,一个always模块采用同步时序描述状态转移;一个always采用组合逻辑判断状态转移条件,描述状态转移规律;第三个always块使用同步时序描述状态输出,寄存器输出。

       三段式与二段式相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。

(2)使用状态机产生序列“11010110”,串行循环输出该序列;

(3)使用状态机检测“1101”,串行输入的测试序列为“11101101011010”,输出信号为valid有效信号,检测到时输出高,否则为低,考虑序列叠加情况,比如“1101101”,则有两个“1101”,

 

 

根据待检测的序列“1101”确定状态,其中:

S1为检测到第1个有效位“1”;

S2为检测到2个有效位“11”;

S3为检测到3个有效位“110”;

S4位检测到4个有效位“1101”;

IDLE为其他状态;

 

IDLE:初始状态,除S1~S4外的其他所有状态

S1:1,            来1则到S2(11),否则回到IDLE;

S2:11,          来0则到S3(110),否则保持S2(11);

S3:110,        来1则到S4(1101),否则回到IDLE;

S4:1101,      来1则到S2(11),否则回到IDLE;

 

 

module FSM_SequDetection_1(
       clk,
       rst_n,
       data_in,
       data_valid
); 
input clk;
input rst_n;
input data_in;
output reg data_valid;
//定义状态,这里采用的独热码(One-Hot),FPGA中推荐用独热码和格雷码(Gray)
//状态较少时(4-24个状态)用独热码效果好,状态多时格雷码(状态数大于24)效果好
parameter IDLE = 5'b00001;
parameter S1       = 5'b00010;
parameter S2       = 5'b00100;
parameter S3       = 5'b01000;
parameter S4       = 5'b10000;
 
reg [4:0] current_state;             //现态
reg [4:0] next_state;                 //次态
 
//三段式FSM,第一段,同步时序逻辑,描述状态切换,这里的写法固定
always @ ( posedge clk )
begin
       if(!rst_n ) begin
              current_state<= IDLE;
       end
       elsebegin
              current_state<= next_state;
       end
end 
//三段式FSM,第二段,组合逻辑,判断状态转移条件,描述状态转移规律
//这里面用"="赋值和用"<="没区别
always @ (*)
begin
       if(!rst_n ) begin
              next_state<= IDLE;
       end
       elsebegin
              case(current_state )
                     IDLE:    begin
                            if(data_in == 1 )
                                   next_state<= S1;
                            else
                                   next_state<= IDLE;
                     end
                     S1   :      begin
                            if(data_in == 1 )
                                   next_state<= S2;
                            else
                                   next_state<= IDLE;
                     end
                     S2   :      begin
                            if(data_in == 0 )
                                   next_state<= S3;
                            else
                                   next_state<= S2;
                     end
                     S3   :      begin
                            if(data_in == 1 )
                                   next_state<= S4;
                            else
                                   next_state<= IDLE;
                     end
                     S4   :      begin
                            if(data_in == 1 )
                                   next_state<= S2;
                            else
                                   next_state<= IDLE;
                     end
                     default   : begin
                            next_state<= IDLE;
                     end
              endcase
       end
end 
//三段式FSM,第三段,同步时序逻辑,描述状态输出,摩尔型输出
always @ ( posedge clk )
begin
       if(!rst_n ) begin
              data_valid<= 1'b0;
       end
       elsebegin
              case(next_state )
                     S4   : data_valid <= 1'b1;
                     default   : data_valid <= 1'b0;
              endcase
       end
end
 
endmodule

2.检测序列10110,用计数计其出现的次数。

module seq_dec(
  input  clk,
  input  rst_n,
  input  din,
  output dout
);
  reg [7:0] cnt; //计满足10110序列的次数

  reg [5:0] P_state;//当前状态
  reg [5:0] N_state;//下一个状态

parameter  S0=6'b000001;//start
parameter  s1=6'b000010;//1
parameter  s2=6'b000100;//10
parameter  s3=6'b001000;//101
parameter  s4=6'b010000;//1011
parameter  s5=6'b100000;//10110

always @(posedge clk or negedge rst_n)
  if(!rst_n)
    P_state <= 6'b0;
  else
    P_state <= N_state;

always @(*)begin
  if(!rst)
    N_state = s0;
  else begin 
    case(P_state)
      s0:if(din==1)  
           N_state = s1;
      s1:if(din==0)
           N_state = s2;
      s2:if(din==1)
           N_state = s3;
         else
           N_state = s0;
      s3:if(din==1)
           N_state = s4;
         else
           N_state = s0;
      s4:if(din==0)
           N_state = s5;
         else 
           N_state = s1;
      s5:if(din==1)
           N_state = s3;
         else
           N_state = s0;
      default:
           N_state = s0;
    endcase
  end
end
assign dout = (P_state==s5);
always @(posedge clk or negedge rst_n)
  if(!rst_n)
    cnt <= 8'b0;
  else if(dout == 1)
    cnt <= cnt + 1'b1;
endmodule

3.序列检测,每检测到一组“11011”,然后输出一个高电平。

 

module FSM_test(
    input       clk,
    input       rst_n,
    input       d_in,
    output      d_out
    );
    
/*     parameter   S0  = 5'b000000,
                S1  = 5'b000001,
                S2  = 5'b000011,
                S3  = 5'b000010,
                S4  = 5'b000110,
                S5  = 5'b000111; */
                
    parameter   S0  = 5'b00000,
                S1  = 5'b00001,
                S2  = 5'b00010,
                S3  = 5'b00100,
                S4  = 5'b01000,
                S5  = 5'b10000;  
/* parameter   S0  = 5'd0,
            S1  = 5'd1,
            S2  = 5'd2,
            S3  = 5'd3,
            S4  = 5'd4,
            S5  = 5'd5; */
                 
    reg         r_d_out;
    reg [4:0]   cs,ns;
    
    always@(posedge clk or negedge rst_n) begin
        if(rst_n == 1'b0)   begin
            cs <= S0;
        end else begin
            cs <= ns;
        end
    end
    
    always@(*) begin
        ns = 5'dx;
        case(cs) 
            S0: begin
                if(d_in == 1'b1) 
                    ns = S1;
                else
                    ns = S0;
            end
            S1: begin
                if(d_in == 1'b1) 
                    ns = S2;
                else
                    ns = S0;
            end
            S2: begin
                if(d_in == 1'b1) 
                    ns = S2;
                else
                    ns = S3;
            end
            S3: begin
                if(d_in == 1'b1) 
                    ns = S4;
                else
                    ns = S0;
            end
            S4: begin
                if(d_in == 1'b1) 
                    ns = S5;
                else
                    ns = S0;
            end
            S5: begin
                if(d_in == 1'b1) 
                    ns = S2;
                else
                    ns = S3;
            end
            default:
                ns = S0;
        
        endcase
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(rst_n == 1'b0)   begin
            r_d_out <= 1'b0;
        end else if(cs == S5)begin
            r_d_out <= 1'b1;
        end else begin
            r_d_out <= 1'b0;
        end
    end
    
    assign  d_out = r_d_out;
endmodule

 

标签:状态,always,检测器,状态机,S2,序列,input,parameter
来源: https://www.cnblogs.com/qqstore/p/15241197.html