自动售卖机状态机设计精解

设计状态机时有一个很好用的问题:

"当前输入消失以后,我还需要记住什么信息?"

实现自动售卖机功能,A饮料5元钱,B饮料10元钱,售卖机可接收投币5元钱和10元钱,每次投币只可买一种饮料,考虑找零的情况。

电路的接口如下图所示。sel信号会先于din信号有效,且在购买一种饮料时值不变。

  • sel为选择信号,用来选择购买饮料的种类,sel=0,表示购买A饮料,sel=1,表示购买B饮料;

  • din表示投币输入,din=0表示未投币,din=1表示投币5元,din=2表示投币10元,不会出现din=3的情况;

  • drinks_out表示饮料输出,drinks_out=0表示没有饮料输出,drinks_out=1表示输出A饮料,drinks_out=2表示输出B饮料,不出现drinks_out =3的情况,输出有效仅保持一个时钟周期;

  • change_out表示找零输出,change_out=0表示没有找零,change_out=1表示找零5元,输出有效仅保持一个时钟周期。

    `timescale 1ns/1ns

    module sale(
    input clk,
    input rst_n,
    input sel,
    input [1:0] din,

    复制代码
      output reg  [1:0]   drinks_out,
      output reg          change_out

    );

    reg state;

    localparam S_ZERO = 1'b0; // 当前余额0元
    localparam S_FIVE = 1'b1; // 当前余额5元

    always @(posedge clk or negedge rst_n) begin

    复制代码
      if (!rst_n) begin
    
          state      <= S_ZERO;
          drinks_out <= 2'd0;
          change_out <= 1'b0;
    
      end
    
      else begin
    
          // 输出只保持一个时钟周期
          drinks_out <= 2'd0;
          change_out <= 1'b0;
    
          case(state)
    
              //============================
              // 当前没有余额
              //============================
              S_ZERO: begin
    
                  // 购买A饮料:5元
                  if (sel == 1'b0) begin
    
                      // 投5元
                      if (din == 2'd1) begin
    
                          drinks_out <= 2'd1;
    
                      end
    
                      // 投10元
                      else if (din == 2'd2) begin
    
                          drinks_out <= 2'd1;
                          change_out <= 1'b1;
    
                      end
    
                  end
    
    
                  // 购买B饮料:10元
                  else begin
    
                      // 投5元
                      if (din == 2'd1) begin
    
                          // 钱不够,记住已经有5元
                          state <= S_FIVE;
    
                      end
    
                      // 投10元
                      else if (din == 2'd2) begin
    
                          drinks_out <= 2'd2;
    
                      end
    
                  end
    
              end
    
    
              //============================
              // 已经投入5元
              // 这里实际上只可能是在购买B饮料
              //============================
              S_FIVE: begin
    
                  // 再投入5元
                  if (din == 2'd1) begin
    
                      // 5 + 5 = 10
                      drinks_out <= 2'd2;
    
                      state <= S_ZERO;
    
                  end
    
    
                  // 再投入10元
                  else if (din == 2'd2) begin
    
                      // 5 + 10 = 15
                      // 买B饮料10元,找5元
                      drinks_out <= 2'd2;
                      change_out <= 1'b1;
    
                      state <= S_ZERO;
    
                  end
    
              end
    
    
              default: begin
                  state <= S_ZERO;
              end
    
          endcase
    
      end

    end

    endmodule

相关推荐
爱吃汽的小橘4 小时前
循环序列生成与并串转换模块设计
硬件工程
wp123_16 小时前
磁式编码器技术特性与场景优势分析,医疗机器人领域应用展望
科技·硬件工程
恒锐丰科技林技术员7 小时前
EG1164 高压大电流升压同步整流芯片解析
经验分享·嵌入式硬件·硬件工程
恒锐丰科技林技术员1 天前
EG2184 半桥栅极驱动芯片详解:高压半桥电路的性价比之选
经验分享·嵌入式硬件·硬件工程
ysu_03142 天前
TinyML 模型部署:从 Edge Impulse 到 STM32F103
驱动开发·stm32·嵌入式硬件·mcu·硬件架构·硬件工程·dsp开发
恒锐丰科技林技术员2 天前
EG1196S:高压宽输入降压 DC‑DC 芯片,电动车工业电源的优选方案
经验分享·嵌入式硬件·硬件工程
深圳市恒锐丰科技杨生2 天前
EG2121 250V 单路半桥栅极驱动芯片|屹晶 EGmicro
嵌入式硬件·硬件工程
深圳市恒锐丰科技杨生2 天前
EG1165 / EG1165S 600V 半桥 PWM 控制芯片|屹晶 EGmicro
嵌入式硬件·硬件工程
不会声调的博er2 天前
AD16 在 PCB 中修改网络级焊盘颜色
硬件架构·硬件工程·pcb工艺