¿Por qué la asignación "sin bloqueo" en Verilog parece un nombre inapropiado?

Como sus nombres lo indican, las asignaciones sin bloqueo permiten la ejecución simultánea mientras que las asignaciones de bloqueo se ejecutan secuencialmente.

Tome la explicación de Nandland, por ejemplo:

En C, "Solo se permite ejecutar la segunda línea una vez que se completa la primera línea". Esto se usa como ejemplo o analogía con las sentencias de bloqueo en HDL.

Luego usa un ejemplo de 3 instrucciones que no bloquean frente a 3 que bloquean dentro de un bloque siempre, pero dice que tomará 3 ciclos de reloj para que el ejemplo sin bloqueo ejecute la tercera instrucción, mientras que las asignaciones de bloqueo "inmediatamente" confieren su valor al siguiente registro. .

always @(posedge i_clock)
  begin
   r_Test_1 <= 1'b1;
   r_Test_2 <= r_Test_1;
   r_Test_3 <= r_Test_2;
  end

// versus:

always @(posedge i_clock)
 begin
  r_Test_1 = 1'b1;
  r_Test_2 = r_Test_1;
  r_Test_3 = r_Test_2;
 end

Me parece que sus nombres deberían cambiarse. ¿Dónde está mi concepto erróneo? ¿Por qué nombrar las asignaciones sin bloqueo en la lógica secuencial cuando las declaraciones secuenciales bloquean evidentemente la ejecución de las declaraciones posteriores, ya que son declaraciones SECUENCIALES?

"tomará 3 ciclos de reloj para que el ejemplo sin bloqueo ejecute la tercera declaración" - No creo que esa sea la interpretación correcta. Se necesitan 3 ciclos para que el valor se propague a Test_3, que no es lo mismo.
Bueno, si consideramos que la tercera declaración es r_Test_3 <= r_Test_2; entonces no estoy seguro de por qué cree que esta es una interpretación errónea porque ciertamente se necesitan 3 flancos de reloj para pasar antes de que el valor de la primera declaración pase a la última. Ergo, las declaraciones intermedias parecen estar "bloqueando"
@Andrew porque si también cambia el valor de r_Test_1 en cada ciclo de reloj, r_Test_3 tendrá un cambio de valor de estado estable en cada ciclo de reloj. "se necesitan 3 ciclos de reloj para pasar antes de que se ejecute la tercera instrucción" implica que eso sería imposible.
Sintetice ambos y anote la velocidad de reloj máxima. Notarás que uno puede ser cronometrado más rápido que el otro.
Si le preocupa el término 'bloqueo': en este caso particular, la asignación de Test3 está 'bloqueada' hasta que se evalúa Test2, cuya asignación está bloqueada hasta que se evalúa Test1.
Uh, esta pregunta otra vez. Parece que esta es una de las partes más confusas de verilog. Le aconsejo que use una herramienta de visualización de netlist para dibujar el diagrama de bloques, ya que será más fácil de entender de esa manera.

Respuestas (3)

No es la asignación lo que se "bloquea", es la evaluación de las sentencias dentro del proceso.

En primer lugar, en ambos casos, todas las declaraciones se evalúan en cada ciclo de reloj. Pero como se señaló en un comentario, con la asignación sin bloqueo, se necesitan tres ciclos de reloj antes de que el valor se propague al último registro.

Con la asignación sin bloqueo, las tres sentencias se pueden ejecutar simultáneamente (por ejemplo, en hardware) o en cualquier orden arbitrario y siempre producen el mismo resultado. La evaluación de cualquier afirmación no "bloquea" la evaluación de las demás.

Con la asignación de bloqueo, las asignaciones deben completarse en el orden en que aparecen, al igual que en el código C. Cada sentencia "bloquea" la ejecución de las sentencias que le siguen.

¿Por qué la asignación "sin bloqueo" en Verilog parece un nombre inapropiado?

Porque es un nombre inapropiado.

El término no bloqueo se creó como un antónimo corolario del nombre inapropiado anterior bloqueo .

Mejores términos para bloquear y no bloquear serían evaluación ordenada y evaluación desordenada o evaluación en serie y evaluación paralela .

Pero luego hay un giro cruel: la evaluación ordenada se sintetiza como un circuito paralelo, mientras que la evaluación desordenada se sintetiza como un circuito en serie.

Nombre inapropiado de "bloqueo" Nombre inapropiado del antónimo "sin bloqueo"
Evaluación ordenada (orden de código fuente) Evaluación desordenada (orden determinado por el simulador)
Evaluación de series (orden de código fuente) Evaluación paralela (orden determinado por el simulador)
Síntesis paralela Síntesis en serie

Aquí hay un ejemplo de Verilog que sinteticé con Quartus.

module BlockingNonBlocking
(
    input wire clock,
    input wire data,

    output reg R1,
    output reg R2,
    output reg R3,
    output reg R4,
    output reg R5,
    output reg R6
);

    // "Blocking" misnomer
    // Ordered evaluation (source-code order)
    // Series evaluation (source-code order)
    // Parallel synthesis
    always @(posedge clock)
    begin
        R1 = data;
        R2 = R1;
        R3 = R2;
    end

    // "Non-Blocking" antonym misnomer
    // Unordered evaluation (order determined by simulator)
    // Parallel evaluation (order determined by simulator)
    // Series synthesis
    always @(posedge clock)
    begin
        R4 <= data;
        R5 <= R4;
        R6 <= R5;
    end

endmodule

Síntesis bloqueante versus no bloqueante

Figura 1 – Síntesis bloqueante versus no bloqueante.

Como puede ver, ambas variantes bloquean (en el verdadero sentido de la palabra) la dataseñal hasta el borde positivo de lo clockque significa que ambos son circuitos secuenciales, pero R1, R2 y R3 están en paralelo mientras que R4, R5 y R6 están en serie.

La mejor explicación que he visto sobre el tema, al menos para mí.
¡realmente fantástico! Me gustaría que esta sea la respuesta aceptada, pero me siento mal por quitársela a Dave porque ya se la di. La imagen del resultado sintetizado es absolutamente esclarecedora. ¡Gracias!

Los términos bloqueo y no bloqueo tienen más que ver con la semántica de ejecución del proceso de simulación que con la síntesis. Es lamentable que bloque sea también homónimo de agrupación o área contigua (a begin/ end bloque de sentencias).

Tanto las asignaciones de bloqueo como las de no bloqueo son declaraciones de procedimiento que se ejecutan secuencialmente dentro del alcance de un begin/endproceso. Ambas declaraciones evalúan la expresión del lado derecho a medida que se encuentran, pero la diferencia entre ellas se muestra mejor con retrasos dentro de la asignación:

initial begin
     #10
     b = #5 a;
     c = #5 b;
end
initial begin
     #10
     b <= #5 a;
     c <= #5 b;
end

Ambos initialprocesos comienzan en el tiempo 0, luego se retrasan 10 unidades de tiempo. Ambas declaraciones de asignación evalúan el valor de aen el tiempo 10. Pero la primera asignación de bloqueo suspende el proceso durante 5 unidades de tiempo, no se actualiza bhasta el tiempo 15 y no comienza a ejecutar la segunda asignación de bloqueo hasta el tiempo 15. También suspende el initialproceso y no se actualiza chasta el momento 20, que es cuando initialfinaliza el primer proceso.

La primera asignación sin bloqueo en el segundo initialproceso programa y actualiza a bla hora 15, pero no suspende el proceso. Entonces, la segunda asignación sin bloqueo se evalúa ben el tiempo 10, que es su valor 'antiguo'. Programa una actualización ccon el valor anterior ben el tiempo 15. El segundo initialproceso finaliza en el tiempo 10.

Por cierto, rara vez ves tareas de bloqueo con retrasos dentro de la tarea. Es un remanente de Verilog muy temprano antes de que yo introdujera las asignaciones sin bloqueo en el lenguaje.