【问题标题】:VHDL Traffic Light ControllerVHDL交通灯控制器
【发布时间】:2015-01-05 16:19:40
【问题描述】:

这是一个交通灯控制器的简单代码。它根据计数器值循环通过状态。但是,当按下按钮时,我希望它在第一个状态下多停留 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;

【问题讨论】:

  • 所以你需要第二个计数器,只要它需要经过 10 秒,它就会计数。如果您的主时钟频率乘以 10 减 1,则循环计数是倒数:)
  • 不要被wait 声明之类的东西甩掉。他们只会在模拟中工作。 “时间”在已实现的 VHDL 中没有价值,您需要计算时钟周期。

标签: vhdl state-machine


【解决方案1】:

我没有模拟这个。

这个想法是将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;


* ...我尝试合成它,但我得到错误消息“信号 pb_event 无法合成,同步描述错误。您用于描述同步元素(寄存器、内存等)的描述风格不是当前软件版本中支持。”您认为这是因为它的异步且与同步设计的其余部分不兼容吗?*

在不知道供应商抱怨 pb_ 的情况下,这有点束缚了我们的手脚。

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

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

请注意,我仍然不了解交通信号灯,并且我在状态 st0_r1_g2 中所做的修改预计在较长的 20 秒间隔的前 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 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 触发器都应该被清除。

【讨论】:

  • 试过了,效果很好。这是有道理的,因此 JK 充当按钮操作的存储器,而交叉时间正在触发适当的计数器。非常感谢
  • 你好大卫,我试图合成这个,我得到错误说“信号 pb_event 无法合成,错误的同步描述。你用来描述同步元素的描述风格(寄存器、内存等) .) 在当前软件版本中不受支持。”您认为这是因为它是异步的并且与同步设计的其余部分不兼容吗?
猜你喜欢
  • 2010-09-27
  • 2014-01-16
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多