Genere flip-flops usando solo lógica combinacional

3

Solo por diversión, quería diseñar y simular flip-flops tipo D utilizando solo lógica combinatoria en Verilog (o SystemVerilog). Estoy usando el uso de Verilator para la simulación.

Mi intento inicial, que utiliza un diseño clásico de seis NAND, parece funcionar bien, y ha pasado todas las pruebas. Mi segundo intento, basado en un tipo JK de cuatro NAND, no está funcionando. La salida no permanece bloqueada durante el nivel positivo del reloj, y para algunas pruebas la simulación ni siquiera converge.

P: Sé que no es normal u óptimo, pero ¿es razonable diseñar flip-flops usando lógica combinacional en Verilog? Si es así, ¿hay algún problema con mi segundo diseño?

Éste funciona:

module dff( input clk, input D, output Q );

   wire a, sn, rn, b, Qn;

always_comb // captures D @( posedge clk )
   begin
   a = !(b&sn);
   sn = !(a&clk);
   rn = !(sn&b&clk);
   b = !(rn&D);
   Q = !(sn&Qn);
   Qn = !(rn&Q);
   end

endmodule

Este no funciona:

module dff( input clk, input D, output Q );

   wire J=D, K=!D;
   wire sn, rn, qn;

always_comb // captures D @( posedge clk ), but fails to hold
   begin
   sn = !(J&clk&qn);
   rn = !(K&clk&Q);
   Q  = !(sn&qn);
   qn = !(rn&Q);
   end

endmodule

En un esfuerzo por eliminar bloqueo de asignación y listas de sensibilidad , reimplementé el enfoque basado en JK de la siguiente manera, pero las formas de onda de salida no se vieron afectadas por esta diferencia.

module dff( input clk, input D, output Q );

   wire J=D, K=!D;
   wire sn, rn, qn;

   assign sn = !(J&clk&qn);
   assign rn = !(K&clk&Q);
   assign Q  = !(sn&qn);
   assign qn = !(rn&Q);

endmodule

Nota: basé el diseño de éstos en las descripciones y diagramas aquí .

    
pregunta nobar

2 respuestas

2

El JK que tienes es un pestillo, no un disparador de borde. También falta retroalimentación entre Q y qn (a su primer código también le falta esta retroalimentación). Combinacional siempre bloquea el trabajo basado en la lista de sensibilidad. La lista de sensibilidad automática de always @* y always_comb 'está determinada por las señales utilizadas en el lado derecho de una expresión y no en el lado izquierdo.

Si declara la lista de sensibilidad, debería funcionar: always @( J,K,clk, Q,qn ) , De esta manera, Q y qn volverán a activar el bloque siempre.

Otro enfoque es usar la declaración del caso:

always_comb
  if (clk)
    Q = Qpre;
  else
    case({J,K})
    2'b10 : Qpre = 1'b1;
    2'b01 : Qpre = 1'b0;
    2'd11 : Qpre = ~Q;
    default : Qpre = Qpre; // no change
    endcase

El problema con el uso de lógica combinacional para fracasos es que puede tener violaciones de tiempo de espera. Verilog un simulador indeterminado. Esto significa que el orden en que se evalúa un bloque siempre no está garantizado. Usando el siguiente código como ejemplo. Verilog puede ejecutar b_combff antes de c_combff , por lo que a c se le asignará el valor de a . Esto es porque estamos usando asignaciones de bloqueo. El simulador también podría ejecutar c_combff antes de b_combff y obtendremos el valor correcto. Ambos escenarios son legales.

dff b_combff(.Q(b), .clk(clk), .D(a);
dff c_combff(.Q(c), .clk(clk), .D(b);

Una asignación sin bloqueo bien colocada ( <= ) en Q puede ayudar. Esto separará la evaluación y la actualización en regiones separadas del programador. Esto corrige la condición de carrera del tiempo de espera, pero no ayuda con la síntesis.

Los sintetizadores modernos son inteligentes, pero no son brillantes. Buscan patrones de codificación para determinar cómo convertir RTL en puertas equivalentes. Cuando vean always @ hará flip-flops sensibles al borde. Lo hacen bien con SR, RS, & muy simples D pestillos. Biond que intentan hacer lógica combinacional. Cuando agregas tus propios flops personalizados, el sintetizador intentará hacerlo coincidir con la lógica que ya conoce, lo que probablemente resultará en una lógica de bloqueo asíncrono.

En resumen, es posible diseñar flip-flops usando lógica combinacional, pero fuera del aprendizaje generalmente no es una buena idea.

    
respondido por el Greg
1

Las descripciones del flip-flop JK tienden a ser muy confusas. En particular, la interacción con el reloj rara vez se describe de una manera totalmente coherente, pero esto puede deberse en gran parte a un problema mayor de Uso suelto y ambiguo de la terminología .

El problema básico con el flip-flop JK de la pregunta se describe en esta respuesta . En resumen, lo que se modela no se desencadena desde el borde, a pesar de las indicaciones en contrario en el artículo de Wikipedia referenciado .

Para crear un flip-flop JK desencadenado por el borde, puede usar una configuración de dos etapas de pestillos en cascada (también llamado "maestro-esclavo"), de manera que las dos etapas estén en estado transparente vs. fases opuestas del reloj. En esta disposición, la primera etapa mantendrá la información estable mientras que la segunda etapa se encuentra en su estado transparente. Esta relación crea el efecto de activación de borde y se implementa a continuación ...

module dff( input clk, input D, output Q );
   wire Q1;
   jkff A(!clk,D,!D,Q1);
   jkff B(clk,Q1,!Q1,Q);
endmodule

... donde jkff es la misma lógica que antes (pero sería mejor denominarlo como "JK gated latch") ...

module jkff( input clk, input J, input K, output Q );

   wire sn, rn, qn;

always_comb
   begin
   sn = !(J&clk&qn);
   rn = !(K&clk&Q);
   Q  = !(sn&qn);
   qn = !(rn&Q);
   end

endmodule

La falta de convergencia notificada puede explicarse por el modo de conmutación no convergente del diseño disparado por nivel, si se permitiera a las entradas mantener el estado (J = K = 1).

De mayor interés: el libro "Verilog HDL", de Samir Palnitkar, incluye una implementación de un flip-flop tipo D que es prácticamente equivalente al que se muestra en la pregunta.

Para ser explícitos: la respuesta a la pregunta inicial es: Sí, esto es algo razonable. Sin embargo, no hay garantía de que ningún hardware en particular pueda realizar dichos diseños. . También los diferentes simuladores pueden dar resultados diferentes, especialmente en lo que respecta a la distinción entre la simulación previa y posterior a la síntesis.

    
respondido por el nobar

Lea otras preguntas en las etiquetas