VHDL 交通灯控制器

VHDL Traffic Light Controller

这是一个交通灯控制器的简单代码。它根据计数器值循环通过状态。但是,我希望它在按下按钮时在第一个状态下多停留 10 秒,我想知道我会怎么做。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity TLC is
    Port (
              Trafficlights: out  STD_LOGIC_Vector (5 downto 0);
              Clck : in  STD_LOGIC;
              Reset : in  STD_LOGIC;
              P_B : in STD_LOGIC);
 end TLC;

architecture Behavioral of TLC is
  type state_type is (st0_R1_G2, st1_R1_A1_A2, st2_G1_R2, st3_A1_R2_A2); 

  signal state: state_type; 
  signal count : std_logic_vector (3 downto 0);

  constant sec10 : std_logic_vector ( 3 downto 0) := "1010";
  constant sec2 : std_logic_vector (3 downto 0 ) := "0010";
  constant sec16: std_logic_vector (3 downto 0 ) := "1111";
begin
  process (Clck,Reset)
  begin
    if Reset='1' then
      state <= st0_R1_G2;         --reset to initial state
      count <= X"0";             -- reset counter
    elsif Clck' event and Clck = '1' then --rising edge
       case (state) is              ---state transitions
         when st0_R1_G2 =>
           if count < sec10 then
             state <= st0_R1_G2;
             count <= count + 1;                
           else  
             state <= st1_R1_A1_A2;
             count <= X"0";
           end if;

         when st1_R1_A1_A2 =>
           if count < sec2 then
             state <=  st1_R1_A1_A2;
             count <= count + 1;
           else
             state <= st2_G1_R2;
             count <= X"0";
           end if;

         when st2_G1_R2 =>
           if count < sec10 then
             state <= st2_G1_R2;
             count <= count + 1;
           else
             state <= st3_A1_R2_A2;
             count <= X"0";
           end if;

         when st3_A1_R2_A2 =>   
           if count < sec2 then
             state <=  st3_A1_R2_A2;
             count <= count + 1;
           else
             state <=st0_R1_G2;
             count <= X"0";
           end if; 

         when others =>
           state <= st0_R1_G2;
       end case;      
     end if;
   end process;

   OUTPUT_DECODE: process (state)
   begin
     case state is 
       when st0_R1_G2 =>    Trafficlights <= "100001";  -- Traffic Red 1, Pedestrian Green 1 
       when st1_R1_A1_A2 => Trafficlights <= "110010";
       when st2_G1_R2 =>    Trafficlights <= "001100";
       when st3_A1_R2_A2 => Trafficlights <= "010110";
       when others =>       Trafficlights <= "100001";
     end case; 
   end process;
 end Behavioral;

我没有模拟过这个。

想法是将 count 计数器延长一点,包括额外的 10 秒。输入 p_b 用于异步设置用于启动扩展计数的按钮事件锁存器,大概允许人行横道交通在前 10 秒内通过。

它由 JK 触发器 (crosstime) 控制。这里值得注意的特征应该是人行横道仅在延长的 20 秒时间段的前 10 秒内启用。你不准许穿越。

所有这些都假定您的按钮是一个按需行人过路请求,您不解释您的州名或您的灯。

我猜你想用 crosstime 关闭行人绿灯。

(如果这不起作用或不是您想要的,那么您就得到了您付出的代价。)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity tlc is
    port (
        trafficlights:  out std_logic_vector (5 downto 0);
        clck:           in  std_logic;
        reset:          in  std_logic;
        p_b:            in std_logic
    );
 end entity tlc;

architecture behavioral of tlc is
    type state_type is (st0_r1_g2, st1_r1_a1_a2, st2_g1_r2, st3_a1_r2_a2); 

    signal state: state_type; 
    signal count: std_logic_vector  (4 downto 0) ; -- (3 downto 0);
    signal pb_event:    std_logic;
    signal crosstime: std_logic;  -- JK FF

    constant sec10 : std_logic_vector (4 downto 0) := "01010"; -- ( 3 downto 0) := "1010";
    constant sec2 : std_logic_vector (4 downto 0) := "00010"; -- (3 downto 0 ) := "0010";
    -- constant sec16: std_logic_vector (4 downto 0) := "01111"; -- (3 downto 0 ) := "1111";
    constant sec20: std_logic_vector (4 downto 0) := "10100"; -- new
begin

    process (clck, reset, p_b)  -- added push button
    begin
        if p_b = '1' and reset = '0' then  -- asynch set for push button
            pb_event <= '1';
        end if;
        if reset = '1' then
            state <= st0_r1_g2;         -- reset to initial state
            count <= (others => '0');   -- reset counter
            pb_event <= '0';
            crosstime  <= '0';
        elsif clck' event and clck = '1' then -- rising edge
            if pb_event = '1' and count = "00000" then  -- J input
                crosstime <= '1';
            end if;
            case (state) is              -- state transitions
                when st0_r1_g2 =>
                    if (crosstime = '0' and count < 20) or 
                       (crosstime = '1' and count < sec10) then
                        state <= st0_r1_g2;
                        count <= count + 1;
                    else  
                        state <= st1_r1_a1_a2;
                        count <= "00000"; -- x"0";
                        if crosstime = '1' then   -- K input
                            crosstime <= '0';
                            pb_event <= '0';
                        end if;
                    end if;
                when st1_r1_a1_a2 =>
                    if count < sec2 then
                        state <=  st1_r1_a1_a2;
                        count <= count + 1;
                    else
                        state <= st2_g1_r2;
                        count <= (others => '0');
                    end if;
                when st2_g1_r2 =>
                    if count < sec10 then
                        state <= st2_g1_r2;
                        count <= count + 1;
                    else
                        state <= st3_a1_r2_a2;
                        count <= (others => '0');
                    end if;
                when st3_a1_r2_a2 =>   
                    if count < sec2 then
                        state <=  st3_a1_r2_a2;
                        count <= count + 1;
                    else
                        state <=st0_r1_g2;
                        count <= (others => '0');
                    end if; 
                when others =>
                    state <= st0_r1_g2;
            end case;
        end if;
    end process;

output_decode: 
    process (state)
    begin
        case state is 
            when st0_r1_g2 =>    trafficlights <= "100001";  -- traffic red 1, pedestrian green 1 
            when st1_r1_a1_a2 => trafficlights <= "110010";
            when st2_g1_r2 =>    trafficlights <= "001100";
            when st3_a1_r2_a2 => trafficlights <= "010110";
            when others =>       trafficlights <= "100001";
        end case; 
    end process;
end architecture behavioral;


* ...我试图综合这个,但我得到错误提示 "Signal pb_event cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release." 你认为这是因为它是异步的并且与同步设计的其余部分不兼容吗?*

不知道供应商抱怨 pb_even 这有点束缚了我们的手脚。

它似乎在抱怨在 pb_event 上同时进行了异步设置和异步重置。删除异步重置可能会解决问题(需要设置来告诉我们有人想要使用人行横道)。

让我们将 pb_event 触发器移出当前进程以使其可用。仅使用设置输入的结果是重置将设置 pb_event 并导致第一个人行横道事件。

请注意,我仍然不了解红绿灯,我在状态 st0_r1_g2 中所做的修改预计人行横道灯会在较长的 20 秒间隔的前 10 秒内启用。这不包括在这里。

您也可以简单地将计数与结束计数进行相等比较,使用“/=”而不是“<”,这可能会导致较少的计数比较逻辑。之所以会发生这种情况,是因为计数始终介于 0 和结束计数之间。平等比大小比较容易得多。我也没有进行这些更改(而且我很想为计数终端值设置单独的识别器)。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity tlc is
    port (
        trafficlights:  out std_logic_vector (5 downto 0);
        clck:           in  std_logic;
        reset:          in  std_logic;
        p_b:            in std_logic
    );
 end entity tlc;

architecture behavioral of tlc is
    type state_type is (st0_r1_g2, st1_r1_a1_a2, st2_g1_r2, st3_a1_r2_a2); 

    signal state: state_type; 
    signal count: std_logic_vector  (4 downto 0) ;
    signal pb_event:    std_logic;
    signal crosstime: std_logic;  -- JK FF

    constant sec10 : std_logic_vector (4 downto 0) := "01010"; 
    constant sec2 : std_logic_vector (4 downto 0) := "00010";
    constant sec20: std_logic_vector (4 downto 0) := "10100";

begin

pbevent:
    process (clck, reset, p_b)
    begin
        if p_b = '1' or reset = '1' then -- async set for push button
            pb_event <= '1';             -- reset will give crosswalk event
        elsif clck'event and clck = '1' then
            if state = st0_r1_g2 and 
              (( crosstime = '1' and count = sec10) or count = sec20) then
                pb_event <= '0';
            end if;
        end if;
    end process;
unlabelled:
    process (clck, reset) 
    begin

        if reset = '1' then
            state <= st0_r1_g2;         -- reset to initial state
            count <= (others => '0');   -- reset counter
            crosstime  <= '0';
        elsif clck'event and clck = '1' then
            if pb_event = '1' and count = "00000" then  -- J input
                crosstime <= '1';
            end if;
            case (state) is
                when st0_r1_g2 =>
                    if (crosstime = '0' and count < sec20) or 
                       (crosstime = '1' and count < sec10) then
                        state <= st0_r1_g2;
                        count <= count + 1;
                    else  
                        state <= st1_r1_a1_a2;
                        count <= "00000";
                        if crosstime = '1' then   -- K input
                            crosstime <= '0';
                        end if;
                    end if;
                when st1_r1_a1_a2 =>
                    if count < sec2 then
                        state <=  st1_r1_a1_a2;
                        count <= count + 1;
                    else
                        state <= st2_g1_r2;
                        count <= (others => '0');
                    end if;
                when st2_g1_r2 =>
                    if count < sec10 then
                        state <= st2_g1_r2;
                        count <= count + 1;
                    else
                        state <= st3_a1_r2_a2;
                        count <= (others => '0');
                    end if;
                when st3_a1_r2_a2 =>   
                    if count < sec2 then
                        state <=  st3_a1_r2_a2;
                        count <= count + 1;
                    else
                        state <=st0_r1_g2;
                        count <= (others => '0');
                    end if; 
                when others =>
                    state <= st0_r1_g2;
            end case;
        end if;
    end process;
output_decode: 
    process (state)
    begin
        case state is 
            when st0_r1_g2 =>    trafficlights <= "100001";  -- traffic red 1, pedestrian green 1 
            when st1_r1_a1_a2 => trafficlights <= "110010";
            when st2_g1_r2 =>    trafficlights <= "001100";
            when st3_a1_r2_a2 => trafficlights <= "010110";
            when others =>       trafficlights <= "100001";
        end case; 
    end process;
end architecture behavioral;

在状态 st0_r1_g2 中找到的条件已折叠,以单独将“0”写入 pb_event 触发器。您可能预计任何时候 count = sec20 应该清除触发器。