Escribí un contador simple en VHDL para un contador de programa. Todo se hace en un proceso, pero lo que no entiendo es que en la simulación, la adición del contador del programa solo se realiza en el siguiente evento del reloj, en lugar de hacerlo inmediatamente después de que se haya emitido PCNext
.
Aquí está el código, así como la simulación:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY dlatch IS
PORT (
Reset, Clock : IN std_logic;
PC_out : OUT std_logic_vector(31 downto 0)
);
end dlatch;
ARCHITECTURE d_arch OF dlatch IS
SIGNAL PC : std_logic_vector(31 downto 0);
SIGNAL PCNext : std_logic_vector(31 downto 0);
BEGIN
PROCESS(Clock, Reset)
BEGIN
IF Reset = '1' THEN
PC <= x"00000000";
ELSIF Clock'event and Clock = '1' THEN
PC <= PCNext;
END IF;
PCNext <= std_logic_vector(unsigned(PC) + 4);
END PROCESS;
PC_out <= PC;
END d_arch;
¿Ves cómo PCNext solo se calcula en el flanco descendente del reloj? ¿Por qué no se calcula inmediatamente después PC <= PCNext
?
En primer lugar, ambas dudas (1) y (2) que en realidad hacen la misma pregunta
(1) La adición del contador de programa solo se realiza en el siguiente evento de reloj [es decir, aquí es el flanco descendente], en lugar de hacerlo inmediatamente después de que se haya generado PCNext.
(2) ¿Ves cómo PCNext solo se calcula en el flanco descendente del reloj? ¿Por qué no se calcula inmediatamente después de PC <= PCNext?]
Respuesta : Es porque la señal PC no está presente en la lista de sensibilidad. Como se muestra en la simulación a continuación, cuando lo agrego en la lista de sensibilidad, la adición se realiza de inmediato porque PCNext <= std_logic_vector(unsigned(PC) + 4);
se ejecuta simultáneamente cuando el cambio signal PC
en la lista de sensibilidad invoca el proceso nuevamente.
Anteriormente, en su caso, la asignación inmediata no sucedía hasta el próximo evento de reloj (que es el borde descendente del reloj presente en la lista de sensibilidad).
Espero que ahora entiendas la lista de sensibilidad y tengas más cuidado la próxima vez.
Una cosa más que puede hacer es declarar signal PC
como variable PC
y usar la asignación de bloqueo :=
, esto también actualizará el resultado de la adición de inmediato y también puede obtener más información sobre la diferencia entre la asignación de bloqueo y la asignación sin bloqueo.
editar: como ya dijo Dave Tweed, mover la declaración PCNext <= std_logic_vector(unsigned(PC) + 4);
fuera del bloque de proceso por completo también funcionará.
PCNext <= std_logic_vector(unsigned(PC) + 4);
ejecutaba justo después de la if
declaración?La razón por la que PCNext
no cambia hasta el siguiente borde del reloj es que tiene esa declaración dentro del process
. El proceso solo se evalúa cuando cambia una de las señales en su lista de sensibilidad.
Tenga en cuenta que esta es una de las diferencias clave entre la simulación y el mundo real. El simulador presta atención a las listas de sensibilidad, pero si realmente sintetiza esta lógica, PCNext
de hecho cambiaría de inmediato.
Para obtener el comportamiento que espera en el simulador , debe mover esa declaración fuera del proceso por completo.
process
PCNext
? Simplemente actualice PC
de la misma manera que lo hace, cycle
es decir,PC <= std_logic_vector(unsigned(PC) + 4);
PCNext
solo.
John