asignación sin bloqueo no funciona como se esperaba en Verilog

5

Tengo un código Verilog muy simple y no parece funcionar como se esperaba:

Aquí está mi código:

always @ (posedge clk, negedge resetn) begin
  if (resetn == 1'b0) begin
     var <= 1'b0;
  end else begin
     if (valid == 1'b1) begin
         var<= 1'b1;
     end else begin
         var <= 1'b0;
     end
  end
end

Esperaba que, asumiendo resetn is H all along , cuando valid goes H el var becomes H en el ciclo siguiente . Pero en la simulación, var se convierte en H en el mismo ciclo. ¿Por qué?

Aquí también hay un diagrama:

next_state_d2 is my var

EDITAR: Código de Testbench:

initial begin
gclk = 1'b1;
resetn = 1'b1;
div_valid=1'b0;
#40 div_valid = 1'b1;
#40 div_valid = 1'b0;
end

always
#20 gclk = ~ gclk;
    
pregunta ghostrider

3 respuestas

3

Esto es en realidad bastante similar a la pregunta I respondí anteriormente , pero intentaré construir una respuesta canónica para este problema un tanto común.

En una simulación de retraso cero como esta, el flip-flop de prueba tiene un tiempo de configuración y un tiempo de espera de cero:

\ $ T_ {configuración} = T_ {mantener} = 0 \ $

Lo que esto significa es que en el instante se produce el borde sensible del reloj, la salida se actualiza, independientemente de lo que haya ocurrido inmediatamente antes o después de ese instante. Esto no es como el hardware real que normalmente tendría un \ $ T_ {setup} \ $ y \ $ T_ {hold} \ $.

Ejecuté tu banco de pruebas, y los resultados son bastante claros. La señal válida cambia al mismo tiempo que la señal del reloj. Los has retrasado precisamente por la misma cantidad. Así que en el límite cuando el reloj está alto, la señal válida también ha cambiado:

Tantolaentrada(div_valid)comoelreloj(gclk)pasanalmismotiempo:220ns.Porlotanto,elDFFretieneestosnuevosdatos,ylasalidacambiainstantáneamenteyaquetambiénhayunretrasodepropagaciónde0.Estasimulaciónpareceríamenosconfusasisimplementeseleccionáramosunvalorderetardodiferenteparalaentradaaldiseño:

En este caso, actualizamos la entrada en el flanco descendente del reloj (620 ns). Ahora queda mucho más claro que el próximo flanco del reloj (640 ns) será cuando el DFF actualice su salida.

Aquí está el código de testbench para que pueda ver exactamente cómo funciona en su propio simulador. Por favor, actualice el nombre del diseño, ya que no estaba claro cuál fue su nombre.

module scratch_tb;

   reg gclk;
   reg resetn;
   reg div_valid;
   wire data;

   // instantiate design under test
   scratch scratch (gclk, resetn, div_valid, data);

   // generate stimulus
   initial begin
      gclk            = 1'b1;
      resetn          = 1'b0;
      div_valid       = 1'b0;

      #80 resetn      = 1'b1;

      // test 1: input switches on rising clock edge
      #160 div_valid   = 1'b1;
      #40 div_valid   = 1'b0;

      #160 div_valid  = 1'b0;

      // test 2: input switches on falling clock edge
      #180 div_valid  = 1'b1;
      #40 div_valid   = 1'b0;

      #2000 $finish;
   end

   always begin
      #20 gclk = ~ gclk;
   end

endmodule
    
respondido por el travisbartley
4

Se trata de las reglas de programación de los simuladores de Verilog, que pueden resultar confusos para los recién llegados y los ingenieros experimentados.

Si lee "Verilog Asignaciones no bloqueadas con retrasos, mitos y misterios" ( aquí ) con cuidado y asegúrese de entender todo lo que explica, no experimentará este tipo de problemas en el futuro o, al menos, sabrá qué buscar cuando haga la depuración.

La respuesta a su pregunta está enraizada en el siguiente diagrama:

Lo que muestra es que la evaluación de RHS de las asignaciones no bloqueadas (< =), y la evaluación y asignación de las asignaciones bloqueadas (=) no tienen reglas de pedido.

Lo que significa es que, en tu caso, donde tanto posedge gclk como div_valid se programan en la misma franja horaria, pueden suceder los siguientes resultados:

  1. div_valid cambia antes se evalúa el RHS de la asignación sin bloqueo
  2. div_valid cambia después de se evalúa el RHS de la asignación sin bloqueo

El # 1 anterior conduce a un comportamiento observado por usted: tanto div_valid como var parecen cambiar en el mismo ciclo de reloj.

# 2 anterior lleva a un retraso de 1 ciclo de reloj desde div_valid a var cambio.

En la práctica, todos los simuladores que vi se comportaron de acuerdo con el # 1 (parece que colocan todos los eventos activados por @(posedge signal) al final de la Cola de eventos activos). Sin embargo, no es recomendable confiar en esta consistencia.

Creo que preferirías ver el retraso entre estas señales, ¿verdad? Es más consistente con la forma en que se comporta un verdadero HW. Hay dos maneras de lograr esto:

  • Cambie los estados de las señales activadas con asignaciones de bloqueo (=) desde el banco de pruebas en los intervalos de tiempo cuando no hay un borde positivo del reloj (consulte la respuesta de @Travis para el ejemplo de forma de onda)
  • Use bloques siempre secuenciales con asignaciones no bloqueantes (< =) para controlar las señales desde testbench (en el borde positivo del reloj).

Si desea comprender por qué funcionarán los enfoques que sugerí, puede leer el documento al que hice referencia anteriormente.

Espero que esto ayude.

    
respondido por el Vasiliy
0

Es una función de cuando válido va alto. Si sube el nivel antes del límite del reloj (o, antes de que finalicen los requisitos de tiempo de configuración / mantenimiento), obtendrá un valor alto en el mismo ciclo. Si va alto después del límite del reloj (o después del requisito de tiempo de espera), obtendrá un máximo válido en el mismo ciclo de reloj. ¿Qué simulador estás usando? Los diferentes simuladores tratan el tiempo de configuración / retención de manera ligeramente diferente. Sin saber nada más acerca de su sistema, supongo que válido no es un resultado registrado y, de hecho, es un resultado combinado, lo que resulta en el primer caso de tiempo que describí. Si comparte lo válido que está siendo manejado, debería quedar claro lo que realmente está sucediendo.

    
respondido por el Doov

Lea otras preguntas en las etiquetas