名称:自动售货机控制与倒计时显示的设计Verilog代码Quartus开发板
软件:QuartusII
语言:Verilog
代码功能
该工程实现一个简化的自动售货机逻辑:6个数码管分别显示6种商品的剩余数量(0~9),6个按键对应选择购买。选择后,LED显示当前商品价格,并启动60秒倒计时;若倒计时内收到“付款成功”信号则出货提示并将该商品数量减1;若超时则取消本次交易并回到待机。当选中商品库存为0时,通过缺货指示灯提示,避免进入付款流程。
FPGA代码Verilog/VHDL代码资源下载:www.hdlcode.com
本代码已在开发板验证,开发板如下,其他开发板可以修改管脚适配:
相关图片
开发板 (1).jpg
管脚.jpg
设计文档:
代码实现思路
整体采用“状态机+计时器+显示驱动”的结构。状态机分为待机/付款计时/取消/确认出货/结束回到待机等阶段:在待机阶段检测各选择键,若库存>0则锁存对应价格并进入付款计时;若库存为0则点亮缺货灯。付款计时阶段使用分频得到的节拍(工程中以计数阈值实现,可根据板卡主频调整)对BCD格式的60秒倒计时做递减,倒计时到0则进入取消流程;若检测到付款成功按键,则进入短暂等待后出货成功指示,并对选中商品库存做一次减1。显示部分将6路库存与倒计时组合成动态扫描的数码管显示,价格则用独立LED直观给出。
代码结构
顶层模块负责把按键、LED与数码管接口连起来,并把核心控制与显示拆成两个子模块:控制侧集中在state_ctrl中,完成按键有效电平处理、价格锁存、缺货判断、状态跳转、倒计时以及库存扣减;显示侧由display_num完成数码管位选/段选扫描,把6路库存与倒计时两位BCD统一显示。这种分层方式把“业务规则”和“显示驱动”解耦,后续如果更换显示器件或扩展商品数量,只需局部修改对应模块。
文件/模块一览
auto_sell_bd7auto_sell.v:auto_sell
部分代码
auto_sell_bd7state_ctrl.v
//状态控制模块 module state_ctrl( input clk_in,//24M input reset_n,//复位--key0 input select_1,//选择商品1--key1 input select_2,//选择商品2--key2 input select_3,//选择商品3--key3 input select_4,//选择商品4--key4 input select_5,//选择商品5--key5 input select_6,//选择商品6--key6 input confirm_key,//成功付款信号(按键)--key7 output less_led,//商品缺货指示灯--LED A7 output [3:0] need_money_led,//LED显示选中商品的价格--LED A0~A3 output reg succeed_ledn,//购买成功指示灯--LED A5 output [7:0] time_60s_bcd, output [3:0] num_1_o,//商品1数量 output [3:0] num_2_o,//商品2数量 output [3:0] num_3_o,//商品3数量 output [3:0] num_4_o,//商品4数量 output [3:0] num_5_o,//商品5数量 output [3:0] num_6_o //商品6数量 ); wire select_1_p;//选择商品1 wire select_2_p;//选择商品2 wire select_3_p;//选择商品3 wire select_4_p;//选择商品4 wire select_5_p;//选择商品5 wire select_6_p;//选择商品6 wire confirm_p; assign select_1_p=~select_1; assign select_2_p=~select_2; assign select_3_p=~select_3; assign select_4_p=~select_4; assign select_5_p=~select_5; assign select_6_p=~select_6; assign confirm_p =~confirm_key; reg [3:0] num_1;//商品1数量 reg [3:0] num_2;//商品2数量 reg [3:0] num_3;//商品3数量 reg [3:0] num_4;//商品4数量 reg [3:0] num_5;//商品5数量 reg [3:0] num_6;//商品6数量 assign num_1_o=num_1;//商品1数量 assign num_2_o=num_2;//商品2数量 assign num_3_o=num_3;//商品3数量 assign num_4_o=num_4;//商品4数量 assign num_5_o=num_5;//商品5数量 assign num_6_o=num_6;//商品6数量 reg [2:0] state=3'd0; parameter s_idle=3'd0;//起始状态 parameter s_coin=3'd1;//付钱状态 parameter s_coin_return=3'd2;//取消状态 parameter s_change=3'd3;//购买成功状态 parameter s_end=3'd4;//结束 parameter s_wait=3'd5;// reg [3:0] need_money; reg [31:0] clk_div_cnt=32'd0; wireclk_1Hz; reg [7:0] time_60s_count=8'd0;//60秒计数器 reg [7:0] time_change_count=8'd0;//成功 always@(posedge clk_in or negedge reset_n) if(reset_n==0) clk_div_cnt<=0; else if(state==s_coin || state==s_change || state == s_wait) if(clk_div_cnt>=32'd999) clk_div_cnt<=0; else clk_div_cnt<=clk_div_cnt+31'd1;//计数 else clk_div_cnt<=0; assign clk_1Hz = (clk_div_cnt>=32'd999) ? 1'b1 : 1'b0; always@(posedge clk_in or negedge reset_n) if(reset_n==0) succeed_ledn<=0; else if(state==s_change)//购买成功状态 succeed_ledn<=1;//购买成功,亮 else succeed_ledn<=0; always@(posedge clk_in or negedge reset_n) if(reset_n==0) need_money<=4'd0; else if(state==s_idle)//选择商品 if(select_1_p==1 && num_1>4'd0) need_money<=4'd1; else if(select_2_p==1&& num_2>4'd0) need_money<=4'd2; else if(select_3_p==1&& num_3>4'd0) need_money<=4'd3; else if(select_4_p==1&& num_4>4'd0) need_money<=4'd4; else if(select_5_p==1&& num_5>4'd0) need_money<=4'd5; else if(select_6_p==1&& num_6>4'd0) need_money<=4'd6; else need_money<=need_money; else if(state==s_end) need_money<=4'd0; else need_money<=need_money; assign need_money_led = need_money;//LED显示选中商品的价格 //缺货指示 reg less_led_buf=0; always@(posedge clk_in or negedge reset_n) if(reset_n==0) less_led_buf<=1'd0; else if(state==s_idle)//选择商品 if(select_1_p==1 && num_1==4'd0) less_led_buf<=1'd1; else if(select_2_p==1&& num_2==4'd0) less_led_buf<=1'd1; else if(select_3_p==1&& num_3==4'd0) less_led_buf<=1'd1; else if(select_4_p==1&& num_4==4'd0) less_led_buf<=1'd1; else if(select_5_p==1&& num_5==4'd0) less_led_buf<=1'd1; else if(select_6_p==1&& num_6==4'd0) less_led_buf<=1'd1; else less_led_buf<=1'd0; else if(state==s_end) less_led_buf<=1'd0; else less_led_buf<=1'd0; assign less_led= less_led_buf;//输出低电平亮 always@(posedge clk_in or negedge reset_n) if(reset_n==0) state<=s_idle; else case(state) s_idle://起始状态,可以选择商品价格 if(need_money>4'd0)//确认后进入付钱状态 state<=s_coin; else state<=s_idle; s_coin://付钱状态 if(time_60s_count==8'd0)//计时60s改小 state<=s_coin_return;//60S内不继续投币取消购买 else if(confirm_p)//支付成功 state<=s_wait; else state<=s_coin; s_coin_return://取消状态 state<=s_end; s_wait: state<=s_change; s_change://购买成功状态,持续3秒 if(time_change_count>=8'd3)//d72_000_000计时3s,改小 state<=s_end; else state<=s_change; s_end://结束状态 state<=s_idle; default:; endcase always@(posedge clk_in or negedge reset_n) if(reset_n==0) time_60s_count<=8'h60; else if(state==s_coin)begin if(clk_1Hz) if(time_60s_count[7:4] ==4'd0 && time_60s_count[3:0] ==4'd0) time_60s_count<=8'h00; else if(time_60s_count[3:0] ==4'd0) begin time_60s_count[7:4] <=time_60s_count[7:4] -4'd1; time_60s_count[3:0] <=4'd9; end else begin time_60s_count[7:4] <=time_60s_count[7:4]; time_60s_count[3:0] <=time_60s_count[3:0] - 4'd1; end end else
253