状态机实现流水灯 FPGA实验

一:什么是状态机?

状态机的基本要素有 3 个,其实我们在第一节的举例中都有涉及,只是没有点明,它们是:状态、输出和输入。
1、状态:也叫状态变量。在逻辑设计中,使用状态划分逻辑顺序和时序规律。比如:设计伪随机码发生器时,可以用移位寄存器序列作为状态;在设计电机控制电路时,可以以电机的不同转速作为状态;在设计通信系统时,可以用信令的状态作为状态变量等。
2、输出:输出指在某一个状态时特定发生的事件。如设计电机控制电路中,如果电机转速过高,则输出为转速过高报警,也可以伴随减速指令或降温措施等。
3、输入:指状态机中进入每个状态的条件,有的状态机没有输入条件,其中的状态转移较为简单,有的状态机有输入条件,当某个输入条件存在时才能转移到相应的状态。
根据状态机的输出是否与输入条件相关,可将状态机分为两大类:摩尔(Moore)型状态机和米勒(Mealy)型状态机。

1.1 状态机的分类:
1、摩尔状态机:摩尔状态机的输出仅仅依赖于当前状态,而与输入条件无关。每个输出仅仅与状态相关,所以它是一个摩尔型状态
机。
2、米勒型状态机:米勒型状态机的输出不仅依赖于当前状态,而且取决于该状态的输入条件。

(老师在上课的时候讲了一个很有趣的例子,一个程序员周一到周五是工作日需要工作,周六周日则休息打游戏,程序员每日的工作状态只是与日期有关,这就是摩尔状态机,如果程序员谈恋爱了,那么他每日的状态还要考虑到对象的问题才能决定自己的状态任务,那这就是米勒型状态机
1.2 状态机的工作原理图

状态机实现流水灯 FPGA实验_第1张图片

 作业:

跑马灯流水灯verilog实现:

一段式状态机:
      S1  :begin
          if(time1_en)begin
                    led_out<=4'b1001;
              state<=S2;
                end
                else begin
                    led_out<=4'b0110;
              state<=S1;
                end    
      end
      S2  :begin
          if(time2_en)begin
                    led_out<=4'b1111;
              state<=S3;
                end
                else begin
                    led_out<=4'b1001;
              state<=S2;
                end    
      end
      S3  :begin
          if(time2_en)begin
                    led_out<=4'b0111;
              state<=S4;
                end
                else begin
                    led_out<=4'b1111;
              state<=S3;
                end    
      end
      S4  :begin
          if(time1_en)begin
                    led_out<=4'b1011;
              state<=S5;
                end
                else begin
                    led_out<=4'b0111;
              state<=S4;
                end    
      end
      S5  :begin
          if(time1_en)begin
                    led_out<=4'b1101;
              state<=S6;
                end
                else begin
                    led_out<=4'b1011;
              state<=S5;
                end    
      end
      S6  :begin
          if(time1_en)begin
                    led_out<=4'b1110;
              state<=S7;
                end
                else begin
                    led_out<=4'b1101;
              state<=S6;
                end    
      end
      S7  :begin
          if(time1_en)begin
                    led_out<=4'b1101;
              state<=S8;
                end
                else begin
                    led_out<=4'b1110;
              state<=S7;
                end    
      end
      S8  :begin
          if(time1_en)begin
                    led_out<=4'b1011;
              state<=S9;
                end
                else begin
                    led_out<=4'b1101;
              state<=S8;
                end    
      end
      S9  :begin
          if(time1_en)begin
                    led_out<=4'b0111;
              state<=S10;
                end
                else begin
                    led_out<=4'b1011;
              state<=S9;
                end    
      end
      S10 :begin
          if(time2_en)begin
                    led_out<=4'b000;
              state<=S10;
                end
                else begin
                    led_out<=4'b0111;
              state<=IDLE;
                end    
            end
            default:begin
                led_out<=4'b0000;
                state<=IDLE;
            end
        endcase
    end
end

仿真波形:

二段式状态机仿真:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: guoliang CLL
// 
// Create Date: 2020/02/21 15:30:49
// Design Name: 
// Module Name: seq_gen_fsm2
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
 
 
module seq_gen_fsm2(
    input clk,
    input rst_n,
    output reg seq
    );
 // state declaration
 parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
 reg [1:0]c_state,n_state;
 // 状态转移
 always@(posedge clk or negedge rst_n)
 begin
    if(!rst_n)
        begin
            c_state <= s0;
        end
    else
        begin
            c_state <= n_state;
        end
 end
// 状态转移条件+输出
 always@(c_state or rst_n)
 begin
    if(!rst_n)
        begin
            n_state = s0;
        end
    else
        begin
            case(c_state)
            s0:begin
            n_state = s1;
            seq = 1'b1;
            end
            s1:begin
            n_state = s2;
            seq = 1'b0;
            end
            s2:begin
            n_state = s3;
            seq = 1'b1;
            end
            s3:begin
            n_state = s0;
            seq = 1'b1;
            end
            default:begin
            n_state = s0;
            seq = 1'b1;
            end
            endcase
        end
 end
 
endmodule 

三段式状态机仿真:

reg[4:0] current_state;
reg[4:0] next_state;
 
//第一段
always@(posedge clk_25m)begin
    current_state<=next_state;
end
 
//第二段
always @(*)begin
    if(reset)begin
        next_state=IDLE;
    end
    else begin
        case(current_state)
            IDLE:begin
                if(time2_en)begin
              next_state=S1;
                end
                else begin
              next_state=IDLE;
                end    
            end
      S1  :begin
          if(time1_en)begin
              next_state=S2;
                end
                else begin
              next_state=S1;
                end    
      end
      S2  :begin
          if(time2_en)begin
              next_state=S3;
                end
                else begin
              next_state=S2;
                end    
      end
      S3  :begin
          if(time2_en)begin
              next_state=S4;
                end
                else begin
              next_state=S3;
                end    
      end
      S4  :begin
          if(time1_en)begin
              next_state=S5;
                end
                else begin
              next_state=S4;
                end    
      end
      S5  :begin
          if(time1_en)begin
              next_state=S6;
                end
                else begin
              next_state=S5;
                end    
      end
      S6  :begin
          if(time1_en)begin
              next_state=S7;
                end
                else begin
              next_state=S6;
                end    
      end
      S7  :begin
          if(time1_en)begin
              next_state=S8;
                end
                else begin
              next_state=S7;
                end    
      end
      S8  :begin
          if(time1_en)begin
              next_state=S9;
                end
                else begin
              next_state=S8;
                end    
      end
      S9  :begin
          if(time1_en)begin
              next_state=S10;
                end
                else begin
              next_state=S9;
                end    
      end
      S10 :begin
          if(time2_en)begin
              next_state=S10;
                end
                else begin
              next_state=IDLE;
                end    
            end
            default:begin
                next_state=IDLE;
            end
        endcase
 end
end
 
//第三段
always@(posedge clk_25m)begin
    if(reset)begin
        led_out<=4'b0000;
    end
    else begin
        case(current_state)
            IDLE:begin
                if(time2_en)begin
                    led_out<=4'b0110;
                end
                else begin
                    led_out<=4'b0000;
                end    
            end
      S1  :begin
          if(time1_en)begin
                    led_out<=4'b1001;
                end
                else begin
                    led_out<=4'b0110;
                end    
      end
      S2  :begin
          if(time2_en)begin
                    led_out<=4'b1111;
                end
                else begin
                    led_out<=4'b1001;
                end    
      end
      S3  :begin
          if(time2_en)begin
                    led_out<=4'b0111;
                end
                else begin
                    led_out<=4'b1111;
                end    
      end
      S4  :begin
          if(time1_en)begin
                    led_out<=4'b1011;
                end
                else begin
                    led_out<=4'b0111;
                end    
      end
      S5  :begin
          if(time1_en)begin
                    led_out<=4'b1101;
                end
                else begin
                    led_out<=4'b1011;
                end    
      end
      S6  :begin
          if(time1_en)begin
                    led_out<=4'b1110;
                end
                else begin
                    led_out<=4'b1101;
                end    
      end
      S7  :begin
          if(time1_en)begin
                    led_out<=4'b1101;
                end
                else begin
                    led_out<=4'b1110;
                end    
      end
      S8  :begin
          if(time1_en)begin
                    led_out<=4'b1011;
                end
                else begin
                    led_out<=4'b1101;
                end    
      end
      S9  :begin
          if(time1_en)begin
                    led_out<=4'b0111;
                end
                else begin
                    led_out<=4'b1011;
                end    
      end
      S10 :begin
          if(time2_en)begin
                    led_out<=4'b000;
                end
                else begin
                    led_out<=4'b0111;
                end    
            end
            default:begin
                led_out<=4'b0000;
            end
        endcase
    end
end 

状态机实现流水灯 FPGA实验_第2张图片

 对比一下整体的效果图

 总结:

对比比较一下三段的区别:

1)一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;

(2)二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;

(3)三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。

你可能感兴趣的:(fpga开发)