-- Simple traffic light controller with push-to-walk -- Elliott 98-2 library ieee; use ieee.std_logic_1164.all; package types is -- NS red, amber, green, EW red, amber, green subtype light_type is std_logic_vector(5 downto 0); end types; library ieee; use ieee.std_logic_1164.all; use work.types.all; -- traffic light controller entity traffic is -- period of slow_clock controls light durations port(NS_button, EW_button, slow_clock, reset : in std_logic; lights : buffer light_type); end traffic; architecture mixed of traffic is -- North-South, East-West light states, "other" direction is red -- light durations are represented as multiple sequential states -- with the same output type lightsequence is ( NSgreen1, NSgreen2, NSgreen3, NSgreen4, NSgreen5, NSamber1, NSamber2, NSred, EWgreen1, EWgreen2, EWgreen3, EWgreen4, EWamber1, EWamber2, EWred ); signal state:lightsequence; signal NS_walk, EW_walk : std_logic; component push_to_walk is port (button, clear_inv, clock, reset : in std_logic; walk_synched : buffer std_logic); end component push_to_walk; begin -- walk buttons cleared on reset or when -- light in other direction is no longer green -- NS,EW_walk signals are synchronized to clock NS_walk_synchronizer:push_to_walk port map(button=>NS_button, clear_inv=>lights(0), clock=>slow_clock, reset=>reset, walk_synched=>NS_walk); EW_walk_synchronizer:push_to_walk port map(button=>EW_button, clear_inv=>lights(3), clock=>slow_clock, reset=>reset, walk_synched=>EW_walk); sequence : process is begin wait until rising_edge(slow_clock); if reset = '1' then -- sychronous reset state <= EWred; -- if walk button, then end green light elsif NS_walk='1' then -- state <= EWamber1; elsif EW_walk='1' then state <= NSamber1; else case state is -- proceed to next state when EWred => state <= NSgreen1; when NSgreen1 => state <= NSgreen2; when NSgreen2 => state <= NSgreen3; when NSgreen3 => state <= NSgreen4; when NSgreen4 => state <= NSgreen5; when NSgreen5 => state <= NSamber1; when NSamber1 => state <= NSamber2; when NSamber2 => state <= NSred; when NSred => state <= EWgreen1; when EWgreen1 => state <= EWgreen2; when EWgreen2 => state <= EWgreen3; when EWgreen3 => state <= EWgreen4; when EWgreen4 => state <= EWamber1; when EWamber1 => state <= EWamber2; when EWamber2 => state <= EWred; -- define next state for any illegal states as well when others => state <= NSgreen1; end case; end if; end process sequence; with state select lights <= -- NS red, amber, green, EW red, amber, green "001100" when NSgreen1 | NSgreen2 | NSgreen3 | NSgreen4 | NSgreen5, "010100" when NSamber1 | NSamber2, "100001" when EWgreen1 | EWgreen2 | EWgreen3 | EWgreen4, "100010" when EWamber1 | EWamber2, "100100" when others; -- all red, including illegal states end mixed; library ieee; use ieee.std_logic_1164.all; -- latch short pulses on push-to-walk button, and -- sychronize to clock -- clear automatically after one clock, on reset, -- of if other light is not green entity push_to_walk is port (button, clear_inv, clock, reset : in std_logic; walk_synched : buffer std_logic); end push_to_walk; architecture behaviour of push_to_walk is -- latched, but not synchronized signal walk_latched, walk_latched2 : std_logic; begin -- SR latch built with AND and OR gates walk_latched2 <= walk_latched or button; walk_latched <= walk_latched2 and (clear_inv and not reset and not walk_synched); -- this synchronizer (D-flipflop) reduces the probablility of -- the asynchronous push button causing metastability d_flipflop : process (clock) is begin if rising_edge(clock) then walk_synched <= walk_latched ; end if; end process d_flipflop; end behaviour;