Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> Verilog

Control de retardo de Verilog

Hay dos tipos de controles de tiempo en Verilog:delay y evento expresiones El retraso El control es solo una forma de agregar un retraso entre el momento en que el simulador encuentra la declaración y cuando realmente la ejecuta. La expresión de evento permite retrasar la declaración hasta que ocurra algún evento de simulación que puede ser un cambio de valor en una red o variable (evento implícito ) o un evento con nombre explícito que se activa en otro procedimiento.

El tiempo de simulación se puede adelantar mediante uno de los siguientes métodos.

Las puertas y redes que se han modelado para tener retrasos internos también aumentan el tiempo de simulación.

Control de retraso

Si la expresión de retraso se evalúa como un valor desconocido o de alta impedancia, se interpretará como retraso cero. Si se evalúa como un valor negativo, se interpretará como un entero sin signo en complemento a 2 del mismo tamaño que una variable de tiempo.

  
  
`timescale 1ns/1ps

module tb;
  reg [3:0] a, b;
  
  initial begin
    {a, b} <= 0;
    $display ("T=%0t a=%0d b=%0d", $realtime, a, b);
    
    #10;
    a <= $random;
    $display ("T=%0t a=%0d b=%0d", $realtime, a, b);
    
    #10 b <= $random;
    $display ("T=%0t a=%0d b=%0d", $realtime, a, b);
    
    #(a) $display ("T=%0t After a delay of a=%0d units", $realtime, a);
    #(a+b) $display ("T=%0t After a delay of a=%0d + b=%0d = %0d units", $realtime, a, b, a+b);
    #((a+b)*10ps) $display ("T=%0t After a delay of %0d * 10ps", $realtime, a+b);
    
    #(b-a) $display ("T=%0t Expr evaluates to a negative delay", $realtime);
    #('h10) $display ("T=%0t Delay in hex", $realtime);
    
    a = 'hX;
    #(a) $display ("T=%0t Delay is unknown, taken as zero a=%h", $realtime, a);
    
    a = 'hZ;
    #(a) $display ("T=%0t Delay is in high impedance, taken as zero a=%h", $realtime, a);
    
    #1ps $display ("T=%0t Delay of 10ps", $realtime);
  end
  
endmodule

  

Tenga en cuenta que la precisión de la escala de tiempo está en 1ps y, por lo tanto, $realtime es necesario para mostrar el valor de precisión de la instrucción con una expresión de retraso (a+b)*10ps.

Registro de simulación
xcelium> run
T=0 a=x b=x
T=10000 a=0 b=0
T=20000 a=4 b=0
T=24000 After a delay of a=4 units
T=29000 After a delay of a=4 + b=1 = 5 units
T=29050 After a delay of 5 * 10ps
T=42050 Expr evaluates to a negative delay
T=58050 Delay in hex
T=58050 Delay is unknown, taken as zero a=x
T=58050 Delay is in high impedance, taken as zero a=z
T=58051 Delay of 10ps
xmsim: *W,RNQUIE: Simulation is complete.

Control de eventos

Los cambios de valor en redes y variables se pueden usar como un evento de sincronización para desencadenar la ejecución de otras declaraciones de procedimiento y es un implícito evento. El evento también se puede basar en la dirección del cambio, como hacia 0, lo que lo convierte en un negedge y un cambio hacia 1 lo convierte en un posedge .

Una transición del mismo estado al mismo estado no se considera un borde. Un evento de borde como posedge o negedge solo se puede detectar en el LSB de una señal vectorial o variable. Si una expresión se evalúa con el mismo resultado, no se puede considerar como un evento.

  
  
module tb;
  reg a, b;

  initial begin
    a <= 0;
    
    #10 a <= 1;
    #10 b <= 1;

    #10 a <= 0;
    #15 a <= 1; 
  end

  // Start another procedural block that waits for an update to
  // signals made in the above procedural block
  
  initial begin 
    @(posedge a); 
    $display ("T=%0t Posedge of a detected for 0->1", $time); 
    @(posedge b); 
    $display ("T=%0t Posedge of b detected for X->1", $time);
  end 
  
  initial begin
    @(posedge (a + b)) $display ("T=%0t Posedge of a+b", $time);

    @(a) $display ("T=%0t Change in a found", $time);
  end
endmodule

  
Registro de simulación
ncsim> run
T=10 Posedge of a detected for 0->1
T=20 Posedge of b detected for X->1
T=30 Posedge of a+b
T=45 Change in a found
ncsim: *W,RNQUIE: Simulation is complete.

Eventos con nombre

La palabra clave event se puede utilizar para declarar un named evento que se puede desencadenar explícitamente. Un event no puede contener ningún dato, no tiene duración de tiempo y se puede hacer que ocurra en cualquier momento en particular. Un evento con nombre es activado por el -> operador prefijándolo antes del identificador de evento nombrado. Se puede esperar un evento con nombre usando el @ operador descrito anteriormente.

  
  
module tb;
  event a_event;
  event b_event[5];
  
  initial begin
    #20 -> a_event;
    
    #30;
    ->a_event;
    
    #50 ->a_event;
    #10 ->b_event[3];
  end
  
  always @ (a_event) $display ("T=%0t [always] a_event is triggered", $time);
  
  initial begin
    #25;
    @(a_event) $display ("T=%0t [initial] a_event is triggered", $time);
    
    #10 @(b_event[3]) $display ("T=%0t [initial] b_event is triggered", $time);
  end
endmodule

  

Los eventos con nombre se pueden usar para sincronizar dos o más procesos que se ejecutan simultáneamente. Por ejemplo, el always bloque y el segundo initial bloque están sincronizados por a_event. Los eventos se pueden declarar como matrices, como en el caso de b_event, que es una matriz de tamaño 5 y el índice 3 se usa para desencadenar y esperar.

Registro de simulación
ncsim> run
T=20 [always] a_event is triggered
T=50 [always] a_event is triggered
T=50 [initial] a_event is triggered
T=100 [always] a_event is triggered
T=110 [initial] b_event is triggered
ncsim: *W,RNQUIE: Simulation is complete.

Evento u operador

El or El operador se puede usar para esperar hasta que cualquiera de los eventos enumerados se active en una expresión. La coma , también se puede usar en lugar del or operador.

  
  
module tb;
  reg a, b;
  
  initial begin
    $monitor ("T=%0t a=%0d b=%0d", $time, a, b);
    {a, b} <= 0;
    
    #10 a <= 1;
    #5  b <= 1;
	#5  b <= 0;
  end
  
  // Use "or" between events
  always @ (posedge a or posedge b) 
    $display ("T=%0t posedge of a or b found", $time);
  
  // Use a comma between
  always @ (posedge a, negedge b)
    $display ("T=%0t posedge of a or negedge of b found", $time);
  
  always @ (a, b) 
    $display ("T=%0t Any change on a or b", $time);
endmodule

  
Registro de simulación
ncsim> run
T=0 posedge of a or negedge of b found
T=0 Any change on a or b
T=0 a=0 b=0
T=10 posedge of a or b found
T=10 posedge of a or negedge of b found
T=10 Any change on a or b
T=10 a=1 b=0
T=15 posedge of a or b found
T=15 Any change on a or b
T=15 a=1 b=1
T=20 posedge of a or negedge of b found
T=20 Any change on a or b
T=20 a=1 b=0
ncsim: *W,RNQUIE: Simulation is complete.

Lista de expresiones de eventos implícitos

La lista de sensibilidad o la lista de expresiones de eventos suele ser una causa común de muchos errores funcionales en el RTL. Esto se debe a que el usuario puede olvidarse de actualizar la lista de sensibilidad después de introducir una nueva señal en el bloque de procedimiento.

  
  
module tb;
	reg a, b, c, d;
	reg x, y;
	
	// Event expr/sensitivity list is formed by all the
	// signals inside () after @ operator and in this case
	// it is a, b, c or d
	always @ (a, b, c, d) begin
		x = a | b;
		y = c ^ d;
	end
	
	initial begin
		$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b x=%0b y=%0b", $time, a, b, c, d, x, y);
		{a, b, c, d} <= 0;
	
		#10 {a, b, c, d} <= $random;
		#10 {a, b, c, d} <= $random;
		#10 {a, b, c, d} <= $random;
	end
endmodule

  
Registro de simulación
ncsim> run
T=0 a=0 b=0 c=0 d=0 x=0 y=0
T=10 a=0 b=1 c=0 d=0 x=1 y=0
T=20 a=0 b=0 c=0 d=1 x=0 y=1
T=30 a=1 b=0 c=0 d=1 x=1 y=1
ncsim: *W,RNQUIE: Simulation is complete.

Si el usuario decide agregar una nueva señal e y capturar la inversa en z, se debe tener especial cuidado para agregar e también a la lista de sensibilidad.

  
  
module tb;
	reg a, b, c, d, e;
	reg x, y, z;
	
  // Add "e" also into sensitivity list
  always @ (a, b, c, d, e) begin
		x = a | b;
		y = c ^ d;
    	z = ~e;
	end
	
	initial begin
      $monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b", 
                				$time, a, b, c, d, e, x, y, z);
      {a, b, c, d, e} <= 0;
	
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
	end
endmodule

  
Registro de simulación
ncsim> run
T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1
T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1
T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0
T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0
ncsim: *W,RNQUIE: Simulation is complete.

Verilog ahora permite que la lista de sensibilidad sea reemplazada por * que es una forma abreviada conveniente que elimina estos problemas al agregar todas las redes y variables que son leídas por la instrucción como se muestra a continuación.

  
  
module tb;
	reg a, b, c, d, e;
	reg x, y, z;
	
  // Use @* or @(*)
  always @ * begin
		x = a | b;
		y = c ^ d;
    	z = ~e;
	end
	
	initial begin
      $monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b", 
                				$time, a, b, c, d, e, x, y, z);
      {a, b, c, d, e} <= 0;
	
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
	end
endmodule

  
Registro de simulación
ncsim> run
T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1
T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1
T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0
T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0
ncsim: *W,RNQUIE: Simulation is complete.

Control de eventos sensibles al nivel

La ejecución de una declaración de procedimiento también se puede retrasar hasta que una condición se vuelve verdadera y se puede lograr con el wait palabra clave y es un control sensible al nivel.

La sentencia de espera evaluará una condición y, si es falsa, las sentencias de procedimiento que le sigan permanecerán bloqueadas hasta que la condición se vuelva verdadera.

  
  
module tb;
  reg [3:0] ctr;
  reg clk;
  
  initial begin
    {ctr, clk} <= 0;
    
    wait (ctr);
    $display ("T=%0t Counter reached non-zero value 0x%0h", $time, ctr);
    
    wait (ctr == 4) $display ("T=%0t Counter reached 0x%0h", $time, ctr);
    
    $finish;
  end
  
  always #10 clk = ~clk;
  
  always @ (posedge clk) 
    ctr <= ctr + 1;
  
endmodule

  
Registro de simulación
ncsim> run
T=10 Counter reached non-zero value 0x1
T=70 Counter reached 0x4
T=90 Counter reached 0x5
T=170 Counter reached 0x9
Simulation complete via $finish(1) at time 170 NS + 1


Verilog

  1. Tutorial de Verilog
  2. Concatenación Verilog
  3. Asignaciones de Verilog
  4. Bloqueo y no bloqueo de Verilog
  5. Bloques de control Verilog
  6. Funciones de Verilog
  7. Tarea Verilog
  8. Retraso de asignación inter e intra de Verilog
  9. Retardo de puerta Verilog
  10. Generador de reloj Verilog
  11. Funciones matemáticas de Verilog