自动售货机 FPGA 设计 Verilog Quartus
名称:自动售货机 FPGA 设计 Verilog Quartus
软件:Quartus
语言:Verilog
功能介绍
本工程实现了一个基于 FPGA 的自动售货机控制系统,使用 Verilog 编写,适用于 Quartus 工程学习、课程设计和数字系统综合实验。系统围绕真实售货机交易流程设计,支持商品选择、确认、投币、金额计算、找零、退币、缺货提示和数码管金额显示等功能。 系统可识别 1 元和 0.5 元两种投币按键,共设置 4 种商品,其中两种商品价格为 2 元,另外两种商品价格为 1.5 元。用户选择商品并确认后进入投币状态,系统实时累计投入金额,并通过数码管显示投币金额、商品价格、找零金额和还差金额。 当投入金额满足商品价格时,系统点亮购买成功指示,并计算找零金额;当商品售空时,系统通过缺货指示灯提示;当确认商品后长时间未投币,或投币不足后超时,系统会返回初始流程或执行退币提示。整体功能覆盖了自动售货机控制系统中较典型的状态转换和异常处理场景。 该设计的模块划分清晰,包含顶层控制、状态控制、数码管显示和按键消抖等模块,便于阅读、仿真和二次修改。商品价格、库存数量、计时参数等逻辑集中在状态控制模块中,适合进一步扩展为更多商品、更复杂支付流程或不同显示方案。
运行环境
开发语言:Verilog 开发软件:Quartus 顶层模块:auto_sell 主要工程文件:auto_sell.qpf、auto_sell.qsf、auto_sell.v、state_ctrl.v、display.v、key_jitter.v 仿真环境:工程包含 ModelSim 仿真相关目录和仿真报告,可用于查看顶层功能、状态控制、按键消抖和数码管显示等模块的仿真过程。
设计思路
本设计采用分层模块化结构完成自动售货机控制逻辑。顶层模块负责外部按键、LED 指示和数码管接口的统一连接,按键输入先经过消抖处理,再送入状态控制模块进行商品选择、投币金额累计、确认交易、缺货判断和超时处理,最后由显示模块将金额信息输出到 8 位数码管。 核心控制部分使用有限状态机实现,工作流程包含空闲等待、商品选择确认、投币、退币、找零和交易结束等过程。顾客选择商品后,系统根据所选商品价格进入投币流程;投币金额达到或超过商品价格时,完成出货和找零计算;投币不足或等待超时后,系统执行退币并返回初始状态。 金额处理采用 BCD 编码表达投币金额、商品价格、找零金额和还差金额,便于直接驱动数码管显示。系统支持 1 元和 0.5 元两类投币输入,四种商品价格分别为 2 元、2 元、1.5 元和 1.5 元,商品库存初始值为每种 10 个,交易成功后会更新对应库存。 为了提升按键输入可靠性,工程为投币、商品选择和确认按键均接入 key_jitter 消抖模块。该模块通过稳定计数方式滤除机械按键抖动,并输出单次有效下降沿脉冲,避免一次按键被状态机重复识别。
模块结构
工程主要模块包括: 1. auto_sell:顶层模块,连接系统时钟、复位、投币按键、商品选择按键、确认按键、状态指示灯和数码管接口,负责各子模块之间的信号组织。 2. state_ctrl:状态控制模块,完成自动售货机核心业务逻辑,包括商品选择、确认、投币累计、价格比较、找零计算、退币处理、缺货判断、库存更新和超时计时。 3. display_num:数码管显示模块,采用动态扫描方式驱动 8 位数码管,用于显示投币金额、商品价格、找零金额和还差金额。 4. key_jitter:按键消抖模块,对机械按键输入进行稳定检测,输出消抖后的下降沿脉冲,保证每次按键操作只触发一次有效事件。
演示视频
配有自动售货机系统演示视频,可直观看到商品选择、确认、投币、金额显示、成功购买、找零/退币指示等运行过程,适合在下载前了解工程实际交互效果。
演示视频请关注公众号后获取对应资料查看。
仿真图/仿真说明/设计文档图片
设计文档包含工程文件说明、程序文件说明、编译结果、RTL 图、Testbench、顶层仿真图、按键消抖模块仿真图、状态控制模块仿真图和数码管显示模块仿真图等内容。 仿真内容覆盖正常购买流程:选择 2.0 元商品后,商品指示灯有效,确认后依次投入 1 元、0.5 元、1 元,系统显示投币金额、商品价格、找钱金额和还差金额。 仿真还覆盖超时处理流程:选择 1.5 元商品后 30 秒无操作,系统返回初始状态;选择 1.5 元商品并投币 1 元后 30 秒无后续操作,系统退回已投金额并点亮退币指示灯。 按键消抖仿真展示了机械抖动期间不产生有效输出,按键信号稳定后输出 key_negedge 脉冲;数码管显示仿真展示了 8 位数码管对投币金额、商品价格、找零金额和剩余金额的动态扫描显示。
部分代码
以下展示顶层模块auto_sell的部分代码,完整代码可关注下方公众号卡片获取。
module auto_sell( input clk_in,//48M input reset_n,//复位 //按键按下低电平 input coin_10_key,//投币1元 input coin_05_key,//投币0.5元 input price_20_1_key,//2元商品1 input price_20_2_key,//2元商品2 input price_15_1_key,//1.5元商品1 input price_15_2_key,//1.5元商品2 input confirm_key,//确认 output succeed_ledn,//购买成功指示灯 output coin_return_ledn,//退币指示灯 output [3:0] goods_ledn,//商品指示灯 output NO_goods_ledn,//商品缺货指示灯 output [7:0] DLA,//数码管位选,低电平选择 output [7:0] HEX//数码管段选,低亮 ); wire [7:0] input_money_BCD;//投币金额 wire [7:0] need_money_BCD;//价钱 wire [7:0] change_money_BCD;//找钱 wire [7:0] left_money_BCD;//还差金额 wire coin_10_p;//投币1元 wire coin_05_p;//投币0.5元 wire price_20_1_p;//2元商品 wire price_20_2_p;//2元商品 wire price_15_1_p;//1.5元商品 wire price_15_2_p;//1.5元商品 wire confirm_p;//确认 //按键消抖模块 key_jitter i0_key_jitter( . clkin(clk_in), . key_in(coin_10_key),//输入 . key_negedge(coin_10_p)//消抖后按键下降沿 ); //按键消抖模块 key_jitter i1_key_jitter( . clkin(clk_in), . key_in(coin_05_key),//输入 . key_negedge(coin_05_p)//消抖后按键下降沿 ); //按键消抖模块 key_jitter i2_key_jitter( . clkin(clk_in), . key_in(price_20_1_key),//输入 . key_negedge(price_20_1_p)//消抖后按键下降沿 ); //按键消抖模块 key_jitter i3_key_jitter( . clkin(clk_in), . key_in(price_20_2_key),//输入 . key_negedge(price_20_2_p)//消抖后按键下降沿 ); //按键消抖模块 key_jitter i4_key_jitter( . clkin(clk_in), . key_in(price_15_1_key),//输入 . key_negedge(price_15_1_p)//消抖后按键下降沿 ); //按键消抖模块 key_jitter i5_key_jitter( . clkin(clk_in), . key_in(price_15_2_key),//输入 . key_negedge(price_15_2_p)//消抖后按键下降沿 ); //按键消抖模块 key_jitter i6_key_jitter( . clkin(clk_in), . key_in(confirm_key),//输入 . key_negedge(confirm_p)//消抖后按键下降沿 ); //状态控制模块 state_ctrl i_state_ctrl( . clk_in(clk_in),//48M . reset_n(reset_n),//复位 . coin_10_p(coin_10_p),//投币1元 . coin_05_p(coin_05_p),//投币0.5元 . price_20_1_p(price_20_1_p),//2元商品 . price_20_2_p(price_20_2_p),//2元商品 . price_15_1_p(price_15_1_p),//1.5元商品 . price_15_2_p(price_15_2_p),//1.5元商品 . confirm_p(confirm_p),//确认 . succeed_ledn(succeed_ledn),//购买成功指示灯 . coin_return_ledn(coin_return_ledn),//退币指示灯 . goods_ledn(goods_ledn),//商品指示灯 . NO_goods_ledn(NO_goods_ledn),//商品缺货指示灯 . input_money_BCD(input_money_BCD),//投币金额 . need_money_BCD(need_money_BCD),//价钱 . change_money_BCD(change_money_BCD),//找钱 . left_money_BCD(left_money_BCD)//还差金额 ); //数码管显示模块 display_num i_display_num( . clk_in(clk_in),// . input_money_BCD(input_money_BCD),//投币金额 . need_money_BCD(need_money_BCD),//价钱 . change_money_BCD(change_money_BCD),//找钱 . left_money_BCD(left_money_BCD),//还差金额 . DLA(DLA),//数码管位选,低电平选择 . HEX(HEX)//数码管段选,低亮 // ... 以下代码略,完整源码请下载压缩包查看
代码获取:下方公众号
“FPGA代码设计学习资料”
