FPGA项目(二)--基于FPGA的自动贩卖机

该文详细介绍了使用FPGA(基于EP4CE6E22C8N的CycloneIV系列)设计的自动贩卖机控制系统,通过拨码开关选择商品和输入投币金额,数码管显示交易信息,当投币金额不足或多余时,系统会相应提示或找零并伴随蜂鸣器报警。设计中采用了一个二段式状态机来管理交易流程,并且利用数码管显示模块显示货物价格、投币金额和找零金额。
摘要由CSDN通过智能技术生成

        先陈述下本次设计实现的功能:用FPGA实现了自动贩卖机。首先可以通过拨码开关选择货物,货物价格有三种,分别为2元,2.5元,3元,然后还是通过拨码开关,输入投币金额,面额为0.5元,1元,2元。当投币金额小于货物价格时,数码管显示所投金额,当投币金额大于货物价格时,数码显示找零的金额,同时蜂鸣器报警。

        先给张实物图:

         接下来介绍设计的思路。本次开发板是基于EP4CE6E22C8N的Cyclone IV系列的FPGA、(型号)的FLASH芯片和50MHz的晶振,通过对板子的元器件进行控制,从而实现特定功能。拨动开关的管脚配置和电路原图如下:

 

        从图中可以看出,当拨码开关拨上时,管脚电平为1。所以可以根据检测电平变换,来决定货物的价格。 本次代码的接口定义如下:

        

        其中三位宽的chose用于选择货物价格。选择价格的代码如下:

         

         接下来,程序执行的核心是一个二段式状态机。状态机代码如下:

        

         状态机执行流程:首先s0状态是输入投币金额,用三个变量分别保存并且记录输入的金额,最后用一个加法式子算出总的投币金额

        

        s1状态是判断所投金额有没有大于货物价格,如果没有大于货物价格,那么继续回到s0状态,继续进行投币。如果所投金额大于货物价格,那么就执行到s2状态。

        s2状态,主要执行蜂鸣器响的操作,然后在数码管上显示出找零的金额。

         在本模块调用了数码管显示模块,将要显示的数据(货物价格、投币金额/找零金额)显示在数码管上。

         在这个模块,取出要显示数据的各个位。举个例子,要显示的货物价格是25(2.5元),那么首先取出十位数字2,再取出个位数字5。将数字传递给显示模块,接下来的任务就是显示模块显示数据了。

        显示模块的代码:

module seg(
input 				sys_clk,sys_rest,
input	[15:0]		data,
output	reg [3:0]	sel,
output  reg [6:0]	seg_led
);

parameter	CLK_NUM=4'd10;
parameter	MSNUM=14'd5000;
reg	[3:0]	CNT_NUM;
reg			CLK;

reg [12:0]	MSCNT;
reg			MS_flag;
reg [3:0]	num_display;

reg [15:0]	num;
reg [2:0]	sel_num; //选择哪一位数码管被点亮
//wire define
wire   [3:0]              data0    ;        // 个位数
wire   [3:0]              data1    ;        // 十位数
wire   [3:0]              data2    ;        // 百位数
wire   [3:0]              data3    ;        // 千位数


//提取显示数值所对应的十进制数的各个位
assign  data0 = data[3:0];      // 个位数
assign  data1 = data[7:4];    // 十位数
assign  data2 = data[11:8];    // 百位数
assign  data3 = data[15:12];   // 千位数


always @(posedge sys_clk or negedge sys_rest) begin
	if(!sys_rest)
		begin
		CNT_NUM<=4'd0;
		CLK<=1'd1;
		end
	else if(CNT_NUM<=CLK_NUM/2-1'b1)
		begin
		CLK<=~CLK;
		CNT_NUM<=4'd0;
		end
	else
		begin
		CNT_NUM<=CNT_NUM+1;
		CLK<=CLK;
		end
end

always @(posedge CLK or negedge sys_rest) begin
	if(!sys_rest)
		num<=16'd0;
	else 
		begin		    
            num[15:12] <= data3;	//则依次给4位数码管赋值
            num[11:8]  <= data2;
            num[ 7:4]  <= data1;
            num[ 3:0]  <= data0;
		end
end


always @(posedge CLK or negedge sys_rest) begin  //产生1ms脉冲
	if(!sys_rest)
		begin
			MSCNT<=13'd0;
			MS_flag<=1'b0;
		end
	else if(MSCNT==MSNUM-1)
		begin
			MSCNT<=13'd0;
			MS_flag<=1'b1;
		end
	else
		begin
			MSCNT<=MSCNT+1;
			MS_flag<=1'b0;
		end
end


always @(posedge CLK or negedge sys_rest) begin
	if(!sys_rest)
		sel_num<=0;
	else if(MS_flag)
		begin
			if(sel_num<3'd3)
				sel_num<=sel_num+1;
			else
				sel_num<=0;
		end
	else
		sel_num<=sel_num;
end

always @(posedge CLK or negedge sys_rest) begin
	if(!sys_rest)
		sel<=4'b1111;
	else
		begin
			case(sel_num)
				3'd0:	begin
						sel<= 4'b1110;  //显示数码管最低位
						num_display<=num[3:0];
						end
				3'd1:	begin
						sel<= 4'b1101;  //显示数码管第1位
						num_display<=num[7:4];
						end
				3'd2:	begin
						sel<= 4'b1011;  //显示数码管第2位
						num_display<=num[11:8];
						end
				3'd3:	begin
						sel<= 4'b0111;  //显示数码管第3位
						num_display<=num[15:12];
						end
				default	sel<= 4'b1111;
			endcase
		end
end

always @(posedge CLK or negedge sys_rest) begin
	if(!sys_rest)
		seg_led<=7'b100000;
	else
		begin
			case(num_display)
			4'h0 :    seg_led <= 7'b1000000;
            4'h1 :    seg_led <= 7'b1111001;
            4'h2 :    seg_led <= 7'b0100100;
            4'h3 :    seg_led <= 7'b0110000;
            4'h4 :    seg_led <= 7'b0011001;
            4'h5 :    seg_led <= 7'b0010010;
            4'h6 :    seg_led <= 7'b0000010;
            4'h7 :    seg_led <= 7'b1111000;
            4'h8 :    seg_led <= 7'b0000000;
            4'h9 :    seg_led <= 7'b0010000;
			4'd10: 	  seg_led <= 7'b1111111;           //不显示任何字符
            default : seg_led <= 7'b1000000;
        endcase
		end
end

endmodule

         这样就大功告成啦。后续会给出完整工程项目!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值