文档库 最新最全的文档下载
当前位置:文档库 › FPGA实验报告

FPGA实验报告

FPGA实验报告
FPGA实验报告

大连理工大学城市学院FPGA实验报告

学院:电子与自动化学院

专业:电子信息工程

学生:张凌飞

指导教师:王颖

完成日期: 2013年4月13日

大连理工大学城市学院实验报告

基于Verilog语言的出租车计费器

第一章引言

1.1 出租车计费器介绍

随着出租车行业的发展,对出租车计费器的要求也越来越高。最近几年出租车行业发展迅速,在全国有几千家出租车公司。因此出租车计费器市场是庞大的。而出租车计费器成为不可缺少的一部分。

信息社会的现代电子产品,性能越来越高,复杂度越来越大,更新步伐也越来越快。实现这种进步的主要原因就是微电子技术和电子技术的发展。而电子技术的发展后者的核心就是电子设计自动化技术。EDA 是指以计算机为工作平台,融合了应用电子技术、计算机技术、智能化技术的最新成果而开发出的电子CAD通用软件包,它根据硬件描述语言HDL完成的设计文件,自动完成逻辑编译、化简、分割、综合、优化、布局布线及仿真,直至完成对于特定目标芯片的适配编译、逻辑映射和编程下载等工作。没有EDA技术的支持,想要完成超大规模集成电路的设计制造是不可想象的;反过来,生产制造技术的不断进步又必将对EDA技术提出新的要求。本文采用verilog语言来设计实现出租车计费系统,经过ModelSim和Quartus仿真将其实例化。如果将该设计再结合到实际应用中,那么,只需改变设计中计费要求,就可以应用到出租车上。另外,如果再任意输入该出租车计价器的计费标准,那么,它的适用范围可能就更广泛了。

第二章出租车计费器设计原理

2.1出租车计费器设计要求

(1)行程3公里内(包括3公里),且等待累计时间2分钟内(包括2分钟),起步费为6.0元;

(2)3公里外(不包括3公里)以每公里1.0元,等待累计时间2分钟外(不包括2分钟)以每分钟以1.0元计费。

(3)能显示行驶公里数、等待累计时间和最后的总费用。

本计费器的显示范围为0~99元,计价分辨率为1元;计程器显示范围为0~99公里,分辨率为1公里;计时器的显示范围是分钟的显示范围是0—99,辨率为1分钟。秒的显示范围是0—59。分辨率为1秒。

2.2出租车计费器工作原理

出租车的一般计费过程为:出租车载客后,启动计费器,整个系统开始运行,里程计数器和时间计数器从0开始计数,费用计数器从6开始计算。再根据行驶里程或停止等待的时间按以上的标准计费。若在行驶状态,则计程器开始加计数,当路程超过三公里后,计费器以每公里1元累加。若出租车停止等待状态,则计时器开始加计数,当时间超过两分钟后,计费器以每分钟1元累加。出租车到达目的地停止后,停止计费器,显示总费用。

根据出租车计费器的工作过程,本系统采用分层次、分模块的方式设计,其本系统组成框图如下所示。其中行驶路程计数模块、等待时间计数模块和计费模块,用来统计路程、等待时间和总费用,控制模块是用来控制计费模块,数码管显示模块用来显示行驶的公里数、等待累计时间和总费用等信息。系统框图如下所示:

第三章出租车计费器模块的仿真

3.1分频模块:

此模块的功能是对总的时钟进行分频,分出的频率是让计数器用的,因为总的时钟是50M的。设计该模块的时候用了一个32位的计数器,当计数器计到25_000000的时候产生时钟

3.2数码管的分频模块:

此模块的功能是对总的时钟进行分频,分出的频率是让数码管用的,因为总的时钟是50M的。设计该模块的时候用了一个32位的计数器,当计数器计到50_000的时候产生时钟。

3.3计程模块:

此模块的功能是计算出租车行驶的路程。在出租车启动并行驶的过程中(即复位/启动信号reset为1,行驶/停止信号start为1),当时钟clk 是上升沿的时候,系统即对路程计数器distance的里程计数器进行加计数,当路程超过三公里时,系统将输出标志正脉冲distance_enable。

3.4计时模块:

此模块用于计算停车等待的时间。在出租车行进中,如果车辆停止等待,计数器则在1Hz信号clk的上升沿进行加计数,每60次产生进位脉冲使分钟计数器位进行加计数,当累计等待时间超过2(不包括2分钟)分钟时,输出标志time_enable正脉冲信号。

3.5控制模块:

控制模块用于为计费模块提供时钟,当start高电平的时候选择公里计费,输出的时钟信号为distance_enable,当start低电平的时候选择时间计费,输出的时钟信号为time_enable。

3.6 计费模块:

费用计数器模块用于出租车启动后,根据行驶路程和等待时间计算费用。当出租车停车时,时钟select_clk用于将费用计数器复位为起步价6.0元;当车处于行驶状态且满3公里时,select_clk信号选择distans_enable,此后路程每满1公里,费用计数器加1元;当出租车处于停止等待状态且时钟满2分钟时,select_clk信号选择time_enable信号,时间每满1分钟,费用计数器加1元。

第四章出租车计费器程序清单

4.1分频模块:

module div(clk_50M,clk,reset);// 端口的定义

input clk_50M,reset;// 总的时钟是50M

output clk;//分频后输的时钟

reg clk;

reg [31:0] count;//32位的计数器

always@ (posedge clk_50M or negedge reset)//异步复位

begin

if(!reset)

begin

clk<='d0;

count=32'd0;

end

else if(count==32'd25_000000)// 判断计时器记到了25_000000吗

begin

count<=32'd0;//计到25_000000计数器清零

clk<=~clk;//输出的时钟取反

end//end begin

else count<=count+1'd1;// 没计到25_000000计数器加一

end//end always

endmodule // 结束分频模块

4.2数码管的分频模块:

module div1(clk_50M,clk1,reset);// 端口的定义

input clk_50M,reset;// 总的时钟是50M

output clk1;//分频后输的时钟

reg clk1;

reg [31:0] count;//32位的计数器

always@ (posedge clk_50M or negedge reset)//异步复位

begin

if(!reset)

begin

clk1<='d0;

count=32'd0;

end

else if(count==32'd50_000)// 判断计时器记到了50_000吗 begin

count<=32'd0;//计到50_000计数器清零

clk1<=~clk1;//输出的时钟取反

end//end begin

else count<=count+1'd1;// 没计到50_000计数器加一

end//end always

endmodule // 结束分频模块

4.3计程模块:

module

distancemokuai(clk,start,reset,distance,distance_enable);

//端口的定义input clk,start,reset;

output [7:0] distance;// 输出的公里

reg [7:0] distance;

output distance_enable;// 控制计费的公里信号

reg distance_enable;

always@(posedge clk or negedge reset)//异步复位

begin

if(!reset)//低电平复位

begin

distance<=8'd0;

end

else if(start)// start 高电平有效

begin

if(distance[3:0]==9)//判断distance的低四位计到了9没有

begin

distance[3:0]<=4'd0;//计到9清零

if(distance[7:4]==9) //判断distance的高四位计到了9没有

distance[7:4]<=4'd0;//计到9清零

else distance[7:4]<= distance[7:4]+1'd1;

// distance的高四位没有计到9的时候加一

end

else distance[3:0]<=distance[3:0]+1'd1;

// distance的低四位没有计到9的时候加一

end//end start

end//end always

//*产生distance_enable信号*//

always@(posedge clk or negedge reset)

begin

if(!reset)

begin

distance_enable<=1'd0;//复位

end

else

if(distance>8'd2)// 大于公里三的时候

begin

distance_enable<=1'd1;//输出distance_enable信号

end

end//end always

endmodule//结束计程模块

4.4计时模块:

module timemokuai(clk,reset,start,s,m,time_enable);// 端口的定义

input clk,reset,start;

output [7:0] s;//输出的秒

output [7:0] m;//输出的分

output time_enable;//输出的控制计费的信号

reg [7:0] s;

reg [7:0] m;

wire time_enable;

always@(posedge clk or negedge reset)//异步复位

begin

if(!reset)//低电平有效

begin //复位

s<=8'd0;

m<=8'd0;

end

else if(!start)//start 信号低电平有效

begin

if(s[3:0]==9)// 秒的低四位是9

begin

s[3:0]<=4'd0;//清零

if(s[7:4]==5) // 秒的高四位是5

begin

s[7:4]<=4'd0; //清零

if(m[3:0]==9) // 分的低四位是9

begin

m[3:0]<=4'd0; //清零

if(m[7:4]==9) // 分的高四位是9

m[7:4]<=4'd0; //清零

else m[7:4]<=m[7:4]+1'd1; // 分的高四位不是9加一end

else m[3:0]<=m[3:0]+1'd1; //分的低四位不是9加一

end

else s[7:4]<=s[7:4]+1'd1; // 秒的高四位不是5加一

end

else s[3:0]<=s[3:0]+1'd1; //秒的低四位不是9加一

end//end always

end

assign time_enable=((m[7:0]>8'd2)&&(s[7:0]==8'd0))?1'd1:1'd0;

//产生time_enable信号。

endmodule//结束计时模块

4.5控制模块:

module control(start,distance_enable,time_enable,select_clk); input start,distance_enable,time_enable;

output select_clk;//输出选择的时钟信号

wire select_clk;

//*当start高电平的时候选择公里计费,输出的时钟信号为distance_enable,当start低电平的时候选择时间计费,输出的时钟信号为time_enable*//

assign select_clk=start?distance_enable:time_enable; endmodule//结束控制模块

4.6 计费模块:

module feemokuai(select_clk,reset,fee,clk);

input select_clk,reset,clk;

output[7:0] fee; //输出的费用

reg [7:0] fee;

always@(posedge clk or negedge reset)//异步复位

begin

if(!reset)//低电平有效

begin

fee<=8’d6;//起步为六元

end

else if(select_clk==1’d1)

begin

if(fee[3:0]==4'd9)//费用的低四位是不是计到了9

begin

fee[3:0]<=4'd0;//计到9清零

if(fee[7:4]==4'd9)// 费用的高四位是不是计到了9 fee[7:4]<=4'd0; //计到9清零

else fee[7:4]<=fee[7:4]+1'd1;// 费用的高四位没有计到9加1 end

else fee[3:0]<=fee[3:0]+1'd1;// 费用的低四位没有计到9加1 end//end begin

end//end always

endmodule //结束计费模块

4.7数码管显示模块:

module scan_led(clk1,dig,seg,distance,s,m,fee);

input clk1;

input[7:0] distance,fee;//输入的公里,费用。

input[7:0] s;//输入的秒

input[7:0] m; // 输入的分。

output[7:0] dig; // 译码结果

output[7:0] seg; // 数码管的选择。

reg [7:0] r_dig;// 译码结果输出寄存器

reg [7:0] r_seg; //数码管的选择寄存器。

reg [3:0] disp_dat;

reg[3:0] a;

assign dig=r_dig;

assign seg=r_seg;

always@(posedge clk1)

begin

a<=a+1'd1; //数码管的选择

end

always@(posedge clk1)

begin

case(a)

4'd0: disp_dat=distance[7:4];//公里的高四位用第一个数码管显示。4'd1: disp_dat=distance[3:0];//公里的低四位用第二个数码管显示。4'd2: disp_dat=m[7:4]; //时间分的高四位用第三个数码管显示。

4'd3: disp_dat=m[3:0]; //时间分的低四位用第四个数码管显示

4'd4: disp_dat=s[7:4]; //时间秒的高四位用第五个数码管显示。

4'd5: disp_dat=s[3:0]; //时间秒的低四位用第六个数码管显示。

4'd6: disp_dat=fee[7:4]; //费用的高四位用第七个数码管显示。4'd7: disp_dat=fee[3:0]; //费用的低四位用第八个数码管显示。

default: disp_dat=4'b1010;

endcase

case(a)

4'd0:r_dig=8'b01111111; // 选择第一个数码管4'd1:r_dig=8'b10111111; // 选择第二个数码管4'd2:r_dig=8'b11011111; // 选择第三个数码管4'd3:r_dig=8'b11101111; // 选择第四个数码管4'd4:r_dig=8'b11110111; // 选择第五个数码管4'd5:r_dig=8'b11111011; // 选择第六个数码管4'd6:r_dig=8'b11111101; // 选择第七个数码管4'd7:r_dig=8'b11111110; // 选择第八个数码管default:r_dig=8'b11111111;

endcase

end

// *译码结果*//

always@(disp_dat)

begin

case(disp_dat)

4'h0: r_seg=8'hc0;// 显示0

4'h1: r_seg=8'hf9;// 显示1

4'h2: r_seg=8'ha4;// 显示2

4'h3: r_seg=8'hb0;// 显示3

4'h4: r_seg=8'h99;// 显示4

4'h5: r_seg=8'h92;// 显示5

4'h6: r_seg=8'h82;// 显示6

4'h7: r_seg=8'hf8;// 显示7

4'h8: r_seg=8'h80;// 显示8

4'h9: r_seg=8'h90;// 显示9

default: r_seg=8'hbf;

endcase

end

endmodule//结束译码模块

4.8顶层模块

module taximeter(clk_50M,reset,start,seg,dig);//端口的定义input clk_50M,reset,start;//总的时钟信号,复位信号,开始信号output[7:0] seg,dig;//数码管的输出

wire [7:0]distance;//公里

wire [7:0] s;//秒

wire [7:0] m;//分

wire[7:0] fee;//费用

wire clk; //计数时钟

wire distance_enable;//公里控制费用的信号

wire time_enable; //时间控制费用的信号

wire select_clk; //控制信号

wire clk1; //数码管显示的时钟

//*模块的调用*//

div u0(.clk_50M(clk_50M),.clk(clk),.reset(reset));

//调用计数分频模块

div1 u1(.clk_50M(clk_50M),.clk1(clk1),.reset(reset));

//调用数码管显示分频模块distancemokuai

u2(.clk(clk),.start(start),.reset(reset),.distance(distance),. distance_enable(distance_enable)); //调用计程模块

timemokuai

u4(.clk(clk),.reset(reset),.start(start),.s(s),.m(m),.time_ena

ble(time_enable)); //调用计时模块

control

u3(.start(start),.distance_enable(distance_enable),.time_enabl

e(time_enable),.select_clk(select_clk));

//调用控制模块

feemokuai

u5(.reset(reset),.fee(fee),.select_clk(select_clk),.clk(clk)); //调用计费模块

scan_led

U6(.clk1(clk1),.dig(dig),.seg(seg),.distance(distance),.s(s),.

m(m),.fee(fee)); //调用数码管显示模块

相关文档