原理
售货机:就像平常在宿舍楼看到的那种售货机,展示着各种商品,一个屏幕上可以点击购买,然后你给钱,最后售货机出货。
我这里用的板子有6个数码管,4个key,4个led,1个蜂鸣器
我的想法:一共2个商品
初始状态下显示商品名和价格,如下
A 1.5 B 2.0
按下key0时进入选择状态,该状态下,按一次key2表示购买一个A,按下一次key1表示购买一个B,并且数码管会显示你购买商品的总金额
在选择状态下再次按下key0进入支付状态,此时数码管显示你购买商品的总金额和你已经支付的金额,当你的支付金额大于等于应付金额时会重新跳转到初始状态。我用蜂鸣器响代替出货,用不同的led灯状态表示找零或者不需要找零,(当你进入支付状态10s,支付金额小于应付金额也会跳转到初始状态),代码中设置有一个找零寄存器,保存你应该找零的金额,这里因为硬件不足,没有展示在板子上,只是展示了是否应该找零。
(当你支付金额不足但跳转到初始状态就令蜂鸣器不响(不出货),但需要找零(找零状态的led))
实现
设计:
1)按键消抖
2)控制模块
3)数码管驱动
按键消抖就不介绍了,需要就去看前面的博客
控制模块
module control (
input clk ,
input rst_n ,
input [2:0] key ,
output [3:0] led ,
output beep ,
output [23:0] seg_data ,
output [2:0] current_state
);
parameter IDLE = 3'b001;//初始状态
parameter SELECT = 3'b010;//选择状态
parameter PAY = 3'b100;//付款状态
parameter TIME_10S = 500_000_000;
parameter TIME_3S = 150_000_000;
wire idle2select ;
wire select2pay ;
wire pay2idle ;
reg [2:0] state_c;//现态
reg [2:0] state_n;//次态
reg [8:0] zhao_ling;//找零寄存器
reg [3:0] led_r;//led寄存
reg led_flag;//led标志
reg finish_flag;//支付完成标志
reg [23:0] idle_seg_data;//初始态显示数据
reg [8:0] select_money_r;//选择商品总金额
wire [23:0] select_money_data;//选择商品总金额显示
wire [3:0] s_bai;
wire [3:0] s_shi;
wire [3:0] s_ge;
reg [8:0] pay_money_r;//支付总金额
wire [23:0] pay_money_data;//支付总金额显示
wire [3:0] p_bai;
wire [3:0] p_shi;
wire [3:0] p_ge;
reg [23:0] seg_data_r;//实际显示数据寄存器
reg [28:0] cnt_10s;//10s计数器
wire add_cnt_10s;
wire end_cnt_10s;
reg [27:0] cnt_3s;//3s计数器
wire add_cnt_3s;
wire end_cnt_3s;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state_c <= IDLE;
end
else begin
state_c <= state_n;
end
end
always @(*) begin
case(state_c)
IDLE:begin
if(idle2select)begin
state_n = SELECT;
end
else begin
state_n = state_c;
end
end
SELECT:begin
if(select2pay