VHDL: contador para la visualización de 7 segmentos

3

Estoy escribiendo un código que cuando se presiona la tecla (0), la letra que se muestra en la pantalla de 7 segmentos cambia de una a la siguiente, como de a a, de b a b. Comienza a partir de A. Cuando la letra llega a H, vuelve a A. Sin embargo, cuando presiono la tecla, la letra cambia, pero vuelve a H cuando no se presiona. No entiendo cuál es el problema. Aquí está el código:

    KEY : in std_logic_vector(1 downto 0);        
    HEX : out std_logic_vector(6 downto 0)

    architecture behavioural of display is        
    signal counter : std_logic_vector(2 downto 0):= "000";
    begin
    process (KEY)
    begin
    if (KEY(0)= '1') then
    counter <= counter + '1';
    end if;
    end process;

    process(counter)
    begin
    case counter is
        when "000" => HEX <= "0001000";
        when "001" => HEX <= "0000011";
        when "010" => HEX <= "1000110";
        when "011" => HEX <= "0100001";            
        when "100" => HEX <= "0000110";
        when "101" => HEX <= "0001110";
        when "110" => HEX <= "0010000";
        when "111" => HEX <= "0001001";
    end case;   
    end process;
    end behavioural;      
    
pregunta user35476

2 respuestas

3

El primer problema que puedo ver es que estás usando un tipo "std_logic_vector" para tu contador. No puedes incrementar un tipo std_logic_vector, por lo que el operador "+" que estás utilizando hará cosas extrañas. (No estoy completamente seguro de lo que "000" + '1' le daría, pero no será la suma de enteros lo que está esperando). Use un tipo sin signo en su lugar.

En segundo lugar, al usar una instrucción if sin otra instrucción en su proceso asíncrono (no bloqueado), está inferiendo un bloqueo. (El proceso de síntesis tiene que encontrar un lugar donde almacenar el valor del contador para las iteraciones del proceso donde no se incrementa). Esto generalmente se considera una mala práctica: no está definiendo completamente el comportamiento del proceso, y la síntesis de los latches puede ser muy ineficiente, ya que utiliza mucho espacio en el FPGA.

Esto sería mucho más fácil de abordar si utilizara un proceso síncrono (sincronizado). Luego puede comparar el valor actual del interruptor con el valor en el último ciclo de reloj. Esto también se ocuparía del cierre inferido que tiene en su declaración if.

Mi proceso de contador se vería así:

...
signal counter : unsigned(2 downto 0);
...

process (RST, CLK)
begin
if RST = '1' then
    counter <= (others => '0')
elsif rising_edge(CLK) then
    if KEY(0) = '1' and key_prev = '0' then
        counter <= counter + 1;
    end if;
end if;
end process;

process (CLK)
begin
if rising_edge(CLK) then
    key_prev <= KEY(0);
end if;
end process;

Cambiar bounce será un problema que no he abordado. Tendrá que tener otro proceso que se ocupe de eso y genere un std_logic abonado que puede usar en lugar de KEY (0).

    
respondido por el LeoR
1

El proceso que incrementa tu contador seguirá incrementando el contador lo más rápido que puedas mientras mantengas presionada la tecla. Luego, cuando sueltas la tecla, el contador deja de cambiar y ves lo que sucedió como su último valor.

Debe hacer dos cosas: primero, debe rebotar el interruptor. Los contactos de los interruptores mecánicos rebotan durante unos pocos milisegundos cuando se presiona o suelta el interruptor, por lo que debe asegurarse de ignorar esos rebotes. En segundo lugar, debe detectar cuándo cambia el interruptor de la condición "no presionado" a la condición "presionado" y solo aumentar el contador cuando se produce ese cambio.

    
respondido por el Joe Hass

Lea otras preguntas en las etiquetas