¿Cuál es la diferencia entre asignación con bloqueo y asignación sin bloqueo?
1. El operador de asignación de bloqueo está representado por el signo igual (es decir, =). "Bloqueo" significa que en la declaración de proceso (inicial y siempre), la declaración de asignación actual bloquea las declaraciones posteriores, lo que significa que las declaraciones posteriores deben esperar hasta que se complete la declaración de asignación actual antes de poder ejecutarse. Además, la asignación de bloqueo se puede considerar completada en un solo paso, es decir: calcular el valor en el lado derecho del signo igual y asignarlo a la variable de la izquierda al mismo tiempo. Por ejemplo:
Al ejecutar "x=next_x;", x alcanzará inmediatamente el valor de next_x. La siguiente oración "y=x;" debe esperar hasta que se ejecute "x=next_x;" antes de poder ejecutarse. Dado que ambas declaraciones no tienen retraso (equivalente a cables), su declaración equivalente es "y=next_x;".
La asignación es en tiempo real. Después de calcular el de la derecha, se asigna inmediatamente al de la izquierda y luego se ejecuta la siguiente oración. La operación es en serie y se completa en uno siempre.
2. El operador de asignación sin bloqueo está representado por el signo menor o igual (es decir, lt; =). "Sin bloqueo" significa que en las declaraciones de proceso (inicial y siempre), la declaración de asignación actual no bloqueará las declaraciones posteriores. Se puede considerar que las declaraciones sin bloqueo se dividen en dos pasos:
① Calcule el valor de la expresión en el lado derecho del signo igual (tengo entendido que: después de ingresar al proceso, el extremo derecho de todas las declaraciones sin bloqueo Las expresiones se evalúan simultáneamente y la asignación ocurre solo en el momento en que la secuencia alcanza la declaración sin bloqueo actual).
②Al final de esta declaración de asignación, asigne el valor en el lado derecho del signo igual a la variable en el lado izquierdo del signo igual.
Por ejemplo:
Al ejecutar "xlt;=next_x;", no se bloqueará la ejecución de la declaración "ylt;=x;". Por lo tanto, el valor de x en la declaración "ylt;=x;" es diferente del valor de x en la declaración "xlt;=next_x;": la x en la declaración "ylt;=x;" el primer flip-flop D Valor inicial (Q0). El valor de x en la declaración "xlt;=next_x;" es el valor de salida (Q1) del flip-flop D después de un pulso de sincronización. En base a esto, este proceso produce un resultado completamente diferente al proceso de asignación de bloqueo, es decir, produce el efecto de un registro de desplazamiento, next_x à x à y.
El entendimiento simple es que la asignación de bloqueo se ejecuta bajo demanda y la asignación sin bloqueo se ejecuta en paralelo.
Para comprender mejor los puntos anteriores, necesitamos tener una comprensión profunda de las funciones y las diferencias de tiempo de ejecución entre la asignación con bloqueo y la asignación sin bloqueo en el lenguaje Verilog. Para facilitar la explicación del problema, a continuación se definen dos abreviaturas:
RHS – La expresión o variable en la dirección derecha de la ecuación se puede abreviar a: expresión RHS o variable RHS respectivamente. LHS: la expresión o variable en el lado izquierdo de la ecuación se puede abreviar como: expresión LHS o variable LHS respectivamente.
El estándar IEEE Verilog define que algunas declaraciones tienen un tiempo de ejecución definido y algunas declaraciones no tienen un tiempo de ejecución definido. Si se preparan dos o más declaraciones para ejecutarse al mismo tiempo, pero debido al orden diferente de las declaraciones (y esta diferencia en el orden está permitida por el estándar IEEE Verilog), se producen resultados de salida diferentes. Esto es lo que provoca riesgo y competencia en los módulos de Verilog. Para evitar carreras, es fundamental comprender la diferencia en el tiempo de ejecución entre las tareas bloqueantes y no bloqueantes.
Asignación de bloqueo
El operador de asignación de bloqueo está representado por el signo igual (es decir, =). ¿Por qué esta tarea se llama asignación de bloqueo? Esto se debe a que al asignar, primero se calcula el valor de la dirección derecha (RHS) del signo igual. En este momento, la declaración de asignación no permite ninguna interferencia de otras declaraciones de Verilog hasta que se complete la asignación actual, es decir. , cuando RHS se asigna a LHS Solo entonces se permite la ejecución de otras declaraciones de asignación. Generalmente, las operaciones de asignación de bloqueo sintetizadas no se pueden configurar para que tengan un retraso en RHS (ni siquiera se permite un retraso cero). En teoría, sólo tiene una secuencia conceptual con la siguiente declaración de asignación, pero ningún retraso sustancial.
Si se agrega un retraso al RHS, se impedirá la ejecución de la declaración de asignación durante el período de retraso y la asignación se ejecutará después del retraso. Este tipo de declaración de asignación no se sintetiza y este estilo de código no se puede utilizar. en el diseño de módulos que requieren síntesis.
La ejecución de la asignación de bloqueo se puede considerar como una operación de un solo paso:
Calcular RHS y actualizar LHS En este momento, no se permite ninguna interferencia de otras declaraciones de Verilog. El llamado concepto de bloqueo significa que en el mismo bloque siempre, la declaración de asignación posterior conceptualmente (incluso si no se establece ningún retraso) comienza a asignar valor después de que finaliza la declaración de asignación anterior.
Si la variable RHS bloqueada en un bloque de procedimiento resulta ser la variable LHS bloqueada en otro bloque de procedimiento, y los dos bloques de procedimiento son activados por el mismo flanco del reloj, entonces la operación de asignación de bloqueo surgirá. , es decir, si el orden de bloqueo de las asignaciones no está bien organizado, se producirá competencia. Si estas dos operaciones de asignación de bloqueo se activan con el mismo flanco del reloj, no se puede determinar el orden de ejecución. El siguiente ejemplo ilustra este problema.
[Ejemplo 1]. Oscilador de retroalimentación usando asignación de bloqueo
módulo fbosc1 (y1, y2, clk, rst);
salida y1, y2; p>
entrada clk, primero;
reg y1, y2;
siempre @(posedge clk o posedge primero)
si (primero) y1 = 0; // restablecer
else y1 = y2;
siempre @(posedge clk o posedge primero)
si (primero) y2 = 1 ; / preset
else y2 = y1;
endmodule
De acuerdo con los estándares IEEE Verilog, los dos bloques siempre en el ejemplo anterior se ejecutan en paralelo, y el el orden no importa. Si la señal de reinicio del bloque siempre anterior llega primero al tiempo 0, tanto y1 como y2 tomarán 1, y si la señal de reinicio del siguiente bloque siempre llega primero al tiempo 0, tanto y1 como y2 tomarán 0. Esto muestra claramente que este módulo Verilog es inestable y puede crear condiciones de carrera y riesgosas.
Asignación sin bloqueo
El operador de asignación sin bloqueo está representado por el signo menor o igual (es decir, lt; =). ¿Por qué esta asignación se llama asignación sin bloqueo? Esto se debe a que la expresión RHS del operador de asignación sin bloqueo se calcula al comienzo de la operación de asignación y la expresión LHS se actualiza al final de la operación de asignación. Durante el cálculo de la expresión RHS de la asignación sin bloqueo y la actualización del LHS, otras declaraciones de Verilog, incluidas otras declaraciones de asignación sin bloqueo de Verilog, pueden calcular la expresión RHS y actualizar el LHS simultáneamente. Las asignaciones sin bloqueo permiten que otras declaraciones de Verilog funcionen simultáneamente. La operación de asignación sin bloqueo se puede ver como un proceso de dos pasos:
1) Al comienzo del momento de la asignación, calcule la expresión RHS de la asignación sin bloqueo.
2) Al final del momento de la asignación, actualice la expresión LHS de la asignación sin bloqueo.
Las operaciones de asignación sin bloqueo solo se pueden usar para asignar valores a variables de tipo de registro, por lo que solo se pueden usar en bloques de procedimiento como bloques "iniciales" y bloques "siempre". No se permiten asignaciones sin bloqueo para asignaciones consecutivas.
El siguiente ejemplo puede ilustrar este problema:
[Ejemplo 2]. Oscilador de retroalimentación usando asignación sin bloqueo
módulo fbosc2 (y1, y2, clk, rst);
salida y1, y2;
entrada clk, primero;
reg y1, y2;
siempre @(posedge clk o posedge primero) p>
if (primero) y1 lt;= 0; // restablecer
else y1 lt;= y2;
siempre @(posedge clk o posedge rst) p>
if (rst) y2 lt;= 1; // preset
else y2 lt;= y1;
endmodule
De manera similar, según Según los estándares IEEE Verilog, los dos bloques siempre del ejemplo anterior se ejecutan en paralelo, independientemente del orden. No importa qué señal de reinicio del bloque siempre llegue primero, las asignaciones sin bloqueo en los dos bloques siempre calculan la expresión RHS al comienzo de la asignación y actualizan la expresión LHS al final. Por lo tanto, después de que llega la señal de reinicio para estos dos bloques siempre, es seguro que y1 es 0 e y2 es 1 al final del bloque siempre. Desde la perspectiva del usuario, estas dos asignaciones sin bloqueo se ejecutan en paralelo.
------------------------------------------- ----- --------------------------------
Ocho consejos para dominar el módulo Verilog La programación en el estilo sintetizable de los principios puede ser de gran ayuda. Tener en cuenta estos ocho puntos al escribir puede resolver los 90-100 problemas de carrera riesgosos que surgen en las simulaciones post-síntesis para la gran mayoría de los usuarios de Verilog.
1) Al modelar circuitos secuenciales, utilice asignación sin bloqueo.
2) Al modelar el circuito de bloqueo, utilice una asignación sin bloqueo.
3) Cuando utilice el bloque siempre para construir un modelo lógico combinacional, utilice la asignación de bloqueo.
4) Al construir circuitos lógicos secuenciales y combinacionales en el mismo bloque siempre, utilice asignación sin bloqueo.
5) No utilices tanto la asignación sin bloqueo como la asignación con bloqueo en el mismo bloque siempre.
6) No asignar un valor a la misma variable en más de un bloque siempre.
7) Utilice la tarea del sistema $strobe para mostrar valores de variables mediante asignación sin bloqueo
8) No utilice el retraso #0 al asignar valores