基于FPGA的地铁自助售票机设计

一、课题要求

1.1 课题设计要求

课题设计的具体要求如下所示:

二、FPGA架构设计

2.1 FPGA顶层设计

根据课题设计需求,设计FPGA的TOP层接口设计如下所示,

顶层接口包括:

1、系统时钟复位;

2、目的地选择,购票数目选择,取消操作控制;

3、纸币,硬币选项;

4、出票使能信号;

5、找余使能信号;

2.2 FPGA内部架构设计

根据课题设计需求,FPGA内部的架构设计如下图所示,

架构内部主要包含:

1、money_count模块:主要功能是统计投入的总金额;

2、sub_control模块:主要功能是计算总的票价,计算找余金额,以及出票使能等控制信号;

3、zhaoling_unit模块:主要功能实现四种货币的找零功能;

4、chupiao模块:主要功能实现不同目的地以及具体的票数的处理任务,完成出票功能。

2.3 money_count模块

投入金额计算功能代码如下:

module money_count ( 
	input 			i_sys_clk,
	input 			i_sys_rst_n,         //  
	input 			i_zhibi_in,				//投纸币
	input 			i_yingbi_in,			//投硬币
   input 			ci1,ci2,ci5,ci10,  	//1元?、2元?、5元、10元输入?
	input 			pi05,pi1,
   output [7:0]	m_cout,              //总钱数输出
	input 			i_idle_en         	//体统完成一次购票操作之后恢复到起始状态使能;   
   );
 
reg [2:0] q1,q2,q5,q10,q05;
 
assign m_cout = q1 + 2*q2 + 5*q5 + 10*q10 + q05/2;
//1元计数; 
always @ (posedge i_sys_clk or negedge i_sys_rst_n)
begin
	if(~i_sys_rst_n)
		q05 <= 0;
	else if (i_yingbi_in & pi05) 
		q05 <= q05 + 1;
	else if (i_idle_en)
		q05 <= 0;
	else	
		q05 <= q05;
end

//1元计数; 
always @ (posedge i_sys_clk or negedge i_sys_rst_n)
begin
	if(~i_sys_rst_n)
		q1 <= 0;
	else if ((i_zhibi_in & ci1) | (i_yingbi_in & pi1))
		q1 <= q1 + 1;
	else if (i_idle_en)
		q1 <= 0;
	else	
		q1 <= q1;
end
//2元计数; 
always @ (posedge i_sys_clk or negedge i_sys_rst_n)
begin
	if(~i_sys_rst_n)
		q2 <= 0;
	else if (i_zhibi_in & ci2)
		q2<= q2 + 1;
	else if (i_idle_en)
		q2 <= 0;
	else	
		q2 <= q2;
end
//5元计数; 
always @ (posedge i_sys_clk or negedge i_sys_rst_n)
begin
	if(~i_sys_rst_n)
		q5 <= 0;
	else if (i_zhibi_in & ci5)
		q5 <= q5 + 1;
	else if (i_idle_en)
		q5 <= 0;
	else	
		q5 <= q5;
end
//10元计数; 
always @ (posedge i_sys_clk or negedge i_sys_rst_n)
begin
	if(~i_sys_rst_n)
		q10 <= 0;
	else if (i_zhibi_in & ci10)
		q10 <= q10 + 1;
	else if (i_idle_en)
		q10 <= 0;
	else	
		q10 <= q10;
end 
 
endmodule

 2.4 sub_control模块

/***************************************************************/
//完成售票机各种控制信号;
//判断目的地,进而确定票价;	i_select_exit [2:0] == 000 -> 第一个站 5元;
//								i_select_exit [2:0] == 001 -> 第一个站 6元;
//								i_select_exit [2:0] == 010 -> 第一个站 7元;
//								i_select_exit [2:0] == 011 -> 第一个站 8元;
//								i_select_exit [2:0] == 100 -> 第一个站 9元;
/***************************************************************/
module sub_control(
	input 				i_sys_clk,
	input 				i_sys_rst_n,
	
	input [2:0] 		i_select_exit,	//5个出站口,票价5、6、7、8、9元;
	input [7:0]			i_money,			//投入总金额;
	input [2:0] 		i_tiks_num,		//购买票数;
	input 				i_cancel,		//取消本次操作;
	
	output reg  		o_finish,      //购票完成;
	output reg [7:0]  o_money_zy,    //找余;	
	output reg 			o_tiks_out_en  //出票使能;
);
wire [7:0] 	total_money; 			//购票所需总金额;
reg  [7:0]  signal_exit_money; 	//目的地金额;
reg  [1:0]	state;
//不同目的地票价;
always @ (*)
begin
	case (i_select_exit)
		3'b000 : signal_exit_money <= 5;
		3'b001 : signal_exit_money <= 6;
		3'b010 : signal_exit_money <= 7;
		3'b011 : signal_exit_money <= 8;
		3'b100 : signal_exit_money <= 9;
		default : ;
	endcase
end
//总票价计算;

assign total_money  = i_tiks_num * signal_exit_money;

//找余;
always @ (*)
begin
	if(~i_sys_rst_n)
		o_money_zy <= 0;
	else if (i_cancel)
		o_money_zy <= i_money;
	else if (total_money > i_money)
		o_money_zy <= 0;
	else if (total_money < i_money)
		o_money_zy <= i_money - total_money;
	else if (total_money == i_money)
		o_money_zy <= 0;		
end
//出票使能
always @ (posedge i_sys_clk or negedge i_sys_rst_n)
begin
	if(~i_sys_rst_n)
	begin
		o_tiks_out_en  <= 0;
		state 			<= 0;
	end
	else
	begin
		case (state)
		0	: 	begin
					if ((total_money <= i_money) & (total_money != 0) & (i_money != 0))
					begin
						state 			<= 1;
						o_tiks_out_en  <= 1;
					end
					else
						state <= 0;
				end
		1	: 	begin
					state 			<= 0;
					o_tiks_out_en  <= 0;
				end
		default : state <= 0;
		endcase	
	end	
end

//购票完成
always @ (posedge i_sys_clk or negedge i_sys_rst_n)
begin
	if (~i_sys_rst_n)
		o_finish <= 0;
	else if (o_tiks_out_en)
		o_finish <= 1;
	else
		o_finish <= 0;
end

endmodule 

2.5 zhaoling_unit模块

// 找零模块,完成找零功能
module zhaoling_unit (    
	rst_n,
	clk,                    //复?位?高?有?? 时?钟?                    
   money,    					//找?零?钱?数?
   cak1,cak2,cak5,cak10    //找?零?1 2 5 10 元?
);
 
input rst_n;
input clk;                    //
input [7:0] money;
output cak1,cak2,cak5,cak10;
 
wire [3:0] qout;
reg  [2:0] q1,q2,q5,q10;
reg  [3:0] state;
/******************************************************/
always @ (posedge clk or negedge rst_n)
begin
	if (~rst_n)
	begin
		q10 	<= 0;            			
		q5  	<= 0;
		q2  	<= 0;
		q1  	<= 0;	
		state <= 0;
	end
	else
	begin
		case (state)
		0	:	begin
					if (money != 0)
					begin
						q10 	= money / 10;            			 //取整
						q5  	=(money - q10*10)/5;
						q2  	=(money - q5*5 - q10*10)/2;
						q1  	= money - q5*5 - q10*10 - q2*2;
						state <= 1;
					end
					else
						state <= 0;
				end
		1	:	begin
					q10 <= q10 - 1; 
					if (q10 == 0)
					begin
						state <= 2;
						q10   <= 0;
					end
					else
						state <= 1;
				end
		2	:	begin
					q5 <= q5 - 1; 
					if (q5 == 0)
					begin
						q5 	<= 0;
						state <= 3;	 
					end
					else
						state <= 2;
				end
		3	:	begin
					q2 <= q2 - 1; 
					if (q2 == 0)
					begin
						q2 	<= 0; 
						state <= 4;
					end
					else
						state <= 3;
				end
		4	:	begin
					q1 <= q1 - 1; 
					if (q1 == 0)
					begin
						q1 <= 0; 
						state <= 5;
					end
					else
						state <= 4;		
				end
		5	:	begin
					state <= 0;
				end
		default : state <= 0;
		endcase
	end
end

/******************************************************/
assign qout[3] = ((q10 != 0) & (state == 1)) ? 1 : 0;
assign qout[2] = ((q5 != 0) & (state == 2))  ? 1 : 0;
assign qout[1] = ((q2 != 0) & (state == 3))  ? 1 : 0;
assign qout[0] = ((q1 != 0) & (state == 4))  ? 1 : 0;
/******************************************************/
assign cak1 	= qout[0];
assign cak2 	= qout[1];
assign cak5 	= qout[2];
assign cak10 	= qout[3];
/******************************************************/
endmodule

2.6 chupiao模块

/********************************************************************/
//出票模块
//sel = 	000 -> 第1个目的地;
//			001 -> 第2个目的地;
//			010 -> 第3个目的地;
//			011 -> 第4个目的地;
//			100 -> 第5个目的地;
/********************************************************************/

 module chupiao (   rst_n,clk,           //
                    en,                  //使能
                    sel,                 //票类别,5个不同的目的地;
                    count,               //票数
                    co1,co2,co3,co4,co5  //各种目的地的票输出
                 );
 
input rst_n,clk;
input en;                        
input [2:0] sel,count;    		
output co1,co2,co3,co4,co5;
 
reg [4:0] q;
 
reg [2:0] qsel;
reg [3:0] qcount;
 
assign co1 = q[0];
assign co2 = q[1];
assign co3 = q[2];
assign co4 = q[3];
assign co5 = q[4];
 
always @ (negedge rst_n  or posedge clk)
begin
   if(rst_n==0)  
	begin
		q <= 0;
		qsel <= 0;
		qcount <= 0;
	end
   else if(en==1)
   begin
       q <= 0;
       qsel <= sel;
       qcount <= count * 2;
   end
   else
   begin
       if(qsel==0)
       begin
           if(qcount != 0)
           begin
               q[0] = ~q[0];
               qcount <= qcount - 1;
           end
       end
       else if(qsel==1)
       begin
           if(qcount != 0)
           begin
               q[1] = ~q[1];
               qcount <= qcount - 1;
           end
       end
       else if(qsel==2)
       begin
           if(qcount != 0)
           begin
               q[2] = ~q[2];
               qcount <= qcount - 1;
           end
       end
       else if(qsel==3)
       begin
           if(qcount != 0)
           begin
               q[3] <= ~q[3];
               qcount <= qcount - 1;
           end
       end
		  else if(qsel==4)
       begin
           if(qcount != 0)
           begin
               q[4] <= ~q[4];
               qcount <= qcount - 1;
           end
       end
   end
end
 
endmodule

三、模块仿真验证

3.1 money_count功能仿真

通过如下仿真图,可知,分别投入纸币1元、2元、5元、10元一次,硬币0.5元2次,硬币1元1次,总计金额统计为20元,结果正确。

 3.2 zhaoling模块功能仿真

如图所示,找零模块输入55元,根据计算,时序途中cak10信号拉高5个时钟周期,出5张10元,cak5拉高一个时钟周期,出一张5元。时序仿真功能正常。

3.3 sub_control模块仿真

如下图所示,购买两张8元的票,投入总金额40元,计算找余金额为24元,在点击取消之后,找余金额为40元。功能正确。

 3.4 chupiao模块仿真

根据仿真模拟买三张第5个目的地的票,等出票使能拉高之后,co5拉高三个时钟周期。功能正确。

3.5 top层仿真 

        投入2张10元纸币 ,买两张目的地9元的票,找零2元,出两张票。功能正常。

 四、总结

        根据具体的课题要求,由自顶向下的设计思想,完成对该课题的设计。每个模块都单独做了仿真工作,且功能实现正常。

五、附录

工程源码点击下面链接下载即可,内部包含仿真测试文件工程源码。可添加V芯:FD0427交流。

 https://download.youkuaiyun.com/download/FDL_AQ/85299173https://download.youkuaiyun.com/download/FDL_AQ/85299173

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿Q在学FPGA (WX-FD0427)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值