EDA出租车计费器设计(共28页).docx
精选优质文档-倾情为你奉上1. 出租车计费器的总体设计1.1 出租车计费设计该出租车计费器按下开关S1后开始计费和计里程数,分为白天和夜晚。当拨动开关K2为0时,系统使用程序设置的起步价,白天起步价是3元,准行2公里,以后2元/公里;夜晚起步价是9元,准行2公里,以后3元/公里。当拨动开关K2为1时,可由矩阵键盘输入起步价09元。当路程大于200公里时,价格会在原来的基础上加50元。1.2 基本设计思想时钟输入为一个1KHz的系统时钟,直流电机模块每转一圈输出一个脉冲信号给CPU,另外用按键模块的S1 来作为整个系统的复位按钮,每复位一次,计费器从头开始计费。直流电机模块用来模拟出租车的车轮子,每转动一圈认为是行走1 米,所以每旋转1000 圈,认为车子前进1 公里。系统设计是需要检测电机的转动情况,每转1000圈,分频模块输出一个下降沿信号。车费和里程数在一个8位7段数码管上显示,前4位显示里程,后4位显示费用。路程的单价由16*16点阵显示,拨动开关K1为0时,2元/公里,点阵显示2;拨动开关K2为1时,3元/公里,点阵显示3。2. 出租车计费器的总体实现2.1 系统总体框图该出租车计费器由一个VHDL程序构成,不同功能的实现分别是多个进程控制,主要进程有:分频模块进程:将每1000个电机脉冲转化为1个输出脉冲;计程模块进程:记录已行里程;计费模块进程:计算应付车费;4*4矩阵键盘进程:设置起步价;数码管显示进程:将已行里程和应付车费显示在数码管上;16*16点阵显示进程:显示当前状态的每公里单价。计程模块分频模块计费模块总程序(系统时钟)4*4矩阵键盘16*16点阵数码管图2-1 系统框图2.2 程序流程图(1) 分频模块:Yrst或motor信号发生变化Rst=0Count<=0Temp<=0Nmotor'event and motor='1'YYCount=0Temp=not tempCount<499NCount<=count+1Glclk<=temp图2-2 分频模块(2) 计程模块Meter1<=0; Meter10<=0; Meter100<=0; Meter1K<=0;Yrst或glclk信号发生变化Rst=0Nglclk'event and glclk='0'YMeter1,meter10,meter100,meter1000代表的四位十进制数加1图2-3 计程模块(3) 计费模块Money1<=qibujia; Money10<=0; Money100<=0; Money1000<=0;Yrst或clk信号发生变化Rst=0Nclk'event and clk='0'Y根据路程计算出总价,再把总价的千位、百位、十位、个位取出显示。图2-4 计费模块2.3 出租车计费器各功能的实现(1)分频模块:直流电机motor每输出1000个脉冲,分频器glclk输出一个下降沿脉冲,表示电机已走1公里,meter1加1.if rst='0' thencount<=0;temp<='0'elsif (motor'event and motor='1') thenif count>499 thencount<=0;temp<=not temp; else count<=count+1;end if;end if;glclk<=temp;(2)计程模块:glclk的下降沿来临时,路程的个位加1,满9往高位进一,同时低位归0。process(glclk)begin if(Rst='0') then Meter1<=0; Meter10<=0; Meter100<=0; Meter1K<=0; elsif(glclk'event and glclk='0') then if(Meter1=9) then Meter1<=0; if(Meter10=9) then Meter10<=0; if(Meter100=9) then Meter100<=0; if(Meter1K=9) then Meter1K<=0; else Meter1K<=Meter1K+1; end if; else Meter100<=Meter100+1; end if; else Meter10<=Meter10+1; end if; else Meter1<=Meter1+1; end if; end if; lucheng<=meter1k*1000+meter100*100+meter10*10+meter1*1; end process;(3)计费模块:路程小于等于2公里时,费用为起步价;路程大于2公里,小于200公里,费用为(起步价+(路程-2)*单价);路程大于200公里时费用为(起步价+(路程-2)*单价+50)。process(clk,rst) begin if(Rst='0') or (lucheng<3) then Money1<=qibujia; Money10<=0; Money100<=0; Money1000<=0; elsif(clk'event and clk='0') then if lucheng>200 then jiage<=(lucheng-2)*danjia+qibujia+50; money1000<=(jiage-(jiage mod 1000)/1000; money100<=(jiage mod 1000)-(jiage mod 1000)mod 100)/100; money10<=(jiage mod 100)-(jiagemod 10)/10; money1<=jiage mod 10; else jiage<=(lucheng-2)*danjia+qibujia; money1000<=(jiage-(jiage mod 1000)/1000; money100<=(jiage mod 1000)-(jiage mod 1000)mod 100)/100; money10<=(jiage mod 100)-(jiage mod 10)/10; money1<=jiage mod 10; end if; end if; end process;(4)4*4矩阵键盘:有键按下时为低电平,脉冲扫描时先判断行,再判断列。process(clk) begin if(clk'event and clk='1') then if(Krow="1111") then kflag1<='0' kcount<=kcount+1; if(kcount=0) then Kcol<="1110" elsif(kcount=1) then Kcol<="1101" elsif(kcount=2) then Kcol<="1011" else Kcol<="0111" end if; else kflag1<='1' keyrow<=Krow; keycol<=Kcol; end if; end if; end process; process(clk) begin if k2='1' then if(clk'event and clk='1') then if(kflag1='1') then if(keyrow="0111") then case keycol is when "0111"=>buff<=1; when "1011"=>buff<=4; when "1101"=>buff<=7; when others=>buff<=buff; end case; elsif(keyrow="1011") then case keycol is when "0111"=>buff<=2; when "1011"=>buff<=5; when "1101"=>buff<=8; when "1110"=>buff<=0; when others=>buff<=buff; end case; elsif(keyrow="1101") then case keycol is when "1101"=>buff<=9; when "1011"=>buff<=6; when "0111"=>buff<=3; when others=>buff<=buff; end case; end if; end if; qibujia<=buff; end if; else qibujia_d<=3; qibujia_n<=9;if (k1='0') then qibujia<=qibujia_d; else qibujia<=qibujia_n;end if; end if; end process;(5)数码管显示:通过位选端控制八位数码管的显示,每次显示一位,通过提高时钟的频率,达到显示的效果。process(SEG_SEL) begin case (SEG_SEL+1) is when "000"=> Disp_Temp<=Meter1K; when "001"=> Disp_Temp<=Meter100; when "010"=> Disp_Temp<=Meter10; when "011"=> Disp_Temp<=Meter1; when "100"=> Disp_Temp<=money1000; when "101"=> Disp_Temp<=Money100; when "110"=> Disp_Temp<=Money10; when "111"=> Disp_Temp<=Money1; end case; end process;process(Disp_Temp) begin case Disp_Temp is when 0=> Disp_Decode<="" -0 when 1=> Disp_Decode<="" -1 when 2=> Disp_Decode<="" -2 when 3=> Disp_Decode<="" -3 when 4=> Disp_Decode<="" -4 when 5=> Disp_Decode<="" -5 when 6=> Disp_Decode<="" -6 when 7=> Disp_Decode<="" -7 when 8=> Disp_Decode<="" -8 when 9=> Disp_Decode<="" -9 when others=> Disp_Decode<="" end case; end process; (6)16*16点阵显示:点阵扫描时,先扫描列,再扫描行,点阵是自下往上、从左到右显示,提高时钟频率达到显示效果。process(cdount) begin case cdount is when "0000"=>ledcol<="0000" -列选择(lg7088Ah) when "0001"=>ledcol<="0001" when "0010"=>ledcol<="0010" when "0011"=>ledcol<="0011" when "0100"=>ledcol<="0100" when "0101"=>ledcol<="0101" when "0110"=>ledcol<="0110" when "0111"=>ledcol<="0111" when "1000"=>ledcol<="1000" when "1001"=>ledcol<="1001" when "1010"=>ledcol<="1010" when "1011"=>ledcol<="1011" when "1100"=>ledcol<="1100" when "1101"=>ledcol<="1101" when "1110"=>ledcol<="1110" when "1111"=>ledcol<="1111" when others=>ledcol<="0000" end case; end process; 3系统调试与仿真从图中可看出,给一个复位信号后,费用的最低位为“0011”,即3,里程数的最低位为“0000”,即0,每当temp信号出现一个下降沿,里程数的最低位各加1,费用增加相应的单价,符合课题要求。图3-1 系统仿真图4总结与体会为期两周的实训已经过去了,对于我来说这两周周的实训赋予了我太多实用的东西了,不仅让我更深层次的对课本的理论知识深入了理解,而且还让我对分析事物的逻辑思维能力得到了锻炼,提高了实际动手能力。 刚开始看到这次的题目“出租车计费器”,感觉应该不难,但真正开始动手编程的时候,感觉有点无从下手,最后老师的指导和同学们的帮助下,慢慢克服了一个又一个困难。在实验室中,我熟悉了对Quartus 软件的一般项目的操作和学到了处理简单问题的基本方法,更重要的是掌握了VHDL语言的基本设计思路和方法,我想这些会对我今后的学习起到很大的助推作用。此外,还要在今后的课本理论知识学习过程中要一步一个脚印的扎实学习,灵活的掌握和运用专业理论知识这样才能在以后出去工作的实践过程中有所成果。 最后还要感谢学校为我们提供这样专业的实践平台还有老师在实训以来的不断指导和同学的热情帮助。总的来说,这次实训我收获很大。 附录A 出租车计费器VHDL源程序library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity dianzhen is port( Clk : in std_logic; -时钟输入 k1,k2 : in std_logic; -danjiaxuanze Rst : in std_logic; -复位输入 Motor : in std_logic; -电机脉冲输入 Krow : in std_logic_vector(3 downto 0); Kcol : buffer std_logic_vector(3 downto 0); Display : out std_logic_vector(7 downto 0); -七段码管显示输出 SEG_SEL : buffer std_logic_vector(2 downto 0); -七段码管扫描驱动 ledcol:out std_logic_vector(3 downto 0); -点阵列控制 ledrow:out std_logic_vector(15 downto 0); -点阵行显示 end dianzhen;architecture behave of dianzhen is signal Disp_Temp : integer range 0 to 15; signal Disp_Decode: std_logic_vector(7 downto 0); signal Meter1,Meter10,Meter100,Meter1K : integer range 0 to 9; signal Money1,Money10,Money100,Money1000 : integer range 0 to 9; signal danjia,day,night,qibujia,qibujia_d,qibujia_n: integer range 0 to 9; signal temp,glclk:std_logic; signal count:integer range 0 to 500; signal lucheng,jiage:integer range 0 to ; signal cdount : std_logic_vector(3 downto 0); signal buff :integer range 0 to 15; signal keyrow,keycol:std_logic_vector(3 downto 0); signal kcount:std_logic_vector(2 downto 0); signal kflag1:std_logic; beginprocess(motor,rst) begin day<=2; night<=3; if (k1='0') then danjia<=day; else danjia<=night; end if;if rst='0' thencount<=0;temp<='0'elsif (motor'event and motor='1') thenif count>499 thencount<=0;temp<=not temp; else count<=count+1;end if;end if;glclk<=temp;end process;process(clk) begin if(clk'event and clk='1') then if(Krow="1111") then kflag1<='0' kcount<=kcount+1; if(kcount=0) then Kcol<="1110" elsif(kcount=1) then Kcol<="1101" elsif(kcount=2) then Kcol<="1011" else Kcol<="0111" end if; else kflag1<='1' keyrow<=Krow; keycol<=Kcol; end if; end if; end process; process(clk) begin if k2='1' then if(clk'event and clk='1') then if(kflag1='1') then if(keyrow="0111") then case keycol is when "0111"=>buff<=1; when "1011"=>buff<=4; when "1101"=>buff<=7; when others=>buff<=buff; end case; elsif(keyrow="1011") then case keycol is when "0111"=>buff<=2; when "1011"=>buff<=5; when "1101"=>buff<=8; when "1110"=>buff<=0; when others=>buff<=buff; end case; elsif(keyrow="1101") then case keycol is when "1101"=>buff<=9; when "1011"=>buff<=6; when "0111"=>buff<=3; when others=>buff<=buff; end case; end if; end if; qibujia<=buff; end if; else qibujia_d<=3; qibujia_n<=9;if (k1='0') then qibujia<=qibujia_d; else qibujia<=qibujia_n;end if; end if; end process; process(glclk) begin if(Rst='0') then Meter1<=0; Meter10<=0; Meter100<=0; Meter1K<=0; elsif(glclk'event and glclk='0') then if(Meter1=9) then Meter1<=0; if(Meter10=9) then Meter10<=0; if(Meter100=9) then Meter100<=0; if(Meter1K=9) then Meter1K<=0; else Meter1K<=Meter1K+1; end if; else Meter100<=Meter100+1; end if; else Meter10<=Meter10+1; end if; else Meter1<=Meter1+1; end if; end if; lucheng<=meter1k*1000+meter100*100+meter10*10+meter1*1; end process; process(clk,rst) begin if(Rst='0') or (lucheng<3) then Money1<=qibujia; Money10<=0; Money100<=0; Money1000<=0; elsif(clk'event and clk='0') then if lucheng>200 then jiage<=(lucheng-2)*danjia+qibujia+50; money1000<=(jiage-(jiage mod 1000)/1000; money100<=(jiage mod 1000)-(jiage mod 1000)mod 100)/100; money10<=(jiage mod 100)-(jiage mod 100)mod 10)/10; money1<=jiage mod 10; else jiage<=(lucheng-2)*danjia+qibujia; money1000<=(jiage-(jiage mod 1000)/1000; money100<=(jiage mod 1000)-(jiage mod 1000)mod 100)/100; money10<=(jiage mod 100)-(jiage mod 10)/10; money1<=jiage mod 10; end if; end if; end process; process(clk) begin if clk'event and clk='1' then if cdount<15 then cdount<=cdount+1; else cdount<="0000" end if; end if; end process; process(SEG_SEL) begin case (SEG_SEL+1) is when "000"=> Disp_Temp<=Meter1K; when "001"=> Disp_Temp<=Meter100; when "010"=> Disp_Temp<=Meter10; when "011"=> Disp_Temp<=Meter1; when "100"=> Disp_Temp<=money1000; when "101"=> Disp_Temp<=Money100; when "110"=> Disp_Temp<=Money10; when "111"=> Disp_Temp<=Money1; end case; end process; process(Clk) begin if(Clk'event and Clk='1') then -扫描累加 SEG_SEL<=SEG_SEL+1; Display<=Disp_Decode; end if; end process; process(Disp_Temp) -显示转换 begin case Disp_Temp is when 0=> Disp_Decode<="" -0 when 1=> Disp_Decode<="" -1 when 2=> Disp_Decode<="" -2 when 3=> Disp_Decode<="" -3 when 4=> Disp_Decode<="" -4 when 5=> Disp_Decode<="" -5 when 6=> Disp_Decode<="" -6 when 7=> Disp_Decode<="" -7 when 8=> Disp_Decode<="" -8