Simulación de flip flop D: ¿qué salida de simulación es la correcta?

Siempre me he preguntado, ¿cuál es la solución correcta para el flip flop D cuando la entrada cambia justo en el flanco ascendente del reloj? He encontrado dos soluciones de estas en línea, pero no tengo idea de cuál es la correcta.

Imagen 1

o

Imagen 2

Creo que la respuesta correcta debería ser la imagen 1 (en la parte superior) donde aparece la salida q en el siguiente flanco ascendente del reloj. Esto es lo que debería hacer el flip flop, es decir, crear un retraso de un ciclo.

Pero siempre obtengo la imagen 2 (imagen inferior) cuando ejecuto mi código Verilog. mi código es:

module beh(q,d,en,clk);
input q,clk,en;
output d;
reg d;
always@(posedge clk)
begin
if(en==1)
d<=q;
end
endmodule

¿Qué estoy haciendo mal?

Respuestas (1)

El primero es generalmente cómo se supone que debe verse, ya que el nivel de salida DESPUÉS del borde del reloj activo debe reflejar el nivel de entrada ANTES del borde del reloj activo. Sin embargo, cuando la transición de entrada cae en el borde del reloj activo, es ambiguo ya que técnicamente es una violación del tiempo de configuración y espera. En este caso, la diferencia entre usar <= y = en su banco de pruebas determinará si obtiene el #1 o el #2. Esto se debe a la forma en que funcionan los ciclos delta. Si usa = en el banco de pruebas, el nuevo valor se reflejará en la entrada del flip-flop inmediatamente al comienzo del ciclo y obtendrá el número 2. Sin embargo, si usa <=, el nuevo valor se reflejará al final del ciclo de actualización y obtendrá el número 1.

Pasé por varias iteraciones diferentes del banco de pruebas para encontrar la más efectiva. Al principio, usé = en el banco de pruebas para el generador de reloj y para la lógica del banco de pruebas y la lógica del banco de pruebas se ejecutó en el flanco descendente en lugar del flanco ascendente. Esto hizo que las trazas en el simulador fueran un poco más obvias (a mitad de camino entre el n.° 1 y el n.° 2); sin embargo, me encontré con algunos problemas de tiempo cuando intentaba obtener una interacción más profunda entre el banco de pruebas y el DUT. Terminé pasando a usar = en el generador de reloj y <= en el banco de pruebas y cambié el banco de pruebas para usar el flanco ascendente del reloj. Esto terminó pareciendo su #1, y resolvió los problemas de interacción que estaba teniendo. Ahora, uso MyHDL basado en Python para la parte funcional del banco de pruebas con un envoltorio verilog para el DUT, pero esa es una historia completamente diferente.

"Es ambiguo, ya que técnicamente es una violación del tiempo de configuración y espera". Todo depende del hardware. En los FPGA, las especificaciones de tiempo de retención cero son comunes. En la lógica 7400, se requiere un tiempo de espera positivo. No trabajo en ASIC, así que no puedo hablar de eso.
Sí, supongo que no es una violación en todos los casos. Creo que es un problema mayor en la simulación que en un circuito real porque la configuración y la retención en el simulador son básicamente cero, ya que verifica el nivel en un ciclo de simulador muy específico, y no antes o después.
Cuando la entrada cambia justo en el borde del reloj, se viola la especificación de tiempo de configuración distinta de cero del hardware real. La especificación de tiempo de espera suele ser 0, pero nunca he visto un FPGA u otra lógica digital real con cero tiempo de configuración. (El tiempo de configuración real varía de una parte a otra y varía con la temperatura). La simulación debe intentar coincidir con la realidad, de lo contrario, ¿cuál es el punto? Apuesto a que si ejecuta la simulación en post-synthesis modellugar del behavioralmodelo ideal, debería ver la forma de onda correcta (salida Q retrasada un ciclo de reloj).
@MarkU, si trata las transiciones simultáneas en el reloj y los datos como un tiempo de espera cero, entonces el tiempo de configuración es un ciclo de reloj completo.
¡Excelente! ¿Qué tal si quiero la solución de la imagen 1 en VHDL, qué cambios van en el banco de pruebas allí?
@MarkU: es posible construir hardware real con un tiempo de configuración cero agregando un pequeño retraso entre la señal de reloj entrante y la entrada de reloj de los registros internos; esto no se hace muy a menudo (el tiempo de espera cero, que se logra retrasando la entrada de datos, suele ser útil) pero puede ser útil cuando se intenta realizar ciertos protocolos.