在 Spartan 3E 上实现由按钮触发的短脉冲信号

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

我正在尝试在交通灯控制器上实现 "emergency" 功能。

此紧急信号是一个 std_logic 输入,由按钮触发(使用 ucf 文件)。

这个信号的作用基本上是只要按下按钮,控制器就会检测到两条路(从北到南或从西到东)中的哪条路是红色的,它会立即将其切换为橙色(另一个当然会变成红色)让紧急车辆通过(例如救护车)。

我试过检测开关,然后将检测信号馈入上升沿检测器。它没有用:按下紧急按钮使两条路(NS 和 WE)的红灯和黄灯同时亮起,简直是一场灾难,我用来配置每盏灯亮多长时间的计数器也受到干扰好一阵子才恢复正常。

到目前为止,这是我的代码:


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;

关于紧急功能为何无法正常工作的任何想法?

您的 debounce_emergency:process 在很多方面都是错误的。我建议您模拟您的设计以查看它。如果 emergency 按钮被按下 40 个时钟周期会怎样?

而且controller: process中的if emergencyc='1' ...部分必须在if rising_edge(clck)里面,否则会触发状态信号的多次变化。