library IEEE;
use IEEE.std_logic_1164.all;

entity Vsvale is 
  port ( CLOCK, RESET, NSCAR, EWCAR, TMSHORT, TMLONG: in  STD_LOGIC;
         OVERRIDE, FLASHCLK:                          in  STD_LOGIC;
         NSRED, NSYELLOW, NSGREEN:                    out STD_LOGIC;
         EWRED, EWYELLOW, EWGREEN, TMRESET:           out STD_LOGIC );
end;

architecture Vsvale_arch of Vsvale is
type Sreg_type is (NSGO, NSWAIT, NSWAIT2, NSDELAY, 
                   EWGO, EWWAIT, EWWAIT2, EWDELAY);
signal Sreg: Sreg_type;
begin

  process (CLOCK)
  begin
    if CLOCK'event and CLOCK = '1' then
      if RESET = '1' then Sreg <= NSDELAY; else
        case Sreg is
          when NSGO =>                                         -- North-south green.
            if    TMSHORT='0' then Sreg <= NSGO;               -- Minimum 5 seconds.
            elsif TMLONG='1'  then Sreg <= NSWAIT;             -- Maximum 5 minutes.
            elsif EWCAR='1' and NSCAR='0' then Sreg <= NSGO;   -- Make EW car wait.
            elsif EWCAR='1' and NSCAR='1' then Sreg <= NSWAIT; -- Thrash if cars both ways.
            elsif EWCAR='0' and NSCAR='1' then Sreg <= NSWAIT; -- New NS car? Make it stop!
            else                               Sreg <= NSGO;   -- No one coming, stay as is.
            end if;
          when NSWAIT  => Sreg <= NSWAIT2;                     -- Yellow light,
          when NSWAIT2 => Sreg <= NSDELAY;                     --   two ticks for safety.
          when NSDELAY => Sreg <= EWGO;                        -- Red both ways for safety.
          when EWGO =>                                         -- East-west green.
            if    TMSHORT='0' then Sreg <= EWGO;               -- Same behavior as above.
            elsif TMLONG='1'  then Sreg <= EWWAIT;             
            elsif NSCAR='1' and EWCAR='0' then Sreg <= EWGO;   
            elsif NSCAR='1' and EWCAR='1' then Sreg <= EWWAIT; 
            elsif NSCAR='0' and EWCAR='1' then Sreg <= EWWAIT; 
            else                               Sreg <= EWGO;   
            end if;
          when EWWAIT  => Sreg <= EWWAIT2;                     
          when EWWAIT2 => Sreg <= EWDELAY;                     
          when EWDELAY => Sreg <= NSGO;                        
          when others  => Sreg <= NSDELAY;                     -- "Reset" state.   
        end case;
      end if;
    end if;
  end process;      

  TMRESET  <= '1' when Sreg=NSWAIT2 or Sreg=EWWAIT2 else '0';
  NSRED    <= FLASHCLK when OVERRIDE='1' else
              '1' when Sreg/=NSGO and Sreg/=NSWAIT and Sreg/=NSWAIT2 else '0';
  NSYELLOW <= '0' when OVERRIDE='1' else
              '1' when Sreg=NSWAIT or Sreg=NSWAIT2 else '0';
  NSGREEN  <= '0' when OVERRIDE='1' else '1' when Sreg=NSGO else '0';
  EWRED    <= FLASHCLK when OVERRIDE='1' else
              '1' when Sreg/=EWGO and Sreg/=EWWAIT and Sreg/=EWWAIT2 else '0';
  EWYELLOW <= '0' when OVERRIDE='1' else
              '1' when Sreg=EWWAIT or Sreg=EWWAIT2 else '0';
  EWGREEN  <= '0' when OVERRIDE='1' else '1' when Sreg=EWGO else '0';

end Vsvale_arch;
