always @(negedge GCLK)
foo<= bar; // foo is equal to bar in this cycle or next?
En los casos simples en los que no hay nada en el código que haga que bar
cambie simultáneamente con GCLK
, este bloque dice que cuando se ve un margen negativo en GCLK, "inmediatamente" cambia el valor de foo
a lo que sea bar
está en ese instante.
"Inmediatamente" significa algo así como una marca de simulación después de que llegó el borde negativo.
Esto significa que cualquier otra transición que ocurra en el mismo borde negativo de GCLK y que dependa del valor de foo
verá el valor anterior de foo
. Pero foo
tendrá el nuevo valor comenzando de inmediato hasta el siguiente borde negativo de GCLK.
Editar en respuesta a los comentarios,
Si "cualquier otra transición" ve el valor anterior de foo, ¿podemos asumir que foo es "está disponible en el próximo reloj"?
En el simulador, sí. En la vida real, debe verificar los retrasos de propagación y los tiempos de configuración y de espera para estar seguro.
¿qué pasa si ponemos siempre código con begin ... end? ¿Todos serán inmediatos? como: siempre @ (negedge GCLK) comienza .. foo < = bar; x < = foo + 1; fin En este ejemplo, ¿x será barra + 1 en el mismo ciclo que la asignación foo?
No, como se mencionó anteriormente, cualquier otra transición que ocurra en el mismo borde negativo de GCLK y que dependa del valor de foo verá el valor anterior de foo.
Si desea el otro comportamiento, puede usar la asignación de bloqueo:
...
foo = bar;
x = foo+1;
...
Las herramientas de síntesis modernas deberían poder compilar esto correctamente, pero las herramientas antiguas podrían no ser capaces de hacerlo. Lo que hará la herramienta moderna es simplemente traducir esto a
foo <= bar;
x <= bar+1;
y compila eso. Desde que aprendí Verilog antes de que este comportamiento fuera confiable, me resulta menos familiar leer el código con tareas de bloqueo.
¿Podemos usar asignaciones de bloqueo para tareas inmediatas y no bloqueadas para tareas "retrasadas"?
No tengo muy claro lo que quieres decir con esto. Lo que hace una asignación de bloqueo (en el simulador) es evitar que la siguiente instrucción se ejecute hasta que se complete. Ambos tipos de asignación son inmediatos, pero la evaluación de bloqueo hace que la siguiente instrucción se retrase.
Si es así, puede ser un enfoque muy útil para hacer pequeños retrasos en el código
Para pequeños retrasos en la simulación, puede usar eventos de retardo
always @(event) begin
foo <= x;
#5
bar <= foo;
end
Para pequeños retrasos en el código sintetizado, es mejor que se asegure de que el hardware realmente pueda hacer lo que está pidiendo.