vhdlfpgadigitalspartan

Implementing a short pulse signal triggered by a push button on a Spartan 3E


I'm trying to implement an "emergency" function on a traffic light controller.

This emergency signal is an std_logic input, and it's triggered by a push button (using a ucf file).

What this signal does is basically whenever the push button is pressed, the controller will detect which of the two roads (north to south or west to east) is on red and it'll immediately switch it to orange (the other one , of course, will turn red) to let the emergency vehicle pass (an ambulance, for example).

I've tried to denounce the switch and then feed the denounced signal into a rising-edge detector. It didn't work: pressing the emergency button makes the red and yellow lights of both roads (NS and WE) light at the same time, just a disaster, the counter which I used to configure how long each light is on also gets disturbed for quite a while before going back to normal.

Here's my code so far:


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

entity TLC is
    Port (    
               Clck : in  STD_LOGIC;
               Reset: in  STD_LOGIC;
               emergency:in std_logic;

               Trafficlights: out  STD_LOGIC_Vector (5 downto 0)  --trafficlights (5 downto 3) for the NS road and (2 downto 0) for the WE road.

             );
 end TLC;

architecture Behavioral of TLC is


-------------for debouncing
constant COUNT_MAX : integer := 20; 

constant BTN_ACTIVE : std_logic := '1';

signal count1 : integer := 0;
type   state_type1 is (idle,wait_time); 
signal state1 : state_type1 := idle;
signal emergency_debounced:std_logic;
-----------------------------------------


  type state_type is (NRWG, NRWY, NGWR, NYWR); --NRWG: North-South on red and West-East on green and so on.
  signal one_second_counter: STD_LOGIC_vector(25 downto 0):="00000000000000000000000000";

  signal one_second_enable: std_logic;


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

  constant sec8 : std_logic_vector ( 3 downto 0) := "1000";
  constant sec3 : std_logic_vector (3 downto 0 ) := "0011";
  constant sec11: std_logic_vector (3 downto 0 ) := "1011";



--edge detector signals
 signal emergencya, emergencyb, emergencyc: std_logic;
----------

begin

controller: process (Clck,reset,emergencyc)

 begin

  if emergencyc='1' then

   if state=NRWG or state=NRWY then ----if NS is on red then switch it to yellow.
         state<=NYWR;
            count<=x"0";
   else
       if state=NGWR or state=NYWR then  ----if WE is on red then switch it to yellow.
          state<=NRWY; 
             count<=x"0";

      end if;
   end if;


  elsif reset ='1' then

      state<=NRWG;
      count<=X"0";


  else
    if rising_edge(clck) then
     if one_second_enable='1' then
       case state is              
         when  NRWG =>
           if count < sec8 then
             state <= NRWG;
             count <= count + 1;                
           else  
             state <= NRWY;
             count <= X"0";
           end if;

         when NRWY =>
           if count < sec3 then
             state <=  NRWY;
             count <= count + 1;
           else
             state <= NGWR;
             count <= X"0";
           end if;

         when NGWR =>
           if count < sec11 then
             state <= NGWR;
             count <= count + 1;
           else
             state <= NYWR;
             count <= X"0";
           end if;

         when NYWR =>   
           if count < sec3 then
             state <=  NYWR;
             count <= count + 1;
           else
             state <=NRWG;
             count <= X"0";
           end if; 

         when others =>
           state <= NRWG;
       end case;      
     end if;
    end if;
  end if;

end process;



-----------decode state
   OUTPUT_DECODE: process (state)
   begin
     case state is 
       when NRWG =>    Trafficlights <= "100001";   
       when NRWY =>    Trafficlights <= "100010";
       when NGWR =>    Trafficlights <= "001100";
       when NYWR =>    Trafficlights <= "010100";
       when others =>  Trafficlights <= "100001";
     end case; 
   end process;
--------------------------------






--------------Slow_Clock-------------

slow_clock:process(clck) begin
if(rising_edge(clck)) then
            if(one_second_counter="10111110101111000010000000") then

                one_second_counter <="00000000000000000000000000";
            else
                one_second_counter <= one_second_counter +1;
            end if;
        end if;
end process;

one_second_enable <= '1' when one_second_counter="10111110101111000010000000" else '0';
--------------------------------------------------- 








-----------------for debouncing---------------
debounce_emergency:process(clck) 

begin
if(rising_edge(Clck)) then
        case (state1) is
            when idle =>
                if(emergency = BTN_ACTIVE) then  
                    state1 <= wait_time;
                else
                    state1 <= idle; 
                end if;
                emergency_debounced <= '0';
            when wait_time =>
                if(count1 = COUNT_MAX) then
                    count1 <= 0;
                    if(emergency = BTN_ACTIVE) then
                        emergency_debounced <= '1';
                    end if;
                    state1 <= idle;  
                else
                    count1 <= count1 + 1;
                end if; 
        end case;       
    end if;        
end process;
------------------------------------------------------------

---------edge_detector--------
edge_detection:process (clck) 

begin

  if(rising_edge(clck)) then
    emergencya <= emergency_debounced;
    emergencyb <= emergencya;
  end if;

end process ;

emergencyc <= not emergencyb and emergencya;
---------------------------------

 end Behavioral;

Any ideas as to why the emergency function doesn't work the way it supposed to?


Solution

  • Your debounce_emergency:process is wrong in many ways. I suggest you simulate your design to see it. What happens if the emergency button is pressed for 40 clock cycles?

    Moreover in the controller: process the if emergencyc='1' ... part must be inside the if rising_edge(clck) otherwise will trigger multiple changes in the state signal.