使用LPM计数器的VHDL交通灯FSM:在哪里设置/重置计数器?

时间:2015-03-19 16:41:35

标签: vhdl fsm

过去两天这一次令人难以置信,所以我来到互联网寻求帮助。

首先背景信息...... 我正在使用Altera DE0板为uni工作的交通灯项目。关于VHDL,我完成了n00b,这个第一个任务或多或少是"这里有一个有限状态机的例子和一个LPM计数器的例子,去做一些流量灯&#34 ;.我认为这个想法只是为了感受使用VHDL并弄乱代码来使某些东西发挥作用。

我们从FSM上的教科书(Free Range VHDL p93 iirc)中得到了一个例子,然后展示了如何使用Quartus中的Megawizard插件管理器创建一个LPM计数器,基本上只需合并/扩展它们。这是我使用VHDL做的第一件事。

交通信号灯应该是主要道路和小路的交叉路口。默认状态将是主要道路绿色和次要道路红色。它应该保持这种状态,直到它检测到按钮(即小路上的汽车)然后变为琥珀色然后变为红色,然后小路将从红色变为绿色并保持绿色10秒。它将保持在彼此状态1秒钟。 我已经使用了9个状态(A-I)和一个LPM计数器,而我只想在" q"的第26位和第29位寻找1。计数器的输出(?)为1秒和10秒延迟。

我的问题是我不知道在哪里设置和重置计时器。从技术上讲,它应该在移动到每个状态后重置,然后在移动到下一个状态时设置(即允许计数)。

我将粘贴下面的代码,目前timer_rst位被注释掉了。我已经尝试将它们放在代码中的所有不同行中,但最接近它的工作是设置和重置定时器,其中注释了设置和重置部分。当我一次一个地取消评论它们并且每次从状态A转到B然后转C时运行它,但之后它会跳到E然后它快速地通过状态移动到所有状态LED发光,似乎随机跳过不同的状态。显然这不是应该怎么做的!

那么有人可以帮助我吗?

我希望我在这里得到了足够好的解释。我会粘贴指向运行我的代码的电路板视频的链接,您也可以查看下面的代码。

感谢您提供的任何帮助!

--Finite state machine using DE0 board implementing a set
--of traffic tights at a major road/minor road junction.
--Major road is green until car present at minor road 
--then goes to red while minor road goes to green.
--8 states, A-H. A is 'default' state
--1 sec delay: state B,C,D,F,G,H, 10 sec delay: state E,I.
--Maj Rd lights: LEDG(5 downto 3) Red/Amber/Green.
--Min Rd lights: LEDG(2 downto 0) Red/Amber/Green.
--State vector printed on LEDG(9 downto 6) in binary                             

--library declarations
LIBRARY ieee; 
USE ieee.std_logic_1164.all;

LIBRARY lpm;        --allows use of Altera LPM functions  
USE lpm.all;

--entity
entity TRAFFICLIGHTS is
  port( 
    KEY      : in std_logic_vector(1 downto 0); --minor rd car present KEY(1) & reset KEY(0)-ACTIVE LOW!
    CLOCK_50 : in std_logic;
    LEDG       : out std_logic_vector(9 downto 0); --6 lights 2 * (red/amber/green) & state vector
    HEX0        : out std_LOGIC_VECTOR(7 downto 0)      --display current state
  ); 
end TRAFFICLIGHTS;

-- architecture
architecture TRAFFICLIGHTS_arch of TRAFFICLIGHTS is
type state_type is (A,B,C,D,E,F,G,H,I);
signal PS, NS       : state_type;
signal timer_rst    : std_logic;    --wiring to delay components , one_sec, ten_sec
signal timer_q  : std_logic_vector(29 downto 0);        --output from timer 
--LPM counter  
component timer
    PORT
    (
        aclr        : IN STD_LOGIC ;
        clock       : IN STD_LOGIC ;
        q           : OUT STD_LOGIC_VECTOR (29 DOWNTO 0)    --uses bit 29 for 10 secs, bit 26 for 1 sec
    );
end component;

begin

--wiring up LPM counter to signals
U1 : timer
    PORT MAP (
        aclr  => timer_rst,
        clock => clock_50,
        q     => timer_q
);

--detects change in clock, next state or reset key press
sync_proc: process (clock_50, NS, KEY(0))
    begin
        if (KEY(0)='0') then    --if reset pressed, return to state A
            PS <= A;
            elsif (rising_edge(clock_50)) then      --else put present state in next state
            PS <= NS;
        end if;
    end process sync_proc;

--detect change in present state or KEY(1) i.e. minor road car present  
comb_proc: process (PS, KEY(1))

begin

    case PS is
            when A => --when in A: MajRd green, MinRd red, no delay
                --show state vector using 4 bit binary 1-8
                LEDG(9 downto 6) <= "0001";
                HEX0(7 downto 0) <= "10001000";   --display state on 7 seg
                LEDG(5) <= '0'; --MajRed
                LEDG(4) <= '0'; --MajAmber
                LEDG(3) <= '1'; --MajGreen
                LEDG(2) <= '1'; --MinRed
                LEDG(1) <= '0'; --MinAmber
                LEDG(0) <= '0'; --MinGreen

                if (KEY(1) = '0') then 
                    --timer_rst <= '1'; -- reset timer
                    --timer_rst      <= '0';    -- allow timer to count
                    NS        <=  B; --if car present @MinRd, next state is B
                else    NS <= A;
                end if;

            when B => --when in B: MajRd amber, MinRd red, 1 sec delay
                --print state vector using 4 bit binary 1-8
                LEDG(9 downto 6) <= "0010";
                HEX0(7 downto 0) <= "10000011";     --display state on 7 seg
                LEDG(5) <= '0'; --MajRed
                LEDG(4) <= '1'; --MajAmber
                LEDG(3) <= '0'; --MajGreen
                LEDG(2) <= '1'; --MinRed
                LEDG(1) <= '0'; --MinAmber
                LEDG(0) <= '0'; --MinGreen    

                if (timer_q(26) = '1') then 
                --timer_rst <= '1'; -- reset timer
                  --timer_rst <= '0';   -- allow timer to count
                        NS        <= C;
                else  NS         <= B;
                end if;

            when C => --when in C: MajRd red, MinRd red, 1 sec delay
                --print state vector using 4 bit binary 1-8
                LEDG(9 downto 6) <= "0011";
                HEX0(7 downto 0) <= "11000110";         --display state on 7 seg

                LEDG(5) <= '1'; --MajRed
                LEDG(4) <= '0'; --MajAmber
                LEDG(3) <= '0'; --MajGreen
                LEDG(2) <= '1'; --MinRed
                LEDG(1) <= '0'; --MinAmber
                LEDG(0) <= '0'; --MinGreen    

                if (timer_q(26) = '1') then 
                  --timer_rst <= '1';   -- reset timer
                  --timer_rst <= '0';   -- allow timer to count
                    NS        <= D;
                else  NS             <= C;
                end if;

            when D => --when in D: MajRd red, MinRd red/amber, 1 sec delay
                --print state vector using 4 bit binary 1-8
                LEDG(9 downto 6) <= "0100";
                HEX0(7 downto 0) <= "10100001";         --display state on 7 seg
                LEDG(5) <= '1'; --MajRed
                LEDG(4) <= '0'; --MajAmber
                LEDG(3) <= '0'; --MajGreen
                LEDG(2) <= '1'; --MinRed
                LEDG(1) <= '1'; --MinAmber
                LEDG(0) <= '0'; --MinGreen

                if (timer_q(26) = '1') then 
                  --timer_rst <= '1';   -- reset timer
                        --timer_rst <= '0'; -- allow timer to count
                  NS        <= E;
                else  NS             <= D;
                end if;

            when E => --when in E: MajRd red, MinRd green, 10 sec delay
                --print state vector using 4 bit binary 1-8
                LEDG(9 downto 6) <= "0101";
                HEX0(7 downto 0) <= "10000110";         --display state on 7 seg
                LEDG(5) <= '1'; --MajRed
                LEDG(4) <= '0'; --MajAmber
                LEDG(3) <= '0'; --MajGreen
                LEDG(2) <= '0'; --MinRed
                LEDG(1) <= '0'; --MinAmber
                LEDG(0) <= '1'; --MinGreen    

            if (timer_q(29) = '1') then
              --timer_rst <= '1';   -- reset timer
              --timer_rst <= '0';   -- allow timer to count
                    NS        <= F;
            else  NS             <= E;
            end if;

        when F => --when in F: MajRd red, MinRd amber, 1 sec delay
            --print state vector using 4 bit binary 1-8
            LEDG(9 downto 6) <= "0110";
            HEX0(7 downto 0) <= "10001110";         --display state on 7 seg
            LEDG(5) <= '1'; --MajRed
            LEDG(4) <= '0'; --MajAmber
            LEDG(3) <= '0'; --MajGreen
            LEDG(2) <= '0'; --MinRed
            LEDG(1) <= '1'; --MinAmber
            LEDG(0) <= '0'; --MinGreen

            if (timer_q(26) = '1') then 
              --timer_rst <= '1';   -- reset timer
              --timer_rst <= '0';   -- allow timer to count
                    NS        <= G;
            else  NS             <= F;
            end if;         

        when G => --when in G: MajRd red, MinRd red, 1 sec delay
            --print state vector using 4 bit binary 1-8
            LEDG(9 downto 6) <= "0111";
            HEX0(7 downto 0) <= "10010000";         --display state on 7 seg
            LEDG(5) <= '1'; --MajRed
            LEDG(4) <= '0'; --MajAmber
            LEDG(3) <= '0'; --MajGreen
            LEDG(2) <= '1'; --MinRed
            LEDG(1) <= '0'; --MinAmber
            LEDG(0) <= '0'; --MinGreen

            if (timer_q(26) = '1') then 
              --timer_rst <= '1';   -- reset timer
              --timer_rst <= '0';   -- allow timer to count
                    NS        <= H;
            else  NS             <= G;
            end if;

        when H => --when in H: MajRd red/amber, MinRd red, 1 sec delay
            --print state vector using 4 bit binary 1-8
            LEDG(9 downto 6) <= "1000";
            HEX0(7 downto 0) <= "10001001";         --display state on 7 seg
            LEDG(5) <= '0'; --MajRed
            LEDG(4) <= '0'; --MajAmber
            LEDG(3) <= '1'; --MajGreen
            LEDG(2) <= '1'; --MinRed
            LEDG(1) <= '0'; --MinAmber
            LEDG(0) <= '0'; --MinGreen

            if (timer_q(26) = '1') then 
              --timer_rst <= '1';   -- reset timer
              --timer_rst <= '0';   -- allow timer to count
                    NS        <= I;
            else  NS             <= H;
            end if;

        --new state allows MajRd to stay green (10 sec) if car at MinRd or not
        when I => --when in I: MajRd green, MinRd red, 10 sec delay
            --print state vector using 4 bit binary 1-8
            LEDG(9 downto 6) <= "1001";
            HEX0(7 downto 0) <= "11111001";         --display state on 7 seg
            LEDG(5) <= '0'; --MajRed
            LEDG(4) <= '0'; --MajAmber
            LEDG(3) <= '1'; --MajGreen
            LEDG(2) <= '1'; --MinRed
            LEDG(1) <= '0'; --MinAmber
            LEDG(0) <= '0'; --MinGreen

            if (timer_q(29) = '1') then 
              --timer_rst <= '1';   -- reset timer
              --timer_rst <= '0';   -- allow timer to count
                    NS        <= C;
            else  NS             <= A;
            end if;

        when others => -- the catch-all condition
          PS <= A; -- if anything else, return to state A
    end case;
  end process comb_proc;
end TRAFFICLIGHTS_arch;

视频: https://www.dropbox.com/s/70tkr67zdjj8pyk/File%2018-03-2015%2017%2057%2054.mov?dl=0

尝试添加中间状态,这里是以下前几个的case语句中的代码。它刚刚开始并直接跳到B状态,而不是去任何地方。

    case PS is
            when A => --when in A: MajRd green, MinRd red, no delay
                --show state vector using 4 bit binary 1-8
                LEDG(9 downto 6) <= "0001";
                HEX0(7 downto 0) <= "10001000";   --display state on 7 seg
                LEDG(5) <= '0'; --MajRed
                LEDG(4) <= '0'; --MajAmber
                LEDG(3) <= '1'; --MajGreen
                LEDG(2) <= '1'; --MinRed
                LEDG(1) <= '0'; --MinAmber
                LEDG(0) <= '0'; --MinGreen

                if (KEY(1) = '0') then 
                    timer_rst <= '1';   -- reset timer
                    --timer_rst      <= '0';    -- allow timer to count
                    NS        <=  B; --if car present @MinRd, next state is B
                else    NS <= A_1;
                end if;

            when A_1 =>
                --LEDs and 7 seg same as A
                LEDG(9 downto 0) <= "0001001100";
                HEX0(7 downto 0) <= "10001000";   --display state on 7 seg
                timer_rst    <= '0';    -- allow timer to count
                NS <= B;

            when B => --when in B: MajRd amber, MinRd red, 1 sec delay
                --print state vector using 4 bit binary 1-8
                LEDG(9 downto 6) <= "0010";
                HEX0(7 downto 0) <= "10000011";     --display state on 7 seg
                LEDG(5) <= '0'; --MajRed
                LEDG(4) <= '1'; --MajAmber
                LEDG(3) <= '0'; --MajGreen
                LEDG(2) <= '1'; --MinRed
                LEDG(1) <= '0'; --MinAmber
                LEDG(0) <= '0'; --MinGreen

                if (timer_q(26) = '1') then 
                      timer_rst <= '1'; -- reset timer
                  --timer_rst <= '0';   -- allow timer to count
                        NS        <= B_1;
                else  NS         <= B;
                end if;

            when B_1 =>
                --LEDs and 7 seg same as B
                LEDG(9 downto 0) <= "0010010100";
                HEX0(7 downto 0) <= "10000011";     --display state on 7 seg
                timer_rst    <= '0';    -- allow timer to count
                NS <= C;

1 个答案:

答案 0 :(得分:0)

克里斯,检查&#34;硬件中的有限状态机......&#34;,V。A. Pedroni,麻省理工学院出版社,第166页。