目录
一、项目功能
1.默认只接收0.5元、1元投币。
⒉货物有4种可以选择,价格分别为0.5,1.5,2.4,3元。
3.满足当前选择的商品价格后自动出货,出货动作用4个LED做跑马灯(闪烁2s)表示。
4.超过前选择的商品价格之后,自动出货并找零,动作用4个LED做跑马灯表示(同样闪烁2s)。
5.显示当前投币的总额、当前选择的商品的价格以及找零的数目。
6.复位时播放音乐并显示彩灯。
7.投币不足目标价格时可以取消,动作用灯闪烁表示(2s)。
二、设计思路
按键按下,KEY输出值为低电平,否则为高电平。
按键实现:
每个按键对应相应的功能:
key0:退货
key1:选择不同的价格(0.5;1.5;2.4,3.0)
key2:投币,按一次个位增加5,即为0.5
key3:投币,按一次十位增加1,即增加1
数码管
数码管通过位选信号控制指定数码管,给0信号值,表示选中此数码管,给1信号值,表示未选中此应数码管,段选信号控制数码管上对应的led灯,数码管的LED灯共阳极,给低电平亮。
数码管显示数字真值表

数码管实现:
数码管6位,从左往右,依次是两位的投币输入金额,两位的商品价格,以及两位的找零金额。初始显示1位,两位,1位,位选总共六种显示状态,段选10种状态
蜂鸣器
不同的音符振动频率不同,周期T=1/频率f

根据上图可以计算出音符振动的周期,单位微秒。Cyclone IV开发板的晶振是50MHz,振动一次是20纳秒,使用周期时间除以20纳秒得出音符振动的次数 。比如高音的DO计算方式如下公式所示。
DO(高)=955*1000/20=47750
按下key0后,蜂鸣器播放5秒的音乐,(音符+每个音符的空白时间),每个音符对应一个外接彩灯闪烁灯
按下key1,key2,key3中任意一个,蜂鸣器会有0.2s的提示音
LED灯
LDE灯对应8种状态:全灭;全亮;只亮led[0];只亮led[1];只亮led[2];只亮led[3];流水灯;闪烁
三、流程图

四、代码实现
1、按键消抖 key_debounce.v
module key_debounce(
input wire clk,
input wire rst_n,
input wire key,
output reg flag,// 0抖动, 1抖动结束
output reg key_value//key抖动结束后的值
);
parameter MAX_NUM = 20'd1_000_000;
reg [19:0] delay_cnt;//1_000_000
reg key_reg;//key上一次的值
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
key_reg <= 1;
delay_cnt <= 0;
end
else begin
key_reg <= key;
//当key为1 key 为0 表示按下抖动,开始计时
if(key_reg != key ) begin
delay_cnt <= MAX_NUM ;
end
else begin
if(delay_cnt > 0)
delay_cnt <= delay_cnt -1;
else
delay_cnt <= 0;
end
end
end
//当计时完成,获取key的值
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
flag <= 0;
key_value <= 1;
end
else begin
// 计时完成 处于稳定状态,进行赋值
if(delay_cnt == 1) begin
flag <= 1;
key_value <= key;
end
else begin
flag <= 0;
key_value <= key_value;
end
end
end
endmodule
2、LED状态选择 led_drive.v
module led_drive (
input wire clk ,//时钟信号
input wire rst_n,//复位信号
input wire [3:0] value,//LED显示状态
output reg [3:0] led //4个LED输出
);
/*
value 效果
0 全灭
1 全亮
2 只亮led[0]
3 只亮led[1]
4 只亮led[2]
5 只亮led[3]
6 流水灯
7 闪烁
*/
parameter MAX_TIME_RUNNING = 28'd4_000_000; //流水灯频率0.08s
parameter MAX_TIME_FLASH = 28'd10_000_000; //闪烁频率0.2s
reg [27:0] cnt_time_running ; //流水灯计时器
reg [27:0] cnt_time_flash; //闪烁灯计时器
reg [7:0] led_running; //流水灯状态寄存器
reg [3:0] led_flash; //闪烁灯状态寄存器
//流水灯计数器0.08s
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt_time_running <=28'd1;
else if(value == 4'd6) begin
if(cnt_time_running == MAX_TIME_RUNNING)
cnt_time_running <=28'd1;
else
cnt_time_running <= cnt_time_running+28'd1;
end
else
cnt_time_running <= 28'd1;
end
//闪烁灯计数器0.2s
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt_time_flash <=28'd1;
else if (value == 4'd7) begin
if(cnt_time_flash == MAX_TIME_FLASH )
cnt_time_flash <=28'd1;
else
cnt_time_flash <= cnt_time_flash+28'd1;
end
else
cnt_time_flash <= 28'd1;
end
//流水灯状态切换 间隔0.08s
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
led_running <= 8'b00001111;
else if(cnt_time_running == MAX_TIME_RUNNING)begin
led_running <= {led_running[0],led_running[7:1]};
end
else
led_running <=led_running;
end
//闪烁状态切换 间隔0.2s
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
led_flash <= 4'b0000;
else if(cnt_time_flash == MAX_TIME_FLASH)begin
led_flash <= ~led_flash;
end
else
led_flash <=led_flash;
end
//根据value值输出对应灯效果
always @(*) begin
case(value)
4'd0: begin
led = 4'b0000;//默认状态LED全灭
end
4'd1:begin
led = 4'b1111;//
end
4'd2:begin
led = 4'b0001;//选择第一种商品
end
4'd3:begin
led = 4'b0010;//选择第二种商品
end
4'd4:begin
led = 4'b0100;//选择第三种商品
end
4'd5:begin
led = 4'b1000;//选择第四种商品
end
4'd6: begin
led = led_running[3:0];//购买成功找零不找零,流水灯
end
4'd7:begin
led = led_flash;//取消订单,闪烁
end
default : led = 4'b0000;
endcase
end
endmodule
3、蜂鸣器模块 beep_drive.v
module beep_drive (
input wire clk,
input wire rst_n,
input wire flag, //蜂鸣器开始鸣叫
input wire status,
output reg beep
);
parameter MAX_TIME = 24'd10_000_000; //鸣叫时间
parameter MAX_TIME_MUSIC = 28'd250_000_000; //音乐播放时间
reg [23:0] cnt_time; //计时
reg [27:0] cnt_time_music; //音乐播放计时器
reg flag_beep_time_out; // 计时是否结束
//音乐播放计时
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_time_music <= 28'd0;
end
else if(cnt_time_music < MAX_TIME_MUSIC) begin
cnt_time_music <= cnt_time_music + 28'd1;
end
else
cnt_time_music <= cnt_time_music;
end
//蜂鸣器输出
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_time <= 0;
beep <= 1;
flag_beep_time_out <= 1;
end
else if(!status && cnt_time_music < MAX_TIME_MUSIC) begin
beep <= 0;
end
else if(status && cnt_time_music < MAX_TIME_MUSIC) begin
beep <= 1;
end
else if(flag && flag_beep_time_out) begin //开始鸣叫
cnt_time <= MAX_TIME;
flag_beep_time_out <= 0;
end
else if(cnt_time >=1 && !flag_beep_time_out) b


3023

被折叠的 条评论
为什么被折叠?



