Cambiar una señal entera con dos botones

-1

Dada una señal del tipo integer , quiero crear un proceso (o varios) para incrementar o disminuir la variable en 1. ¿Cómo puedo hacer esto? Parece que una señal no puede ser activada por dos relojes (en mi caso, key(0) y key(1) ) y si uso una variable en su lugar, me da el mismo problema de no poder cambiarla en varios relojes.

Este enfoque no funciona:

process(clock_50,key)
begin
    if rising_edge(clock_50) then
        if rising_edge(key(0)) then
          setting.temp <= setting.temp + 1;
        elsif rising_edge(key(1)) then
            setting.temp <= setting.temp - 1;
        end if;
    end if;
end process;
    
pregunta Dmitri Nesteruk

4 respuestas

3

¿Qué te parece esta variante en el código de Andrews?

signal oldKeys, kd1, kd2 : std_logic_vector(1 downto 0);

process(clock_50)
begin
    if rising_edge(clock_50) then
        kd2 <= kd1; -- 2 stage flipflop syncroniser to 
        kd1 <= key; -- deal with metastability risk.

        if (kd2(0) and not oldkeys(0)) then
          setting.temp <= setting.temp + 1;
        elsif (kd2(1) and not oldkeys(1)) then
            setting.temp <= setting.temp - 1;
        end if;

        oldkeys <= kd2;
    end if;
end process;

La otra variante que a veces veo es un registro de desplazamiento de dos etapas y busca "10", pero equivale a casi lo mismo.

Tenga en cuenta que las teclas se introducen a través de un sincronizador para evitar el riesgo de metastabilidad si la tecla se presiona demasiado cerca del borde ascendente del reloj. En la práctica, probablemente también querrá algo de lógica de rebote, ¿tal vez inhibir cada tecla durante 10 ms o más después de que se detecte una pulsación de tecla?     

respondido por el Dan Mills
2

ACTUALIZACIÓN: vea la respuesta de Dan Mills, que también maneja los problemas de metastabilidad que pasé por alto. Este se ha dejado en su lugar debido a la cantidad de referencias a él en otras respuestas / comentarios.

¿Cumpliría con sus requisitos?

signal oldKeys : std_logic_vector(1 downto 0);

-- register the key input into oldKeys
-- the oldKeys signal will be delayed by a single clock cycle
reg : process(clock_50)
begin
    if rising_edge(clock_50) then
        oldKeys <= key;
    end if;
end process;

-- use the one clock delayed oldKeys and the current key signals to detect changes in key
process(clock_50)
begin
    if rising_edge(clock_50) then
        if (key(0) and not oldkeys(0)) then
          setting.temp <= setting.temp + 1;
        elsif (key(1) and not oldkeys(1)) then
            setting.temp <= setting.temp - 1;
        end if;
    end if;
end process;

El circuito que esto producirá es aproximadamente esto.

simular este circuito : esquema creado usando CircuitLab

Donde reg1 es el primer proceso y el contador es el segundo proceso. Como se puede ver, ambos procesos se ejecutan al mismo tiempo, sin embargo, siempre que la diferencia de tiempo de la señal CLK entre el registro y el contador sea menor que el retardo de salida de reg1 más el retardo de propagación de la no compuerta más el retardo de la y puerta entonces el comportamiento es correcto. Si este no fuera el caso, el compilador arrojaría todo tipo de advertencias.

    
respondido por el Andrew
0

¡Creo que te estás metiendo en un lío, la solución de tu problema es mucho más fácil!

process(clock_50)
begin
    if rising_edge(clock_50) then
        if key(0) = '1' then
          setting.temp <= setting.temp + 1;
        elsif key(1) = '1' then
            setting.temp <= setting.temp - 1;
        end if;
    end if;
end process;

No entiendo por qué verifica el borde ascendente de una señal si ya tiene un reloj. En un circuito secuencial , cuando se produce un borde de reloj, se leen las entradas NIVEL y se obtiene una salida.

    
respondido por el ferdepe
-1

Logré resolver este problema, pero antes de publicar la solución, solo quería señalar algunas cosas, a saber:

  • No puede tener una señal que sea sensible a dos relojes. Es por eso que no puedes reaccionar a las presiones de key(0) y key(1) al mismo tiempo.
  • No puede detectar un borde ascendente y descendente de una señal. Es por eso que, incluso si combina ambas pulsaciones de tecla en un signal bit , todavía no podría hacer mucho con eso.
  • La solución presentada por @Andrew no funciona porque está basada en suposiciones inseguras. Si lo coloca en el hardware, los botones responderán de manera intermitente (de manera poco confiable). Lo que se explica fácilmente por el hecho de que los procesos son concurrentes en VHDL.

Así que ahora, la solución real. Lo que hacemos es introducir dos señales que indican la cantidad de veces que se presionó cada botón:

signal up, down : integer := 0;

Luego, simplemente asignamos estas señales al presionar cada botón:

process(key)
begin
    if (key(0)'event and key(0) = '0') then
        up <= up + 1;
    end if;
    if (key(1)'event and key(1) = '0') then
        down <= down + 1;
    end if;
end process;

Y luego, a nivel de arquitectura, simplemente ponemos:

setting.temp <= up - down;

Si desea realizar un cambio rápido, esta solución no controla el desbordamiento (botón presionado > 2 ^ 31 veces) pero eso no es un problema real.

    
respondido por el Dmitri Nesteruk

Lea otras preguntas en las etiquetas