Diferencia entre asignación de bloqueo y no bloqueo Verilog

Estaba leyendo esta página http://www.asic-world.com/verilog/verilog_one_day3.html cuando encontré lo siguiente:

Normalmente tenemos que restablecer los flip-flops, por lo que cada vez que el reloj hace la transición de 0 a 1 (posposición), verificamos si se afirma el restablecimiento (reinicio sincrónico), luego continuamos con la lógica normal. Si nos fijamos bien vemos que en el caso de la lógica combinacional teníamos "=" para la asignación, y para el bloque secuencial teníamos el operador "<=". Bueno, "=" es una asignación de bloqueo y "<=" es una asignación de no bloqueo. "=" ejecuta el código secuencialmente dentro de un comienzo/final, mientras que el no bloqueante "<=" se ejecuta en paralelo.

Estaba bastante seguro de que las asignaciones sin bloqueo eran secuenciales mientras que las asignaciones de bloqueo eran paralelas. Después de todo, puede realizar asignaciones de bloqueo con declaraciones de asignación fuera de los bloques always, y todas se ejecutan en paralelo. ¿Es esto un error o el comportamiento es diferente dentro de un bloque siempre? Y, si el comportamiento ES diferente dentro de un bloque siempre, ¿se pueden realizar asignaciones sin bloqueo fuera de un bloque siempre?

Respuestas (3)

Estaba bastante seguro de que las asignaciones sin bloqueo eran secuenciales mientras que las asignaciones de bloqueo eran paralelas.

La asignación de bloqueo se ejecuta "en serie" porque una asignación de bloqueo bloquea la ejecución de la siguiente declaración hasta que se completa. Por lo tanto, los resultados de la siguiente declaración pueden depender de que se complete la primera.

La asignación sin bloqueo se ejecuta en paralelo porque describe asignaciones que ocurren todas al mismo tiempo. El resultado de un enunciado en la 2.ª línea no dependerá de los resultados del enunciado en la 1.ª línea. En cambio, la segunda línea se ejecutará como si la primera línea aún no hubiera sucedido.

Entonces, ¿qué pasa con las declaraciones de asignación? ¿Están en una clase completa propia?
Sí, assignlas declaraciones ocurren fuera de los bloques always y generalmente se usan para describir la lógica combinatoria (sin enclavamiento) (mientras que los bloques always, con algunas excepciones, describen la lógica secuencial). AFAIK, assignlas declaraciones siempre se ejecutan "en paralelo" cada vez que su LHS tiene un cambio de valor.
De acuerdo... Empiezo a tener la impresión de que Verilog no es el lenguaje de diseño más elegante. Esto va a ser como lo fue aprender C.
Verilog fue diseñado para "describir" el hardware que ya existe. Usarlo como lenguaje para diseñar (sintetizar) hardware es un truco.
si Verilog "le gusta aprender C" es un problema, eche un vistazo a VHDL. Algunas personas tienen preferencias bastante marcadas por uno u otro. Para algunos, VHDL es demasiado detallado. Para mí, está mucho mejor pensado. (la semántica de asignación de señal/variable es mucho más clara que la de bloqueo/no, por ejemplo). stackoverflow.com/questions/13954193/… y sigasi.com/content/vhdls-crown-jewel Puede que lo prefieras o lo odies. Pero vale la pena echarle un vistazo.
Sí, no me malinterpreten, me encanta C, pero es bueno tener opciones. Buscaré en VHDL, gracias.
La principal diferencia entre VHDL y verilog es que VHDL tiene un sistema de tipos mucho más estricto y tiene el lío de "entidad/arquitectura". Los principios del diseño RTL, como la diferencia entre asignaciones de bloqueo y no bloqueo y el uso de formulaciones de comportamiento específicas para describir el comportamiento secuencial de una manera que las herramientas de síntesis puedan entender, se aplican por igual en ambos lenguajes.

Las declaraciones de asignación no son "de bloqueo" o "no bloqueantes", son "continuas". La salida de una declaración de asignación siempre es igual a la función especificada de sus entradas. Las asignaciones de "bloqueo" y "no bloqueo" solo existen dentro de los bloques always.

Una asignación de bloqueo surte efecto inmediatamente después de ser procesada. Una asignación sin bloqueo tiene lugar al final del procesamiento del "delta de tiempo" actual.

Los bloques always pueden usarse para modelar lógica combinatoria o secuencial (systemverilog tiene always_comb y always_ff para hacer esto explícito). Cuando se modela la lógica combinatoria, generalmente es más eficiente usar = pero, por lo general, en realidad no importa.

Al modelar la lógica secuencial (por ejemplo, siempre @(posge clk) ), normalmente utiliza asignaciones sin bloqueo. Esto le permite determinar el "estado después del borde del reloj" en términos de "estado antes del borde del reloj".

A veces es útil usar asignaciones de bloqueo en bloques siempre secuenciales como "variables". Si hace esto, hay dos reglas clave a tener en cuenta.

  1. No acceda a un registro que esté configurado con asignaciones de bloqueo dentro de un bloque siempre secuencial desde fuera del bloque siempre en el que está asignado.
  2. No mezcle asignaciones de bloqueo y no bloqueo en el mismo registro.

Es probable que romper estas reglas provoque fallas en la síntesis y/o diferencias de comportamiento entre la simulación y la síntesis.

""No acceda a un registro que está configurado con asignaciones de bloqueo dentro de un bloque siempre secuencial desde fuera del bloque siempre en el que está asignado"." ¿Puede explicarlo?
Los diferentes bloques siempre secuenciales no tienen un orden definido. Por lo tanto, leer un conjunto "reg" con una asignación de bloqueo en un bloque siempre desde otro bloque siempre conducirá a un comportamiento impredecible.
E incluso si parece funcionar en simulación, una herramienta de síntesis debería mirar eso y decir "no". Utilizo registros locales para esos vars intermedios, y me aseguro de que siempre estén asignados en cada reloj antes de ser leídos, de modo que no se implique 'almacenamiento'.
IIRC al menos en quartus solo se considera una advertencia, no un error.
No debe usar la asignación sin bloqueo en la lógica combinacional, puede bloquear la simulación. Para obtener más detalles, consulte esta respuesta: electronics.stackexchange.com/a/506047/238188

El término Asignación de bloqueo confunde a las personas porque la palabra bloqueo parecería sugerir una lógica secuencial en el tiempo. Pero en lógica sintetizada no significa esto , porque todo opera en paralelo .

Quizás un término menos confuso sería asignación inmediata , que aún diferenciaría los resultados intermedios de la lógica combinacional de las entradas a elementos de memoria no transparentes (por ejemplo, registros sincronizados), que pueden tener una asignación retrasada .

Desde un punto de vista legalista, todo funciona muy bien. De hecho, puede considerar =que es una operación de bloqueo (secuencial en el tiempo) incluso dentro de always_combsecuencias. Sin embargo, la distinción entre tiempo secuencial y paralelo no hace absolutamente ninguna diferencia en este caso porque el always_combbloque está definido para repetirse hasta que la secuencia de instrucciones converja en un estado estable, que es exactamente lo que hará el circuito de hardware (si cumple con la sincronización). requisitos).

El subconjunto sintetizable de Verilog (y especialmente SystemVerilog) es extremadamente simple y fácil de usar, una vez que conoce los modismos necesarios. Solo tiene que superar el uso inteligente de la terminología asociada con los llamados elementos de comportamiento en el lenguaje.

En los estilos de codificación de comportamiento ( en comparación con RTL ), la distinción entre bloqueo y no bloqueo puede ser relevante. En algunos casos, la herramienta de síntesis puede inferir RTL funcionalmente equivalente a partir de diseños de componentes de comportamiento.
Por supuesto, el modo de procedimiento de SystemVerilog, aplicable especialmente a initialdeclaraciones dentro de bloques, utiliza exclusivamente la asignación de bloqueoprogram (secuencial en el tiempo) . Esto es útil para el diseño del banco de pruebas , pero generalmente no para la especificación RTL.