Diferencia entre asignación de bloqueo y no bloqueo Verilog

15

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

Normalmente tenemos que reiniciar los flip-flops, por lo tanto, cada vez que el reloj realiza la transición de 0 a 1 (posedge), verificamos si se reafirma el reinicio (reinicio sincrónico), luego continuamos con la lógica normal. Si miramos de cerca, 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 tarea de bloqueo y "<=" es una tarea sin bloqueo. "=" ejecuta código secuencialmente dentro de un inicio / fin, mientras que el no bloqueo "<=" se ejecuta en paralelo.

Estaba bastante seguro de que las tareas sin bloqueo eran secuenciales mientras que las tareas de bloqueo eran paralelas. Después de todo, puede hacer asignaciones de bloqueo con instrucciones de asignación fuera de los bloques siempre, y todos 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?

Estrella vacía
fuente

Respuestas:

21

estaba bastante seguro de que las tareas sin bloqueo eran secuenciales mientras que las tareas 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 instrucción hasta que se complete. 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 las tareas que ocurren todas al mismo tiempo. El resultado de una declaración en la segunda línea no dependerá de los resultados de la declaración en la primera línea. En cambio, la segunda línea se ejecutará como si la primera línea aún no hubiera sucedido.

El fotón
fuente
Entonces, ¿qué pasa con las declaraciones de asignación? ¿Están en una clase entera propia?
Void Star
44
Sí, las assigndeclaraciones ocurren fuera de los bloques siempre y generalmente se usan para describir la lógica combinatoria (no bloqueada) (mientras que los bloques, con algunas excepciones, describen la lógica secuencial). AFAIK, las assigndeclaraciones siempre se ejecutan "en paralelo" cuando su LHS tiene un cambio de valor.
El Photon
Bien ... Estoy empezando a tener la impresión de que Verilog simplemente no es el lenguaje más elegantemente diseñado. Esto será como aprender C fue.
Void Star
1
Verilog fue diseñado para "describir" el hardware que ya existe. Usarlo como lenguaje para diseñar (sintetizar) hardware es un truco.
El Photon
44
Si Verilog "le gusta aprender C" es un problema, eche un vistazo a VHDL. Algunas personas tienen preferencias bastante fuertes 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 el bloqueo / no, por ejemplo). stackoverflow.com/questions/13954193/… y sigasi.com/content/vhdls-crown-jewel Puede preferirlo u odiarlo. Pero vale la pena echarle un vistazo.
Brian Drummond el
6

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

Una asignación de bloqueo surte efecto de inmediato cuando se procesa. Una asignación sin bloqueo tiene lugar al final del procesamiento del "delta de tiempo" actual.

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

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

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

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

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

Peter Green
fuente
"" No acceda a un registro configurado con asignaciones de bloqueo dentro de un bloque secuencial siempre desde fuera del bloque siempre asignado. "" ¿Puede explicarlo?
user125575
Los diferentes bloques secuenciales siempre no tienen un orden definido. Por lo tanto, leer un conjunto "reg" con una evaluación de bloqueo en un bloque siempre de otro bloque siempre dará lugar a un comportamiento impredecible.
Peter Green
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 a cada reloj antes de ser leídos, de modo que no implique 'almacenamiento'.
Greg
IIRC, al menos en cuartos, solo se considera una advertencia, no un error.
Peter Green
5

El término asignación de bloqueo confunde a las personas porque la palabra bloqueo parece sugerir lógica secuencial en el tiempo. Pero en lógica sintetizada no significa esto , porque todo funciona en paralelo .

Quizás un término menos confuso sería la 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 cronometrados), 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 las always_combsecuencias. Sin embargo, la distinción entre secuencial y paralela en el tiempo 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á la circuitería de hardware (si cumple con el tiempo 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.

sin bar
fuente
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.
nobar
Por supuesto, el modo de procedimiento de SystemVerilog, aplicable especialmente a las initialdeclaraciones dentro de los programbloques, utiliza exclusivamente la asignación de bloqueo (secuencial) . Esto es útil para el diseño de banco de pruebas , pero generalmente no para la especificación RTL.
nobar