HNUST数字系统设计---EDA课设:出租车计价器设计

一.声明

1. 首先该博客由本人的EDA课设报告改写而成,在此发布以供各位参考,目的是为大家提供一些理解和思路,希望大家不要盲目复制粘贴,一定要在自己有一定的理解基础上借鉴本文,才能在本次eda大作业中有所收获。(vhdl代码放在文章最后)

2. 如果遇到USB-Blaster驱动问题记得禁用驱动程序强制签名(一般是临时的,每次重启都需要重新禁用一遍),如果跳出小弹窗提示兼容性问题(无法在此设备上加载驱动程序),就需要打开“Windows安全中心”的控制面板,依次点击“设备安全性”->“内核隔离详细信息”->“内存完整性”,将“内存完整性”的选项关闭,然后重启电脑并重新安装驱动程序。

二.正文

1.题目要求

完成简易出租车计价器设计,选做停车等待计价功能。

基本功能:

1)起步8元/3公里,此后2元/公里;

2)里程指示信号为每前进50米一个高电平脉冲,上升沿有效;显示行驶公里数,精确到0.1公里。

4)前进里程开始之前显示价钱,精确到0.1元;

5)用两个按键分别表示开始行程和结束行程。

选做功能:

增加一个停车等待/恢复行程按钮,用2个数码管显示等待时间,精确到0.1分钟。

等候费1元/分钟,计价精度为0.1元。

2.分析与设计思路

1. 考虑到数码管只有八个,从左往右,这里把前三个数码管设置成价格显示部分,精确到0.1,第四个为最大行程的计数器,第五,六个数码管为行程显示部分,最后两个为等待时间显示

 

2. 前3公里为8元,意味着价格默认显示为0 8 0,其他数码管显示0,由于行程需要精确到0.1公里,而每50米一个上升沿脉冲,为了方便仿真,这里设置成每两个时钟脉冲,行程的小数部分要加1;等待部分精确到0.1分钟,这里设置成每6个时钟脉冲到来时等待时间的小数部分加1,同时对相应的价格进行计算和累加

3. 由于最大显示9.9公里(相当于10公里),为解决这个超限的问题,我们加了一个数码管记录行驶了多少个最大行程,而实际上在计费的时候,不是把计数部分乘以(行程-3)*2+8就能得到结果,因为当计数的数码管显示大于1时,计费标准依然是按3公里之后算的,所以第二段行程是从3开始累计。如果从行程0开始重新累计,那么前3公里就会停止计费,对一段未结束的行程来说,这是不符合现实情况的,所以将第二段及以上的行程从三公里开始计费,相当于对于同一个行程,除了第一段,其他都是7公里,由于重点是价格显示,我们不想做太大的改动,就让行程的显示不那么直观,否则价格变动不符合实际

4. 按下启动键,行程开始计数,到三公里以后,价格累加;按下停止键就会暂停;按下等待键也会停止行程,等待时间开始累加,价格也会相应增加,恢复行程按下启动键即可,清零键可随时作用,但除了停止状态,其他状态下按清零键依然会计数,所以需要手动停止(结束行程)再清零

5. 当价格显示部分超限就自动回到初始状态,同样要手动停止清零

3.引脚设置

4.开发板测试

验证公式:设n为数码管显示经过最大行程的个数(对应从左往右第四个数码管),m为行程部分显示的数,p为等待时间,则价格w=[(10*n+m-3*n)-3]*2+8+p元

5.总结

1. vhdl语言用起来并不顺手,但逻辑理清后多调试几次很快就能熟悉

2.这道题主要分为运行、等待、停止状态,三者的状态转换需要明确;事实上停止状态stop_state并不需要成为进程的敏感信号,因为在状态转换进程中任意一个状态经判断都是唯一的,即只允许一个状态为“1”,停止按键按下后,其他两个状态就会为“0”,计费和行程自然就停止了;

3.为了方便开发板测试,需要设置合适频率的时钟,不能过快导致捕捉不到变化;也不能太慢增加不必要的时间;

4.在处理进位的时候一定要注意语句的顺序问题,否则数码管会显示混乱

5.动态扫描进程需要用到conv_std_logic_vector函数来对数码管进行选择,要引入use ieee.std_logic_arith.all;

6.给最大行程计数,不至于因为量程不够影响计费,算是一个创新点;

7.代码没有考虑按键消抖问题,因为几乎没有冲突和按键失灵

8.验证价格是否正确,可以采用以下方式:

  设n为数码管显示经过最大行程的个数(对应从左往右第四个数码管),m为行程部分显示的数,p为等待时间,则价格w为[(10*n+m-3*n)-3]*2+8+p元

9.通过此次eda大作业,加深了我对软硬结合应用的理解,也让我初步掌握vhdl的基本使用方法,锻炼了我分析问题解决问题的能力.

6.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(start_key:in std_logic;--启动
     stop_key:in std_logic;--停止
     wait_key:in std_logic;--等待
     reset_key:in std_logic;--清零重置
     drive_clk:in std_logic;--运行状态时钟
     digital_clk:in std_logic;--选择数码管时钟
     digital_sel:out std_logic_vector(7 downto 0);--控制八个数码管显示
     choose:out std_logic_vector(7 downto 0));--选择第几个数码管
end Taxi;

Architecture situation of Taxi is

--数码管部分
type digital_status is array (0 to 9) of std_logic_vector(7 downto 0);--控制七段数码管的数组,用来控制0-9的数字显示
signal digital_array:digital_status;--不包含小数点
signal digital_array_dot:digital_status;--显示小数点
signal number:integer range 0 to 7:=0;--用于动态扫描数码管的数字显示选择
type sels is array(0 to 7) of std_logic_vector(7 downto 0);--定义选择数码管的数组类型
signal digitals:sels;--定义选择第几个数码管的信号,方便为digital-sel赋值

signal run_state:std_logic:='0';--判断是否处于运行状态的标志
signal wait_state:std_logic:='0';--判断是否处于等待状态的标志
signal stop_state:std_logic:='0';--判断是否处于停止状态的标志
signal state_temp:std_logic:='0';--临时判断标志,备用

--数码管的功能模块

--费用
signal pay0:integer range 0 to 9:=0;
signal pay1:integer range 0 to 9:=0;
signal pay2:integer range 0 to 9:=0;

--记录完成多少个最大行程10公里
signal counter_km:integer range 0 to 9:=0;

--行程
signal pos1:integer range 0 to 9:=0;
signal pos2:integer range 0 to 9:=0;

--等待
signal w1:integer range 0 to 9:=0;
signal w2:integer range 0 to 9:=0;

begin
  --选择有小数点的显示
  digital_array_dot(9)<="11110111";
  digital_array_dot(8)<="11111111";
  digital_array_dot(7)<="11100001";
  digital_array_dot(6)<="10111111";
  digital_array_dot(5)<="10110111";
  digital_array_dot(4)<="01100111";
  digital_array_dot(3)<="11110011";
  digital_array_dot(2)<="11011011";
  digital_array_dot(1)<="01100001";
  digital_array_dot(0)<="11111101";
  
  --选择无小数点的显示
  digital_array(9)<="11110110";
  digital_array(8)<="11111110";
  digital_array(7)<="11100000";
  digital_array(6)<="10111110";
  digital_array(5)<="10110110";
  digital_array(4)<="01100110";
  digital_array(3)<="11110010";
  digital_array(2)<="11011010";
  digital_array(1)<="01100000";
  digital_array(0)<="11111100";
  
  --需要显示的数码管
  show:process(digital_clk)
  begin
    digitals(7)<=digital_array(pay0);
    digitals(6)<=digital_array_dot(pay1);
    digitals(5)<=digital_array(pay2);
    
    digitals(4)<=digital_array(counter_km);
    
    digitals(3)<=digital_array_dot(pos1);
    digitals(2)<=digital_array(pos2);
    
    digitals(1)<=digital_array_dot(w1);
    digitals(0)<=digital_array(w2);
    end process;
    
    --启动或停止或等待的进程状态判断和转化,1表示处于当前状态
  state_reverse:process(start_key,stop_key,wait_state)
  begin
    --按下等待键
    if wait_key='0' then
       wait_state<='1';
       run_state<='0';
       stop_state<='0';
    --按下启动键
    elsif start_key='0' then
       run_state<='1';
       stop_state<='0';
       wait_state<='0';
    --按下停止键
    elsif stop_key='0' then
       stop_state<='1';
       run_state<='0';
       wait_state<='0';
    end if;
 end process;
     
  run:process(drive_clk,run_state,wait_state,stop_state)
    variable temp_pay0:integer range 0 to 9:=0;
    variable temp_pay1:integer range 0 to 9:=8;
    variable temp_pay2:integer range 0 to 9:=0;
    
    variable temp_pos1:integer range 0 to 9:=0;
    variable temp_pos2:integer range 0 to 9:=0;
    
    variable temp_w1:integer range 0 to 9:=0;
    variable temp_w2:integer range 0 to 9:=0;
    variable count_pos:integer range 0 to 2:=0;--判断上升沿的次数,方便公里部分计数,每两个时钟脉冲相当于0.1㎞
    variable count_wait:integer range 0 to 6:=0;--给等待时间计数,每六个时钟脉冲上升相当于0.1分钟
    variable temp_counter_km:integer range 0 to 9:=0;--记录完成多少个9.9公里
    --variable flag_empty:integer range 0 to 1:=0;--清零标志
    begin
        if rising_edge(drive_clk) then
      
           --处于运行状态
           if run_state='1' then
             count_pos:=count_pos+1;
             
             if count_pos>=2 then  --行驶了0.1公里
                temp_pos2:=temp_pos2+1;
                
               if temp_pos1>=3 and temp_pos2>=0 then --三公里外价格才开始累加
                  temp_pay2:=temp_pay2+2;
                 if temp_pay2>9 then
                    temp_pay2:=0;
                    temp_pay1:=temp_pay1+1;
                 end if;
                 
               --一旦费用超出最大显示限额,全部清理,属于极端情况
                 if temp_pay1>9 then
                    temp_pay1:=0;
                    temp_pay0:=temp_pay0+1;
                    if temp_pay0>9 then
                       temp_pay0:=0;
                       temp_pay1:=8;
                       temp_pay2:=0;
                       temp_counter_km:=0;
                       temp_pos1:=0;
                       temp_pos2:=0;
                       temp_w1:=0;
                       temp_w2:=0;
                    end if;
                 end if;
               
               end if;--三公里外的价格计算
               
               if temp_pos2>9 then 
                  temp_pos2:=0;
                  temp_pos1:=temp_pos1+1;
                  if temp_pos1>9 then
                     temp_pos2:=0;
                     temp_pos1:=3;
                     temp_counter_km:=temp_counter_km+1;--已完成一个最大行程
                  end if;
               end if;
               
              count_pos:=0;--重新计数
             end if;
           end if;--运行状态
         
         --处于等待状态
         if wait_state='1' then
            count_wait:=count_wait+1;
             
            if count_wait>=6 then ----经过0.1分钟
                  temp_w2:=temp_w2+1;
                  if temp_w2>9 then 
                     temp_w2:=0;
                     temp_w1:=temp_w1+1;
                     if temp_w1>9 then
                        temp_w1:=0;
                        temp_w2:=0;
                     end if;
                  end if;
                  
                  --等待时间下价格累加
                  temp_pay2:=temp_pay2+1;
                  if temp_pay2>9 then
                     temp_pay1:=temp_pay1+1;
                     temp_pay2:=0;
                  end if;
                  
                  --一旦费用超出最大显示限额,全部清理,属于极端情况
                  if temp_pay1>9 then
                     temp_pay1:=0;
                     temp_pay0:=temp_pay0+1;
                     if temp_pay0>9 then
                        temp_pay0:=0;
                        temp_pay1:=8;
                        temp_pay2:=0;
                        temp_counter_km:=0;
                        temp_pos1:=0;
                        temp_pos2:=0;
                        temp_w1:=0;
                        temp_w2:=0;
                     end if;
                  end if;
                  
               count_wait:=0;--重新计数
            end if;
          end if;--等待状态
          
            if reset_key='0' then --清零重置
               temp_pay0:=0;
               temp_pay1:=8;
               temp_pay2:=0;
               temp_counter_km:=0;
               temp_pos1:=0;
               temp_pos2:=0;
               temp_w1:=0;
               temp_w2:=0;
            end if;
      end if;--时钟上升沿
      
--给信号赋值
      pay0<=temp_pay0;
      pay1<=temp_pay1;
      pay2<=temp_pay2;
      
      counter_km<=temp_counter_km;
      
      pos1<=temp_pos1;
      pos2<=temp_pos2;
      
      w1<=temp_w1;
      w2<=temp_w2;     
  end process;

--动态扫描数码管
 scan_sel:process(digital_clk)
  begin
    if rising_edge(digital_clk) then
       digital_sel<=digitals(number);
       choose<=not(conv_std_logic_vector(2**number,8));
       
       if number=7 then number<=0;
       else number<=number+1;
       end if;
    end if;
  end process;
 end situation;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值