基于FPGA的自动售货机设计---第一版

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的自动售货机设计---第一版。

功能说明:

 

1. 自动售货机的显示信息为数码管。

2. 前三个数码管显示商品的名字和价格(A 2.0 B2.5 C 3.0)

3. 在未确定状态,可以通过选择商品按键进行商品选择。

4. 选择好商品后,可以按下确认选择按键,此时前三个数码馆开始闪烁。此时选择商品键将无法使用。

5. 当选择完商品后,可以通过按键模拟投入0.5元和1元,钱数显示在最后两个数码管上。

6. 当输入钱数等于商品价格时,钱数显示归0,控制led(leda、ledb、ledc),点亮1秒钟,表示有商品输出,商品从新进入可以选择的状态。

7. 当输入钱数大于商品价格时,钱数显示归0,控制led(leda、ledb、ledc),点亮1秒钟,表示有商品输出,商品从新进入可以选择的状态;控制led2,点亮一秒钟,表示有找零输出。

8. 在输入钱的时候,商品无法切换,且前三个数码管一直闪烁。9. 在选择商品时,无法输入金钱。

 

使用平台:本次设计应用Altera的平台设计(芯片:EP4CE10F17C8N)。

作者QQ:746833924

说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;

设计思想如下:

 

key_ctrl模块负责将外部的按键信号进行消抖,并且产生对应边沿变化时的脉冲;auto_seller_ctrl模块负责根据脉冲信号和设计逻辑产生对应数字逻辑;water_mode_convert模块负责将选择的水和价格译码出来,并且根据是否选择确定,来控制数码管对应的位置是否闪烁;led_ctrl模块是根据外部的脉冲,控制led点亮一秒钟;seven_tube_drive(七段数码管驱动)模块负责将产生的数字逻辑显示到数码管上。

 

key_ctrl模块设计思想为:按键信号是由外部机械式按键产生,每次按下或者抬起时,会产生一定的抖动。如果直接对其进行边沿检测就会导致多次触发。故而需要设计按键消抖,进而对消抖之后的波形进行边沿检测。消抖原理为:外部按键信号发生改变后,如果能够持续20ms,没有新的改变,就认为此次改变不是抖动,而是真正的按下,然后进行采样即可。

 

auto_seller_ctrl模块的设计思想:利用状态机设计进行实现。共有八个状态。

  localparam      STATE_IDLE              =     8'b0000_0001;
  localparam      STATE_SEL               =     8'b0000_0010;
  localparam      STATE_ZERO_ZERO         =     8'b0000_0100;
  localparam      STATE_ZERO_FIVE         =     8'b0000_1000;
  localparam      STATE_ONE_ZERO          =     8'b0001_0000;
  localparam      STATE_ONE_FIVE          =     8'b0010_0000;
  localparam      STATE_TWO_ZERO          =     8'b0100_0000;
  localparam      STATE_TWO_FIVE          =     8'b1000_0000;

 

复位结束后,在IDLE状态。之后进入SEL状态,可以通过切换商品按键切换商品的选择。通过按下选择OK键,进入到投递金钱的状态。下面把所有的有可能出现的金钱都做状态设计,根据现有状态和投入的金钱做出对应的动作(输出对应的出货脉冲和找零脉冲、输出输入的钱数)即可。

 

 

  always @ * begin
    case (c_state)
      STATE_IDLE            :   n_state = STATE_SEL;
      STATE_SEL             :   n_state = (flag_ok == 1'b1) ? STATE_ZERO_ZERO : STATE_SEL;
      STATE_ZERO_ZERO       :   if (flag_half == 1'b1)
                                  n_state = STATE_ZERO_FIVE;
                                else 
                                  if (flag_one == 1'b1)
                                    n_state = STATE_ONE_ZERO;
                                  else
                                    n_state = STATE_ZERO_ZERO;
      
      STATE_ZERO_FIVE       :   if (flag_half == 1'b1)
                                  n_state = STATE_ONE_ZERO;
                                else 
                                  if (flag_one == 1'b1)
                                    n_state = STATE_ONE_FIVE;
                                  else
                                    n_state = STATE_ZERO_FIVE;
      
      STATE_ONE_ZERO       :    if (flag_half == 1'b1)
                                  n_state = STATE_ONE_FIVE;
                                else 
                                  if (flag_one == 1'b1)
                                    if (water_mode == 2'd0)
                                      n_state = STATE_IDLE;
                                    else
                                      n_state = STATE_TWO_ZERO;
                                  else
                                    n_state = STATE_ONE_ZERO;
                                  
      STATE_ONE_FIVE      :   if (flag_half == 1'b1)
                                  if (water_mode == 2'd0)
                                    n_state = STATE_IDLE;
                                  else
                                    n_state = STATE_TWO_ZERO;
                              else 
                                if (flag_one == 1'b1)
                                  if (water_mode == 2'd0)
                                    n_state = STATE_IDLE;
                                  else
                                    if (water_mode == 2'd1)
                                      n_state = STATE_IDLE;
                                    else
                                      n_state = STATE_TWO_FIVE;
                                else
                                  n_state = STATE_ONE_FIVE;
                                                    
      STATE_TWO_ZERO      :   if (flag_half == 1'b1)
                                  if (water_mode == 2'd1)
                                    n_state = STATE_IDLE;
                                  else
                                    n_state = STATE_TWO_FIVE;
                              else 
                                if (flag_one == 1'b1)
                                  n_state = STATE_IDLE;
                                else
                                  n_state = STATE_TWO_ZERO;
                                  
      STATE_TWO_FIVE     :   if (flag_half == 1'b1)
                                n_state = STATE_IDLE;
                              else 
                                if (flag_one == 1'b1)
                                  n_state = STATE_IDLE;
                                else
                                  n_state = STATE_TWO_FIVE;
                                  
      default             :     n_state = STATE_IDLE;
    endcase
  end

 

water_mode_convert模块的设计思想为:根据选择的水,解析出对应的种类和价格;当未确定选择时,正常输出水的种类和价格;当确定选择时,让输出在正常输出和息屏输出每0.5s进行切换一次。

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      water_mode_bcd_src <= 12'hA20;
    else
      case (water_mode)
        2'd0    :   water_mode_bcd_src <= 12'hA20;
        2'd1    :   water_mode_bcd_src <= 12'hB25;
        2'd2    :   water_mode_bcd_src <= 12'hC30;
        default :   water_mode_bcd_src <= 12'hA20;
      endcase
  end

led_ctrl模块的设计思想为:根据外部输入的脉冲,控制对应的led点亮一秒钟即可。

 

七段数码管为普通六位一体的共阳极数码,采用动态驱动的方式,在此不再赘述。

 

下板时,按下复位,此项设计开始运行。

 

 

 

讲解和演示视频链接如下:
https://www.bilibili.com/video/BV1Tr42177wX/?spm_id_from=333.999.0.0&vd_source=b5405faeab8632f02533bcbfc5e52e55
     本设计所有内容(设计代码、设计工程)链接为:

     

链接:https://pan.baidu.com/s/1JfUSrUaIRrb5-4aEg7vfeA
提取码:ojzq

 

  本篇内容中有部分资源来源于网络,如有侵权,请联系作者。

 

  如果您觉得本公众号还不错的话,可以推给身边的朋友们,感谢并祝好!

 

posted on 2024-05-13 06:44  郝旭帅电子设计团队  阅读(31)  评论(0编辑  收藏  举报

导航