La regla 4.7 de Systemverilog (no determinismo) se interpreta de manera diferente por vcs vs iverilog / modelsim

Todavía estoy un poco confundido sobre cómo se implementa la regla 4.7 de SystemVerilog 2012. La regla establece que en una situación como esta:

module test; logic a; integer cnt; initial begin cnt = 0; #100; a <= 0; a <= 1; a <= 0; a <= 1; a <= 0; end always @(posedge a) begin cnt <= cnt + 1; end endmodule 

todas las asignaciones se progtwigrían en la queue Asignación sin locking, y luego se deben ejecutar en order. El último valor gana. Hasta aquí, todo está claro.

Lo que sucede a continuación, sin embargo, no es lo mismo para todos los simuladores. iverilog y Modelsim (al less la edición de Vivado 2016/3) crean un evento en 'a', lo que hace que cnt incremente. Esto parece coincidir con el comportamiento ilustrado por Mr Cummings en SNUG 2000

Sin embargo, VCS filtra los valores intermedios y aplica solo el último, que por cierto es también la forma en que funcionan las flip-flops reales.

En este caso, no es una discusión puramente hipotética, los resultados de la simulación son diferentes, y el comportamiento de iverilog / modelsim podría causar errores que son muy difíciles de atrapar, porque el flop alterna, pero no se observa cambio de valor en las forms de onda.

El otro punto es este: si iverilog / modelsim son correctos, ¿por qué están creando un evento y no dos?

EDITAR: nota adicional.

El ejemplo anterior de hecho no es muy significativo. Un caso más realist sería

 always @(posedge clk) begin clk2 <= 1'b1; if (somecondition) clk2 <= 1'b0; end always @(posedge clk2, negedge rst_n) begin if (!rst_n) q <= 1'b0; else q <= ~q; end 

esto es perfectamente legal y en hardware real nunca fallaría. el primero siempre es lógicamente idéntico a

 always @(posedge clk) begin if (somecondition) clk2 <= 1'b0; else clk2 <= 1'b1; end 

Sin embargo, si simulas la primera versión con ModelSim, verás que tu q se aleja felizmente, con clk2 constante 0. Esto sería una pesadilla de debugging.

Tu última pregunta es fácil de explicar. No es que los simuladores creen un solo evento, no lo hacen, es que solo el primer evento progtwig el @ (posedge) para reanudar el process always y los otros events suceden en la región NBA antes de que el bloque siempre reanude la ejecución en el próximo activo región del evento.

No puedo justificar el comportamiento de otros simuladores. No puedes hacer múltiples asignaciones al mismo flip-flop en hardware real, por lo que tu analogía no es tan simple. Es posible tener una descripción sin time y get múltiples (@ posedge) sin pasar el time. Entonces el filtrado evitaría ese coding style.