有限状态机FSM(自动售卖机、序列检测器)


   有限状态机FSM的分类:
   1)、 Moore型状态机:状态机的输出只与当前的状态有关系。
在这里插入图片描述
   2)、 Mealy型状态机:状态机的输出不仅与当前的状态有关,还与当前的输入有关。
在这里插入图片描述
有限状态机的写法根据always块的数量分一段式、两段式和三段式(本文第三段采用的是assign输出,always输出亦可),其中三段式状态机(包含 次态逻辑、状态寄存器、输出逻辑三部分)可以清晰完整的显示出状态机的结构, 代码清晰,便于编写,易于维护。下面以三段式为例编写代码。

一、自动售卖机实现

设计一个自动售卖饮料机,设饮料售价为2.5元,可使用5角和一元硬币,有找零功能。

  • 代码编写前,先画出状态转化图,注明各个参数含义
    在这里插入图片描述
module drink_status_moore(clk,reset,half.one,out,cout);
  input clk;
  input reset;
  input half;
  input one;
  output out;
  output cout;
   
  parameter [2:0] s0 = 3'b000,       //3'd0,参数声明
                  s1 = 3'b001,       //3'd1
                  s2 = 3'b010,       //3'd2
                  s3 = 3'b011,       //3'd3
                  s4 = 3'b100,       //3'd4
                  s5 = 3'b101,       //3'd5
                  s6 = 3'b110;       //3'd6

  reg [2:0] curr_state;        //内部信号声明
  reg [2:0] next_state;

//first segement: state transfer---描述状态寄存器、时序逻辑
always @(posedge clk, negedge reset) begin
  if(!reset)
    curr_state <= s0;
  else
    curr_state <= next_state;
end

//second segment: transfer condition--描述次态逻辑、组合逻辑
always @(curr_state,one,half)begin     //等价 always@(*)
  case(curr_state)
    s0:begin
       if(half)     next_state = s1;
       else if(one) next_state = s2;
       else         next_state = s0;
       end
    s1:begin
       if(half)     next_state = s2;
       else if(one) next_state = s3;
       else         next_state = s1;
       end
    s2:begin
       if(half)     next_state = s3;
       else if(one) next_state = s4;
       else         next_state = s2;
       end
    s3:begin
       if(half)     next_state = s4;
       else if(one) next_state = s5;
       else         next_state = s3;
       end
    s4:begin
       if(half)     next_state = s5;
       else if(one) next_state = s6;
       else         next_state = s4;
       end
    s5:begin
                    next_state = s0;
       end
    s6:begin
                    next_state = s0;
       end
    default:        next_state = s0;
 endcase
end

//third segement: state output---状态输出(描述输出逻辑)
assign out = ((curr_state == s5) || (curr_state == s6))?1:0;
assign cout = (curr_state == s6)?1:0;               //assign可简化输出

endmodule

上述Moore FSM的Testbench:

`timescale  1ns/1ns
module drink_status_moore_tb();
  reg          half;
  reg          one;
  reg          clk;
  reg          reset;
  wire         out
  wire         cout;
  
initial 
    begin
       clk = 0;
       reset = 0;                      //初始化时钟与复位信号
       #20   reset = 1;                //拉起reset
    end

always #20  clk = ~clk            //时钟周期为40ns

initial
    begin
      half = 0;
      one = 0;
      #20;
      repeat(5)begin
        @(posedge clk)  half = 1;
        @(posedge clk)  half = 0;
      end
 
      #100;
      repeat(3)begin
        @(posedge clk)  one = 1;
        @(posedge clk)  one = 0;
      end 
 
      #200;
      $finish;
end
drink_status_moore drink_status_moore_u1(
                                 .clk  (clk),
                                 .reset (reset),
                                 .one  (one),
                                 .half  (half),
                                 .out  (out),
                                 .cout(cout));  
endmodule

在这里插入图片描述

在这里插入图片描述

module drink_status_mealy(
  input clk,               //verilog-2001
  input reset,
  input half,
  input one,
  output out,
  output cout);
   
  parameter [2:0] s0 = 3'b000,       //3'd0
                  s1 = 3'b001,       //3'd1
                  s2 = 3'b010,       //3'd2
                  s3 = 3'b011,       //3'd3
                  s4 = 3'b100,       //3'd4
  reg [2:0] curr_state;
  reg [2:0] next_state;

//first segement: state transfer---时序逻辑、描述状态寄存器
always @(posedge clk, negedge reset) begin
  if(!reset)
    curr_state <= s0;
  else
    curr_state <= next_state;
end

//second segment: transfer condition---组合逻辑、描述次态逻辑
always @(*)begin     //等价 always @(curr_state,one,half)
  case(curr_state)
    s0:begin
       if(half)     next_state = s1;
       else if(one) next_state = s2;
       else         next_state = s0;
       end
    s1:begin
       if(half)     next_state = s2;
       else if(one) next_state = s3;
       else         next_state = s1;
       end
    s2:begin
       if(half)     next_state = s3;
       else if(one) next_state = s4;
       else         next_state = s2;
       end
    s3:begin
       if(half)     next_state = s4;
       else if(one) next_state = s0;
       else         next_state = s3;
       end
    s4:begin
       if(half)     next_state = s0;
       else if(one) next_state = s0;
       else         next_state = s4;
       end       
    default:        next_state = s0;
 endcase
end

//third segement: state output---状态输出(描述输出逻辑)
assign out = ((curr_state == s4) & (half|one))?1:((curr_state == s3) & (one))?1:0;    //等价于if--else if--else,即条件操作符的嵌套使用
assign cout = ((curr_state == s4) & (one))?1:0;

endmodule

注意区别Moore型状态机与Mealy型状态机,一般Moore型状态机的状态数量较Mealy型要多。

二、序列检测器

设计一个序列检测器,检查的序列为“1110010”,当输入的信号依次为“1110010”时,输出信号Y输出一个高电平,否则输出信号Y为低电平。

  • 状态转换图如下:在这里插入图片描述
module seq_checker_moore(
      input  in, clk, reset;
      output  out;
      output  [2:0] state;     //000-111
       
      parameter  s0 = 'd0,
          	  	  s1 = 'd1,
     			  s2 = 'd2,
     			  s3 = 'd3,
      			  s4 = 'd4,
      			  s5 = 'd5,
      			  s6 = 'd6,
      			  s7 = 'd7,
      			  s8 = 'd8;
      			  
  reg [2:0] curr_state;
  reg [2:0] next_state;

//first segement: state transfer---时序逻辑、描述状态寄存器
always @(posedge clk, negedge reset) begin
  if(!reset)
    curr_state <= s0;
  else
    curr_state <= next_state;
end

//second segment: transfer condition---组合逻辑、描述次态逻辑
always @(*)begin     //等价 always @(curr_state,in)
  case(curr_state)     
    s0:begin
       if(in==0)  next_state = s0;
       else       next_state = s1;
       end
    s1:begin
       if(in==0)  next_state = s0;
       else       next_state = s2;
       end
    s2:begin
       if(in==0)  next_state = s0;
       else       next_state = s3;
       end       
    s3:begin
       if(in==0)  next_state = s4;
       else       next_state = s3;
       end
    s4:begin
       if(in==0)  next_state = s5;
       else       next_state = s1;
       end
    s5:begin
       if(in==0)  next_state = s0;
       else       next_state = s6;
       end
    s6:begin
       if(in==0)  next_state = s7;
       else       next_state = s2;
       end
    s7:begin
       if(in==0)  next_state = s0;
       else       next_state = s1;
       end
    default:        next_state = s0;
 endcase
end

//third segement: state output---状态输出(描述输出逻辑)
assign out = (curr_state == s7)?1:0;

endmodule

mealy型序列检测器的状态机不再赘述。
以下为上述Moore FSM的Tsetbench:

`timescale  1ns/1ns
module seq_checker_moore_tb();
  reg          in;
  reg          clk;
  reg          reset;
  reg  [7:0]   data[0:7];
  wire         out
  wire [3:0]   state;
  reg          i;
  
initial 
    begin
       clk = 0;
       reset = 0;                      //初始化时钟与复位信号
       #20   reset = 1;                //拉起reset
    end

always #20  clk = ~clk            //时钟周期为40ns

initial
    begin
      in = 0;
      #30   in = 1;
      #40   in = 1;
      #40   in = 0;
      #40   in = 0;    
      #40   in = 1;
      #40   in = 0;    
      #40   in = 1;  
      #40   in = 0;    
      #40   in = 1;  
      #40   in = 1;  
      #40;
      $finish;
    end

initial begin                  //该模块与仿真无关
  $readmemh("data.txt",data);
  for(i=0;i<8;i=i+1)begin
     #40;
     $display("data=%d",data[i]);
  end
  #200;
  $finish;
end

seq_checker_moore seq_ckecker_moore_u1(
                                 .clk  (clk),
                                 .reset (reset),
                                 .in  (in),
                                 .out  (out),
                                 .state(state));  
endmodule

在这里插入图片描述

发布了21 篇原创文章 · 获赞 10 · 访问量 1828

猜你喜欢

转载自blog.csdn.net/weixin_46022434/article/details/105166407