基于CPLD出租车计费器的课程设计..doc
目录一总体设计思路11. 设计目的12系统原理框图1二功能模块设计21. 计费模块22. 数据转换模块23. 片选信号产生模块34. 显示模块35. 数码管控制模块46. 分频模块47. 数码管选择模块4三各个模块设计及仿真51计费模块52数据转换模块83片选信号产生模块114显示模块125数码管控制模块146分频模块157 数码管选择模块17四总体设计电路图18五 硬件实现19六心得体会21七程序清单22八参考文献32一总体设计思路1. 设计目的随着EDA技术的高速发展,电子系统的设计技术发生了深刻的变化,大规模可编程逻辑器件COLD/FPGA的出现,给设计人员带来了诸多方便,利用它进行产品开发,不仅成本低,周期、可靠性高,而且具有完全的知识产权。随着社会的不断进步,人们生活水平的不断提高,出租车逐渐成为人们日常生活不可缺少的交通工具。而计价器作为出租车的一个重要组成部分,关系着出租车司机和乘客双方利益,起着重要的作用,因而出租车司机和乘客双方利益,起着重要的作用,因而出租车计价器的发展非常迅猛。2系统原理框图基于CPLD的出租车计费器的组成如图1所示。各部分主要功能包括:信号输入模块对车轮传感器的脉冲信号进行计数,并以高低电平模拟出租车启动、停止、暂停、加速按钮,具有输入信号作用;数据转换模块将计费模块输出的车费和路程换成4位的十进制数据;译码/动态扫描模块将路程与费用的数值译码后用动态扫描的方式驱动数码管;数码管显示模块将公里和计费金额用4位LED数码管显示。图1.1 系统总体框图二功能模块设计1. 计费模块 此模块为计费模块(即总体结构中的信号输入模块),实现计费功能,计费标准为:按行驶里程计费,起步价为7.00元,并在车行3公里后按2.20元/km计费,当计数器达到或超过20元时,每公里加收50%的车费,即按3.30元/km计费。CLK、START、STOP、PAUSE、JS为输入信号,分别代表汽车的起动、停止、暂停和加速,CLK为扫描时钟,硬件实现时加入时钟信号,另有两个输出,即CHEFEI和LUC,分别代表车费和路程,当车处于行驶状态时,此模块会自动记录下路程与车费状况并作为转换模块的输入。其模块生成图如下:图2.1 计费模块2. 数据转换模块此模块功能是将计费模块产生的车费与路程的模拟量转换成数字量并输出,它是一个模为10的加法计数器,可将计费模块输出的车费和路程转换成4位的十进制数。其中DACLK为时钟信号,ASCORE、BSCORE连接计费模块的CHEFEI和LUC,输出为2个4位的十进制数,可以分别表示路程和车费情况。当车运行于不同状况时,此模块会将不同的车费与路程状况转换为数字量并输出。其模块生成图如下:图2.2 数据转换模块3. 片选信号产生模块此模块功能是选择八段数码管按照设计要求进行正确的显示。其模块生成图如下:图2.3 片选信号产生模块4. 显示模块此模块为显示模块中的动态扫描/译码/数码管显示模块,功能是将已转换好的数字量加载到两个4位七段数码管上并加以显示。C2.0为片选端,用来连接片选模块的片选输出端A2.0,A1、A2、A3、A4、B1、B2、B3、B4分别连接数据转换模块的八个转换输出端,因为设计要求路程和车费都要用2位小数点来表示,所以须设置一个控制小数点的变量,即程序中的DP端,D3.0连接数码管控制模块的输入端。其模块生成图如下:图2.4 显示模块5. 数码管控制模块 此模块功能是控制七段数码管对转换后的数字量进行显示,使其完成路程和车费的显示。其中D3.0连接动态扫描/译码/数码管显示模块的D3.0端,Q6.0连接七段数码管,利用其控制特性在数码管上显示出车费和路程。其模块生成图如下:数码管控制模块6. 分频模块 div模块将实验箱上50Mhz脉冲信号分频为500hz。div生成模块图:图2.6 分频模块7. 数码管选择模块 sel通过decode3_8模块选择数码管decode3_8生成模块图: 数码管选择模块三各个模块设计及仿真1计费模块计费模块源程序:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity jfmk is port(clk,start,stop,pause,js:in std_logic; chefei,luc:out integer range 0 to 8000);end jfmk;architecture one of jfmk isbegin process(clk,start,stop,pause,js) variable a,b:std_logic; variable aa:integer range 0 to 100; variable chf,lc:integer range 0 to 8000; variable num:integer range 0 to 9; begin if(clk'event and clk='1')then if(stop='0') then chf:=0; num:=0; b:='1' aa:=0; lc:=0; elsif(start='0') then b:='0' chf:=700; lc:=0; elsif(start='1' and js='1' and pause='1') then if(b='0')then num:=num+1; end if; if(num=9)then lc:=lc+5; num:=0; aa:=aa+5; end if; elsif(start='1' and js='0' and pause='1')then lc:=lc+1; aa:=aa+1; end if; if(aa>=100)then a:='1' aa:=0; else a:='0' end if; if(lc<300)then null; elsif(chf<2000 and a='1') then chf:=chf+220; elsif(chf>=2000 and a='1')then chf:=chf+330; end if; end if; chefei<=chf; luc<=lc; end process; end one;jifei模块的时序仿真图:图3.1 计费模块时序仿真图图3.2 计费模块时序仿真图时序仿真图分析: 图中的stop为汽车停止输入端,上升沿有效;start为汽车启动输入端,上升沿有效;pause为汽车暂停输入端,上升沿有效;js为汽车加速输入端,上升沿有效。CLK为时钟源信号;chefei为汽车车费输出端,luc为汽车路程输出端。由图3.1可知:当stop,Start,pause,js全为高电平时路程按5的速度增加,起车车价为700.由图3.2可知,当路程增加到300时,车费变为920,以后路程每增加100,车费增加2202数据转换模块 x模块的源程序:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity x is port(daclk:in std_logic; ascore,bscore:in integer range 0 to 8000; age,ashi,abai,aqian,bge,bshi,bbai,bqian:out std_logic_vector(3 downto 0);end x;architecture rt1 of x isbegin process(daclk,ascore) variable comb1:integer range 0 to 8000; variable comb1a,comb1b,comb1c,comb1d:std_logic_vector(3 downto 0); begin if (daclk'event and daclk='1')then if(comb1<ascore)then if(comb1a=9 and comb1b=9 and comb1c=9)then comb1a:="0000" comb1b:="0000" comb1c:="0000" comb1d:=comb1d+1; comb1:=comb1+1; elsif(comb1a=9 and comb1b=9)then comb1a:="0000" comb1b:="0000" comb1:=comb1+1; comb1c:=comb1c+1; elsif(comb1a=9)then comb1a:="0000" comb1b:=comb1b+1; comb1:=comb1+1; else comb1a:=comb1a+1; comb1:=comb1+1; end if; else ashi<=comb1b; age<=comb1a; abai<=comb1c; aqian<=comb1d; comb1:=0; comb1a:="0000" comb1b:="0000" comb1c:="0000" comb1d:="0000" end if; end if; end process; process(daclk,bscore) variable comb2:integer range 0 to 8000; variable comb2a,comb2b,comb2c,comb2d:std_logic_vector(3 downto 0); begin if(daclk'event and daclk='1')then if(comb2<bscore)then if(comb2a=9 and comb2b=9 and comb2c=9)then comb2a:="0000" comb2b:="0000" comb2c:="0000" comb2d:=comb2d+1; comb2:=comb2+1; elsif(comb2a=9 and comb2b=9)then comb2a:="0000" comb2b:="0000" comb2:=comb2+1; comb2c:=comb2c+1; elsif(comb2a=9)then comb2a:="0000" comb2b:=comb2b+1; comb2:=comb2+1; else comb2a:=comb2a+1; comb2:=comb2+1; end if; else bshi<=comb2b; bge<=comb2a; bbai<=comb2c; bqian<=comb2d; comb2:=0; comb2a:="0000" comb2b:="0000" comb2c:="0000" comb2d:="0000" end if; end if; end process;end rt1;图3.3 数据转换模块时序仿真图图3.4 数据转换模块时序仿真图图3.5 数据转换模块时序仿真图3片选信号产生模块se模块的源程序如下:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity sel is port(clk:in std_logic; a:out std_logic_vector(2 downto 0);end sel;architecture rt1 of sel isbegin process(clk) variable b:std_logic_vector(2 downto 0); begin if(clk'event and clk='1')then if(b="111")then b:="000" else b:=b+1; end if; end if; a<=b; end process;end rt1; 片选信号产生模块时序仿真图由图可以看出,当CLK加入时钟信号时,a从000到111逐个变化,该模块可将模拟信号进行片选并有对应的数码管进行显示。4显示模块xxx1模块的源程序:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity xxxl isport(c:in std_logic_vector(2 downto 0);dp:out std_logic;a1,a2,a3,a4,b1,b2,b3,b4:in std_logic_vector(3 downto 0);d:out std_logic_vector(3 downto 0);end xxxl;architecture rtl of xxxl isbeginprocess(c,a1,a2,a3,a4,b1,b2,b3,b4)variable comb:std_logic_vector(2 downto 0);begin comb:=c;case comb iswhen"000"=>d<=a1;dp<='0'when"001"=>d<=a2;dp<='0'when"010"=>d<=a3;dp<='1'when"011"=>d<=a4;dp<='0'when"100"=>d<=b1;dp<='0'when"101"=>d<=b2;dp<='0'when"110"=>d<=b3;dp<='1'when"111"=>d<=b4;dp<='0'when others=>null;end case;end process;end rtl;图3.7 显示模块时序仿真图由上图可知,输入信号C为3位片选信号其变化范围为0到7,输入信号c从0到7逐个变化时,输出d逐个输a1,a2,a3,a4,b1,b2,b3,b4的输入信号。5数码管控制模块di模块的源程序: library ieee;use ieee.std_logic_1164.all;entity di isport(d:in std_logic _vector(3 downto 0); q:out std_logic_vector(6 downto 0);end di;architecture rtl of di isbegin process(d) begin case d is when"0000"=>q<="0111111" when"0001"=>q<="0000110" when"0010"=>q<="1011011" when"0011"=>q<="1001111" when"0100"=>q<="1100110" when"0101"=>q<="1101101" when"0110"=>q<="1111101" when"0111"=>q<="0100111" when"1000"=>q<="1111111" when others=>q<="1101111" end case; end process;end rtl; 图3.8 数码管控制模块时序仿真图图3.9 数码管控制模块时序仿真图从波形图中可看出,此模块可控制数码管完成对数字量的显示。当输入为0000-1000时数码管分别显示0,1,2,3,4,5,6,7,8。当输入为其他时数码管显示9。6分频模块div模块源程序:LIBRARY ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;ENTITY div IS port(clk:IN std_logic; clkout:OUT std_logic );end div;ARCHITECTURE one OF div IS BEGIN process(clk) variable cnt:integer range 0 to 100000; variable tmp:std_logic;begin if clk'event and clk='1' then if cnt>=99999 thencnt:=0;tmp:=not tmp;else cnt:=cnt+1;end if;end if;clkout<=tmp;end process;end one;图3.10 分频模块时序仿真图7 数码管选择模块其源程序: LIBRARY ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;ENTITY decode3_8 IS PORT(SEL:IN std_logic_vector(2 downto 0); Q:OUT std_logic_vector(7 downto 0);END decode3_8;ARCHITECTURE a OF decode3_8 ISBEGIN Q<="11111110"when sel=0 else "11111101"when sel=1 else "11111011"when sel=2 else "11110111"when sel=3 else "11101111"when sel=4 else "11011111"when sel=5 else "10111111"when sel=6 else "01111111"when sel=7 else "11111111" END a;数码管选择模块时序仿真图四总体设计电路图 总原理图五 硬件实现通过硬件下载,该电路可以完成硬件实现,芯片管脚定义可以直接用编辑pin文件。完成管脚定义后选择器件,编译后生成sof、pof文件。选择sof文件进行下载。通过对每一模块的仿真和下载,可以实现各个模块的逻辑功能,验证了各个模块的正确性。在出租车计费系统的5个模块中 ,重点在于jifei模块,x(转化)模块,显示模块。jifei模块主要有汽车的启动、停止、暂停、加速按键;转化模块主要是把车费和路程转化为4位十进制;显示模块是将车费和路程显示出来。各模块完成后,在将它们组合成完整的出租车系统,在设计过程中还需要改进的是控制系统的纠错功能。出租车计费器系统的设计已全部完成,能按预期的效果进行模拟汽车启动、停止、暂停等功能,并设计动态扫描电路显示车费数目,由动态扫描电路来完成。车暂时停止不计费,车费保持不变。若停止则车费清零,等待下一次计费的开始。出租车计费系统的设计中体现了VHDL覆盖面广,描述能力强,是一个多层次的硬件描述语言及PLD器件速度快,使用方便,便于修改等特点,本设计在实用方面具有一定的价值。实验表明:该计费器实现了按预置参数自动计费(最大计费金额为99.99元)、自动计程(最大计程公里数为99.99 km)等功能;能够实现起步价、每公里收费、车型及加费里程的参数预置(如:起步价7.00元;3 km后,2.20元/km;计费超过20.00元,每公里加收50的车费等),且预置参数可调范围广。由于采用CPLD大规模可编程逻辑器件,整机功耗小、抗干扰能力强、系统稳定、工作可靠、升级方便。其调试结果如下图所示:由图5.1可知,起步价为7元。图5.2 调试结果六心得体会短短两周的EDA课程设计已经接近尾声了,我们从挑选课设题目,查阅资料,到研究出总体设计,详细设计,然后分工合作,再到最后的编程上机调试,修改程序,完善程序,收获颇多。出租车计费器系统的设计已全部完成,能按预期的效果进行模拟汽车启动,停止、暂停等功能,并设计动态扫描电路显示车费数目。车暂停时停止计费。若停止清零,等待下一次计费的开始。出租车计费系统设计中体现了VHDL覆盖面广,描述能力强,是一个多层次的硬件描述语言及PLD器件速度快,使用方便,便于修改等特点。本设计在使用方面居庸一点的价值。由于时间有限和经验是平的欠缺,不足之处还望老师予以指正。在这辆周里我们再次熟悉和增强了对VHDL语言的基本知识,熟悉利用VHDL语言对常用的的组合逻辑电路和时序逻辑电路编程,把编程和实际结合起来。VHDL硬件描述语言打破了硬件和软件设计人员之间互不干涉的界限,可以使用语言的形式来进行数字系统的硬件结构、行为的描述,直接设计数字电路硬件系统。通过编程、下载后,该芯片已经具备了原来需要使用复杂的数字电路实现的功能;更加了解和加深了对编制和调试程序的技巧,进一步提高了上机动手能力,培养了使用设计综合电路的能力,养成了提供文档资料的习惯和规范编程的思想。本次的课程设计将各个单一的模块实现其功能后,学会通过原理图或顶层文件把各模块连接,从而实现对出租车自动计费。课设注重的不仅是把理论知识巩固,而且应把理论和实际相结合,把知识应用到生活中。在课设过程中,遇到了不少问题,数码管无法正常显示,计费不按要求等。通过的对源代码的修改,发现了一些易忽略的细节。课设考验的是思维逻辑能力,对知识的灵活应用,当然,合作精神是不可或缺的。课设时间不长,要在短时间内完成绝不是个人力量能达到的,要学会集众人之精华,还要善于利用已有的工具为自己服务,开拓思维。课设让我们认识到所学本科知识的真正实用性,只是这门课开始研究的第一步。在设计程序时,不能妄想一次就将整个程序设计好,反复修改、不断改进是程序设计的必经之路;要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便;在设计课程过程中遇到问题是很正常的,但应该将每次遇到的问题记录下来,并分析清楚,以免下次再碰到同样的问题。课程设计结束了,但是从中学到的知识会让我受益终身。发现、提出、分析、解决问题和实践能力的提高都会受益于我在以后的学习、工作和生活中。在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。最后,我们衷心的感谢课设期间一直指导和陪伴着我们的老师。七程序清单计费模块源程序:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity jfmk is port(clk,start,stop,pause,js:in std_logic; chefei,luc:out integer range 0 to 8000);end jfmk;architecture one of jfmk isbegin process(clk,start,stop,pause,js) variable a,b:std_logic; variable aa:integer range 0 to 100; variable chf,lc:integer range 0 to 8000; variable num:integer range 0 to 9; begin if(clk'event and clk='1')then if(stop='0') then chf:=0; num:=0; b:='1' aa:=0; lc:=0; elsif(start='0') then b:='0' chf:=700; lc:=0; elsif(start='1' and js='1' and pause='1') then if(b='0')then num:=num+1; end if; if(num=9)then lc:=lc+5; num:=0; aa:=aa+5; end if; elsif(start='1' and js='0' and pause='1')then lc:=lc+1; aa:=aa+1; end if; if(aa>=100)then a:='1' aa:=0; else a:='0' end if; if(lc<300)then null; elsif(chf<2000 and a='1') then chf:=chf+220; elsif(chf>=2000 and a='1')then chf:=chf+330; end if; end if; chefei<=chf; luc<=lc; end process; end one;数据转换模块的源程序:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity x is port(daclk:in std_logic; ascore,bscore:in integer range 0 to 8000; age,ashi,abai,aqian,bge,bshi,bbai,bqian:out std_logic_vector(3 downto 0);end x;architecture rt1 of x isbegin process(daclk,ascore) variable comb1:integer range 0 to 8000; variable comb1a,comb1b,comb1c,comb1d:std_logic_vector(3 downto 0); begin if (daclk'event and daclk='1')then if(comb1<ascore)then if(comb1a=9 and comb1b=9 and comb1c=9)then comb1a:="0000" comb1b:="0000" comb1c:="0000" comb1d:=comb1d+1; comb1:=comb1+1; elsif(comb1a=9 and comb1b=9)then comb1a:="0000" comb1b:="0000" comb1:=comb1+1; comb1c:=comb1c+1; elsif(comb1a=9)then comb1a:="0000" comb1b:=comb1b+1; comb1:=comb1+1; else comb1a:=comb1a+1; comb1:=comb1+1; end if; else ashi<=comb1b; age<=comb1a; abai<=comb1c; aqian<=comb1d; comb1:=0; comb1a:="0000" comb1b:="0000" comb1c:="0000" comb1d:="0000" end if; end if; end process; process(daclk,bscore) variable comb2:integer range 0 to 8000; variable comb2a,comb2b,comb2c,comb2d:std_logic_vector(3 downto 0); begin if(daclk'event and daclk='1')then if(comb2<bscore)then if(comb2a=9 and comb2b=9 and comb2c=9)then comb2a:="0000" comb2b:="0000" comb2c:="0000" comb2d:=comb2d+1; comb2:=comb2+1; elsif(comb2a=9 and comb2b=9)then comb2a:="0000" comb2b:="0000" comb2:=comb2+1; comb2c:=comb2c+1; elsif(comb2a=9)then