Verilog siempre bloquea
Un always
bloque es uno de los procedimiento bloques en Verilog. Las declaraciones dentro de un bloque siempre se ejecutan secuencialmente.
Sintaxis
always @ (event)
[statement]
always @ (event) begin
[multiple statements]
end
El always
bloque se ejecuta en algún evento en particular. El evento está definido por una lista de sensibilidad.
¿Qué es la lista de sensibilidad?
Una sensibilidad list es la expresión que define cuándo debe ejecutarse el bloque always y se especifica después de @
operador entre paréntesis ( )
. Esta lista puede contener una o un grupo de señales cuyo cambio de valor ejecutará el bloque siempre.
En el código que se muestra a continuación, todas las declaraciones dentro del always
el bloque se ejecuta cada vez que cambia el valor de las señales a o b.
// Execute always block whenever value of "a" or "b" change
always @ (a or b) begin
[statements]
end
¿Para qué se usa el bloque siempre?
Un always
El bloque se puede utilizar para realizar elementos combinacionales o secuenciales. Un elemento secuencial como el flip flop se activa cuando se le proporciona un reloj y se reinicia. De manera similar, un bloque combinacional se activa cuando cambia uno de sus valores de entrada. Estos bloques de hardware funcionan todos al mismo tiempo, independientemente unos de otros. La conexión entre cada uno es lo que determina el flujo de datos. Para modelar este comportamiento, un always
El bloque se crea como un proceso continuo que se activa y realiza alguna acción cuando se activa una señal dentro de la lista de sensibilidad.
En el siguiente ejemplo, todas las declaraciones dentro del bloque always se ejecutan en cada flanco positivo de la señal clk.
// Execute always block at positive edge of signal "clk"
always @ (posedge clk) begin
[statements]
end
¿Qué sucede si no hay una lista de sensibilidad?
El always
bloque se repite continuamente a lo largo de la duración de una simulación. La lista de sensibilidad trae consigo un cierto sentido de tiempo, es decir, cada vez que cambia cualquier señal en la lista de sensibilidad, se activa el bloque siempre. Si no hay sentencias de control de tiempo dentro de un bloque siempre, la simulación se bloqueará debido a un bucle infinito sin retardo.
Ejemplo
El ejemplo que se muestra a continuación es un bloque always que intenta invertir el valor de la señal clk. La sentencia se ejecuta cada 0 unidades de tiempo. Por lo tanto, se ejecuta para siempre debido a la ausencia de demora en la declaración.
// always block is started at time 0 units
// But when is it supposed to be repeated ?
// There is no time control, and hence it will stay and
// be repeated at 0 time units only. This continues
// in a loop and simulation will hang !
always clk = ~clk;
Incluso si la lista de sensibilidad está vacía, debería haber alguna otra forma de retraso de tiempo. El tiempo de simulación avanza mediante una declaración de retraso dentro del always
construir como se muestra a continuación. Ahora, la inversión del reloj se realiza cada 10 unidades de tiempo.
always #10 clk = ~clk;
Nota: ¡Los retrasos explícitos no se pueden sintetizar en puertas lógicas!
Por lo tanto, el código de diseño real de Verilog siempre requiere una lista de sensibilidad.
Ejemplo de diseño de elementos secuenciales
El código que se muestra a continuación define un módulo llamado tff que acepta una entrada de datos, un reloj y un restablecimiento bajo activo. La salida se invierte cada vez que se encuentra que d es 1 en el borde positivo del reloj. Aquí, el always
el bloque se activa en el flanco positivo de clk o en el flanco negativo de rstn.
¿Qué sucede en el flanco positivo del reloj?
Los siguientes eventos ocurren en el flanco positivo del reloj y se repiten para todos los flancos positivos del reloj.
- Primer
if
el bloque comprueba el valor de reinicio activo-bajo rstn - Si rstn es cero, entonces la salida q debe restablecerse al valor predeterminado de 0
- Si rstn es uno, significa que no se aplica el restablecimiento y debe seguir el comportamiento predeterminado
- Si el paso anterior es falso:
- Verifique el valor de d y, si se encuentra que es uno, invierta el valor de q
- Si d es 0, entonces mantenga el valor de q
module tff (input d,
clk,
rstn,
output reg q);
always @ (posedge clk or negedge rstn) begin
if (!rstn)
q <= 0;
else
if (d)
q <= ~q;
else
q <= q;
end
endmodule
¿Qué sucede en el borde negativo del reinicio?
Los siguientes eventos suceden en el borde negativo de rstn y suceden en todos esos casos.
- Primer
if
el bloque comprueba el valor de reinicio activo-bajo rstn. En el borde negativo de la señal, su valor es 0. - Si el valor de rstn es 0, significa que se aplica el reinicio y la salida debe restablecerse al valor predeterminado de 0
- El caso donde el valor de rstn es 1 no se considera porque el evento actual es flanco negativo del primero
Ejemplo de diseño de elementos combinados
Un always
bloque también se puede utilizar en el diseño de bloques combinacionales. Por ejemplo, el siguiente circuito digital representa una combinación de tres puertas lógicas diferentes que proporcionan una determinada salida en la señal o.
El código que se muestra a continuación es un module
con cuatro puertos de entrada y un solo puerto de salida llamado o. El always
El bloque se activa cada vez que alguna de las señales en la lista de sensibilidad cambia de valor. La señal de salida se declara como tipo reg
en la lista de puertos del módulo porque se usa en un bloque de procedimiento. Todas las señales utilizadas en un bloque de procedimiento deben declararse como tipo reg
.
module combo ( input a,
input b,
input c,
input d,
output reg o);
always @ (a or b or c or d) begin
o <= ~((a & b) | (c^d));
end
endmodule
Vea que la señal o se convierte en 1 cada vez que la expresión combinacional en el RHS se vuelve verdadera. De manera similar, o se convierte en 0 cuando RHS es falso.
Salida de simulación¡Haga clic aquí para ver una presentación de diapositivas con un ejemplo de simulación!
Verilog