Restablecimiento síncrono en diseño de FPGA multirreloj

Quiero comenzar a usar el restablecimiento de sincronización dentro de mis diseños de FPGA y soy nuevo en el diseño de FPGA de Xilinx.

Normalmente tengo 5-6 relojes en cada diseño, y el reinicio se realiza desde el botón pulsador en el tablero.

¿Cuál es una buena práctica para usar esta señal asíncrona que llega a mi FPGA como reinicio síncrono de todos los relojes en mi diseño de FPGA?

Lo que pensé es simplemente sincronizar la misma señal de botón asíncrono con cada reloj en el tablero en paralelo, como el diagrama de bloques que dibujé aquí:

Ingrese la descripción de la imagen aquí

El código de nivel superior para relojes y generación de reinicio:

`escala de tiempo 1 ns / 1 ps

module top_test1 (

    input  wire       clk_200mhz_p,     // external clock 200 MHz - p
    input  wire       clk_200mhz_n,     // external clock 200 MHz - n
    input  wire       reset             // reset push button
);

//*--------------------------------
//* Clock and reset
//*--------------------------------
// Internal 200 MHz clock - System
wire clk_200mhz_ibufg;  // internal 200 MHz clock
wire rst_200mhz_int;    // internal 200 MHz synchronous reset

// Internal 125 MHz clock - Ethernet
wire clk_mmcm_out;      // mmcm clk out - 125 MHz
wire clk_125mhz_int;    // internal 125 MHz clock
wire rst_125mhz_int;    // internal 125 MHz synchronous reset

// Internal 50 MHz clock - DSP
wire clk_bufr_out_50mhz;    // bufr 50mhz clock -> 200 MHz / 4 = 50 MHz
wire clk_50mhz_int;         // internal 50 MHz clk
wire rst_50mhz_int;         // internal 50 MHz synchronous reset


wire mmcm_rst = reset;
wire mmcm_locked;
wire mmcm_clkfb;

IBUFGDS
clk_200mhz_ibufgds_inst(
    .I    (clk_200mhz_p),
    .IB   (clk_200mhz_n),
    .O    (clk_200mhz_ibufg)
);

sync_reset #(
    .N        (4)
)
sync_reset_inst_200mhz (
    .clk    (clk_200mhz_ibufg),
    .rst    (reset),
    .out    (rst_200mhz_int)
);

MMCME2_BASE #(
    .BANDWIDTH           ("OPTIMIZED"),
    .CLKOUT0_DIVIDE_F    (8),
    .CLKOUT0_DUTY_CYCLE  (0.5),
    .CLKOUT0_PHASE       (0),
    .CLKOUT1_DIVIDE      (8),
    .CLKOUT1_DUTY_CYCLE  (0.5),
    .CLKOUT1_PHASE       (0),
    .CLKOUT2_DIVIDE      (1),
    .CLKOUT2_DUTY_CYCLE  (0.5),
    .CLKOUT2_PHASE       (0),
    .CLKOUT3_DIVIDE      (1),
    .CLKOUT3_DUTY_CYCLE  (0.5),
    .CLKOUT3_PHASE       (0),
    .CLKOUT4_DIVIDE      (1),
    .CLKOUT4_DUTY_CYCLE  (0.5),
    .CLKOUT4_PHASE       (0),
    .CLKOUT5_DIVIDE      (1),
    .CLKOUT5_DUTY_CYCLE  (0.5),
    .CLKOUT5_PHASE       (0),
    .CLKOUT6_DIVIDE      (1),
    .CLKOUT6_DUTY_CYCLE  (0.5),
    .CLKOUT6_PHASE       (0),
    .CLKFBOUT_MULT_F     (5),
    .CLKFBOUT_PHASE      (0),
    .DIVCLK_DIVIDE       (1),
    .REF_JITTER1         (0.010),
    .CLKIN1_PERIOD       (5.0),
    .STARTUP_WAIT        ("FALSE"),
    .CLKOUT4_CASCADE     ("FALSE")
)
clk_mmcm_inst (
    .CLKIN1              (clk_200mhz_ibufg),
    .CLKFBIN             (mmcm_clkfb),
    .RST                 (mmcm_rst),
    .PWRDWN              (1'b0),
    .CLKOUT0             (clk_mmcm_out),
    .CLKOUT0B            (),
    .CLKOUT1             (),
    .CLKOUT1B            (),
    .CLKOUT2             (),
    .CLKOUT2B            (),
    .CLKOUT3             (),
    .CLKOUT3B            (),
    .CLKOUT4             (),
    .CLKOUT5             (),
    .CLKOUT6             (),
    .CLKFBOUT            (mmcm_clkfb),
    .CLKFBOUTB           (),
    .LOCKED              (mmcm_locked)
);

BUFG clk_bufg_inst_125mhz (
    .I    (clk_mmcm_out),
    .O    (clk_125mhz_int)
);

sync_reset #(
    .N        (4)
)
sync_reset_inst_125mhz (
    .clk    (clk_125mhz_int),
    .rst    (reset),
    .out    (rst_125mhz_int)
);

BUFR #(
    .BUFR_DIVIDE("4"),      // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8"
    .SIM_DEVICE("7SERIES")  // Must be set to "7SERIES"
)
BUFR_inst_50mhz (
    .O      (clk_bufr_out_50mhz),   // Clock output port
    .CE     (1'b1),                 // Active high, clock enable (Divided modes only)
    .CLR    (rst_int),              // Active high, asynchronous clear (Divided modes only)
    .I      (clk_200mhz_ibufg)      // Clock buffer input..
                                    // ..driven by an IBUF, MMCM or local interconnect
);

BUFG clk_bufg_inst_50mhz (
    .I    (clk_bufr_out_50mhz),
    .O    (clk_50mhz_int)
);

sync_reset #(
    .N        (4)
)
sync_reset_inst_50mhz (
    .clk    (clk_50mhz_int),
    .rst    (reset),
    .out    (rst_50mhz_int)
);

endmodule

El módulo "sync_reset" es solo una canalización de N registros. Entonces, ¿es una buena manera de producir todos los reinicios de sincronización que necesito para mi diseño?

Solo quiero estar seguro.

Probablemente quieras construir algo que controle el reinicio de todo lo demás. En particular, tenga en cuenta que para cualquier reloj de fuente DLL, debe mantener la lógica del reloj en reinicio hasta que el reloj sea bueno; de lo contrario, podría ver resultados sorprendentes, por ejemplo, la "ROM" de FPGA puede ver contenido dañado si se viola el tiempo de lectura .

Respuestas (4)

Se ve bien. Normalmente, un sincronizador de 2 flop es suficiente para las frecuencias de reloj que desea. Eso es lo que he usado con los reinicios de botón en las placas FPGA. Pero un sincronizador de 4 flop sigue dando mejor MTBF. Dado que su diseño utiliza un restablecimiento sincrónico, tanto la afirmación como la liberación del "reinicio asincrónico del botón pulsador" deben sincronizarse mediante esta cadena de flip-flops con los dominios de reloj respectivos.

Dado que ha diseñado una cadena sincronizadora propia, es recomendable especificar la propiedad ASYNC_REG (página n.° 9 del documento) en los flops de destino. Vivado dice -

Especificar ASYNC_REG también afecta la optimización, la ubicación y el enrutamiento para mejorar el tiempo medio antes de fallar (MTBF) para los registros que pueden volverse metaestables. Si se aplica ASYNC_REG, el colocador se asegurará de que los flip-flops en una cadena de sincronización se coloquen cerca para maximizar MTBF

También puede considerar agregar un antirrebote en la ruta para evitar reinicios erróneos. Para que su circuito no se reinicie si el ancho del pulso de reinicio no es "lo suficientemente largo", digamos cuatro ciclos de reloj.

Ejemplo:

Ingrese la descripción de la imagen aquí

El superior es para un restablecimiento activo-bajo.

El inferior es para un restablecimiento activo-alto.

Hay un elemento de biblioteca que hace esto. Mira mi respuesta.

En general, querrá que la liberación de reinicio esté sincronizada con el reloj del bloque. También desea asegurarse de que realmente haya un reloj funcionando cuando eso ocurra, y que haya estado funcionando el tiempo suficiente para que el reinicio tenga efecto por completo.

La biblioteca de Xilinx incluye un bloque de reinicio configurable que lo manejará por usted. Enlace: https://www.xilinx.com/products/intellectual-property/proc_sys_reset.html

Traes un buen punto aquí. ¿Qué quieres decir con "lo suficientemente largo"? ¿Suficiente para que el reinicio fluya a través de las etapas de la canalización sin reinicio? Para que el PLL sea estable (período de reloj estable)....? (uno requiere un contador, el otro una señal de bloqueo, etc.)
Ambos PLL estables y lo suficientemente largos después de eso para que cualquier reinicio de sincronización se produzca.
Gracias, y ¿consideraría la señal de bloqueo/estable como síncrona o asíncrona? Algunos manuales afirman que la salida de bloqueo de su dispositivo está sincronizada con uno de los relojes, pero resulta que todavía puede parlotear...
Consideraría que un bloqueo estable es asincrónico, y necesitaría resincronizarse en el dominio de destino.
Acordado. Gracias. ¿Te importa si edito tus comentarios en la respuesta? O, por supuesto, podría hacerlo usted mismo, ya que es un aporte valioso.
Está bien como está gracias. Los usuarios interesados ​​pueden ver nuestra discusión aquí.
Por supuesto, estoy bien, pero los comentarios se eliminan con el tiempo y Google no los indexa.

Aquí hay un ejemplo de un diseño de FPGA con dos dominios de reloj. Uno es una interfaz PCI de 33 MHz y circuitos asociados, y el otro es para un bloque de 50 MHz. Nota: la clave aquí, como han dicho otros, es liberar el reinicio sincrónicamente con el reloj del dominio.

ingrese la descripción de la imagen aquí

En realidad, OP usa un reinicio síncrono en su diseño, pero el botón de reinicio que configuró en el tablero es una señal asíncrona. Por lo tanto, AMBAS afirmaciones y la liberación de ese "reinicio asíncrono" deben sincronizarse con el reloj. Si el OP estuviera usando un reinicio asíncrono en su diseño, solo se debe sincronizar la liberación.
¿Dónde "y" lo haría con la señal estable de bloqueo/reloj PLL? ¿Antes de las entradas RST / _RST_N o después de las salidas Creset?

Idealmente, un restablecimiento se inicializa de forma asíncrona mediante un estado bajo activo "antirrebote" y luego permanece en este estado hasta que se libera, lo que se sincroniza con el reloj del sistema con un solo flip flop.

La liberación no es solo mecánica, sino que se mantiene baja mediante un capacitor cuya constante de tiempo RC es más larga que el tiempo de rebote de un viejo interruptor de botón desgastado o 15 ms o más en un disparador Schmitt .

  • Se espera que los interruptores de botón reboten en el rango de 1 a 5 ms y los interruptores de palanca de 1 A en 10 a 25 ms.

    : recomendación

  • todo lo que necesita es una tapa, una puerta de activación Schmitt y un reloj de sistema D FF con un interruptor de botón a tierra y, por supuesto, su pull-up de 10 kΩ a 1 MΩ.

¿Entiendo?

  • La idea es que el contacto del primer botón se cargue y mantenga el voltaje bajo de Restablecimiento y, si la liberación rebota, el capacitor permanece bajo de todos modos el tiempo suficiente para evitar múltiples flancos.

  • Solo asegúrese de tener un reinicio controlado por "estado" en su diseño y no controlado por "borde" a menos que el circuito se sincronice automáticamente o no necesite estar sincronizado.

¿Necesito dibujar esto?

Esto no responde a la pregunta, que trata sobre cómo lidiar con esto dentro de un diseño de FPGA multirreloj.
Todos los relojes son sincronizados en frecuencia pero pueden variar en latencia. Así que mi respuesta sigue siendo cierta. Sincronizas todos los relojes con 1 eliminación de reinicio del reloj maestro. Así que estoy totalmente en desacuerdo @Graham