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í:
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.
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:
El superior es para un restablecimiento activo-bajo.
El inferior es para un restablecimiento activo-alto.
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
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?
chris stratton