EDA项目 出租车计价器 赏析

祝青春不虚度,充实,饱满,热烈。

1.0项目简介:

本项目是一个出租车计价器(taxi_fee.vhd)
满足以下要求:

–(1)起步8元/3公里,此后2元/公里;
–(2)里程指示信号为每前进50米一个高电平脉冲,上升沿有效;显示行公里数,精确到0.1公里。(为了方便运算,模拟时速100m/s)也就是说,3km之后,每0.1km,更新价格,上涨0.2元。
–(3)前进里程开始之前显示价钱,精确到0.1元;
–(4)用两个按键分别表示开始行程和结束行程。

1.1项目整体结构

本项目由三个部分:脉冲产生模块Speed_pulse.vhd, 计费模块taxi_state.vhd, 显示模块display.vhd
下面对每个模块的具体介绍,请按照显示模块display.vhd,脉冲产生模块Speed_pulse.vhd, 计费模块taxi_state.vhd的顺序阅读,因为我就是按照这个顺序写的,但是我懒得调整顺序了,因为模块的先后顺序是按照数据的流向排列的。

输入:
reset:计价器复位。
start: 下降沿时刻,开始行程,模拟开始开车
stop: 下降沿时刻,结束行程,模拟停车
隐含的输入:模拟时速100m/s。

输出:
数码管HEX0,HEX1,HEX2:显示里程
数码管HEX3,HEX4,HEX5: 显示金额

信号:
totel_money: 金额
mileage:里程(项目里粗心了,totel写错了英文单词,正确的是total,只好将错就错了)
在这里插入图片描述


2.速度脉冲产生模块Speed_pulse.vhd

模块功能:为每前进50米一个高电平脉冲,模拟汽车前进了50米;
显示行公里数,精确到0.1公里。(模拟时速)

输入:clk --时钟
reset–复位信号,低有效

输出: one_pulse --50米一个高电平脉冲

模块结构
本部分大部分采用process语句,使用算法(顺序语句)描述硬件行为,是行为描述风格
在这里插入图片描述

1,只要敏感信号(本部分的敏感信号为时钟clk)在变化,就会运行,由于敏感信号往往一直在变化,包括本部分的时钟clk一直在随时间变化,所以process也在无限循环运行
2. process语句内部是顺序执行的,但是和其他的process相比,则是并行运行,两个process各自运行,而不是顺序先运行一个process再运行另外一个,所以是并行运行。

2.1声明部分

	  clk             : IN STD_LOGIC;--时钟,两次clk=1的中间,间隔了0.1s
      reset           : IN STD_LOGIC;--复位信号,低有效 
      one_pulse   : OUT STD_LOGIC--50米一个高电平脉冲,即每过50米,one_pulse=1,其余时间one_pulse=0

2.2进程process语句

   SIGNAL one_pulse_cnt   : integer := 0;   --用于计数的integer,由于clk是、0.1s从10再到1,但是one_pulse是0.5s从10再到1,表示0.5s走了50米。所以用one_pulse_cnt来计时,每过0.1s,one_pulse_cnt就加1,但是one_pulse_cnt不等于5,所以one_pulse。当one_pulse_cnt加到5的时候,就表示过去了0.5s,one_pulse就会变成1,然后one_pulse_cnt就会被重新赋值为0,进入下一个循环。详细过程间下面process代码
   

    PROCESS (clk)--括号里的clk是敏感信号,只要敏感信号在变化,就会不断运行。
   --下面代码请按照注释的甲乙丙的顺序阅读。
   --
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN--甲 两次clk=1的中间,间隔了0.1s
		 IF (reset = '0') THEN--如果reset是0则复位,下面的elsif和else都是reset不为0,就不用复位。
            one_pulse_cnt <= 0;
            one_pulse <= '0';
         ELSIF (one_pulse_cnt >= 5) THEN--丙 每0.5秒走50m。
               one_pulse_cnt <= 0;
               one_pulse <= '1';--走了50米,出现一个高电平脉冲
         ELSE --乙 过去的时间不足0.5s,暂时让one_pulse=0,表示还没走50米
               one_pulse_cnt <= one_pulse_cnt + 1;
               one_pulse <= '0';
         END IF;
      END IF;
   END PROCESS;

3.计费模块taxi_state.vhd

模块功能
–(1)起步8元/3公里,此后2元/公里;
–(2)里程指示信号为每前进50米一个高电平脉冲,上升沿有效;显示行公里数,精确到0.1公里。(模拟时
–速100m/s)也就是说,3km之后,每100米,更新价格,上涨0.2元。
–(3)前进里程开始之前显示价钱,精确到0.1元;
–(4)用两个按键分别表示开始行程和结束行程。

输入:clk:时钟
reset:复位信号 低有效
stop --本次行程结束,停止计费,低有效
start-启动信号,行程开始,低有效
one_pulse --50米一个高电平脉冲,这个输入来自速度脉冲产生模块Speed_pulse.vhd的输出

输出:mileage_out 里程
totel_money_out 车费

本部分主要采用process语句,同上不再赘述

3.1 process语句

--这一部分将从 速度脉冲产生模块Speed_pulse.vhd 获得的50m一次的脉冲one_pulse,换算为100m一次脉冲two_pulse
PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (reset = '0') THEN
            flag_pulse <= '0';
	     ELSIF(one_pulse='1')THEN
				flag_pulse <= not flag_pulse;--本部分将50m脉冲one_pulse转换为100m一次电平变化flag_pulse。
				--也就是说,one_pulse从1变成0再变成1,表示走了50m,然而flag_pulse从1变成0再变成1,走了100m
			END IF;
		END IF;
	END PROCESS;
two_pulse<=	 flag_pulse and one_pulse;--获得100m脉冲two_pulse
--这一部分是出租车的状态转换,和不同状态下,根据里程,进行价格计算。注意state有000空闲,001起步价,010两元每三公里,110停车几种状态。
PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (reset = '0') THEN--重置
            state <= "000";
            totel_money <= "0000000000000000";
            totel_money_out <= "0000000000000000";
         ELSIF (stop = '0') THEN--注意,下面三句话是同时进行的,所以totel_money_out是车费,不是"0000000000000000"
         --因为停下来了,所以totel_money也要重置为0000000000000000。
            state <= "110";
            totel_money <= "0000000000000000";
            totel_money_out <= totel_money;--输出合计费用
         ELSE--没有停下来,只是输出车费。
            totel_money_out <= totel_money;--输出合计费用
            CASE state IS`--注意state有000空闲,001起步价,010两元每三公里,110停车几种状态。
               WHEN "000" =>--空闲状态 注意state有000空闲,001起步价,010两元每三公里,110停车几种状态。
                  totel_money <= totel_money;
                  IF (start = '0') THEN --如果开始开车,那么进入下一个阶段。
                     state <= "001";--变成起步价阶段
                  ELSE
                     state <= "000";--否则停留在空闲阶段
                  END IF;
               WHEN "001" =>--起步价
                  totel_money <= "0000_0000_0101_0000";--起步费为 8.0 元(800.1元)
                  IF (mileage >= "0000_0000_0001_1110") THEN--大于3.0公里(300.1km)后按公里计费
                     state <= "010";
                  ELSE
                     state <= "001";
                  END IF;
               WHEN "010" =>--车行驶3公里后按每公里2元计费
                  IF (two_pulse = '1') THEN--走了0.1km
                     totel_money <= totel_money + "0000000000000010";--0.1公里 0.2元计费
                  END IF;
                     state <= "010";
               WHEN OTHERS =>
                  state <= "000";
            END CASE;
         END IF;
      END IF;
   END PROCESS;
--这一部分是里程计算
PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (reset = '0') THEN
            mileage <= "0000000000000000";
         ELSIF (state = "001" OR state = "010" OR state = "100") THEN--如果汽车处于正在开的状态
            IF (two_pulse = '1') THEN--0.1公里脉冲
               mileage <= mileage + "0000000000000001";--0.1公里里程加1
            ELSE
               mileage <= mileage;
            END IF;
         ELSIF (stop = '0') THEN
            mileage <= "0000000000000000";
         ELSE
            mileage <= mileage;
         END IF;
      END IF;
   END PROCESS;

4. 显示模块display.vhd

模块功能:将里程和价格显示到LED屏幕上

输入:reset: 重置 复位信号,低有效 ?
clk 标准时钟
totel_money 车费 来自计费模块taxi_state.vhd
mileage 里程 来自计费模块taxi_state.vhd

输出
HEX0,1,2
HEX3,4,5

此部分采用了元件例化语句 端口映射方式为名字关联方式 是组件描述风格
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

4.1 Component声明部分

结构体trans描述了2种component:

b_to_bcd:

将二进制转BCD码(BCD码是指用4bit来表示十进制的一位的方式,其中一种4bit与十进制一位的映射方法如下)
在这里插入图片描述

SIGNAL Kmmoney_H : STD_LOGIC_VECTOR(3 DOWNTO 0); --费用的百位,注意他的数据类型是4个LOGIC类型的数组,因为这个数组表示十进制的一位,用4bit(1个Logic类型是1bit)表示。
SIGNAL BCD_mileage_out   :  STD_LOGIC_VECTOR(15 DOWNTO 0);--路程的输出,共16个LOGIC,所以是4位十进制数。

LED7s:

例化显示模块

--一个LED7S接收一个4bit的BCD码,也就是十进制的1位,然后输出7bit,刚好作为LED显示屏上每一个“杠”是亮是暗,从而显示一个数字。
COMPONENT LED7S is
Port(din: in std_logic_vector(3 downto 0);
	 y: out std_logic_vector(6 downto 0));
END COMPONENT;

LED
上图为LED显示数字,可以看到有7个杠,通过各自的亮暗决定显示什么数字。

4.2 功能描述部分

--二进制表示的里程 转BCD码,使用了b_to_bcd  component
--=>左边是 b_to_bcd  component的引脚,右边是这些引脚链接的外部引脚。
--下面这一部分交代了b_to_bcd的各个引脚的连接关系
BCD_mileage : b_to_bcd 
   PORT MAP (      
      clk       =>clk,
      rst_n     =>reset,
      binary    =>mileage_exd,
      state_en  =>'1',
      BCD       =>BCD_mileage_out
   );

BCD_totel_money也使用了b_to_bcd component,不赘述

--信号BCD_totel_money_out从BCD_totel_money的BCD 输出口获得车费的BCD码,然后根据BCD码的规则,将最高4位分给Kmmoney_H作为十进制的百位,以此类推。
   Kmmoney_H <= BCD_totel_money_out(11 downto 8);--百位
   Kmmoney_M <= BCD_totel_money_out(7 downto 4);--十位
   Kmmoney_L <= BCD_totel_money_out(3 downto 0);--个位
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值