0
点赞
收藏
分享

微信扫一扫

状态机——可乐机自动售卖机可找零的实现

非宁静不致远 2022-03-16 阅读 52

可乐定价为2.5元/瓶,投币可投0.5元或者1元硬币,若投入不超过2.5元,则不出可乐,若投入3元则可以出一瓶可乐,还要找回0.5元。与之前相比,这里的输入变量有时钟复位,一元输入pi_money_one,0.5元输入pi_money_half,输出为可乐po_cola和找零po_money;

输入只有两种情况,0.5元,1元;输出有三个:不出可乐/不找零,出可乐/找零,出可乐/找零

状态有五个:0,0.5,1,1.5,2,2.5,3

这里用00表示不投钱,01表示投入0.5元,10表示投入1元,还用00表示不出可乐不找零,10表示出可乐不找零,11表示即出可乐又找零。绘制状态转移图:

定义中间变量pi_money,表示投入的钱数,00表示0元,10表示投入1元,01表示0.5元。

状态变量的初始状态为IDLE,当投入1元时,状态跳转到ONE状态,不出可乐不找零即po_cola,po_money均为低电平0,再投入1元,状态跳转到TWO状态,不出可乐不找零po_cola,po_money均为低电平0,再投入1元,状态跳转到THREE状态,出可乐找零po_cola,po_money均为高电平1.....

绘制输入输出信号的波形如下图所示:

编写代码:

module  complex_fsm
(
    input   wire    sys_clk         ,   
    input   wire    sys_rst_n       ,   
    input   wire    pi_money_one    ,   //投币1元
    input   wire    pi_money_half   ,   //投币0.5元
                    
    output  reg     po_money        ,   //po_money为1时表示找零
                                        //po_money为0时表示不找零
    output  reg     po_cola             //po_cola为1时出可乐
                                        //po_cola为0时不出可乐
);

parameter   IDLE     = 5'b00001;
parameter   HALF     = 5'b00010;
parameter   ONE      = 5'b00100;
parameter   ONE_HALF = 5'b01000;
parameter   TWO      = 5'b10000;

reg     [4:0]   state; //五个状态

wire    [1:0]   pi_money;

//pi_money:为了减少变量的个数,我们用位拼接把输入的两个1bit信号拼接成1个2bit信号
//00表示投入0元,01表示投入了0.5元,10表示投入了1元
assign pi_money = {pi_money_one, pi_money_half};

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        state <= IDLE;
    else	case(state)
                IDLE    : if(pi_money == 2'b01)   
                              state <= HALF;
                          else    if(pi_money == 2'b10)
                              state <= ONE;
                          else
                              state <= IDLE;
    
                HALF    : if(pi_money == 2'b01)
                              state <= ONE;
                          else    if(pi_money == 2'b10)
                              state <= ONE_HALF;
                          else
                              state <= HALF;
    
                ONE     : if(pi_money == 2'b01)
                              state <= ONE_HALF;
                          else    if(pi_money == 2'b10)
                              state <= TWO;
                          else
                              state <= ONE;
    
                ONE_HALF: if(pi_money == 2'b01)
                              state <= TWO;
                          else    if(pi_money == 2'b10)
                              state <= IDLE;
                          else
                              state <= ONE_HALF;
    
                TWO     : if((pi_money == 2'b01) || (pi_money == 2'b10))
                              state <= IDLE;
                          else
                              state <= TWO;
        
                default :       state <= IDLE;
            endcase

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        po_cola <= 1'b0;
    else    if((state == TWO && pi_money == 2'b01) || (state == TWO && 
          pi_money == 2'b10) || (state == ONE_HALF && pi_money == 2'b10))
        po_cola <= 1'b1;
    else
        po_cola <= 1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n ==	1'b0)
        po_money <= 1'b0;
    else if((state == TWO) && (pi_money == 2'b10))
        po_money <= 1'b1;
    else
        po_money <= 1'b0;

endmodule

编译完成后通过综合器综合出来的状态图如图所示:

 编写仿真代码查看波形:

 任取一个位置分析,如图,当状态为10000即此时已经有两元了,pi_money等于10即投入了1元,此时应该输出一瓶可乐,找零0.5元,所以po_cola,po_money均信号拉高一个时钟周期,波形仿真正确。

举报

相关推荐

0 条评论