基于FPGA的可乐自动贩卖机的实现

任务要求

在这里插入图片描述

任务拆分

首先是要划分不同的状态,不投币,投了0.5元,投了1元,投了1.5元,投了2元,投了2.5元,投了三元。状态的输入有两个,一个是1元,一个0.5元。输出有三个,一个是给可乐不找零,不给可乐找零,还有led根据不同的输出,实现不同的功能。最后还有延迟的要求,需要按键按下之后,10秒不操作就归零(可乐机吃钱事件)。

verilog代码

module cola_ma_top
#(
	parameter cnt_20_ms =  'd999_999,
    parameter cnt_0_5s =   'd24_999_999,
	parameter cnt_1s =   'd49_999_999
)
(
    input clk,
    input rst_n,
    input key1,//代表5毛
	input key2,//代表1元
    output reg [3:0] led,
	output reg [1:0] out_1 //10表示出水,01表示出找零
);
	
	parameter IDLE   = 'b0000001;
	parameter mo_0_5 = 'b0000010;    	
	parameter mo_1_0 = 'b0000100; 
	parameter mo_1_5 = 'b0001000;    	
	parameter mo_2_0 = 'b0010000; 	
	parameter LED_water1 = 'b0100000; //单向流水状态    	
	parameter LED_water2 = 'b1000000; //双向流水状态	
	reg [6:0]state;
	
	wire key1_temp  ;
	wire key2_temp;//按键消抖后的输出值	
	wire [3:0]led1;//单向流水的led灯
	wire [3:0]led2;//双向流水的led灯
	reg [27:0] cnt0;
	reg work_water;//一个使能信号
	reg rst;
	reg cnt_20_flag;//10s的信号
	//reg filter_en_temp;
	//wire filter_en;
	reg cnt_en;
	reg en_key1_temp;
	reg en_key2_temp;
	wire en_key1;
	wire en_key2;
	
	//状态转移
	always@(posedge clk or negedge rst_n)
		if(!rst_n || cnt_20_flag)
		//if(!rst_n )		
			state <= IDLE;
		else case(state)
		IDLE: //if(key1_temp)
		      if(key1_temp)
				state <= mo_0_5;
			  //else if(key2_temp)
			  else if(key2_temp)
				state <= mo_1_0;	
			  else	
				state <= IDLE;
		mo_0_5: if(key1_temp)
				    state <= mo_1_0;
			    else if(key2_temp)
				    state <= mo_1_5;	
			    else	
				    state <= mo_0_5;	
		mo_1_0: if(key1_temp)
				  state <= mo_1_5;
			   else if(key2_temp)
				  state <= mo_2_0;	
			   else	
				  state <= mo_1_0;
		mo_1_5: if(key1_temp)
					state <= mo_2_0;
				else if(key2_temp)
					state <= LED_water1;	
			    else	
					state <= mo_1_5; 
		mo_2_0:  if(key1_temp)
					state <= LED_water1;
			    else if(key2_temp)
					state <= LED_water2;	
			    else	
				    state <= mo_2_0;
					
		LED_water1:  if(key1_temp) 
			      		state <= mo_0_5;
			        else if(key2_temp)
			      		state <= mo_1_0;	
			        else	
					    state <= LED_water1;		
		LED_water2: if(key1_temp) 
			      		state <= mo_0_5;
			        else if(key2_temp)
			      		state <= mo_0_5;	
			        else	
					    state <= LED_water2;							
        default: state <= IDLE;
        endcase
  
 	always@(posedge clk or negedge rst_n)
		if(!rst_n)
			led <= 4'd0;
		else 
		case(state)
			IDLE: led <= 4'b0000;
			mo_0_5: led <= 4'b0001;//投入五毛
			mo_1_0: led <= 4'b0011;//投入1元
			mo_1_5: led <= 4'b0111;//投入1.5元
			mo_2_0: led <= 4'b1111;//投入2元
			LED_water1: led <= led1;
			LED_water2: led <= led2;
			default : led <= led;
	    endcase   
    //这边这个outen是为了防止可乐机器一直出可乐
    reg  out_en;
 	always@(posedge clk or negedge rst_n)
		if(!rst_n)
		    begin
			  out_1 <= 2'b00;
			  out_en <= 1'b1;
			end
		else 
		case(state)
			IDLE:   begin
						out_1 <= 2'b00;
				        out_en <= 1'b1;
					end
			mo_0_5: begin
						out_1 <= 2'b00;//投入五毛
				        out_en <= 1'b1;
					end					    
			mo_1_0: begin
						out_1 <= 2'b00;//投入1元
					    out_en <= 1'b1;
					end
			mo_1_5: begin
						out_1 <= 2'b00;//投入1.5元
					    out_en <= 1'b1;
					end						
			mo_2_0: begin
						out_1 <= 2'b00;//投入2元
					    out_en <= 1'b1;
					end							
			LED_water1: if(out_en)begin
							out_1 <= 2'b10;
					        out_en <= 1'b0;
					end	
			LED_water2: if(out_en)begin 
							out_1 <= 2'b01;
					        out_en <= 1'b0;
					end	
			default : begin
							out_1 <= 2'b00;
							out_en <= 1'b1;
					  end
	    endcase  	
    //这个out输出应该只出现一次,否则就会一直出水		
	//在上面我们已经记录了输入是如何影响输入的金额,接下来我们需要可视化显示
    //可视化主要还是led灯
	//可视化输出一共有3种情况,一个是led灯点亮
	//一个是led的单向流水点亮
	//一个是led的双向流水点亮
	//在这里已经有半秒的计数,

	always@(posedge clk or negedge rst_n)
		if(!rst_n)
			cnt0 <= 28'd0;
		else if(rst)
		    cnt0 <= 28'd0; 
        else if( cnt0 == cnt_0_5s) 
			cnt0 <= 28'd0;
		else if( cnt_en )
			cnt0 <= cnt0 + 1'b1;
	
	reg cnt0_flag;
	always@(posedge clk or negedge rst_n)
		if(!rst_n)
			cnt0_flag <= 1'b0;
        else if( cnt0 == cnt_0_5s-1)
			cnt0_flag <= 1'b1;
		else 
			cnt0_flag <= 1'b0 ;
			
	reg [4:0]cnt_20; //0.5s表示计数20次,一共10s
	always@(posedge clk or negedge rst_n)
		if(!rst_n)
			cnt_20 <= 5'd0;
        else if(( cnt_20 == 'd19) || key2_temp || key1_temp)
			cnt_20 <= 5'd0;
		else if( cnt0_flag )
			cnt_20 <= cnt_20 + 1'b1;
	

	always@(posedge clk or negedge rst_n)
		if(!rst_n)
			cnt_20_flag <= 1'b0;
        else if( cnt_20 == 'd18)
			cnt_20_flag <= 1'b1;
		else 
			cnt_20_flag <= 1'b0 ;
			

			
	//这里有两个done信号
	//进入流水状态需要持续1s状态然后结束


	always@(posedge clk or negedge rst_n)
		if(!rst_n) begin
			 cnt_en <= 1'b0;
		end
		else if( key2_temp || key1_temp )
			cnt_en <= 1'b1 ;

	    else 
            cnt_en <= cnt_en;

//按键消抖的模块
	key_fitter 
#(
	.cnt_20_ms(cnt_20_ms)
)
Q_0_5
(
     .clk(clk),
     .rst_n(rst_n),
     .key_in(key1),
	// .en(en_key1),
     .led(key1_temp)
);

	key_fitter 
#(
	.cnt_20_ms(cnt_20_ms)
)
Q_1
(
     .clk(clk),
     .rst_n(rst_n),
     .key_in(key2),
	// .en(en_key2),
     .led(key2_temp)

);	
//LED流水的模块
water_led
#(
	.cnt_0_5s(cnt_0_5s)
)
w0
(
     .clk(clk),
     .rst_n(rst_n),
     .led(led2)
);

water_2_led
#(
	.cnt_0_5s(cnt_0_5s)
)
w111
(
     .clk(clk),
     .rst_n(rst_n),
     .led(led1)
);
endmodule

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值