(转)出租车计价器设计VHDL_小纯的博客-程序员资料

发布于 2021-12-01  737 次阅读


  

出租车计价器设计

题目

题目九:出租车计价器设计(平台实现)★★
完成简易出租车计价器设计,选做停车等待计价功能。
基本功能:
(1)起步8元/3公里,此后2元/公里;
(2)里程指示信号为每前进50米一个高电平脉冲,上升沿有效;显示行公里数,精确到0.1公里。(模拟时速40KM/h)
(3)前进里程开始之前显示价钱,精确到0.1元;
(4)用两个按键分别表示开始行程和结束行程。
选做功能:
(1)增加一个停车等待/恢复行程按钮,用2个数码管显示等待时间,精确到0.1分钟。
(2)等候费1元/分钟,计价精度为0.1元。

总体结构分析与设计

在这里插入图片描述
从思维导图看出,本次设计为分为分频、计时(内含有计算)、显示三个部分。分频得到一秒,计时内分为两个部分:等待模块和行驶模块。
最后通过显示模块输出到数码管。

实现与仿真

1.实现步骤:分频得到一秒,将一秒的频率作为输入,传入计时模块。在计时模块的行驶模块中:当汽车行驶时,如果km大于3km,那么每9s,km加上0.1km,即小数位加1,价钱加0.2元。
在计时模块的等待模块中:当汽车等待时,每6s即0.1min,等待时间加上0.1min,价钱加上0.1元。

2.VHDL代码

library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
entity taxi is
port(clk_100:in std_logic;
     clk_scan:in std_logic;                                        
     start:in std_logic;                    --开始
     stop:in std_logic;						--停车与恢复行驶
     reset:in std_logic;					--重置键
     ended:in std_logic;                    --结束            
     op,led:out std_logic_vector(7 downto 0));--数码管位选与段选
end taxi;
architecture one of taxi is
	signal f_1:std_logic;       			--1Hz频率
	signal q_1:integer range 0 to 99;
	signal c2,c1,c0:std_logic_vector(3 downto 0);--费用cost
	signal k2,k1,k0:std_logic_vector(3 downto 0);--km 
	signal m1,m0:std_logic_vector(3 downto 0);	 --min
	signal bit_2:integer range 9 downto 0;		--op
	signal num:std_logic_vector(3 downto 0);	--led
begin

feipin:process(clk_100,start)					--分频得1s
begin
  if (clk_100'event and clk_100='1') then
     if start='0' then q_1<=0;f_1<='0';
     else
        if q_1=99 then q_1<=0;f_1<='1';
        else q_1<=q_1+1;f_1<='0';
        end if;
     end if;
  end if;
end process;


jishi:process(f_1,start)						--计时模块
variable x:integer range 9 downto 0:=0;
variable w:integer range 9 downto 0:=0;
begin
  if f_1'event and f_1='1' then
     if reset='1' then					  --重置
		k2<="0000";k1<="0000";k0<="0000";
		m1<="0000";m0<="0000";
		c2<="0000";c1<="1000";c0<="0000"; --行驶状态,3km以内8元
	 elsif (start='1' and stop='0' and ended='0') then                     --行驶状态
        if x=8 then x:=0;                         --9s行程加0.1km,即0.2元
			if k0="1001" then k0<="0000";                   
			   if k1="1001" then k1<="0000";
				  if k2="1001" then k2<="0000";  
				  else k2<=k2+1;
				  end if;    
			   else k1<=k1+1;
			   end if;  
			else k0<=k0+1;
			end if;
			
			if (k2&k1&k0>="000000110000") then  --大于3km,开始行驶计费
			  if c0>="1001" then c0<=c0-"1000";     --行驶计费
				if c1="1001" then c1<="0000";
				  if c2="1001" then c2<="0000";
				  else c2<=c2+1;
				  end if;
				 else c1<=c1+1;
				 end if;
			  else c0<=c0+2;           --9s行程加0.1km,即0.2元
			  end if;
			end if;
        else x:=x+1;
        end if;
        
     elsif (start='1' and stop='1' and ended='0') then                    --等待停车状态
        if w=5 then w:=0;                     --计时0.1分钟即6s,即0.1元
           if m0="1001" then m0<="0000";             
              if m1="1001" then m1<="0000";               
              else m1<=m1+1;
			  end if;
           else m0<=m0+1;
           end if;
           
          if c0="1001" then c0<="0000";       --等待计费
			if c1="1001" then c1<="0000";
			  if c2="1001" then c2<="0000";
			  else c2<=c2+1;
			  end if;
			 else c1<=c1+1;
			 end if;
		  else c0<=c0+1;
		  end if;
        else w:=w+1;
        end if;
     end if;
   end if;
end process;

xiangshi:process(clk_scan,c0,k0,m0)		     --显示模块
variable a:integer range 9 downto 0:=0;
begin
  if clk_scan'event and clk_scan='1' then
	 if start='1' then
		bit_2<=a;
		a:=a+1;
		a:=a rem 8;
		case bit_2 is
		  when 0=>num<=k0;op<="11111110";
		  when 1=>num<=k1;op<="11111101";
		  when 2=>num<=k2;op<="11111011";
		  when 3=>num<=c0;op<="11110111";
		  when 4=>num<=c1;op<="11101111";
		  when 5=>num<=c2;op<="11011111";
		  when 6=>num<=m0;op<="10111111";
		  when 7=>num<=m1;op<="01111111";
		  when others=>null;
	    end case;
	 end if;
  end if;
end process;

shumaguan:process(num)
variable y:std_logic_vector(6 downto 0);
begin
	case num is
		  when "0000" =>y:="1111110";
		  when "0001" =>y:="0110000";
		  when "0010" =>y:="1101101";
		  when "0011" =>y:="1111001";
		  when "0100" =>y:="0110011";
		  when "0101" =>y:="1011011";
		  when "0110" =>y:="1011111";
		  when "0111" =>y:="1110000";
		  when "1000" =>y:="1111111";
		  when "1001" =>y:="1111011";
		  when others =>null;
	end case;
	if (bit_2=2 or bit_2=5 or bit_2=0) then 		--添加小数点
		  led<=y&'1';
    else  led<=y&'0';
    end if;
end process; 
end one;

管脚编号:
在这里插入图片描述

3.仿真:
在这里插入图片描述
4.板载测试
在这里插入图片描述
上图为:等待3.9min,总费用为23.9元,行驶里程为9.0km.
23.9=3.9*1+8+(9-3)*2,符合题意。
多次测试各种情况也符合题意。
测试成功!

设计结论与分析

1.系统测试结论: 通过反复地测试工作情况,得出本次实验的设计满足题意,并且只要输入的为标准100Hz的时钟信号,那么就能正确计算出行驶路程、等待时间、总费用,能精确到0.1。

2.性能特点: ①优点:计费、计时、计程很准确,达到40km/h的效果。功能全部实现。

3.可扩展性分析: 可以在加上几个模式:比如把模式分为:白天、黑夜、雨天等,不同的环境下实现计时、计程、计费。

小结与心得体会

1.设计过程中的困难和解决方法:
问题一:一个信号量只能在一个进程中赋值。解决:想办法在一个进程中赋值。
问题二:需要1500多个单元,但是只有1150个。解决:这个时候是用整形做的,然后把整形换为位矢量,并且优化过程,因为此时有六个进程process.
有的问题解决了,有的没解决,就换了思路。
当然还有一些小问题。

2.经验与收获体会、对EDA的认识
刚开始的时候感觉这一题还挺简单的,因为思路真的是异常清晰(之前习惯软件思维的我,把它当软件看),然后感觉用C语言写,分分钟的事情。一写起来,到处报错,才发现一些语法的细节不是很了解,在不断摸索中,终于对VHDL的越来越熟悉,通过不断地认识,从刚开始的数码管显示的有点乱七八糟,最后终于达到了自己的一点点要求,最后不断完善程序,终于达到了自己的要求。
发现VHDL这种硬件语言真的和之前学过的很不一样,有的时候编译通过,逻辑没问题,但是到了物理层次,还是出了问题。于是,在写VHDL的时候把它看出是一个物理盒子,写代码就是在连线一样,把变量尽量用二进制表示,成功率会提升许多。