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.