50--出租车计费器

设计流程图
在这里插入图片描述

/*信号说明:
clk:系统时钟
rst_n:复位(开始)信号;
finish:结束信号
mile_int:里程整数部分,最大为2047,单位km
mile_dec:里程小数部分,逢九进一
tmp_100price:路费的100倍
sel_seg:数码管位选
seg_led:数码管段选
flag_dec:进位信号
div_cnt:分频计数器
dri_clk:分频后的驱动时钟
display_num:显示数字
data 10-6表示里程(1位小数),5-0表示费用(2位小数)
2km内为起步价7元,超过2km收1.8元/km
*/
module taxi(
input clk,
input rst_n,
input finish,
output reg [10:0]mile_int,//计数行驶路程极限为2^11-1+1=2048km
output reg [3:0]mile_dec,
output reg[17:0]tmp_100price,
output reg [10:0]sel_seg,//数码管位选,前5位是路程,后6位是价格,精确到2位小数
output reg [7:0]seg_led//数码管段选
);
parameter MAX_NUM=2'd2;
parameter CLK_DIV=4'd2;
//车速为36km/h
//为使计费精确到两位小数,1个脉冲10s计数100m
//假设系统时钟5MHz
reg [23:0]sec_cnt;//10秒计数,dri_clk下sec_cnt计满5M次为10s
reg flag_dec;
//分频模块
reg [3:0]div_cnt;//分频计数
reg dri_clk;
wire [3:0]data10;//路程千位
wire [3:0]data9;//路程百位
wire [3:0]data8;//路程十位
wire [3:0]data7;//路程个位
wire [3:0]data6;//路程后1位小数

wire [3:0]data5;//价格千元
wire [3:0]data4;//价格百元
wire [3:0]data3;//价格十元
wire [3:0]data2;//价格元
wire [3:0]data1;//价格角
wire [3:0]data0;//价格分
assign data10=mile_int/10'd1000%4'd10;
assign data9=mile_int/10'd100%4'd10;
assign data8=mile_int/4'd10%4'd10;
assign data7=mile_int%4'd10;
assign data6=mile_dec;

assign data5=tmp_100price/17'd100000%4'd10;
assign data4=tmp_100price/15'd10000%4'd10;
assign data3=tmp_100price/10'd1000%4'd10;
assign data2=tmp_100price/10'd100%4'd10;
assign data1=tmp_100price/4'd10%4'd10;
assign data0=tmp_100price%4'd10;

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        div_cnt<=1'b0;
        dri_clk<=1'b0;
    end
    else if(div_cnt==CLK_DIV/2-1)begin
        dri_clk<=~dri_clk;
        div_cnt<=4'd0;
    end
    else begin
        div_cnt<=div_cnt+1'b1;
        dri_clk<=dri_clk;
    end
end

//里程小数部分模块,mile_dec计一次为0.1km,满10进1
always @(posedge dri_clk or negedge rst_n or posedge finish)begin
    if(!rst_n)begin
        sec_cnt<=1'b0;//10s钟计数
        mile_dec<=4'd0;
        flag_dec<=1'b0;
    end
    else if(finish==0)begin
    
    if(sec_cnt==24'd500)begin
        if(mile_dec==4'd9)begin
            sec_cnt<=24'd0;
            mile_dec<=4'd0;
            flag_dec<=1'b1;    			
        end
       
        else begin
            flag_dec<=1'b0;
            sec_cnt<=24'd0;
            mile_dec<=mile_dec+1'b1;	    
        end
    end
    
    else begin
	    flag_dec<=1'b0;
        mile_dec<=mile_dec;
        sec_cnt<=sec_cnt+1'b1;
    end
 end
 
else begin
    sec_cnt<=sec_cnt;
end 

end   
//里程整数部分模块
always @(posedge dri_clk or negedge rst_n)begin
    if(!rst_n)begin
        mile_int<=8'd0;
    end
    else if(flag_dec)begin
       mile_int<=mile_int+1'b1;
    end
    
    else 
        mile_int<=mile_int;     
end
parameter sprice=2'd2;//起步价
//计费模块
//reg[17:0]tmp_price;
always@(posedge dri_clk or negedge rst_n or posedge finish)begin
    if(!rst_n)begin
        tmp_100price<=6'd0;
    end
    else if(finish==0)
        if(mile_int<10'd2)begin
            tmp_100price<=18'd700;
        end
     else tmp_100price<=(mile_int*4'd10-5'd20+mile_dec)*5'd18+18'd700;  
    else tmp_100price<=tmp_100price;    
end

//数码管显示模块
//reg [10:0]sel,//数码管位选,前5位是路程,后6位是价格,精确到2位小数
//reg [7:0]seg_led//数码管段选
reg flag;
reg [3:0]cnt0;//位选计数
reg [13:0]cnt1;
reg [3:0]display_num;
always @(posedge dri_clk or negedge rst_n)begin//控制刷新速度
    if(!rst_n)begin
        cnt1<=14'd0;
        flag<=1'b0;
    end
    else if(cnt1==MAX_NUM-1)begin
        cnt1<=14'd0;
        flag<=1'b1;    
    end
    else begin
        flag<=1'b0;
        cnt1<=cnt1+1'b1;
    end
end

always @(posedge dri_clk or negedge rst_n)begin//控制位选
    if(!rst_n)begin
        cnt0<=4'd0;
        end
    else if(flag)begin
        if(cnt0==4'd10)
            cnt0<=4'd0;
        else cnt0<=cnt0+1'b1;
    end
    else cnt0<=cnt0;
end


always @(posedge clk or negedge rst_n)begin//低电平数码管选通
    if(!rst_n)begin
        sel_seg<=11'b11111111111;
        display_num<=4'd0;
    end
    else begin
        case(cnt0)
        4'd0:begin
            sel_seg<=11'b11111111110;
            display_num<=data0;
            end
        4'd1:begin
            sel_seg<=11'b11111111101;
            display_num<=data1;
            end
        4'd2:begin
            sel_seg<=11'b11111111011;
            display_num<=data2;
            end
        4'd3:begin
            sel_seg<=11'b11111110111;
            display_num<=data3; 
            end   
        4'd4:begin
            sel_seg<=11'b11111101111;
            display_num<=data4;
            end
        4'd5:begin
            sel_seg<=11'b11111011111;
            display_num<=data5;
            end
        4'd6:begin
            sel_seg<=11'b11110111111;
            display_num<=data6;
            end
        4'd7:begin
            sel_seg<=11'b11101111111;
            display_num<=data7;
            end
        4'd8:begin
            sel_seg<=11'b11011111111;
            display_num<=data8;
            end
        4'd9:begin
            sel_seg<=11'b10111111111;
            display_num<=data9;
            end
        4'd10:begin
            sel_seg<=11'b01111111111;
            display_num<=data10;
            end
        default:begin
                sel_seg<=11'b11111111111;
                display_num<=4'd0;
                end
        endcase
    end
end



//数码管显示
always@(posedge dri_clk or negedge rst_n)begin
    if(!rst_n)
    seg_led<=8'd11111111;//数码管段选低电平有效
    else begin
        case(display_num)
        4'd0:begin
            if(cnt0==4'd3||cnt0==4'd8)
            seg_led<=8'b01000000;
            else seg_led<=8'b11000000;
            end
        4'd1:begin           
             if(cnt0==4'd3||cnt0==4'd8) seg_led<=8'b01111001;
             else  seg_led<=8'b11111001;
             end
        4'd2:begin
             if(cnt0==4'd3||cnt0==4'd8)
             seg_led<=8'b00100100;
             else seg_led<=8'b10100100;
             end
        4'd3:begin
             if(cnt0==4'd3||cnt0==4'd8)
             seg_led<=8'b00110000;
             else seg_led<=8'b10110000;
             end   
        4'd4:begin
              if(cnt0==4'd3||cnt0==4'd8)
             seg_led<=8'b00011001;
             else  seg_led<=8'b10011001;
             end
        4'd5:begin
            if(cnt0==4'd3||cnt0==4'd8)
            seg_led<=8'b00010010;   
            else
            seg_led<=8'b10010010; 
            end
        4'd6:begin
             if(cnt0==4'd3||cnt0==4'd8)
             seg_led<=8'b00000010;
             else  seg_led<=8'b10000010;
             end
        4'd7:begin
             if(cnt0==4'd3||cnt0==4'd8)
             seg_led<=8'b01111000;
             else  seg_led<=8'b11111000;
             end
        4'd8:begin
             if(cnt0==4'd3||cnt0==4'd8)
             seg_led<=8'b00000000;
             else  seg_led<=8'b10000000;
             end
        4'd9:begin
             if(cnt0==4'd3||cnt0==4'd8)
             seg_led<=8'b00010000;
             else  seg_led<=8'b10010000;
             end
        default:seg_led<=8'b1111111;
        endcase
    end
end


endmodule

在这里插入图片描述
复位信号开始为0,拉高后开始计费,可见当路程小于2km时,收费为起步价7元,超过2km后按1.8元/km收费。如图行驶了2.1km,收费7.18元,数码管刷到第1位(路费的角位),数字为1,符合预期。

在这里插入图片描述

路程为14.9km,路费此时为30.22元(7+12.9*1.8),此时位选cnt0=1 ,data1为路费(角)为2,数码管刷新到第1位,显示数字为2,符合预期。

在这里插入图片描述
此时finish信号被拉高,mile_int,mile_dec和tmp_100price一直保持不变,全程行驶了24.9km,路费为7+22.9*1.8=48.22符合要求,此时位选是第9位(路程百位),数码管显示为0,符合预期。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值