Dominar Timescale en Verilog: Unidades, precisión y temporización de simulación precisa
La simulación en Verilog depende de cómo se define el tiempo porque el simulador necesita saber qué significa un #1 en términos de tiempo. La directiva de compilador `timescale especifica la unidad de tiempo y precisión para los módulos que la siguen.
Sintaxis
`timescale <unidad_tiempo>/<precisión_tiempo>
// Ejemplo
`timescale 1ns/1ps
`timescale 10us/100ns
`timescale 10ns/1ns
La unidad_tiempo es la medida de retardos y tiempo de simulación mientras que la precisión_tiempo especifica cómo se redondean los valores de retardo antes de usarse en simulación.
Use las siguientes construcciones de timescale para usar diferentes unidades de tiempo en el mismo diseño. Recuerde que las especificaciones de retardo en el diseño no son sintetizables y no pueden convertirse a lógica de hardware.
`timescalepara unidad base de medida y precisión de tiempo- $printtimescale tarea de sistema para mostrar unidad de tiempo y precisión
$timey$realtimefunciones de sistema devuelven el tiempo actual y el formato de reporte por defecto puede cambiarse con otra tarea de sistema$timeformat.
| Carácter | Unidad |
|---|---|
| s | segundos |
| ms | milisegundos |
| us | microsegundos |
| ns | nanosegundos |
| ps | picosegundos |
| fs | femtosegundos |
Los enteros en estas especificaciones pueden ser 1, 10 o 100 y la cadena de caracteres que especifica la unidad puede tomar cualquier valor mencionado en la tabla anterior.
Ejemplo #1: 1ns/1ns
// Declarar timescale donde unidad_tiempo es 1ns
// y precisión_tiempo también es 1ns
`timescale 1ns/1ns
module tb;
// Para entender el efecto de timescale, conduzcamos
// una señal con algunos valores después de algún retraso
reg val;
initial begin
// Inicializar la señal a 0 en tiempo 0 unidades
val <= 0;
// Avanzar 1 unidad de tiempo, mostrar mensaje y alternar val
#1 $display ("T=%0t En tiempo #1", $realtime);
val <= 1;
// Avanzar 0.49 unidad de tiempo y alternar val
#0.49 $display ("T=%0t En tiempo #0.49", $realtime);
val <= 0;
// Avanzar 0.50 unidad de tiempo y alternar val
#0.50 $display ("T=%0t En tiempo #0.50", $realtime);
val <= 1;
// Avanzar 0.51 unidad de tiempo y alternar val
#0.51 $display ("T=%0t En tiempo #0.51", $realtime);
val <= 0;
// Dejar simulación correr 5 unidades de tiempo más y salir
#5 $display ("T=%0t Fin de simulación", $realtime);
end
endmodule
La primera declaración de retraso usa #1 lo que hace que el simulador espere exactamente 1 unidad de tiempo que se especifica como 1ns con la directiva `timescale. La segunda declaración de retraso usa 0.49 que es menos de media unidad de tiempo. Sin embargo, la precisión de tiempo se especifica como 1ns y por tanto el simulador no puede ir más pequeño que 1 ns lo que hace que redondee la declaración de retraso dada y rinda 0ns. Así que el segundo retraso falla en avanzar el tiempo de simulación.
La tercera declaración de retraso usa exactamente media unidad de tiempo [hl]#0.5[/lh] y de nuevo el simulador redondeará el valor para obtener #1 que representa una unidad de tiempo completa. Así que esto se imprime en T=2ns.
La cuarta declaración de retraso usa un valor más de media unidad de tiempo y también se redondea haciendo que la declaración display se imprima en T=3ns.
ncsim> run T=1 En tiempo #1 T=1 En tiempo #0.49 T=2 En tiempo #0.50 T=3 En tiempo #0.51 T=8 Fin de simulación ncsim: *W,RNQUIE: Simulation is complete.
La simulación corre por 8ns como se esperaba, pero observe que la forma de onda no tiene divisiones más pequeñas entre cada nanosegundo. Esto es porque la precisión de tiempo es la misma que la unidad de tiempo.
Ejemplo #2: 10ns/1ns
El único cambio hecho en este ejemplo comparado con el anterior es que el timescale se ha cambiado de 1ns/1ns a 10ns/1ns. Así que la unidad de tiempo es 10ns y la precisión está en 1ns.
// Declarar timescale donde unidad_tiempo es 10ns
// y precisión_tiempo es 1ns
`timescale 10ns/1ns
// NOTA: El testbench es el mismo que en el ejemplo anterior
module tb;
reg val;
initial begin
val <= 0;
#1 $display ("T=%0t En tiempo #1", $realtime);
val <= 1;
#0.49 $display ("T=%0t En tiempo #0.49", $realtime);
val <= 0;
#0.50 $display ("T=%0t En tiempo #0.50", $realtime);
val <= 1;
#0.51 $display ("T=%0t En tiempo #0.51", $realtime);
val <= 0;
#5 $display ("T=%0t Fin de simulación", $realtime);
end
endmodule
El tiempo de simulación real se obtiene multiplicando el retraso especificado usando # con la unidad de tiempo y luego se redondea basado en la precisión. La primera declaración de retraso rendirá 10ns y la segunda da 14.9 que se redondea a 15ns.
La tercera declaración similarmente suma 5ns (0.5 * 10ns) y el tiempo total se vuelve 20ns. La cuarta suma otras 5ns (0.51 * 10) para avanzar el tiempo total a 25ns.
ncsim> run T=10 En tiempo #1 T=15 En tiempo #0.49 T=20 En tiempo #0.50 T=25 En tiempo #0.51 T=75 Fin de simulación ncsim: *W,RNQUIE: Simulation is complete.
Tenga en cuenta que la unidad base en la forma de onda está en decenas de nanosegundos con una precisión de 1ns.
Ejemplo #3: 1ns/1ps
El único cambio hecho en este ejemplo comparado con el anterior es que el timescale se ha cambiado de 1ns/1ns a 1ns/1ps. Así que la unidad de tiempo es 1ns y la precisión está en 1ps.
// Declarar timescale donde unidad_tiempo es 1ns
// y precisión_tiempo es 1ps
`timescale 1ns/1ps
// NOTA: El testbench es el mismo que en el ejemplo anterior
module tb;
reg val;
initial begin
val <= 0;
#1 $display ("T=%0t En tiempo #1", $realtime);
val <= 1;
#0.49 $display ("T=%0t En tiempo #0.49", $realtime);
val <= 0;
#0.50 $display ("T=%0t En tiempo #0.50", $realtime);
val <= 1;
#0.51 $display ("T=%0t En tiempo #0.51", $realtime);
val <= 0;
#5 $display ("T=%0t Fin de simulación", $realtime);
end
endmodule
Vea que las unidades de tiempo se escalaron para coincidir con el nuevo valor de precisión de 1ps. También note que el tiempo se representa en la resolución más pequeña que en este caso es picosegundos.
ncsim> run T=1000 En tiempo #1 T=1490 En tiempo #0.49 T=1990 En tiempo #0.50 T=2500 En tiempo #0.51 T=7500 Fin de simulación ncsim: *W,RNQUIE: Simulation is complete.
Verilog
- Dominar Verilog: Tutorial completo para diseño de circuitos digitales
- Dominar la concatenación en Verilog: Guía práctica
- Comprender las asignaciones en Verilog: tipos, sintaxis y mejores prácticas
- Bloqueante vs. No bloqueante en Verilog: Diferencias clave explicadas
- Dominar las funciones en Verilog para diseño RTL eficiente
- Comprender las Tasks en Verilog: Funciones vs Tasks, sintaxis y uso
- Comprender la semántica de programación en Verilog: Temporización, eventos y orden de ejecución
- Generador de reloj en Verilog: Guía de diseño e implementación
- Dominar las funciones matemáticas en Verilog para diseño de hardware eficiente
- Dominar $timeformat en Verilog: Control de precisión y visualización
- Comprender e imprimir timescales de Verilog en cualquier alcance