¿Cómo diseñar un sincronizador de dos etapas con un divisor de reloj en Verilog?

1

Tengo un reloj muy rápido llamado CLOCK_50 que me gustaría reducir la velocidad mediante el uso de un divisor de reloj. La salida es clock . También quiero usar un sincronizador de dos etapas para un puerto de reinicio asíncrono reset0 que debería generar reset en el núcleo. Sin embargo, no estoy seguro de cómo hacer que funcionen en diferentes dominios de reloj.

Esto es lo que se me ocurrió. Se generó varios errores cuando se compila.

logic clock, reset1, reset2, reset;
logic [13:0] countCLK;

always_ff @(posedge CLOCK_50) begin
    reset1 <= reset0;
    reset2 <= reset1;
    reset <= reset2;
end

always_ff @(posedge CLOCK_50 or negedge reset) begin
    if (!reset) begin
        clock <= 1'b0;
        countCLK <= 14'b0;
    end

    else begin
        if (countCLK[13])
            clock <= ~clock;

        countCLK <= countCLK + 14'b1;
    end
end

Y las advertencias:

Warning (308040): (Medium) Rule C104: Clock signal source should drive only clock input ports. Found 1 nodes related to this rule.
    Warning (308010): Node  "clock"
Warning (308027): (Medium) Rule R105: The reset signal that is generated in one clock domain and used in another clock domain should be synchronized. Found 1 node(s) related to this rule.
    Warning (308010): Node  "reset"
    
pregunta geft

1 respuesta

1

Lo que tienes ahora es un sincronizador de tres etapas que se ejecuta en el dominio de reloj rápido, por lo que la salida de reinicio no es un reinicio sincronizado adecuado para el núcleo. Cambia el bloque de siempre a @(posedge clock) . Pero hay otras consideraciones:

Para los restablecimientos, debe especificar con precisión cómo debe aparecer el restablecimiento en el dominio de reloj lento:

  • ¿debería estar sincronizado en ninguno, uno o dos bordes del reloj lento?
  • ¿Necesita una duración mínima de más de un ciclo?
  • ¿debería aceptar o rechazar pulsos de restablecimiento de entrada más cortos que un ciclo?

Una vez que sepa las respuestas, puede diseñar el circuito de reinicio. Si necesita aceptar pulsos de entrada cortos, debe usar la compensación asincrónica en el primer flop y configurarse automáticamente una vez que se entrega el reinicio. El primer flop es seguido por la cadena de sincronización.

En el divisor de reloj

No menciona qué dispositivo está utilizando; si se trata de un hardware (FPGA, a juzgar por las advertencias) en lugar del ejercicio teórico, le aconsejaría que utilice las tecnologías integradas en el dispositivo para hacer la división de reloj. En un FPGA, cree una instancia de fPLL / PLL para generar el reloj de velocidad más baja, en lugar de inferirlo de la lógica. Esto sigue siendo aplicable para la relación que tiene aquí: ahórrese el contador de 14 bits y use el incorporado. Más tarde, puede agregar fácilmente otros relojes derivados y aprovechar las conexiones directas a la red de distribución de reloj (controlada por sesgo). Para la simulación, puede simular fácilmente el pll / reemplazarlo con un reloj separado.

Sin embargo, lo que podría desear es una habilitación de reloj sincronizado (con el mismo período) en lugar de un nuevo reloj; depende de si el núcleo lento puede cumplir con el tiempo en el dominio del reloj rápido. Haría esto si el núcleo es pequeño (por lo que la potencia no es un problema) es trivial (cumple con el tiempo) y el cambio de reloj fue solo para cumplir con algunos requisitos externos del bus. Esto puede facilitar el traslado de datos entre el núcleo y el resto del diseño.

Si utilizara este divisor de reloj inferido, no hay necesidad de conectar la lógica de reinicio para ello. Funcionará y simulará bien si inicializa countCLK a cero en el Verilog para que tenga ese valor fuera de configuración.

    
respondido por el shuckc

Lea otras preguntas en las etiquetas