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