基于FPGA的售货机

文章目录

  • 一、要求
  • 二、效果
  • 三、设计思路
    • 1.按键
    • 2.数码管
    • 3.LED
    • 4.蜂鸣器
  • 四、程序流程图
  • 五、项目RTL视图
  • 六、代码实现
    • 1.按键消抖
    • 2.售货机
    • 3.LED
    • 4.数码管
    • 5.音乐播放
    • 6.蜂鸣器
    • 7.顶层模块
  • 七、仿真

一、要求

  1. 默认只接收0.5元、1元投币。
  2. 货物为2.5元。
  3. 满足2.5元后自动出货,出货动作用4个LED同时闪烁(闪烁2s)表示。
  4. 满足3元之后,自动出货并找零,动作用4个LED做流水灯表示(同样闪烁2s)。

二、效果

  1. 默认只接收0.5元、1元投币。
  2. 货物有4种可以选择,价格分别为0.5,1.5,2.4,3元。
  3. 满足当前选择的商品价格后自动出货,自动出货并找零,出货动作用4个LED做跑马灯(持续2s)表示。
  4. 显示当前投币的总额、当前选择的商品的价格以及找零的数目。
  5. 复位时播放音乐并显示彩灯。
  6. 投币不足目标价格时可以取消,动作用灯闪烁表示(2s)。

三、设计思路

1.按键

在这里插入图片描述

2.数码管

数码管6位,从左往右,依次是两位的投币输入金额,两位的商品价格
以及两位的找零金额。初始显示1位,两位,1位。
位选总共六种显示状态,段选10种状态。

3.LED

在这里插入图片描述

4.蜂鸣器

在这里插入图片描述

四、程序流程图

在这里插入图片描述

五、项目RTL视图

在这里插入图片描述

六、代码实现

1.按键消抖

module key_drive (input   wire clk,input   wire rst_n,input   wire [2:0] key, //按键output  reg [19:0] value //输出到数码管显示的值
);parameter MAX_VALUE = 20'd1024;     //最大显示数字always @(posedge clk or negedge rst_n) beginif(!rst_n) beginvalue <= 20'd0;endelse if (value >= MAX_VALUE) beginvalue <= 20'd0;end// 根据按下的键进行对应的操作else beginif(key[0]) beginvalue <= 2;endelse if (key[1]) beginvalue <= 3;endelse if (key[2]) beginvalue <= 4;endelse beginvalue <= value;endend
end
endmodule

2.售货机

module machine_drive(input    wire			   clk			,        //时钟信号input    wire			   rst_n		   ,			//复位信号input    wire	[2:0] 	key			,        //3个按键 KEY4-key[2]:1元 KEY3-key[1]:0.5元 KEY2-key[0]:更换商品价格output	reg 	[3:0] 	led_value	,			//对应led显示效果的类型output 	reg 	[6:0] 	price_put	,			//用户投入的钱output 	reg 	[6:0] 	price_need	,			//商品价格output 	reg 	[6:0] 	price_out				//找零
);//四种商品对应价格
parameter	P1 = 7'd5;
parameter	P2 = 7'd15;
parameter	P3 = 7'd24;
parameter	P4 = 7'd30;parameter MAX_TIME = 28'd100_000_000;	//退款过程持续时间reg 	[1 :0] 	price_tmp			  	;	//当前商品价格
reg 	[27:0] 	cnt_time 			 	;   //用作退款过程计时
reg 			flag_can_operation  	;	//可以继续投币和切换商品
reg 			flag_is_retreat_end 	;	//结算完毕wire			flag_is_retreat     	;	//开始结算
wire			flag_price_is_enough	;	//可以买下商品
reg		[6:0] 	price_put_last      	;	//结算前的投币数//结算倒计时模块
always @(posedge clk,negedge rst_n) beginif(!rst_n)begincnt_time <= 28'd0;          //初始设置计数器为0flag_can_operation <= 1'b1 ;//设置KEY键可操作flag_is_retreat_end <= 1'b0;//设置结算完毕标志为0endelse beginif (flag_is_retreat) begin     //开始结算cnt_time <= MAX_TIME;       //计数器设置最大值flag_can_operation <= 1'b0 ;//当前处于结算状态,设置KEY键不可用flag_is_retreat_end <= 1'b0;//设置结算未完毕endelse if(cnt_time > 28'd1) begin //计数器数值大于1cnt_time <= cnt_time - 28'd1;//倒计时flag_can_operation <= 1'b0;  //当前处于结算状态,设置KEY键不可操作flag_is_retreat_end <= 1'b0; //设置结算未完毕endelse if(cnt_time == 28'd1) begin//计数器倒计时数到1cnt_time <= 28'd0;           //计数器清零flag_can_operation <= 1'b1;  //结算完毕,设置KEY键可操作flag_is_retreat_end <= 1'b1; //设置结算完毕endelse begincnt_time <= cnt_time;flag_can_operation <= flag_can_operation;flag_is_retreat_end <= 1'b0;endendend//按下KEY2-key[0]切换商品价格 
always@(posedge clk,negedge rst_n)beginif(!rst_n)beginprice_tmp<= 2'd0;  //初始设置商品价格为1号商品endelse if(flag_can_operation) begin//当前按键可操作// 当没有投币的时候按下 KEY2-key[0] 为切换商品 if(key[0] && ! price_put) beginprice_tmp <= (price_tmp + 2'd1) % 4;//%操作,循环切换endelse beginprice_tmp <= price_tmp;	//没有按下切换按键,当前商品价格保持endendelse beginprice_tmp <= price_tmp;	end 
end// 切换商品价格
always@(posedge clk,negedge rst_n)beginif(!rst_n)price_need<=P1;elsecase(price_tmp)2'b00 : price_need <= P1;2'b01 : price_need <= P2;2'b10 : price_need <= P3;2'b11 : price_need <= P4;default:price_need <= P1;endcase
end//切换商品价格时led灯光效果
always @(posedge clk,negedge rst_n) beginif(!rst_n)led_value <= 4'd1;//退款的时候判断是 补差价 或者 全额退款//补差价为流水灯效果//全额退款为闪烁效果	else if(flag_is_retreat)begin//开始结算led_value <= price_put_last >= price_need ? 4'd6 : 4'd7 ;//当前投币数大于等于商品价格,LED状态为6,否则状态为7end//正常操作状态根据当前选择商品亮起对应商品ledelse if(flag_can_operation)begincase(price_tmp)2'b00 : led_value <= 4'd2;2'b01 : led_value <= 4'd3;2'b10 : led_value <= 4'd4;2'b11 : led_value <= 4'd5;default:led_value <= 4'd2;endcaseendelse led_value <= led_value;
end//用户通过按键进行投币
always@(posedge clk,negedge rst_n)beginif(!rst_n)beginprice_put_last<=7'd0;//累计投币数初始化为0endelse if(flag_can_operation) begin//当前按键可操作//超过100 或者 if(price_put_last>=7'd100 || flag_is_retreat) begin//当前投币大于10超过可显示数字或开始结算,投币清零price_put_last<=7'd0;end/*按下 key[2] 投币 + 10按下 key[1] 投币 + 5*/	else beginif(key[2])//KEY4-key[2]投币1元price_put_last<=price_put_last+7'd10;else if(key[1])//KEY3-key[1]投币0.5元price_put_last<=price_put_last+7'd5;else	price_put_last<=price_put_last;endendelse beginprice_put<=price_put;end
end//投币数码显示保持2s
always @(posedge clk,negedge rst_n) beginif(!rst_n)beginprice_put<=7'd0;endelse if(!flag_can_operation)//按键不可操作price_put <= price_put;//输出投币保持else price_put <= price_put_last;//否则将当前投币值赋值给输出投币寄存器
end// 输出找零
always @(posedge clk,negedge rst_n) beginif(!rst_n)beginprice_out <= 7'd0;//初始找零0元end//结算完毕,归零else if(flag_is_retreat_end) beginprice_out =7'd0 ;end	//当退款标志到来,计算退款金额为 补差价 或者 全额退款else if(flag_is_retreat) begin//开始结算price_out <= price_put_last >= price_need ? price_put_last - price_need : price_put_last ;//当前投币大于商品价格则找零差值,否则找零为0endelse beginprice_out <= price_out;end
end//当投币可以买下商品
assign flag_price_is_enough = price_put_last >= price_need;//当前投币数大于等于商品价格,投币足够标志置1
//为了保证在结算前得到最后一次投币数量
// assign price_put_last = price_put;
// 当币足够 或者 在投币过程选择切换商品则开始退款
assign flag_is_retreat = flag_price_is_enough || (price_put && key[0]);//投币足够或退款,结算处理标志置1
endmodule

3.LED

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.2sreg [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) beginif(!rst_n)cnt_time_running <=28'd1;else if(value == 4'd6) beginif(cnt_time_running == MAX_TIME_RUNNING)cnt_time_running <=28'd1;elsecnt_time_running <= cnt_time_running+28'd1;endelse cnt_time_running <= 28'd1;
end//闪烁灯计数器0.2s
always @(posedge clk or negedge rst_n) beginif(!rst_n)cnt_time_flash <=28'd1;else if (value == 4'd7) beginif(cnt_time_flash == MAX_TIME_FLASH )cnt_time_flash <=28'd1;elsecnt_time_flash <= cnt_time_flash+28'd1;endelse cnt_time_flash <= 28'd1;
end//流水灯状态切换 间隔0.08s
always @(posedge clk or negedge rst_n) beginif(!rst_n)led_running <= 8'b00001111;else if(cnt_time_running == MAX_TIME_RUNNING)beginled_running <= {led_running[0],led_running[7:1]};endelse led_running <=led_running;end//闪烁状态切换 间隔0.2s
always @(posedge clk or negedge rst_n) beginif(!rst_n)led_flash <= 4'b0000;else if(cnt_time_flash == MAX_TIME_FLASH)beginled_flash <= ~led_flash;endelse led_flash <=led_flash;end//根据value值输出对应灯效果
always @(*) begincase(value)4'd0: beginled = 4'b0000;//默认状态LED全灭end4'd1:beginled = 4'b1111;//end4'd2:beginled = 4'b0001;//选择第一种商品end4'd3:beginled = 4'b0010;//选择第二种商品end4'd4:beginled = 4'b0100;//选择第三种商品end4'd5:beginled = 4'b1000;//选择第四种商品end4'd6: beginled = led_running[3:0];//购买成功找零不找零,流水灯end4'd7:beginled = led_flash;//取消订单,闪烁enddefault : led = 4'b0000;endcase
end
endmodule 

4.数码管

位选

module sel_drive(input    wire             clk			   ,input    wire             rst_n			,input    wire    [6:0]    price_put		,	//投入的钱input    wire    [6:0]    price_need	,	//商品的价格input    wire    [6:0]    price_out		,	//找零的钱output    reg    [5:0]    sel				//数码管位选
);
//状态
localparam state0 = 3'd0;
localparam state1 = 3'd1;
localparam state2 = 3'd2;
localparam state3 = 3'd3;
localparam state4 = 3'd4;
localparam state5 = 3'd5;parameter	 MAX_NUM = 1_000;//计数器最大计数值 刷新频率20微秒reg    [2 :0]    current_state;
reg    [2 :0]    next_state;
reg    [20:0]	  cnt; //时钟分频计数器
reg              flag;//计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)beginflag <= 1'b0;cnt <= 0;endelse if(cnt == 0)begin//一轮计数完毕flag <= 1'b1;cnt <= 1;endelse	begin flag <= 1'b0;cnt <= (cnt + 1'b1) % MAX_NUM;//循环+1end
end
// 状态跳转
always @(posedge clk or negedge rst_n) beginif(!rst_n) begincurrent_state <= state0;endelse if(flag) begincurrent_state <= next_state;endelse current_state <= current_state;
end//状态判断
always @(*) beginif(!rst_n) beginnext_state <= state0;endelse if(flag) begincase(current_state)state0: beginnext_state <= state1;endstate1: beginnext_state <= state2;endstate2: beginnext_state <= state3;endstate3: beginnext_state <= state4;endstate4: beginnext_state <= state5;endstate5: beginnext_state <= state0;enddefault:beginnext_state <= state0;endendcaseendelse beginnext_state <= next_state;end
end//根据value的值确定需要亮几位
always@(current_state) begincase (current_state)state0: begin                 //右第一位数码管显示sel <= 6'b011111;endstate1: begin                 //右第二位数码管显示if (price_out >=1) beginsel <= 6'b101111;endelse beginsel <= 6'b111111;endendstate2: begin                 //右第三位数码管显示if (price_need >=0) beginsel <= 6'b110111;endelse beginsel <= 6'b111111;endendstate3: begin                 //右第四位数码管显示if (price_need >=1) beginsel <= 6'b111011;endelse beginsel <= 6'b111111;endendstate4: begin                 //右第五位数码管显示if (price_put >=0) beginsel <= 6'b111101;endelse beginsel <= 6'b111111;endendstate5: begin                 //右第五位数码管显示if (price_put >=1) beginsel <= 6'b111110;endelse beginsel <= 6'b111111;endenddefault:beginsel <= 6'b111111;endendcase
end
endmodule 

段选

module seg_drive(input   wire    			 clk         ,input   wire    			 rst_n       ,       //复位input   wire    [5:0]   sel         ,       //数码管位选input   wire    [6:0]   price_put   ,       //投入的钱input   wire    [6:0]   price_need  ,       //商品的价格input   wire    [6:0]   price_out   ,       //找零的钱output   reg    [7:0]   seg                 //数码管段选);reg [3:0] num;
always@(*) begincase(sel)//投入的钱6'b111_110: num = (price_put % 100) / 10;       //十位  6'b111_101: num = price_put % 10;               //个位//需要的钱6'b111_011: num = (price_need % 100) / 10;      //十位6'b110_111: num = price_need % 10;              //个位//找回的钱6'b101_111: num = (price_out % 100) / 10;       //十位6'b011_111: num = price_out % 10;               //个位default:num = 4'd0;endcase
endalways @ (*) begin//需要显示小数点if(!sel[1] || !sel[3] || !sel[5]) begincase(num)4'd0:    seg = 8'b1100_0000; //匹配到后参考共阳极真值表4'd1:    seg = 8'b1111_1001;4'd2:    seg = 8'b1010_0100;4'd3:    seg = 8'b1011_0000;4'd4:    seg = 8'b1001_1001;4'd5:    seg = 8'b1001_0010;4'd6:    seg = 8'b1000_0010;4'd7:    seg = 8'b1111_1000;4'd8:    seg = 8'b1000_0000;4'd9:    seg = 8'b1001_0000;default : seg = 8'b1100_0000;endcaseendelse begincase(num)4'd0:    seg = 8'b0100_0000; //匹配到后参考共阳极真值表4'd1:    seg = 8'b0111_1001;4'd2:    seg = 8'b0010_0100;4'd3:    seg = 8'b0011_0000;4'd4:    seg = 8'b0001_1001;4'd5:    seg = 8'b0001_0010;4'd6:    seg = 8'b0000_0010;4'd7:    seg = 8'b0111_1000;4'd8:    seg = 8'b0000_0000;4'd9:    seg = 8'b0001_0000;default : seg = 8'b0100_0000;endcaseendend
endmodule

5.音乐播放

module freq_select
(input   wire 		clk,input   wire		rst_n,output  reg 		status, //蜂鸣器1/0output  reg [2:0]	spec_flag//音符);parameter NOTE_NUM=6'd50;  //50个音符
//中
parameter   DO  	= 20'd95600		;//1
parameter   RE  	= 20'd83150		;//2
parameter   MI  	= 20'd75850		;//3
parameter   FA  	= 20'd71600		;//4
parameter   SO  	= 20'd63750		;//5
parameter   LA    = 20'd56800		;//6
parameter   XI    = 20'd50600		;//7
//高
parameter   HDO  	= 16'd47750		;//1
parameter   HRE  	= 16'd42250		;//2
parameter   HMI  	= 16'd37900		;//3
parameter   HFA  	= 16'd37550		;//4
parameter   HSO  	= 16'd31850		;//5
parameter   HLA   = 16'd28400		;//6
parameter   HXI   = 16'd25400		;//7
//低
parameter   LDO  	= 20'd190800	;//1
parameter   LRE  	= 20'd170050	;//2
parameter   LMI  	= 20'd151500	;//3
parameter   LFA  	= 20'd143250	;//4
parameter   LSO  	= 20'd127550	;//5
parameter   LLA    = 20'd113600	;//6
parameter   LXI    = 20'd101200	;//7reg [25:0] 	inte_cnt;  		//300ms,间隔
reg [19:0] 	note_cnt;		//音符持续时间计时
reg [5:0] 	spec_cnt;		//音谱个数计数
reg [19:0] 	spec_data;		//音符频率
reg [25:0] 	continue_time;	//持续时间
reg [27:0] 	blank_time; 		//空白时间 wire[18:0] 	duty_data;		//占空比数据
wire 			end_note; 		//音符结束时间
wire 			end_spectrum;	//音谱结束时间//音符之间间隔时间计数
always@(posedge clk,negedge rst_n)beginif(!rst_n)inte_cnt<=26'b0;else if(inte_cnt==continue_time+blank_time)inte_cnt<=26'b0;else begininte_cnt<=inte_cnt+1'b1;end
end//单个音符频率计数
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginnote_cnt <= 20'd0;//20end else if(end_note)beginnote_cnt <= 20'd0;end else beginnote_cnt <= note_cnt + 1'd1;end 
end//音符数计时
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginspec_cnt <= 6'd0;end else if(end_spectrum)beginspec_cnt <= 6'd0;end else if(inte_cnt == continue_time+blank_time)beginspec_cnt <= spec_cnt + 1'd1;end else beginspec_cnt <= spec_cnt;end 
end always@(posedge clk or negedge rst_n)begincase(spec_cnt)6'd0:	continue_time<=26'd10_000_000;//你爱我6'd1:	continue_time<=26'd_000_000;6'd2:	continue_time<=26'd10_000_000;						6'd3:	continue_time<=26'd20_000_000;6'd4:	continue_time<=26'd10_000_000;//我爱你蜜雪					6'd5:	continue_time<=26'd10_000_000;					6'd6:	continue_time<=26'd20_000_000;					6'd7:	continue_time<=26'd10_000_000;6'd8:	continue_time<=26'd10_000_000;6'd9:	continue_time<=26'd10_000_000;//冰城甜蜜				6'd10:continue_time<=26'd15_000_000;6'd11:continue_time<=26'd10_000_000;6'd12:continue_time<=26'd9_000_000;6'd13:continue_time<=26'd25_000_000;//蜜6'd14:continue_time<=26'd10_000_000;//你爱我6'd15:continue_time<=26'd10_000_000;6'd16:continue_time<=26'd10_000_000;6'd17:continue_time<=26'd20_000_000;6'd18:continue_time<=26'd10_000_000;//我爱你蜜雪6'd19:continue_time<=26'd10_000_000;6'd20:continue_time<=26'd20_000_000;6'd21:continue_time<=26'd10_000_000;6'd22:continue_time<=26'd10_000_000;6'd23:continue_time<=26'd10_000_000;//冰城甜蜜6'd24:continue_time<=26'd15_000_000;6'd25:continue_time<=26'd10_000_000;6'd26:continue_time<=26'd9_000_000;6'd27:continue_time<=26'd25_000_000;//蜜6'd28:continue_time<=26'd20_000_000;//你爱6'd29:continue_time<=26'd20_000_000;6'd30:continue_time<=26'd20_000_000;//我呀6'd31:continue_time<=26'd10_000_000;6'd32:continue_time<=26'd10_000_000;6'd33:continue_time<=26'd20_000_000;//我爱6'd34:continue_time<=26'd10_000_000;6'd35:continue_time<=26'd10_000_000;6'd36:continue_time<=26'd50_000_000;//你6'd37:continue_time<=26'd10_000_000;//你爱我6'd38:continue_time<=26'd10_000_000;6'd39:continue_time<=26'd10_000_000;						6'd40:continue_time<=26'd20_000_000;6'd41:continue_time<=26'd10_000_000;//我爱你蜜雪					6'd42:continue_time<=26'd10_000_000;					6'd43:continue_time<=26'd20_000_000;					6'd44:continue_time<=26'd10_000_000;6'd45:continue_time<=26'd10_000_000;6'd46:continue_time<=26'd10_000_000;//冰城甜蜜				6'd47:continue_time<=26'd25_000_000;6'd48:continue_time<=26'd10_000_000;6'd49:continue_time<=26'd9_000_000;6'd50:continue_time<=26'd25_000_000;//蜜default:	continue_time<=26'd24_000_000;endcase
end
//空白时间
always@(spec_cnt)begincase(spec_cnt)6'd0:	blank_time<=26'd2_000_000;//你爱我6'd1:	blank_time<=26'd2_000_000;6'd2:	blank_time<=26'd2_000_000;						6'd3:	blank_time<=26'd5_000_000;6'd4:	blank_time<=26'd2_000_000;	//我爱你蜜雪					6'd5:	blank_time<=26'd2_000_000;					6'd6:	blank_time<=26'd5_000_000;					6'd7:	blank_time<=26'd2_000_000;6'd8:	blank_time<=26'd2_000_000;	6'd9:	blank_time<=26'd2_000_000;	//冰城甜蜜					6'd10:blank_time<=26'd5_000_000;6'd11:blank_time<=26'd2_000_000;6'd12:blank_time<=26'd2_000_000;6'd13:blank_time<=26'd5_000_000;//蜜6'd14:blank_time<=26'd2_000_000;//你爱我6'd15:blank_time<=26'd2_000_000;6'd16:blank_time<=26'd2_000_000;6'd17:blank_time<=26'd2_000_000;6'd18:blank_time<=26'd2_000_000;//我爱你蜜雪6'd19:blank_time<=26'd2_000_000;6'd20:blank_time<=26'd5_000_000;6'd21:blank_time<=26'd2_000_000;6'd22:blank_time<=26'd2_000_000;6'd23:blank_time<=26'd2_000_000;//冰城甜蜜6'd24:blank_time<=26'd5_000_000;6'd25:blank_time<=26'd2_000_000;6'd26:blank_time<=26'd2_000_000;6'd27:blank_time<=26'd5_000_000;//蜜6'd28:blank_time<=26'd2_000_000;//你爱6'd29:blank_time<=26'd5_000_000;6'd30:blank_time<=26'd2_000_000;//我呀6'd31:blank_time<=26'd2_000_000;6'd32:blank_time<=26'd5_000_000;6'd33:blank_time<=26'd2_000_000;//我爱6'd34:blank_time<=26'd2_000_000;6'd35:blank_time<=26'd5_000_000;6'd36:blank_time<=26'd10_000_000;//你6'd37:blank_time<=26'd2_000_000;//你爱我6'd38:blank_time<=26'd2_000_000;6'd49:blank_time<=26'd2_000_000;						6'd40:blank_time<=26'd5_000_000;6'd41:blank_time<=26'd2_000_000;	//我爱你蜜雪					6'd42:blank_time<=26'd2_000_000;					6'd43:blank_time<=26'd5_000_000;					6'd44:blank_time<=26'd2_000_000;6'd45:blank_time<=26'd2_000_000;	6'd46:blank_time<=26'd2_000_000;	//冰城甜蜜					6'd47:blank_time<=26'd5_000_000;6'd48:blank_time<=26'd2_000_000;6'd49:blank_time<=26'd2_000_000;6'd50:blank_time<=26'd5_000_000;//蜜default:blank_time<=26'd1_000_000;endcase
end
always@(posedge clk,negedge rst_n)beginif(!rst_n)spec_data<=DO;elsecase(spec_cnt)6'd0:	spec_data <= MI;//你爱我6'd1:	spec_data <= SO;6'd2:	spec_data <= SO;						6'd3:	spec_data <= LA;6'd4:	spec_data <= SO;	//我爱你蜜雪				6'd5:	spec_data <= MI;					6'd6:	spec_data <= DO;					6'd7:	spec_data <= DO;6'd8:	spec_data <= RE;6'd9:	spec_data <= MI;	//冰城甜蜜				6'd10:spec_data <= MI;6'd11:spec_data <= RE;6'd12:spec_data <= DO;6'd13:spec_data <= RE;  //蜜6'd14:spec_data <= MI;  //你爱我6'd15:spec_data <= SO;6'd16:spec_data <= SO;6'd17:spec_data <= LA;6'd18:spec_data <= SO;  //我爱你蜜雪	6'd19:spec_data <= MI;6'd20:spec_data <= DO;6'd21:spec_data <= DO;6'd22:spec_data <= RE;6'd23:spec_data <= MI;  //冰城甜蜜6'd24:spec_data <= MI;6'd25:spec_data <= RE;6'd26:spec_data <= RE;6'd27:spec_data <= DO;  //蜜6'd28:spec_data <= FA;  //你爱6'd29:spec_data <= FA;6'd30:spec_data <= FA;  //我呀6'd31:spec_data <= LA;6'd32:spec_data <= LA;6'd33:spec_data <= SO;  //我爱6'd34:spec_data <= SO;6'd35:spec_data <= MI;6'd36:spec_data <= RE;  //你6'd37:spec_data <= MI;  //你爱我6'd38:spec_data <= SO;6'd39:spec_data <= SO;6'd40:spec_data <= LA;6'd41:spec_data <= SO;  //我爱你蜜雪	6'd42:spec_data <= MI;6'd43:spec_data <= DO;6'd44:spec_data <= DO;6'd45:spec_data <= RE;6'd46:spec_data <= MI;  //冰城甜蜜6'd47:spec_data <= MI;6'd48:spec_data <= RE;6'd49:spec_data <= RE;6'd50:spec_data <= DO;  //蜜default:spec_data <= DO;endcase
end
//当前音符spec_flag
always@(posedge clk,negedge rst_n)beginif(!rst_n)spec_flag<=3'd0;elsecase(spec_data)DO:spec_flag<=3'd1;RE:spec_flag<=3'd2;MI:spec_flag<=3'd3;FA:spec_flag<=3'd4;SO:spec_flag<=3'd5;LA:spec_flag<=3'd6;XI:spec_flag<=3'd7;default:spec_flag<=3'd0;endcase
endassign duty_data = spec_data >> 4;assign end_note = note_cnt== spec_data; //spec_dara对音谱计数
assign end_spectrum = spec_cnt == NOTE_NUM && inte_cnt == continue_time;//pwm信号产生模块
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginstatus <= 1'b0;end else	status <= (note_cnt >= duty_data) ? 1'b1 : 1'b0; 
end         endmodule

6.蜂鸣器

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) beginif(!rst_n) begincnt_time_music <= 28'd0;endelse if(cnt_time_music < MAX_TIME_MUSIC) begincnt_time_music <= cnt_time_music + 28'd1;endelse cnt_time_music <= cnt_time_music;
end//蜂鸣器输出
always @(posedge clk or negedge rst_n) beginif(!rst_n) begincnt_time <= 0;beep <= 1;flag_beep_time_out <= 1;endelse if(!status && cnt_time_music < MAX_TIME_MUSIC) beginbeep <= 0;endelse if(status && cnt_time_music < MAX_TIME_MUSIC) beginbeep <= 1;endelse if(flag && flag_beep_time_out) begin //开始鸣叫cnt_time <= MAX_TIME;flag_beep_time_out <= 0;endelse if(cnt_time >=1 && !flag_beep_time_out) begincnt_time <= cnt_time -24'd1;beep <= 0;endelse if(cnt_time == 0) begin//计时结束beep <= 1;flag_beep_time_out <= 1;endelse begincnt_time <= cnt_time ;beep <= beep;flag_beep_time_out <= flag_beep_time_out;end
endendmodule

7.顶层模块

module automatic_machine_top(input    wire             clk       ,   //时钟 50Minput    wire             rst_n     ,   //复位input    wire    [2:0]    key       ,   //按键output    wire             beep     ,   //蜂鸣器output    wire    [3:0]    led      ,   //售货机状态灯效output    wire    [5:0]    sel      ,   //数码管位选output 	  wire    [7:0]    seg      ,   //数码管段选output    wire    [6:0]    lan_led      //音乐播放灯效);wire            status;         //音乐播放驱使蜂鸣器标志
wire    [2:0]   key_flag;       //按键消抖完成标志
wire    [2:0]   key_value;      //按键消抖完成后的按键值
wire    [4:0]   led_value;      //售货机驱使led模块效果的值
wire    [6:0]   price_put;      //售货机输出到数码管的投币值
wire    [6:0]   price_need;     //售货机输出到数码管的商品价格
wire    [6:0]   price_out;      //售货机输出到数码管的退款
wire    [2:0]   spec_flag;      //音乐模块输出的音符,用于音乐灯效//数码管位选模块
sel_drive inst_sel_drive(
.clk            (clk)           ,
.rst_n          (rst_n)         ,
.price_put      (price_put)     ,      
.price_need     (price_need)    ,     
.price_out      (price_out)     ,  
.sel            (sel)
);//数码管段选模块
seg_drive inst_seg_drive(
.clk            (clk)           ,	
.rst_n          (rst_n)         ,.price_put      (price_put)     ,      
.price_need     (price_need)    ,     
.price_out      (price_out)     ,   
.sel            (sel)           ,          
.seg            (seg));//售货机模块
machine_drive inst_machine_drive(
.clk        (clk)               ,
.rst_n      (rst_n)             ,
.key        ({key_value[2] && key_flag[2], key_value[1] && key_flag[1], key_value[0] && key_flag[0] }),.led_value  (led_value)         ,
.price_put  (price_put)         ,
.price_need (price_need)        ,
.price_out  (price_out)			 
);//led模块
led_drive inst_led(
.clk        (clk)               ,
.rst_n      (rst_n)             ,
.value      (led_value)         ,.led        (led)
);//音乐模块
freq_select inst_freq_select
(
.clk        (clk   )            ,
.rst_n      (rst_n )            ,.status     (status)            , 
.spec_flag  (spec_flag)
);//音乐灯效模块
lanterns inst_lanterns(
.clk        (clk   )            ,
.rst_n      (rst_n )            ,
.spec_flag  (spec_flag)         ,.lan_led    (lan_led)
);//蜂鸣器
beep_drive inst_beep_drive(
.clk        (clk)               ,
.rst_n      (rst_n)             ,
.flag       ((key_value[2] && key_flag[2]) || ( key_value[1] && key_flag[1]) || (key_value[0] && key_flag[0])),    
.status     (status)            ,
.beep       (beep)
);//按键消抖
key_debounce inst_key_debounce_key0(
.clk        (clk)               ,
.rst_n      (rst_n)             ,
.key        (key[0])            ,.flag       (key_flag[0])       ,
.key_value  (key_value[0])
);key_debounce inst_key_debounce_key1(
.clk        (clk)               ,
.rst_n      (rst_n)             ,
.key        (key[1])            ,.flag       (key_flag[1])       ,
.key_value  (key_value[1])
);key_debounce inst_key_debounce_key2(
.clk        (clk)               ,
.rst_n      (rst_n)             ,
.key        (key[2])            ,.flag       (key_flag[2])       ,
.key_value  (key_value[2])
);endmodule

七、仿真

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/63979.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动售卖系统开发系列——人脸识别自动售卖机二代ChingTom

大纲&#xff1a; 售卖机二代ChingTom的简介 售卖机二代ChingTom的方案介绍 #系统整体组成 #软件平台 #硬件平台 售卖机二代ChingTom的实现过程 #业务逻辑介绍 #软件流程图 #源码 售卖机二代ChingTom的技术难点解析 #售卖机二代ChingTom的简介 自动售卖机ChingTom是基于人脸…

无人售货机如何更智能?

行业现状 随着互联网经济渗透生活&#xff0c;无人零售行业的业务发展变得更加多样化。各类零售功能的自助售货机如饮料售货机、自助榨汁机、自助咖啡机、自助售酒机、盒饭售货机遍布城市大街小巷。新冠疫情之后&#xff0c;更是大量涌现口罩自动售货机、自助售药机等医药无人零…

医日健自助售药机

产品概述 医日健智能自助售药机整合了信息化管理技术 、远程监控管理技术 、自动化技术、人脸识别技术等多种先进技术 &#xff0c;结合药品零售的特点 &#xff0c;通过在医院、诊所、药店、便利店、社区等场所部署药品自助售药机 &#xff0c;为用户提供自选购药服务&#x…

医院买药也能自助? 揭秘24小时营业的AI售药机

疫情期间&#xff0c;你是否会期待&#xff0c;医院的人工取药窗口也能实现“无接触”&#xff1f;是否希望在突发状况时&#xff0c;可以避免等待&#xff0c;第一时间就能买到急需药品&#xff1f;现在&#xff0c;药品 AI 售卖机的出现&#xff0c;让这一切问题都得到了解决…

python自动售货机

说明 分享python实现自动售货一个小作业 主要功能 1.查询商品列表 2.购买商品 输入2进行购买商品,输入商品id和数量&#xff0c;可以选择不同商品&#xff0c;最后进行结账操作。 3.订单查询 可以有两种查询方式,全部查询和按时间条件查询 具体操作如下: 全部查询&#x…

程序员的新出路:维护老项目?

1 张大胖刚进入公司&#xff0c;遇到了一个神奇的同事&#xff1a;何小痩。 别人工作都很忙&#xff0c; 何小痩工作似乎特别轻松&#xff0c;从来不加班&#xff0c;到点儿就回家。 张大胖向别人一打听&#xff0c;原来何小痩一直在维护一个老项目&#xff0c;维护了5年了。 …

为什么说程序员唯一出路是变成超级个体?

先来看一篇昨天AI新智能的报道&#xff0c; Midjourney 是 AI 绘画工具头部公司&#xff0c; 每年1亿美金的营收&#xff0c; 已经累计1000多万用户&#xff0c; 这么伟大的公司&#xff0c;仅仅只有11人。 Amazing! 你会震惊&#xff1a;真是家神奇的公司。 在 ChatGPT 新时代…

数据可视化①:dashboard展示大学生就业现状

大学生就业是和我们息息相关的话题&#xff0c;每一位大学生都关注着&#xff0c;我们常常在网络上看到有关大学生就业的话题&#xff0c;比如毕业季的一些讨论。在大一的创新创业课中&#xff0c;我们也了解到自己所学的专业和以后如何就业&#xff0c;往哪方面就业。但我们了…

基于数据挖掘的大学生智慧就业双向推荐系统

目 录 摘 要 I Abstract II 1 引言 1 1.1选题背景及目的意义 1 1.1.1选题背景 1 1.1.2目的及意义 1 1.2研究现状 2 1.3研究主要内容及结构 3 2 相关理论和开发工具 4 2.1 数据挖掘简述 4 2.2 相关数据挖掘算法概述 4 2.2.1关联规则 4 2.2.2 聚类算法 5 2.2.3 分类算法 5 2.3 文…

python项目之基于大数据分析算法的大学生就业系统

目录 一、使用技术及功能模块 二、具体操作及界面展示 &#xff08;一&#xff09;普通用户 &#xff08;二&#xff09;系统管理员 三、各个模块的具体代码实现 系统仅供学习用&#xff01; 一、使用技术及功能模块 采用python语言和django的web框架&#xff0c;使用B/S模…

数据可视化④:大学生就业可视化呈现

大学生就业是和我们息息相关的话题&#xff0c;每一位大学生都关注着&#xff0c;我们常常在网络上看到有关大学生就业的话题&#xff0c;比如毕业季的一些讨论。在大一的创新创业课中&#xff0c;我们也了解到自己所学的专业和以后如何就业&#xff0c;往哪方面就业。但我们了…

「2023大学生就业报告 」出炉,应届生都去了哪些行业?

2023年的应届毕业生人数再创新高&#xff0c;达到1158万人&#xff0c;是不是开始担忧他们的就业了&#xff1f;别急&#xff0c;最近Boss直聘发布的一组数据&#xff0c;会让这样的担忧有所缓解。 期望薪资有所下降 和增长明显的毕业人数相反的是&#xff0c;这一届大专、本…

基于网络爬虫的大学生就业数据分析与预测模型研究

&#x1f525;作者主页&#xff1a;疯狂行者&#x1f525; &#x1f496;✌java领域优质创作者,专注于Java技术领域技术交流✌&#x1f496; &#x1f496;文末获取源码&#x1f496; 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1…

《 2021大学生就业分析报告 》

2021年&#xff0c;我国高校毕业生将突破900万人&#xff0c;创历史新高&#xff0c;毕业生求职就业状况备受各界瞩目。 智联招聘发起2021大学生就业力调研&#xff0c;聚焦就业去向、就业期待、求职心态、求职进展等方面&#xff0c;从学历、毕业院校、专业等维度&#xff0c;…

如何做好商务合同翻译,需要注意这三点!

众所周知&#xff0c;商务合同属于庄重文体&#xff0c;用词极其考察&#xff0c;具有特定性和严肃的风格。那么&#xff0c;如何做好商务合同翻译&#xff0c;在进行商务合同的英语翻译项目中&#xff0c;需要注意什么? 首先、用词精准。合同语言是法律语言&#xff0c;它和口…

翻译航空合同需要注意什么

近年来&#xff0c;随着我国航空领域技术的发展&#xff0c;航空翻译也成为一项重要项目。那么&#xff0c;针对航空合同翻译&#xff0c;中译英需要注意什么事项&#xff0c;北京翻译公司哪个比较专业&#xff1f; 我们知道&#xff0c;航空合同翻译的专业性强&#xff0c;又涉…

发票中英文对照

发票中英文对照 英文中文InvoiceType发票类型MachineNumber机器编号InvoiceCode发票代码InvoiceNumber发票号码IssueDate开票日期InvoiceCheckCode校验码BuyerName购方名称BuyerTaxCode购方纳税人识别号BuyerAddressTel购方地址、电话BuyerBankAccount购方开户行及账号SellerN…

进出口英文合同翻译,如何处理效果好

众所周知&#xff0c;进出口英文合同翻译对于企业与客户双方来说都是非常重要的&#xff0c; 翻译进出口英文合同&#xff0c;需要处理好各项内容的规定以及双方的权利和义务。那么&#xff0c;进出口英文合同翻译&#xff0c;如何处理效果比较好&#xff1f; 据了解&#xff0…

英文外贸合同翻译,涉外合同如何翻译效果好?

我们知道&#xff0c;涉外合同是一种具有法律效力的对外文书&#xff0c;对签约当事人都有约束力&#xff0c;因此&#xff0c;正确无误的翻译至关重要。那么&#xff0c;针对英文外贸合同翻译&#xff0c;涉外合同如何翻译效果好&#xff1f; 据了解&#xff0c;合同翻译具有固…

【文献研究】国际班轮航运的合作博弈:The coopetition game in international liner shipping

背景&#xff1a;本人在整理资料时翻找出来的以前做的研究自己写的总结&#xff0c;2017年发布在《Maritime Policy & Management》期刊的一篇关于国际班轮航运合作博弈的英文文献&#xff0c;本人本着学习的目的就文献的重点内容进行了浅层次的解读&#xff0c;就自己的理…