原创 VHDL实验二:设计一个地铁自动售票系统

2010-12-20 16:49 3146 7 7 分类: FPGA/CPLD

一、实验题目:


功能实现:


1、具备3各车站的选择


2、可接受5元,1元的输入


3、可按照1元的输出找零


设计框图:



图1.1整体设计框图


设计要求:


1、 输入均以低电平有效,对于投币口,在一个时钟的上升沿扫描到一次低电平,表示投币一次,


2、 三个车站:2元  5元 7元


3、 找钱口输出一个脉冲代表找回1元


4、 系统在使用时应先按下所选车站后,在投币,其中系统自动判断投入钱的是否足够


二、实验过程:


为了简化实验,本实验采用了模块化设计。模块化的好处有:有利于设计的简便性,在设计过程中由于采用模块化,将每个模块相互独立开来,让设计思路更加明确。同时每一个模块都能独立测试,为仿真检错带来了方便。


在本次设计方案中,采用了三个子模块,分别是按键模块,车站模块,找零并行转串行输出模块。下面是每一个模块的设计方框图:


按键模块:



图2.1按键模块设计框图


车站模块:



 


图2.2车站模块设计框图



图2.3找零模块设计框图


1、    算法流程与程序设计:


按键模块设计:


程序设计:


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


entity key is


   port(clk:in std_logic;


        rst:in std_logic;


        key:in std_logic_vector(2 downto 0);


        s0:out std_logic;


        s1:out std_logic;


        s2:out std_logic);


end entity;


 


architecture behav of key is


  begin


  process(clk,rst)


  begin


  if(rst='0') then


  s0<='1';


  s1<='1';


  s2<='1';


   else


  case key is


  when "011"=>


        s0<='0';


        s1<='1';


        s2<='1';


  when "101"=>


        s0<='1';


        s1<='0';


        s2<='1';


  when "110"=>


        s0<='1';


        s1<='1';


        s2<='0';


   when others=>


       s0<='1';


       s1<='1';


       s2<='1';


  end case;


 


  end if;


   end process;


     


end behav;


仿真波形:



仿真波形分析:


clk信号为时钟信号,产生时钟脉冲。rst为系统复位信号。低电平复位。fan信号用车站进程结束反馈信号。key分别为三个输入按键。s0,s1,s3分别选通车站的片选信号。


 


车站模块设计:每个车站的设计思想都是一样的。只是设计的状态机不一样。


车站一:收费2元;输入可能是两个1元,一个1元一个5元,一个5元:三种可能。


状态机设计流图:



程序设计如下:


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


entity tran1 is


   port(clk:in std_logic;


        s:in std_logic;


        x:in std_logic;


        y:in std_logic;


        chu1:out std_logic;


        z1:out std_logic_vector(2 downto 0));


end entity;


 


 


architecture behav of tran1 is


   type state is(s0,s1,s2);


   signal present_state:state:=s0;


   begin


  process(clk,x,y,s)


        begin


   if clk'event and clk='1' then


   case present_state is


     when s0=>


        if(s='0') then


        chu1<='0';z1<="000";


        present_state<=s1;


        else


        chu1<='0'; z1<="000"; present_state<=s0;


        end if;


     when s1=>


      if(x='1') then


       if(y='0') then


           chu1<='1';


           z1<="011";  ----找回3块钱


           present_state<=s0;


           else chu1<='0';  present_state<=s1;


        end if;


       else


       chu1<='0'; present_state<=s2;  


       end if;


        when s2=>


      if(x='1') then


           if(y='1')  then


             chu1<='0';  present_state<=s2;


             else


             chu1<='1';


             z1<="100"; ----找回4块钱


             present_state<=s0;


             end if;


           else chu1<='1';


                z1<="000";


                present_state<=s0;      


        end if;


    end case;


    end if;


    end process;      


end behav;仿真波形如下:



 


车站二:收费5元;输入可能是5个1元,or先输入n(0<=n<5)个1元和一个5元:6种可能。


状态机设计流程图如下:



程序设计如下:


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


entity tran2 is


   port(clk:in std_logic;


        s:in std_logic;


        x:in std_logic;


        y:in std_logic;


        chu2:out std_logic;


        z2:out std_logic_vector(2 downto 0));


end entity;


 


architecture behav of tran2 is


   type state is(s0,s1,s2,s3,s4,s5);


   signal present_state:state:=s0;


   begin


  process(clk,x,y,s)


        begin


   if clk'event and clk='1' then


   case present_state is


     when s0=>


        if(s='0') then


        chu2<='0';z2<="000";


        present_state<=s1;


        else


        chu2<='0'; z2<="000"; present_state<=s0;


        end if;


     when s1=>


      if(x='1') then


       if(y='1') then


        chu2<='0';


        z2<="000"; 


        present_state<=s1;


           else


           chu2<='1';


           z2<="000";


           present_state<=s0;


        end if;


       else


       chu2<='0'; z2<="000"; present_state<=s2;


       end if;


        when s2=>


          if(x='1') then


             if(y='1') then


               chu2<='0';


               z2<="000";


               present_state<=s2;


               else


               chu2<='1';


               z2<="001";


               present_state<=s0;


           


             end if;


           else


               chu2<='0';z2<="000";  present_state<=s3;       


           end if;


       when s3=>


           if(x='1') then


             if(y='1') then


             chu2<='0';


             z2<="000";


             present_state<=s3;


             else 


             chu2<='1';


             z2<="010";


             present_state<=s0;


             end if;


           else


               chu2<='0';z2<="000";  present_state<=s4;       


           end if;


       


        when s4=>


           if(x='1') then


             if(y='1') then


             chu2<='0';


             z2<="000";


             present_state<=s4;


             else


             chu2<='1';


             z2<="011";


             present_state<=s0;


             end if;


           else


               chu2<='0';z2<="000";  present_state<=s5;       


           end if;


       


        when s5=>


           if(x='1') then


             if(y='1') then


             chu2<='0';


             z2<="000"; 


             present_state<=s5;


             else 


             chu2<='1';


             z2<="100";


             present_state<=s0;


             end if;


           else


               chu2<='1';z2<="000";  present_state<=s0;       


           end if;


    end case;


    end if;


    end process;


    


    end behav;


仿真波形如下:



 


车站三:收费7元:



程序设计如下:


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


entity tran3 is


   port(clk:in std_logic;


        s:in std_logic;


        x:in std_logic;


        y:in std_logic;


        chu3:out std_logic;


        z3:out std_logic_vector(2 downto 0));


end entity;


 


 


architecture behav of tran3 is


   type state is(s0,s1,s2,s3,s4,s5,s6,s7,m0);


   signal present_state:state:=s0;


   begin


qian:  process(clk,x,y,s)


        begin


   if clk'event and clk='1' then


   case present_state is


    when s0=>


        if(s='0') then


        chu3<='0';z3<="000";


        present_state<=s1;


        else


        chu3<='0'; z3<="000"; present_state<=s0;


        end if;


 


     when s1=>


      if(x='1') then


       if(y='1') then


           chu3<='0'; z3<="000";


           present_state<=s1;


           else chu3<='0'; z3<="000"; present_state<=m0;


        end if;


       else


      chu3<='0'; z3<="000";  present_state<=s2;


       end if;


      


        when s2=>


         if(x='1') then


           if(y='1') then


           chu3<='0'; z3<="000";  present_state<=s2;


           else


           chu3<='0'; z3<="000";  present_state<=s7;


           end if;


           else


           chu3<='0'; z3<="000";  present_state<=s3;  


          end if;


         


        when s3=>


         if(x='1') then  


           if(y='1') then


           chu3<='0'; z3<="000"; present_state<=s3;


           else


           chu3<='1';


           z3<="000";


           present_state<=s0;


           end if;


           else


           chu3<='0'; z3<="000"; present_state<=s4;  


          end if;   


         


          when s4=>


         if(x='1') then  


           if(y='1') then


           chu3<='0'; z3<="000"; present_state<=s4;


           else


           chu3<='1';


           z3<="001";


           present_state<=s0;


           end if;


           else


           chu3<='0'; z3<="000"; present_state<=s5;  


          end if;  


         


         


           when s5=>


         if(x='1') then  


           if(y='1') then


           chu3<='0'; z3<="000"; present_state<=s5;


           else


           chu3<='1';


           z3<="010";


           present_state<=s0;


           end if;


           else


           chu3<='0'; z3<="000"; present_state<=s6; 


          end if;


         


         


            when s6=>


         if(x='1') then  


           if(y='1') then


           chu3<='0'; z3<="000"; present_state<=s6;


           else


           chu3<='1';


           z3<="011";


           present_state<=s0;


           end if;


           else


           chu3<='0'; z3<="000"; present_state<=s7; 


          end if;  


         


         


             when s7=>


         if(x='1') then  


           if(y='1') then


           chu3<='0'; z3<="000"; present_state<=s7;


           else


           chu3<='1';


           z3<="100";


           present_state<=s0;


           end if;


           else


           chu3<='1';


           z3<="000";


           present_state<=s0;


          end if;


         


         


         


           when m0=>


         if(x='1') then


           if(y='1') then 


           chu3<='0'; z3<="000"; present_state<=m0;


           else


           chu3<='1';


           z3<="011";


           present_state<=s0;


           end if;


          else


             chu3<='0'; z3<="000"; present_state<=s7;


          end if;


           when others=>


           chu3<='0';


           z3<="000";


          


    end case;


    end if;


    end process;


end behav;


 



 


找零并行转串行脉冲输出模块:输入信号为3位并行信号,输出为串行脉冲信号。


状态机设计:



 


程序设计:


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


 


entity change is


port(clk,send:in std_logic;


     d_in:in std_logic_vector(2 downto 0);


     y:out std_logic:='0');


end entity;


 


architecture behav of change is


  type state is(s0,s1);


  signal reg:std_logic_vector(0 to 7);


begin


 


process(clk,send,d_in)


variable present_state:state;


variable cnt:integer range 0 to 8:=0;


variable count:integer range 0 to 5:=0;


variable sign:integer range 0 to 1:=0;


  begin


    if(clk'event and clk='1') then


    case present_state is


      when s0=>


      cnt:=0;


      sign:=0;


      y<='0';


      reg<=(others=>'0');


      if(send='1') then


          if(d_in="100") then


            reg<="10101010";


            elsif(d_in="011") then


              reg<="10101000";


              elsif(d_in="010") then


                reg<="10100000";


              elsif(d_in="001") then


                reg<="10000000";


           end if;


           present_state:=s1;


          else


          present_state:=s0;


       end if;


      


       when s1=>


         if(sign=0) then


            y<='0';


            sign:=1;


            present_state:=s1;


            else


              if(cnt<8) then


                if(reg(cnt)='0') then   


                       y<='0';


                       cnt:=cnt+1;


                       present_state:=s1;


                   elsif(reg(cnt)='1') then


                         y<='1';


                         cnt:=cnt+1;                     


                         present_state:=s1;


 


                 end if;


                  else


                    present_state:=s0;


                 end if;


                end if;


               end case;


             end if;


  end process;


end behav;


仿真运行结果:



综合设计


图形化设计:



仿真波形图:



仿真分析:key0选通车站3,y投入两个5元,change3找回零钱3元,out3出票一张。key1选通车站2,x投入1元,y投入5元,change2找回零钱1元,out2出票一张。Key2选通车站1,y投入5元,change1找回零钱3元,out1出票一张。


 


实验总结:啊。又完成了一次对自己的超越。好开心。一直以来自己的编程能力都是一般般,但是这次的程序基本上都是自己设计完成的。发现状态机真的是化腐朽为神奇,特别是在设计找零钱这一个模块上。开始接触VHDL的时候,听说他是并行的,速度快,挺不错。但是现在编程才发现,并行的同时也意味着程序的无序性。这是个相当纠结的问题。好在还有状态机,将原来并行的无序性治的服服帖帖。感觉两次作业都是一次对自己的飞跃性的超越,第一次作业是一次对自己从不懂到懂的一个过程的超越。而第二次作业时一次对自己从局部到整体的一个过程的超越。在这次作业中,自己不但能够独立的设计程序的同时,更加深的一层的熟悉了软件的开发环境,学会了利用图形化设计的工具,学会了模块化设计,掌握了一个工程如何构架,如何分工,如何实现的开发过程,特别是在模块化设计的同时,深深体会到一个工程可以分割成多个子模块进行同步设计,这样的话一个团队工作可以共同进行,同时也加快了工程的设计进度,同时也减轻了程序的繁杂,化繁为简,有利于工程的顺利进行,体现了团队合作的精神。感觉这也是每一个工程师的必走之路。希望以后再接再厉,不断超越自我。


 


主要遇到的问题:


问题1:并行程序的并行性和无序性。在设计程序的时候这个问题是相当郁闷,后来利用状态机搞掂了这个问题。


问题2:error(10028):can't resolve multiple constant drivers for net



在可逆计数器的设计中的错误,两个进程里都有同一个条件判断的话,会产生并行信号冲突的问题。


同一个信号不允许在多个进程中赋值,否则则为多驱动。


进程的并行性决定了多进程不同能对同一个对象进行赋值。


 


原本以为可以将每一个找零钱的端口都连接在一起。但是却发现怎么也行不通,当初在这个地方纠结了好一阵。后来就直接放弃了。将每一个找零的口都分别接出来。再后来利用波形仿真的时候才发现,这是根本行不通的。如下图:



change3和change2冲突了。


问题3:系统的bug,原本设计的时候在系统框图上设计了一个反馈信号,用于等完成一次才能选择下一个车站。但是后来感觉不用反馈信号也能完成功能。所以程序设计的时候没有加上去。现在想想这里应该是系统的一个bug,应用到实际中,不加反馈信号好像是会有一些意想不到的问题出现


 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条