Primero, algunos preliminares.
La declaración wait
espera a que un evento y la condición sea verdadera. Entonces, si no hay evento, la condición no será evaluada. Por lo tanto, si start
ya es 1 al ingresar S0, se detendrá en la declaración wait
hasta que start
cambie y se convierta en 1.
También, como señalé en mi comentario, la asignación de señales no se produce hasta el final del paso de tiempo. Las asignaciones de señal son sin bloqueo . Es decir, la asignación no bloquea la ejecución hasta que se completa la asignación. Como lo ha escrito, tomará 2 cambios en start
yendo a 1 para provocar una transición al estado S1. Ajusté su código para agregar algunas declaraciones de informe y lo puse en un banco de pruebas. Aquí está el código:
main : PROCESS
BEGIN
while true loop
CASE state IS
WHEN S0 =>
report "Entering S0, waiting for start";
WAIT UNTIL start = '1';
state <= S1;
WHEN S1 =>
report "Entering S1, waiting for stop";
WAIT UNTIL stop = '1';
state <= S2;
WHEN OTHERS =>
END CASE;
end loop;
END PROCESS;
Ahora, el banco de pruebas solo pulsa start
dos veces (usando pulsos anchos de 1 ps, así que '0' en el momento 0, '1' en el tiempo 1 ps, '0' en el tiempo 2 ps y '1' en el tiempo 3 ps). Mira lo que pasa:
VSIM 1> run 5 ps
# ** Note: Entering S0, waiting for start
# Time: 0 ps Iteration: 0 Instance: /foo
# ** Note: Entering S0, waiting for start
# Time: 1 ps Iteration: 1 Instance: /foo
# ** Note: Entering S1, waiting for stop
# Time: 3 ps Iteration: 1 Instance: /foo
¿Ver la transición a S1? Esto se debe a que tu código está haciendo esto.
- Supongamos un estado inicial de S0
- Espera a que
start
cambie y se convierta en 1
- Programe
state
para ir a S1. El estado de la nota aún no es S1. La asignación sin bloqueo permite que la ejecución continúe antes de que se complete la asignación.
- Reinicia el proceso.
- El estado sigue siendo S0 (la actualización programada a
state
aún no se ha producido).
- Espere a que
start
cambie y se convierta en 1. Esto completa el intervalo de tiempo y ahora state
cambia a S1.
- Programe
state
para ir a S1. Ya es S1.
- Reinicia el proceso.
- El estado ahora es S1. Espere a que
stop
cambie y se convierta en 1. Esto completa el intervalo de tiempo y ahora state
cambia (nuevamente) a S1.
Por lo tanto, hay dos maneras de solucionarlo. La primera es asignar state
antes a la espera de que cambie la señal. Por ejemplo:
main : PROCESS
BEGIN
while true loop
CASE state IS
WHEN S0 =>
report "Entering S0, waiting for start";
state <= S1;
WAIT UNTIL start = '1';
WHEN S1 =>
report "Entering S1, waiting for stop";
state <= S2;
WAIT UNTIL stop = '1';
WHEN OTHERS =>
END CASE;
end loop;
END PROCESS;
Ahora, mira lo que sucede con el mismo estímulo en start
:
VSIM 1> run 5 ps
# ** Note: Entering S0, waiting for start
# Time: 0 ps Iteration: 0 Instance: /foo
# ** Note: Entering S1, waiting for stop
# Time: 1 ps Iteration: 1 Instance: /foo
De hecho, este es el tipo de estilo recomendado para la inferencia de registros. Primero asigne el nuevo valor, luego espere el evento.
Pero como este es un modelo, podemos ir uno más lejos. Podemos usar un variable
y luego podemos hacer una asignación de bloqueo . Esto bloquea la ejecución hasta que se completa la asignación. Por ejemplo:
main : PROCESS
variable state : states := S0;
BEGIN
while true loop
CASE state IS
WHEN S0 =>
report "Entering S0, waiting for start";
WAIT UNTIL start = '1';
state := S1;
WHEN S1 =>
report "Entering S1, waiting for stop";
WAIT UNTIL stop = '1';
state := S2;
WHEN OTHERS =>
END CASE;
end loop;
END PROCESS;
Tenga en cuenta que he hecho de state
una variable y ahora uso la asignación de bloqueo ( :=
). Y el resultado:
VSIM 1> run 5 ps
# ** Note: Entering S0, waiting for start
# Time: 0 ps Iteration: 0 Instance: /foo
# ** Note: Entering S1, waiting for stop
# Time: 1 ps Iteration: 1 Instance: /foo
De hecho, puedo poner la asignación antes o después de la declaración wait
y obtener el mismo resultado.
Tu solución para agregar wait for time_value
es problemática. Introduce un retraso donde uno no es necesario y quizás no deseable. Te recomiendo que cambies tu modelo al ejemplo basado en variable
para un comportamiento más obvio.