完整word版Verilog HDL语言编写的基于EDA的多功能出租车计费器.docx
《完整word版Verilog HDL语言编写的基于EDA的多功能出租车计费器.docx》由会员分享,可在线阅读,更多相关《完整word版Verilog HDL语言编写的基于EDA的多功能出租车计费器.docx(33页珍藏版)》请在冰豆网上搜索。
完整word版VerilogHDL语言编写的基于EDA的多功能出租车计费器
桂林电子科技大学信息科技学院
《EDA技术及应用》实训报告
学号:
**********
姓名唐超
指导教师:
覃琴
2012年4月19日
实训题目:
出租车计费设计
1系统设计
1.1设计要求
1.1.1设计任务
VerilogHDL是一种硬件描述语言(HDL:
HardwareDiscriptionLanguage),是一种用文本形式来描述数字系统硬件的结构和行为的语言,用它可以表示逻辑电路图、逻辑表达式,还可以表示数字逻辑系统所完成的逻辑功能。
VerilogHDL和VHDL是目前世界上最流行的两种硬件描述语言,都是在20世纪80年代中期开发出来的。
现在,随着系统级FPGA以及片上系统的出现,软硬件协同设计和系统设计变得越来越重要。
传统意义上的硬件设计越来越倾向于与系统设计和软件设计相结合。
随着出租车行业的发展,对出租车计费器的要求也越来越高,用户不仅要求计费器性能稳定计费准确,而且要求在乘坐出租车时,显示起步价、行车里程二部分,由自动计费器自动记录。
安装在与汽车轮相连接的传感器在汽车行进时向自动计费器发送脉冲信号,在一定的公里数内,按起步价计费;超过这一里程后,自动计费器按里程计费;超过一定费用后,则则增加里程费用。
1.1.2性能指标要求
①用EDA实训仪的I/O设备和PLD芯片实现出租车计费器的设计。
②出租车起步开始计程和计费,计程系统按实际公里数计程,计费系统首先显示起步价(如7.0),车行驶2km以内,只收起步价7元。
③出租车行驶超过2km后,按每公里1.6元在7.0元的基础上增加。
④出租车行驶超过10km后(或超过20元路费),每公里加收50%的车费,即车费变为每公里2.4元。
⑤出租车达到目的地后,(用一个按钮)计程和计费数据清零,为下一次计费开始。
1.2设计思路及设计框图
1.2.1设计思路
我的设计思路是,车的状态由传感器传回来当作控制信号,用控制信号来控制计算里程和车费模块,我这里是用脉冲来控制车胎的转速,每过来一个脉冲相当于车辆行走了25米,然后再进行按照里程进行相应的计费,同时车上的数据一起送到动态扫描模块,由片选信号控制哪部分译码模块输出的数据用数码管显示。
当车启动后,计算里程和车费模块就开始计数,起步价为7.00元,并在车行2Km后按1.60元/Km计费,在里程达到10km时,每公里回收50%的车费,车停止和暂停时不计费;然后将里程和车费与万年历一起送到动态显示模块动态显示,最后显示在七段数码管上,然后动态显示的时间间隔为4秒钟。
1.2.2总体设计框图
2各个模块程序的设计
2.1总计程器模块
这个是一个总的模块,它是由主要万年历模块、车载模块和选择显示构成,从而做到数码管动态和手动选择显示年月日、时分秒、车费和车程以及各种状态显示灯。
下面就给大家分模块介绍程序。
2.2车载模块设计
这个模块是由很多小模块组成,共同实现车程和车费及相关状态的显示。
共分为调档模块、计算模块、显示费用模块、紧急情况模块、转向灯模块、载客显示模块。
下面就分模块介绍:
调档模块
这个模块的主要作用是用于调节车速d1、d2是有来选择脉冲的,他能显示00,01,10,11四种状态来选择不同的时间脉冲,在d1、d2等于00时ting=0,表示车子未开动,而其他d1、d2为01.10.11时ting=1,车子开动。
s2,s3是速度状态显示灯,根据不同的来显示不同颜色的灯。
clk是输出脉冲,clkn是输入脉冲。
计算模块
modulejisuan(stop,clk,ting,chefei,lucheng);
inputclk,stop,ting;
outputreg[19:
0]lucheng;
outputreg[19:
0]chefei;
always@(posedgeclk)
begin
if(stop==0)
eginchefei=0;lucheng=0;end
else
begin
if(ting==1)
beginlucheng[7:
4]=lucheng[7:
4]+2;lucheng[3:
0]=lucheng[3:
0]+5;
if(lucheng[3:
0]=='ha)
beginlucheng[3:
0]=0;lucheng[7:
4]=lucheng[7:
4]+1;
if(lucheng[7:
4]=='ha)
beginlucheng[7:
4]=0;lucheng[11:
8]=lucheng[11:
8]+1;
if(lucheng[11:
8]=='ha)
beginlucheng[11:
8]=0;lucheng[15:
12]=lucheng[15:
12]+1;
if(lucheng[15:
12]=='ha)
begin
lucheng[15:
12]=0;lucheng[18:
16]=lucheng[18:
16]+1;
end
end
end
end
end
end
if(lucheng<='h2000)chefei[11:
8]=7;
elseif(lucheng<='h10000)chefei[3:
0]=chefei[3:
0]+4;
elseif(lucheng>'h10000)chefei[3:
0]=chefei[3:
0]+6;
if(chefei[3:
0]>9)
beginchefei[7:
4]=chefei[7:
4]+1;chefei[3:
0]=chefei[3:
0]%'ha;
if(chefei[7:
4]>9)
beginchefei[7:
4]=0;chefei[11:
8]=chefei[11:
8]+1;
if(chefei[11:
8]>9)
beginchefei[11:
8]=0;chefei[15:
12]=chefei[15:
12]+1;
if(chefei[15:
12]>9)
begin
chefei[15:
12]=0;chefei[19:
16]=chefei[19:
16]+1;
end
end
end
end
end
endmodule
这个模块的主要的作用是是用来进行车程和车费的计算与累加,这个模块的程序是整个实训最核心的程序,也是我最满意的模块,它只占内存资源4%,很多人这个模块要占很大的资源。
stop是表示是否载有客人,stop=1表示有客,stop=0表示无客。
ting是车辆是否开动,ting=1表示车辆开动,ting=0表示车子未开动。
clk是表示调档后过来的脉冲。
当一个脉冲过来时车,车的车程加25m,当车程在2000时,车费始终未起步价700,当车程大于2000m小于10000m时一个脉冲过来就加4,(一公里1.6元,则25米要4分钱),当车程大于10000m时一个脉冲过来就加6,(一公里2.4元,则25米要6分钱)。
当无客时(stop=0)时车程和车费都清零。
显示费用模块
这个模块的主要作用是用来切换显示车程和车费。
当xk=1时选择手动显示,则k2有效,k2=1时显示的是车费,k2=0时显示的是车程,当xk=0是是自动显示,每一个脉冲过来时,车程和车费相互切换。
我为了区分车费和车程,我在数码管的上车费显示前面用cf,车程显示前面用cc。
载客模块
modulezaike(stop,youke,wuke);
inputstop;
outputregyouke,wuke;
always
begin
if(stop)
beginyouke=1;wuke=0;end
else
beginyouke=0;wuke=1;end
end
endmodule
这个模块的主要作用是用来显示车辆是否载客,当zaike=1时,说明车上已有乘客,则youke=1;wuke=0。
当zaike=1时,说明车上没有乘客,则youke=0;wuke=1。
紧急事件模块
modulejinji(clk,tf,tfd1,tfd2,tfd3,xiang);
inputclk,tf;
outputregtfd1,tfd2,tfd3,xiang;
reg[24:
0]qs,q;
always@(posedgeclk)
begin
if(tf==0)
begintfd1=0;tfd2=0;tfd3=0;xiang=0;end
else
begin
if(qs>=1000000-1)
qs=0;
elseqs=qs+1;
if(qs<500000-1)
begintfd1=0;tfd2=0;tfd3=0;xiang=0;end
else
begintfd1=1;tfd2=1;tfd3=1;xiang=1;end
end
end
endmodule
这个模块的主要作用是当车辆出现紧急情况是车辆,车上的会发出警报。
当tf==0时车辆无反应,当tf==1就给个状态显示灯和蜂鸣器一个0.01秒的脉冲。
转向灯模块
这个模块的主要作用是显示车辆行走时车辆的转向情况,当车辆左转,给左转向灯(zuod)一个0.1秒的脉冲,当车辆右转,给左转向灯(youd)一个0.1秒的脉冲。
2.3万年历模块
这是一个万年历模块,方便在车上看时间,它主要用来产生时间并显示时间,以及显示白昼的状态,它是由校时、时分秒、年月日、选择显示和夜灯模块。
下面就简单介绍各模块。
校时模块
modulejiaoshi(k,jr,jy,jn,jm,jf,js,j1,j2,j3);
inputk,j1,j2,j3;
outputregjm,jf,js,jr,jy,jn;
always
begin
if(k==1){jm,jf,js}={j1,j2,j3};
else{jr,jy,jn}={j1,j2,j3};
end
endmodule
这个模块的主要作用是用来校时,通过控制k来控制校
准年月日和时分秒。
当k==0时校准年月日,当k==1时校
准时分秒。
时分秒模块年月日模块
选择显示时间模块夜灯模块
由以上各模块共同组成了万年历模块,夜灯的模块的主要作用是当晚上时(19时到第二天7时)给夜灯一个信号,即就是让车顶的广告箱灯亮,白天时则不亮。
选择显示模块的作用是用来切换显示年月日和时分秒。
当xk=1时选择手动显示,则k1有效,k1=1时显示的是时分秒,k2=0时显示的是年月日,当xk=0是是自动显示,每一个脉冲过来时,年月日和时分秒相互切换。
2.4选择显示与分频模块
选择模块
modulexuanzhe(k1,k2,x1,x2,x,xk,clkn2);
inputk1,k2,xk,clkn2;
input[31:
0]x1,x2;
outputreg[31:
0]x;
always
begin
if(xk==1)
begin
if({k2,k1}==0^{k2,k1}==3)
x=x1;
elsex=x2;
end
else
begin
if(clkn2==0)
x=x1;
elsex=x2;
end
end
endmodule
这个模块的主要作用是用来切换显示时间与车费、车程。
8s分频16s分频
这两个分别是8s、16s模块,分频的占空比是2/1,分频出来的信号是分别用来给选择的显示费用、选择显示时间和选择模块的脉冲,从而来控制他们4s切换显示一次。
3调试过程
要完成一个程序最重要的一部分便是调试部分,有时一个程序的各模块都想好了,且大致的程序都写好的,但也并不一定能代表成功,往往做一个项目调试一个程序要占到编写一个程序大部分时间。
所以不可避免的也出现了很多问题,由于这个程序的所有部分都是自己一个字母敲打而成,在调试中出现了很多问题,由于自己为了简化程序,尽量少利用资源来完成实训,这个程序在调试时出现的最大的问题就是车费和车程从16进制转10进制的过程遇到了一定的问题,最终自己在调试了几个小时候还是完成了调试,在调试过程还遇到了如年不能进位,动态显示不能实现,程序出现管脚过多等一系列问题。
由于是第一接触做实际的项目,所以没什么经验,在调试过程中总有一些细节问题不能很快察觉。
自己根据试验箱上的效果来调试程序,把程序做到了最好。
4功能测试
4.1测试仪器与设备
EDA实训箱一台
4.2性能指标测试
我这个程序字实训箱上运行都实现了预想效果,此次是自己完全动手实践写成的程序,当然也有我的很多特点。
其一我只用了三个拨把开关就能实现控制车程、车费、年月日、时分秒四个数据的动态与手动显示,以及切换校时的三个按钮。
其次就是我利用所学知识尽量少用乘除法,把计算模块所耗资源减到了4%。
还用我的程序增加了很多功能,如汽车转向,调档,显示是否有客,紧急情况显示,车顶广告箱会根据白昼自动亮灭。
试验箱上的S0和S1用来控制车速,S2用来控制显示是否有客人,S2往上拨表示有客人。
S5用来控制是否手动显示,S5往上拨表示手动显示,负责为4S一切换的动态显示。
S6和S7用来手动控制分别显示车程、车费、时分秒、年月日,当手动显示到年月日是可用K8、K9、K10来校时年月日,当手动显示到时分秒是可用K8、K9、K10来校时时分秒。
S8是紧急情况控制,s8往上拨,表示有紧急情况,蜂鸣器响同时有三个LED黄灯亮。
S9是控制右转,S10控制左转。
S15用来时钟的清零端,当s15往上拨时时钟清零。
5实训心得体会
这次实训是我第一次通过自己的能力将EDA知识运用到实际中,从中受益匪浅,激发的学习兴趣,同时也培养了我思考能力和创新能力,为我今后的实践创新提供了很好的铺垫作用。
我选的实训题目是出租车计费器,虽然在此之前听老师大致讲解过车租车计费器的设计方案,但自己真正设计时,在一开始还是有点摸不着头脑,于是根据实训里的每一个要求,通过查找资料,,再综合实际情况,有了一个总体的设计框架。
设计一个良好的EDA程序,不仅要求符合题意,同时也应将尽量少的占用系统的资源,在初步编写的程序中,所占的资源比较大,通过自己一步步调试,修改了很多语句,最终能顺利地将系统资源降低到29%,特别是计费和计程模块,我从占系统资源150%降低到4%。
通过这一点,让我们明白了,想要得到一个优异的程序,必须善于发现问题改正问题,同时要有一颗持之以恒的心。
虽然在实训中遇到了一些我们不能完成的问题,但也能在问题中提高很多专业知识,尤其是课堂上自己还没掌握的知识点,通过本次实验加深了理解,当然也离不开老师的悉心教导。
程序的调试是让我收获最多的,在调试时,可以锻炼自发现问题和解决问题的能力。
我一定会在大学以后的时间里继续努力学习EDA相关方面的知识和进行一些实际的项目,为自己在以后在电子大赛做好准备。
6参考文献
【1】曹昕燕、周凤臣、聂春燕,EDA技术实验与课程设计【M】,清华大学出版社
【2】刘欲晓、方强、黄宛宁,EDA技术与VHDL电路开发应用实践【M】,电子工业出版社。
【3】基于EDA技术出租车计费器的设计(样本)XX文库
附录
附录1:
仿真波形图(部分模块)
车辆计费部分仿真波形图
24进制的仿真波形图
60进制的仿真波形图
夜灯模块显示仿真波形图
附录2:
程序清单
一秒分频器
moduleclk_1s(clk,cnt);
inputclk;
outputregcnt;
reg[24:
0]qs;
always@(posedgeclk)
begin
if(qs==20000000-1)
qs=0;
elseqs=qs+1;
if(qs<10000000-1)
cnt=0;
else
cnt=1;
end
endmodule
八秒分频器
modulefenpin1(clk,clkn);
inputclk;
outputregclkn;
reg[28:
0]qs;
always@(posedgeclk)
begin
if(qs>=160000000-1)
qs=0;
else
qs=qs+1;
if(qs<=80000000-1)
clkn=1;
else
clkn=0;
end
endmodule
十六秒分频器
modulefenpin2(clk,clkn2);
inputclk;
outputregclkn2;
reg[32:
0]qs;
always@(posedgeclk)
begin
if(qs>=320000000-1)
qs=0;
else
qs=qs+1;
if(qs<160000000-1)
clkn2=1;
else
clkn2=0;
end
endmodule
时分秒模块
moduleclk_1s(clk,cnt);
inputclk;
outputregcnt;
reg[24:
0]qs;
always@(posedgeclk)
begin
if(qs==20000000-1)
qs=0;
elseqs=qs+1;
if(qs<10000000-1)
cnt=0;
else
cnt=1;
end
endmodule
modulecnt24(clr,clk,cnt,q,j);
inputclr,clk,j;
outputregcnt;
outputreg[7:
0]q;
always@(posedgeclk^jornegedgeclr)
begin
if(~clr)
q=0;
elseif(q=='h23)
beginq=0;cnt=1;end
else
begincnt=0;q=q+1;
if(q[3:
0]=='ha)
beginq[7:
4]=q[7:
4]+1;q[3:
0]=0;end
end
end
endmodule
modulecnt60(clr,clk,cnt,q,j);
inputclr,clk,j;
outputregcnt;
outputreg[7:
0]q;
always@(posedgeclk^jornegedgeclr)
begin
if(~clr)
q=0;
elseif(q=='h59)
beginq=0;cnt=1;end
else
begincnt=0;q=q+1;
if(q[3:
0]=='ha)
beginq[7:
4]=q[7:
4]+1;q[3:
0]=0;end
end
end
endmodule
modulesfm(clk,clr,jm,jf,js,qm,qf,qs,cout);
inputclk,clr,jm,jf,js;
output[7:
0]qm,qf,qs;
outputcout;
wireq1,q2,q3;
clk_1s(clk,q1);
cnt60(clr,q1,q2,qm,jm);
cnt60(clr,q2,q3,qf,jf);
cnt24(clr,q3,cout,qs,js);
endmodule
年月日模块
modulenyr(clk,clrn,jr,jy,jn,qn,qy,qr);
inputclrn,clk,jn,jy,jr;
output[15:
0]qn;
output[7:
0]qy,qr;
reg[15:
0]qn;
reg[7:
0]qy,qr;
regclkn,clky;
reg[7:
0]date;
regclkn1,clkn2,clkn3;
initialbeginclkn1=1;clkn2=1;clkn3=1;end
initialbeginqn='h2000;qy=1;qr=1;end
always@(posedge(clk^jr)ornegedgeclrn)
begin
if(~clrn)qr=1;
elsebegin
if(qr==date)qr=1;
elseqr=qr+1;
if(qr[3:
0]=='ha)begin
qr[3:
0]=0;qr[7:
4]=qr[7:
4]+1;end
if(qr==date)clky=1;
elseclky=0;
end
end
always@(posedgeclky^jyornegedgeclrn)
begin
if(~clrn)qy=1;
elsebegin
if(qy=='h12)qy=1;
elseqy=qy+1;
if(qy[3:
0]=='ha)
begin
qy[3:
0]=0;
qy[7:
4]=qy[7:
4]+1;
end
if(qy=='h12)clkn=1;
elseclkn=0;
end
end
always
begin
case(qy)
'h01:
date='h31;
'h02:
beginif(qn%4==0)date='h29;elsedate='h28;end
'h03:
date='h31;
'h04:
date='h30;
'h05:
date='h31;
'h06:
date='h30;
'h07:
date='h31;
'h08:
date='h31;
'h09:
date='h30;
'h10:
date='h31;
'h11:
date='h30;
'h12:
date='h31;
default:
date='h30;
endcase
end
always@(posedgeclkn^jnornegedgeclrn)
begin
if(~clrn)qn[3:
0]=0;
elsebeginif(qn[3:
0]==9)qn[3:
0]=0;
elseqn[3:
0]=qn[3:
0]+1;
if(qn[3:
0]==9)clkn1=0;
elseclkn1=1;
end
end
always@(posedgeclkn1ornegedgeclrn)
begin
if(~clrn)qn[7:
4]=0;
elsebeginif(qn[7:
0]==9)qn[7:
4]=0;
elseqn[7:
4]=qn[7:
4]+1;
if(qn[7:
4]==9)clkn2=0;
elseclkn2=1;
end
end
always@(posed