¿Por qué este sumador necesita dos ciclos de reloj (dos pulsaciones del botón) para mostrar un resultado?

1

Estoy implementando un sumador simple que se realiza en VHDL en una placa BASYS2.

Este es el siguiente código:

entity adder is
    port (
        a, b        : in std_logic_vector(3 downto 0);
        sum     : out std_logic_vector(3 downto 0);
        cout        : out std_logic;
        kopce       : in std_logic;
        ledica  : buffer std_logic
    );
end adder;

architecture sobirac of adder is

signal tmp : signed(4 downto 0);

begin
    process(kopce)
    begin
        if(rising_edge(kopce)) then

            ledica <= (not ledica);

            tmp <= signed(("0" & a)) + signed(("0" & b));
            --sum <= std_logic_vector(tmp(3 downto 0));

            sum(3) <= std_logic(tmp(3));
            sum(2) <= std_logic(tmp(2));
            sum(1) <= std_logic(tmp(1));
            sum(0) <= std_logic(tmp(0));

            cout <= tmp(4);
        end if;
    end process;

end sobirac;

El "problema" es que necesito presionar el botón dos veces para que genere una salida que muestro en los indicadores LED integrados, ¿por qué se comporta así? Si elimino la declaración de proceso y la hago concurrente, funciona en el instante en que le doy una entrada (conmutadores 2x4).

Saludos, Aleks

    
pregunta Aleks

2 respuestas

1

La asignación <= en el proceso se realiza de una manera especial. Primero se evalúan todas las declaraciones del lado derecho y luego se asignan todas las señales del lado izquierdo. En su caso, primero se evalúan las partes std_logic(tmp(n)); con el valor 'antiguo' de tmp , y solo entonces se asignan los valores tmp y sum .

    
respondido por el Eugene Sh.
0

Vea esta respuesta que describe el ciclo de simulación VHDL

En su caso, significa que no puede evaluar una expresión compuesta por una señal asignada en el ciclo de simulación actual. Está programado para entrar en vigor en algún momento en el futuro de la simulación. Esto incluye una asignación sin demora.

Su ejemplo de código ha definido cuatro registros. ledica , tmp , sum y cout .

Para eliminar un retraso en la suma por la que podría mover la asignación fuera del margen de reloj, evalúe parte del proceso (lo que requiere agregar a, b y tmp a la lista de sensibilidad) o conviértalas en declaraciones de asignación concurrentes:

architecture foo of adder is
    signal tmp : signed(4 downto 0);
begin
    process(kopce)
    begin
        if rising_edge(kopce) then
            ledica <= not ledica;  
            sum    <= std_logic_vector(tmp(3 downto 0)); 
            cout   <= tmp(4);
        end if;
    end process;

    tmp <= signed("0" & a) + signed ("0" & b);

end architecture;

Dado que no hay nada entre tmp y sum y cout , no hay razón para usar un registro de canalización para tmp .

Dependiendo del paquete que proporcione operadores agregados firmados, la concatenación con b puede no ser necesaria. Algunos operadores "+" toman la longitud del resultado del argumento de la izquierda.

(Me deshice de muchos pares de paréntesis superfluos, no pude evitarlo).

    
respondido por el user8352

Lea otras preguntas en las etiquetas