Bootstrap

22.状态机设计--可乐机设计(投币三元出一瓶可乐)

理论知识:

(1)状态机简写为FSM(Finite State Machine),也称为同步有限状态机。同步是指状态的变化都是在时钟的边沿发送变化,有限值得是状态的个数是可数的。

(2)分类:Moore型状态机(摩尔型)、Mealy型状态机(米利型)

(3)在FPGA低速系统中,如果状态机的状态个数小于四个,可以用二进制码;如果个数大于4个小于24个,推荐使用独热码,如果个数大于24个,推荐使用格雷码。在FPGA高速系统中,一律推荐独热码。

(4)

设计一个基于状态机的可乐机,要求投币三元出一瓶可乐:

(1)Visio视图:

(2)Verilog代码:

module fsm_cola(clk,reset_n,pi_money,po_cola);

    input clk;
    input reset_n;
    input pi_money;
    
    output reg po_cola;
    
    reg[2:0] state;
    
    parameter IDLE  = 3'b001;
    parameter ONE   = 3'b010;
    parameter TWO   = 3'b100;
    
//状态跳转设计:
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            state <= IDLE;
        else begin
            case(state)
                IDLE:   begin
                        if(pi_money)
                            state <= ONE;
                        else 
                            state <= state;
                end
                
                ONE:    begin
                        if(pi_money)
                            state <= TWO;
                        else 
                            state <= state;
                end
                TWO:    begin
                        if(pi_money)
                            state <= IDLE;
                        else    
                            state <= state;
                end
                
                default:begin
                        state <= IDLE;
                end
            endcase
        end

//输出信号设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            po_cola <= 1'd0;
        else if((state == TWO) && (pi_money))
            po_cola <= 1'd1;
        else 
            po_cola <= 1'd0;

endmodule

(3)仿真文件代码:

`timescale 1ns / 1ps

module fsm_cola_tb;
    
    reg clk;
    reg reset_n;
    reg pi_money;
    
    wire po_cola;
    
    fsm_cola fsm_cola_inst(
        .clk(clk),
        .reset_n(reset_n),
        .pi_money(pi_money),
        .po_cola(po_cola)
    );
    
    initial clk = 1'd1;
    always #10 clk = ~clk;
    
    initial begin
        reset_n <= 1'd0;
        pi_money <= 1'd0;
        #15;
        reset_n <= 1'd1;
        #1500;
        $stop;
    end

    always #200 pi_money <= ~ pi_money;

endmodule

(4)仿真波形:

;