基于FPGA的出租车计价器设计(Verilog、basys3、含数码管模块、EDA设计与实践课程)

版权声明:本文为博主原创文章,转载请注明作者和出处。


前言

本文章是总结EDA设计与实践课程的成果,设计题目为出租车计价器


以下是本篇文章正文内容

一、系统功能及设计要求

1.系统功能

出租车启动和停驶由司机控制。启动后显示里程,用四位数字显示,精确到1公里;停止后显示金额,四位显示,格式为XXXX,精确到1元。
功能
1、当行程小于基本里程时,显示起步价,基本里程设3公里,起步价设5元。
2、当行程大于基本里程时,每多行一公里,在起步价上加2元;不足一公里按一公里收费。
3、当出租车等待时,由司机按下等候键,每等待一分钟加1元,不足一分钟的按一分钟计算。
4、此处用脉冲信号模拟轮胎的转数,设每计一个脉冲汽车前进100米。

2.设计要求

系统设计一个频率为1Hz的基本脉冲,该脉冲用于等待计时和轮胎转数。
一个该脉冲表征1s;用于计轮胎转数时,计10个记为1公里。用于等待计时时,计60个记为1分钟。
设计拨动开关A 用于控制和表征模拟出租车的钥匙(插入钥匙和拔出钥匙)。
拨动开关B 用于控制和表征模拟客人的上下车行为(预备上车和即将下车)。
拨动开关C 用于控制和表征模拟出租车行驶状态(行驶或等待)。
一个四位七段数码管用于分时分状态表示里程数或总计价。

二、系统设计方案、Verilog源程序与仿真结果分析

本系统采用层次化、模块化的设计方法,设计顺序为自下向上。首先实现系统框图中的各子模块,然后由顶层模块调用各子模块来完成整个系统。

1.计数分频模块div

输入:基准时钟100MHz,频率信号CLK_100M,重置信号reset
输出:1Hz频率时钟信号CLK
module div(
    input clk_100M,
    input reset,
    output reg clk
    );
    
    reg [31:0] count;
    always@(posedge clk_100M , negedge reset)
    begin
        if(!reset)
            begin
                clk<=1'd0;
                count=32'd0;
            end
        else if(count==32'd50_000000)
            begin
                count<=32'd0;
                clk<=!clk;
            end
       else
            count<=count+1'd1;
    end         
endmodule

clk_100M为主频,当reset为1时,div模块工作,此处为了仿真采取六分频,clk_100M触发6个周期,clk输出1个周期。
在这里插入图片描述

2.计程模块distancecount

输入:1HZ频率时钟信号CLK,模块使能信号work,计程开始信号start,计程重置信号reset
输出:16位二进制里程计数值distance,里程使能输出distance_enable
module distanceCount(
    input clk,
    input work,
    input start,
    input reset,
    output reg [15:0] distance,
    output reg distance_enable
    );  
    
    always@(posedge clk or negedge reset)
    begin
            if(!reset)
                begin
                    distance<=16'd0;
                end
            else if(start&&work)
                begin
                    if(distance[3:0]==9)
                        begin
                            distance[3:0]<=4'd0;
                            if(distance[7:4]==9)
                                begin
                                    distance[7:4]<=4'd0;
                                    if(distance[11:8]==9)
                                        begin
                                            distance[11:8]<=4'd0;
                                            if(distance[15:12]==9)
                                                distance[15:12]<=4'd0;
                                            else
                                                distance[15:12]<=distance[15:12]+1'd1;
                                        end        
                                    else    
                                        distance[11:8]<=distance[11:8]+1'd1;
                                end            
                            else
                                distance[7:4]<=distance[7:4]+1'd1;
                        end
                    else
                        distance[3:0]<=distance[3:0]+1'd1;
                end
    end
    //产生distance_enable信号
    always@(posedge clk or negedge reset)
    begin
        if(!reset)
            begin
                distance_enable<=1'd0;
            end
        else
            if(distance>=16'd2)
                begin
                    distance_enable<=1'd1;
                end
    end                                     
endmodule

当reset为1时,distancecount模块工作。当work为0时,车无顾客,不论start为0还是为1,即不论此时车停止还是行驶,distance里程均为0,distance_enable也为0;当work为1时,车有顾客,start为0时车停止,distance里程不增即为0,start为1时车行驶,distance里程增加;当distance大于3公里时,distance_enable为1,代表此时里程增加就要计费。
在这里插入图片描述

3.计时模块timecount

输入:1HZ频率时钟信号CLK,计时开始信号start,计时重置信号reset
输出:8位二进制计时秒输出s,8位二进制计时分输出m,计时使能输出time_enable
module timeCount(
    input clk,
    input reset,
    input start,
    output reg [7:0] s,
    output reg [7:0] m,
    output wire time_enable
    );
    
    always@(posedge clk or negedge reset)
    begin
        if(!reset)
            begin
                s<=8'd0;
                m<=8'd0;
            end
        else if(!start)
            begin
                if(s[3:0]==9)
                    begin
                        s[3:0]<=4'd0;
                        if(s[7:4]==5)
                            begin
                                s[7:4]<=4'd0;
                                if(m[3:0]==9)
                                    begin
                                        m[3:0]<=4'd0;
                                        if(m[7:4]==5)
                                            m[7:4]<=4'd0;
                                        else
                                            m[7:4]<=m[7:4]+1'd1;
                                    end
                                else
                                    m[3:0]<=m[3:0]+1'd1;
                             end
                         else
                            s[7:4]<=s[7:4]+1'd1;
                    end
                else
                    s[3:0]<=s[3:0]+1'd1;
            end
    end
    assign time_enable=((m[7:0]>=8'd1)&&(s[7:0]==8'd0))?1'd1:1'd0;
endmodule

当reset为1时,timecount模块工作。Start为1时,不计算等待时间。当start为0时,计算等待时间。每过一秒,s增加1,当s计到60时清零,m进1,同时time_enable产生一个脉冲,代表一分钟增一次等待费用。
在这里插入图片描述
在这里插入图片描述

4.控制模块control

输入:控制开始信号start,计程使能信号distance_enable,计时使能信号time_enable
输出:选择脉冲信号select_clk
module control(
    input start,
    input distance_enable,
    input time_enable,
    output wire select_clk
    );
    
    assign select_clk=start?distance_enable:time_enable;
endmodule

当start为0时,select_clk的值为time_enable的值;当start为1时,select_clk的值为distance_enable的值。
在这里插入图片描述

5.计费模块fee

输入:计费工作信号work,计费使能信号start,选择脉冲信号select_clk,计费重置信号reset,1HZ频率时钟工作信号CLK
输出:16位二进制费用输出fee
module fee(
    input work,
    input start,
    input select_clk,
    input reset,
    input clk,
    output reg [15:0] fee
    );
    
    reg [3:0]cnt=0;
    always@(posedge clk or negedge reset or negedge work)
        begin
            if(!reset&&!work)
                fee<=16'd5;
            else if(select_clk==1'd1&&start==0&&work==1)
                begin
                    if(fee[3:0]==4'd9)
                        begin
                            fee[3:0]<=4'd0;
                            if(fee[7:4]==4'd9)
                                begin
                                    fee[7:4]<=4'd0;
                                    if(fee[11:8]==4'd9)
                                        begin
                                            fee[11:8]<=4'd0;
                                            if(fee[15:12]==4'd9)
                                                fee[15:12]<=4'd0;
                                            else
                                                fee[15:12]<=fee[15:12]+1'd1;
                                        end
                                    else
                                        fee[11:8]<=fee[11:8]+1'd1;
                                end
                            else 
                                fee[7:4]<=fee[7:4]+1'd1;
                        end
                    else 
                        fee[3:0]<=fee[3:0]+1'd1;
                end
            else if(select_clk==1'd1&&start==1&&work===1)
                begin
                    cnt<=cnt+1;
                    if(cnt==11)
                        begin
                            cnt<=0;
                            repeat(2)
								begin
									if(fee[3:0]==4'd9)
										begin
											fee[3:0]=4'd0;
											if(fee[7:4]==4'd9)
												begin
													fee[7:4]=4'd0;
													if(fee[11:8]==4'd9)
														begin
															fee[11:8]=4'd0;
															if(fee[15:12]==4'd9)
																fee[15:12]=4'd0;
															else
																fee[15:12]=fee[15:12]+1'd1;
														end
													else
														fee[11:8]=fee[11:8]+1'd1;
												end
											else 
												fee[7:4]=fee[7:4]+1'd1;
										end
									else 
										fee[3:0]=fee[3:0]+1'd1;      
								end
                        end
                end
       end
endmodule


当reset为1时,fee模块工作。Select_clk为1代表计费使能。work为0时无顾客,费用一直为起步价5,当work为1时,有顾客开始计价。当start为0时,车停止,代表此时等待计费,每等一分钟,费用加1;当start为1时,车行驶,代表此时行驶计费,每行驶1公里,费用加2。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.数码管显像模块smg_ip_model

输入:1HZ频率时钟工作信号CLK,显像工作信号work,显像使能信号start,显像重置信号reset,16位二进制费用输入fee,16位二进制里程输入dis
输出:4位数码管位选信号sm_wei,8位数码管段选信号sm_duan
module smg_ip_model(
    input clk,
    input work,
    input start,
    input reset,
    input [15:0] fee,
    input [15:0] dis,
    output [3:0] sm_wei,
    output [7:0] sm_duan
    );
    
    //分频
    integer clk_cnt;
    reg clk_400Hz;
    always@(posedge clk, negedge reset)
    begin
        if(!reset)
            begin
                clk_400Hz<=1'd0;
                clk_cnt=32'd0;
            end
        else if(clk_cnt==32'd1000)
            begin
                clk_cnt<=32'b0;
                clk_400Hz<=!clk_400Hz;
            end
        else
            clk_cnt<=clk_cnt+1'd1;
            
    //位控制
    end
    reg [3:0] wei_ctrl = 4'b1110;
    always@(posedge clk_400Hz)
    wei_ctrl<={wei_ctrl[2:0],wei_ctrl[3]};
    
    //段控制
    reg [3:0] duan_ctrl;
    always@(wei_ctrl)
    begin
        if(work)
            case(wei_ctrl) 
            4'b1110:duan_ctrl=dis[3:0];
            4'b1101:duan_ctrl=dis[7:4];
            4'b1011:duan_ctrl=dis[11:8];
            4'b0111:duan_ctrl=dis[15:12];
            default:duan_ctrl=4'hf;
            endcase
        else if(!work)
            case(wei_ctrl) 
            4'b1110:duan_ctrl=fee[3:0];
            4'b1101:duan_ctrl=fee[7:4];
            4'b1011:duan_ctrl=fee[11:8];
            4'b0111:duan_ctrl=fee[15:12];
            default:duan_ctrl=4'hf;
            endcase
    end
    
    //解码
    reg [7:0]duan;
    always@(duan_ctrl)
    case(duan_ctrl)
    4'h0:duan=8'b1100_0000;
    4'h1:duan=8'b1111_1001;
    4'h2:duan=8'b1010_0100;
    4'h3:duan=8'b1011_0000;
    4'h4:duan=8'b1001_1001;
    4'h5:duan=8'b1001_0010;
    4'h6:duan=8'b1000_0010;
    4'h7:duan=8'b1111_1000;
    4'h8:duan=8'b1000_0000;
    4'h9:duan=8'b1001_0000;
    default:duan=8'b1100_0000;
    endcase
    assign sm_wei=wei_ctrl;
    assign sm_duan=duan;
    
endmodule

当reset为1时,smg_ip_model模块工作。sm_wei在e、d、b、7间循环,即是在1110、1101、1011、0111间循环,循环选中数码管。work为1时,数码管显示里程数,dis为7,即为f8,而且显示在e选中的个位数码管上,其他位的数码管均显示0,即为c0。
在这里插入图片描述

7.顶层模块taximeter

输入:100MHZ频率时钟工作信号CLK_100M,模块复位信号reset,模块工作信号start,模块使能信号work
输出:4位数码管位选信号sm_wei,8位数码管段选信号sm_duan
module taximeter(clk_100M, reset,start,sm_wei,sm_duan,work);
    input clk_100M,reset,start,work;
    output [3:0] sm_wei;
    output [7:0] sm_duan;
    wire [15:0]distance;
    wire [7:0] s;
    wire [7:0] m;
    wire [15:0] fee;
    wire clk;
    wire distance_enable;
    wire time_enable;
    wire select_clk;
    reg clk_car;
    reg [31:0] count;
    
    always@(posedge clk , negedge reset)
    begin
        if(!reset)
            begin
                clk_car<=1'd0;
                count=32'd0;
            end
        else if(count==32'd5)
            begin
                count<=32'd0;
                clk_car<=!clk_car;
            end
       else
            count<=count+1'd1;
    end 

    div u0(.clk_100M(clk_100M),.clk(clk),.reset(reset));
    distanceCount u2(.work(work),.clk(clk_car),.start(start),.reset(reset),.distance(distance),.distance_enable(distance_enable));
    timeCount u4(.clk(clk),.reset(reset),.start(start),.s(s),.m(m),  .time_enable(time_enable));
    control u3(.start(start),.distance_enable(distance_enable),.time_enable(time_enable),.select_clk(select_clk));
    fee u5(.work(work),.start(start),.reset(reset),.fee(fee),.select_clk(select_clk),.clk(clk));
    smg_ip_model u6(.work(work),.start(start),.fee(fee),.reset(reset),.clk(clk_100M),.dis(distance),.sm_wei(sm_wei),.sm_duan(sm_duan));
    
endmodule

当reset为1时,taximeter模块工作。work为0时,无顾客,distance里程、fee费用一直为0。work为1时,有顾客,当start为1是,汽车行驶,distance里程加1,费用为起步价5,当distance大于3时,每公里2元。当start为0时,汽车停止行驶,开始等待计费,每等待1分钟,费用加1元,此时distance不变化。最后work为0,顾客下车,distance里程和fee费用都不再变化。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、约束与综合

1.原理图

在这里插入图片描述
在这里插入图片描述

2.引脚配置图

W7,W6,U8,V8,U5,V5,U7,V7:八段数码管显示0-7
W4,V4,U4,U2:四个片选信号
W5:clk时钟
reset:车钥匙,1为启动汽车
start:油门,1汽车行驶,0汽车停止
work:代表顾客,1代表接客,0代表接待结束

在这里插入图片描述

四、系统硬件测试

启动油门,显示起步价5元。
在这里插入图片描述
顾客上车,汽车行驶,里程开始增加。
在这里插入图片描述
在这里插入图片描述
若此时下车,费用为起步价5元。
在这里插入图片描述
行驶至5公里时,价格为9元。
在这里插入图片描述
在这里插入图片描述
当汽车停止行驶,每等待1分钟,价格加1,顾客下车显示价格。
在这里插入图片描述
在这里插入图片描述


总结

以上就是本文章所有内容,详细总结了出租车计价器设计的全过程。

版权声明:本文为博主原创文章,转载请注明作者和出处。

  • 73
    点赞
  • 592
    收藏
    觉得还不错? 一键收藏
  • 52
    评论
评论 52
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值