VHDL Fpga debouncing

0

Tuve algunos problemas con el debouncing en un botón, así que busqué en Google para encontrar una solución para mi problema de debouncing.

Encontré este código:

enlace

Lo que parece hacer el truco, pero me cuesta mucho entender el código, y funciona.

Alguien podría aclarar cómo funciona este código y cómo puedo modificarlo, así que enciendo y apago un LED.

Intenté cambiarlo un poco aquí

LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

ENTITY debounce IS
  GENERIC(
    counter_size  :  INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
  PORT(
    clk     : IN  STD_LOGIC;  --input clock
    button  : IN  STD_LOGIC;  --input signal to be debounced
    result  : OUT STD_LOGIC; --debounced signal
     LED        : out std_logic_vector(3 downto 0);
     Segment: out std_logic_vector (7 downto 0); 
     AN: out std_logic
     );
END debounce;

ARCHITECTURE logic OF debounce IS
  SIGNAL flipflops   : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops
  SIGNAL counter_set : STD_LOGIC;                    --sync reset to zero
  SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output
  signal counter_10:            integer range 0 to 9 := 0;
  signal counter_10r:  std_logic_vector(7 downto 0);
BEGIN

  counter_set <= flipflops(0) xor flipflops(1);   --determine when to start/reset counter
  An <= '1';

  PROCESS(clk)
BEGIN
        IF(clk'EVENT and clk = '1') THEN
            flipflops(0) <= button;
            flipflops(1) <= flipflops(0);
                If(counter_set = '1') THEN --reset counter because input is changing
                    counter_out <= (OTHERS => '0');
                ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met
                    counter_out <= counter_out + 1;
            ELSE --stable input time is met
                result <= flipflops(1);
                counter_10 <= counter_10 + 1;
                case counter_10 is 
                    when 0 => counter_10r <= "01000000";
                    when 1 => counter_10r <= "01111001";
                    when 2 => counter_10r <= "00100100";
                    when 3 => counter_10r <= "00110000";
                    when 4 => counter_10r <= "00011001";
                    when 5 => counter_10r <= "00010010";
                    when 6 => counter_10r <= "00000010";
                    when 7 => counter_10r <= "01111000";
                    when 8 => counter_10r <= "00000000";
                    when 9 => counter_10r <= "00010000";
                    when others => counter_10r <= "00000000";
                end case;
                LEd <= conv_std_logic_vector(counter_10,4);
                segment <= counter_10r;

END IF; 
END IF;
END PROCESS;
END logic;

Pero no parece funcionar, el LED está constantemente tapado ...

    
pregunta Carlton Banks

1 respuesta

1

Ya que no identificaste ninguna dificultad específica, aquí tienes un recorrido rápido. Si hay puntos que aún no comprende, haga preguntas de seguimiento en los comentarios a continuación.

flipflops se usa para crear un detector de bordes; counter_set pulsa alto cada vez que hay una transición de entrada. (Tenga en cuenta que este es un diseño deficiente, ya que button es una entrada asíncrona, debería haber al menos un flipflop más para reducir la posibilidad de metastabilidad).

Cada vez que counter_set pulsa alto, counter_out se borra; de lo contrario, cuenta hasta que MSB se establece, momento en el que result se establece en el mismo estado que button .

Como demostración, el código se incrementa counter_10 en cada transición de rebote (tanto de bajo a alto como de alto a bajo), que luego se decodifica para una pantalla de 7 segmentos. En lugar de esto, podrías cambiar tu LED. Si desea que el LED solo se active en un borde y no en el otro, hágalo condicional en result .

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas