数电实习报告中国石油大学.docx
《数电实习报告中国石油大学.docx》由会员分享,可在线阅读,更多相关《数电实习报告中国石油大学.docx(15页珍藏版)》请在冰豆网上搜索。
数电实习报告中国石油大学
2011—2012学年第二学期
《数字电子技术课程设计》设计报告
专业班级自动化10—4
姓名孙勇
学号10051421
开课系室电工电子学教学中心
设计日期2012年7月10日--15日
设计题目:
基于FPGA的出租车计费器
一、设计任务及要求:
本设计要求设计一个基于FPGA的出租车计费器,其具体要求如下:
1、能够实现计费的功能
费用是按行驶的里程进行计算,设出租车的起价为6元,当里程小于3km时,按起价计算费用;当里程大于3km时每km按1元计费。
2、能够实现显示的功能
1) 左边四个数码管显示里程:
用四位数字显示,显示方式为“XXXX”,单位为km。
里程范围为0~9999km,里程分辨率为1km。
2) 右边四个数码管显示费用:
用四位数字显示,显示方式为“XXXX”,单价为元。
计价范围为0~9999元,费用分辨率为1元。
二、设计原理与方案:
(一)、顶层设计方案:
原理框图:
(包括原理框图及其工作原理说明等内容)。
工作原理:
实际设计共4个模块,分别为显示学号模块、分频模块、里程费用计量电路模块、动态扫描显示模块。
详细功能如下:
1、显示学号模块:
该模块设计了一个3位二进制计数器,三个输出端sel0、sel1、sel2表示这八位数从000~111循环。
每个二进制数分别对应3-8译码器的一个输出端Y,从而点亮此输出端对应的数码管。
由于视觉暂留效果,当频率为1khz时,貌似8个数码管同时点亮,从而显示出学号。
2、分频模块:
此模块的功能是对输入的1000Hz进行分频,分出的频率供里程费用计量电路模块使用,每来1000个脉冲输出一个脉冲。
3、里程费用计量电路模块:
里程每1km记一次数,最大可计9999km。
同时按行驶里程收费,起步费为6元,并在车行3公里后按1元/km,最大可计9999元。
4、动态扫描显示模块:
通过动态扫描显示车费和里程数。
将十进制数转化为四位十进制数,(如将9999转化为四个9)分别在8个数码管上显示出来。
(二)、显示学号电路设计方案
首先设计一个3位二进制计数器,有三个输出端sel0、sel1、sel2,表示000~111八位数的循环。
每个二进制数分别对应3-8译码器的一个输出端Y,从而点亮此输出端对应的数码管。
上电后由于视觉暂留效果,当频率为1khz时,貌似8个数码管同时点亮,从而显示出学号。
这一部分与下一部分里程费用计量模块的衔接非常重要,因为学号的显示的停止意味着里程费用计量模块开始运行。
而这两部分共用的是同样的八个数码管,并且同时受s1牵制。
所以就需要把显示学号模块与显示里程计费模块综合到一个模块中,通过判断语句选择性执行。
(3)里程费用计量电路电路设计方案
该模块由两个子模块构成:
第一个小模块是里程计费模块,包含控制按钮S1、S2、S3。
上电后,当按下按钮S1时,此电路模块开始运行。
出租车开始计量里程和相应费用。
起步价为6元,3千米以内为6元;当超过3千米后,按1元/千米计量。
当按下S2,里程计费停止计时,数码管显示相应数值。
当按下S3,里程计费清零。
第二个小模块是小数点控制计数模块。
.里程和计费分别从0开始,一直可计数到9999.9。
当里程不满1Km时,按整数部分计费(例如当里程显示3.3km时,费用为6元)。
(四)、译码、动态扫描显示电路设计方案:
该模块也由两个子模块构成:
第一个小模块将十进制里程和费用数值转换为四位十进制数(因而在定义里程的费用的寄存器位数时是[15:
0]而不是[13:
0]),分别用八个数码管显示。
第二个小模块控制信号输入时,每个数码管分别应显示的数值。
三、电路设计、仿真与实现:
(一)、顶层设计实现:
1、顶层原理图文件;
2、顶层设计功能仿真波形。
(2)、显示学号模块
1、基于Verilog的设计源文件:
modulecnt_8(clk,k);
inputclk;
output[2:
0]k;
reg[2:
0]k;
always@(posedgeclk)
begin
if(k<7)
k=k+1;
else
k=4'b000;
end
Endmodule
2、功能仿真波形
(二)、分频模块
1、基于Verilog的设计源文件
modulefenpin(clk,q,r);
inputclk;
outputq,r;
reg[9:
0]q;
regr;
always@(posedgeclk)
begin
if(q<10'b1111101000)
begin
q=q+10'b0000000001;r=0;
end
if(q==10'b1111101000)
begin
q=10'b0000000000;r=1;
end
end
Endmodule
2、功能仿真波形。
(三)、里程和费用计量电路电路的设计实现:
1、基于Verilog的设计源文件及功能仿真波形
模块一(里程费用计量)
moduletaxi(clk,s1,s2,s3,dis,mon);
inputclk;
output[15:
0]dis;
output[15:
0]mon;
reg[15:
0]dis;
reg[15:
0]mon;
inputs1,s2,s3;
reg[1:
0]k;
initial
begin
k=0;
dis=16'b0001_0000_0000_0101;
mon=16'b0001_0100_0010_0001;
end
always@(negedges1ornegedges2ornegedges3)
if(!
s3)k=2'b11;
elseif(!
s2)k=2'b10;
elseif(!
s1)k=2'b01;
elsek=0;
always@(posedgeclk)
begin
if(k==3)
begin
dis<=0;
end
elseif(k==1)
begin
if(dis==16'b0001000000000101)
dis=0;
elseif(dis[3:
0]==9)
begin
dis[3:
0]<=4'd0;
if(dis[7:
4]==9)
begin
dis[7:
4]<=4'd0;
if(dis[11:
8]==9)
begin
dis[11:
8]<=4'd0;
if(dis[15:
12]==9)dis[15:
12]<=4'd0;
elsedis[15:
12]<=dis[15:
12]+1'd1;
end
elsedis[11:
8]<=dis[11:
8]+1'd1;
end
elsedis[7:
4]<=dis[7:
4]+1'd1;
end
elsedis[3:
0]<=dis[3:
0]+1'd1;
end
elseif(k==2)dis=dis;
elsedis=16'b0001000000000101;
end
always@(posedgeclk)
begin
if(k==3)
begin
mon<=0;
end
elseif(k==1)
begin
if(mon==16'b0001010000100001)
mon=0;
elseif(dis>=16'b0000000000110000)
begin
if(mon[3:
0]==9)
begin
mon[3:
0]<=4'd0;
if(mon[7:
4]==9)
begin
mon[7:
4]<=4'd0;
if(mon[11:
8]==9)
begin
mon[11:
8]<=4'd0;
if(mon[15:
12]==9)mon[15:
12]<=4'd0;
elsemon[15:
12]<=mon[15:
12]+1'd1;
end
elsemon[11:
8]<=mon[11:
8]+1'd1;
end
elsemon[7:
4]<=mon[7:
4]+1'd1;
end
elsemon[3:
0]<=mon[3:
0]+1'd1;
end
elsemon=16'b0000000001100000;
end
elseif(k==2)mon=mon;
elsemon=16'b0001010000100001;
end
endmodule
模块二(以小数计量出租车里程和费用)
modulexiaoshudian(dis,mon,in,D);
input[15:
0]dis,mon;
input[2:
0]in;
outputD;
regD;
always@(in[2:
0]ormon[15:
0]ordis[15:
0]orD)
begin
if(mon==16'b0001010000100001&&dis==16'b0001000000000101)D=0;
elseif(in==2||in==6)D=1;
elseD=0;
end
endmodule
(四)、译码、动态扫描显示电路的设计实现:
1、基于Verilog的设计源文件及功能仿真波形
模块一(十进制数值转换)
modulelicheng_jifei(dis,mon,c_in,c_out);
input[15:
0]dis,mon;
input[2:
0]c_in;
output[3:
0]c_out;
reg[3:
0]c_out;
always@(c_inorc_out)
begin
case(c_in)
3'b111:
c_out=mon[3:
0];
3'b110:
c_out=mon[7:
4];
3'b101:
c_out=mon[11:
8];
3'b100:
c_out=mon[15:
12];
3'b011:
c_out=dis[3:
0];
3'b010:
c_out=dis[7:
4];
3'b001:
c_out=dis[11:
8];
3'b000:
c_out=dis[15:
12];
endcase
end
Endmodule
模块二(显示数值)
moduleshumaguan(d,out);
input[3:
0]d;
output[6:
0]out;
reg[6:
0]out;
always@(d)
begin
case(d[3:
0])
4'b0000:
out=7'b1111110;
4'b0001:
out=7'b0110000;
4'b0010:
out=7'b1101101;
4'b0011:
out=7'b1111001;
4'b0100:
out=7'b0110011;
4'b0101:
out=7'b1011011;
4'b0110:
out=7'b0011111;
4'b0111:
out=7'b1110000;
4'b1000:
out=7'b1111111;
4'b1001:
out=7'b1110011;
default:
out=7'b0000000;
endcase
end
Endmodule
四、分析与讨论:
经过了为期五天的数字电子技术实习,我学会了很多。
这些天精力几乎全部放在了编程上,有几个晚上甚至在图书馆熬夜到凌晨两点钟,虽然并不是每一份付出都会带来满意的结果,但过程是快乐的。
虽然只有短暂的五天,但我们一起奋斗的日子,我觉得很充实,很开心。
同样,在这几天的实习中我也发现了自己的很多不足,一些问题总是眼高手低,总以为自己很明白这些方面,但真正做起来却没有那么简单。
实习工程中我的程序出现了很多错误。
去调试的时候,发现学号数码管竟然不显示。
然后同学的一句话将我点醒了,学号显示与后面的里程模块是有衔接的。
。
我又将程序拿回来认真的进行修改,然后再点报上进行了一次总体仿真,发现S1的使用就是非常关键的一点。
当按下S1时,学号显示模块就应该在整个运行过程中结束了,即使无论随后按钮S1、S2、S3处于何种状态,都不能再影响到学号显示。
所以我又开始进行修改,查证了一次逻辑后,才发现原来是在赋值时存在逻辑错误,然后将逻辑顺序调整后,又进行过了仿真,这一次就没有问题了。
在编写程序的过程中,我对always语句和initial语句理解上存在错误。
用的时候不知道该用那一个,分不清楚改什么时候用所以在编程过程中出现了一些错误,主要是显示数的不同,如应该显示59,却显示了60。
然后经过同学的讲解我真正搞明白了两种语句的不同,要想真正的掌握Verilog语言,还得自己下功夫认真自学一下。
再一个印象比较深刻的错误就是因为quartus版本不同上电调试时浪费了好多时间。
因为自己电脑上安装的软件是7.2,而试验箱上要求7.0,当我兴冲冲的将前一天晚上编好的程序上电调试时,所有文件都打不开了。
。
。
浪费了时间,浪费了机会,给老师带来了麻烦,对此深表歉意。
。
。
在这几天的实习中不断编程,不断调试,不断修改,虽然很辛苦,但最后我的程序下载到实验板上也实现了,这令我非常高兴。
其实一个人的成功背后有多个人的汗水。
当问题频频出现,自己已经没有信心再继续下去的时候,身边的同学就会站出来鼓励你,帮助你找出无论怎么调试都发现不了的错误,那一刻,心里真的有很多感动。