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

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

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

实现自动售卖机功能,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

相关推荐
深圳市恒锐丰科技杨生2 小时前
# CSM9118|芯晞微电 7.5V/1.5A 单通道 H 桥电机 / 线圈驱动
嵌入式硬件·硬件工程
wp123_12 天前
圆盘拨动电位器机电转换原理,国内外产品性能与成本比拼
人工智能·科技·硬件工程
逍遥5966070102 天前
网络设备交换机路由器 AI 配置助手
node.js·硬件工程
ye150127774552 天前
220V降压24V700mA交转直芯片WT5110
stm32·单片机·嵌入式硬件·其他·硬件工程
恒锐丰科技林技术员2 天前
EG2181 半桥驱动芯片原理与应用解析
经验分享·嵌入式硬件·硬件工程
恒锐丰科技林技术员2 天前
EG2113D 高压半桥驱动芯片:高压功率变换的实用驱动方案
经验分享·嵌入式硬件·硬件工程
ACP广源盛139246256732 天前
Type-C 扩展坞方案选型笔记|国产 DP1.2 转 HDMI2.0 桥接芯片 GSV2201D@ACP 评估
开发语言·笔记·硬件架构·硬件工程·hdmi·国产芯片
ACP广源盛139246256733 天前
Type‑C 扩展坞方案选型笔记|国产 DP1.4 转 HDMI2.0 桥接芯片 GSV2201S @ACP评估
c语言·开发语言·笔记·硬件架构·硬件工程·国产芯片
独孤九剑打醒他3 天前
【原创开源·修订版】源-栅-漏-栅-源横向双栅MOS:从“被误解的短路”到“电流路径多值逻辑与顶层供电架构”
前端·嵌入式硬件·架构·开源·硬件工程
comyccccc3 天前
自制多路输出DCDC电源板,3.3V-12V可调 学习笔记
单片机·嵌入式硬件·硬件工程