Simulación de asignaciones de bloqueo en siempre @ bloques

5

Al rastrear algunos resultados de simulación extraños, descubrí que el uso de las tareas de bloqueo en los bordes del reloj era el culpable. Más específicamente, diferentes simuladores parecen tratarlos de manera diferente.

Toma el siguiente ejemplo:

module test;

reg clk, foo, bar;

initial
begin
  clk = 0;
  foo = 0;
  bar = 0;
  #10 $finish;
end

always
  #1 clk = ~clk;

always @(posedge clk)
  foo = ~foo;

always @(posedge clk)
  bar <= foo;

endmodule

Ejecutar esto en Xilinx 'ISim proporciona la siguiente forma de onda:

Estoparecerazonable,aunquemepareceunpocoextrañoqueuncambioenfooenelbordedelrelojseadetectadoporlabarraenelmismobordedelreloj.

LasiguienteformadeondaseproducealejecutarelmismoejemploutilizandoIcarusVerilog:

Esto me parece completamente incorrecto. Un cambio en foo de 0 a 1 no es recogido por bar en el mismo borde del reloj. Sin embargo, un cambio en foo de 1 a 0 hace que se recoja por bar en el mismo borde del reloj (de lo contrario, bar cambiaría a 1 en el segundo borde positivo del reloj, supongo).

Entonces, tengo dos preguntas:

  1. ¿Cuál, si alguno, de estos simuladores es correcto? En otras palabras, ¿cómo debe comportarse el código anterior?
  2. ¿Las diferencias entre los simuladores son algo de lo que siempre debemos estar conscientes? Si es así, ¿existen pautas para escribir código que sean deterministas en diferentes simuladores?

Nota: soy consciente del hecho de que usar asignaciones de bloqueo en always @ blocks no es una buena idea y que usar una asignación de no bloqueo en mi ejemplo proporciona resultados lógicos y consistentes. Estoy haciendo esta pregunta porque actualmente estoy depurando un código de simulación de terceros.

    
pregunta Job

1 respuesta

4

No soy un gurú de Verilog, pero como lo entiendo (desde aquí enlace entre otros lugares ), el uso de asignaciones de bloqueo para comunicarse entre procesos cronometrados exige un no determinismo.

Respecto a la parte 2: como lo entiendo ... si solo usa asignaciones no bloqueantes cuando se comunica entre procesos, obtendrá un comportamiento determinista en todos los simuladores. El no determinismo de bloquear las asignaciones no es una "cosa del simulador", es inherente a la forma en que funciona Verilog. Cambiar el orden de los procesos en los archivos de origen (por ejemplo) puede cambiar el orden de las actualizaciones y, por lo tanto, el comportamiento del código, incluso dentro del mismo simulador.

    
respondido por el Martin Thompson

Lea otras preguntas en las etiquetas