一、课题要求
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交流。