Macro Parametrada de Xilinx (XPM) xpm_cdc_pulse para Transferencia de Señales entre Dominios de Reloj

En Verilog, xpm_cdc_pulse es un módulo de cruce de dominio de reloj (CDC) dentro de las macros paramétricas de Xilinx (XPM), diseñado específicamente para la transferencia segura de señales de pulso de un solo ciclo entre diferentes dominios de reloj.

Introducción Técnica

La macro xpm_cdc_pulse garantiza que cada pulso de un solo ciclo en el dominio de reloj de origen se transfiera correctamente al dominio de reloj de destino, generando un pulso correspondiente de un solo ciclo en el destino sin pérdidas ni duplicaciones.

Sintaxis Básica

// Instanciación en Verilog
xpm_cdc_pulse #(
   .DEST_SYNC_FF(3),        // Rango: 2-10
   .INIT_SYNC_FF(0),        // 0-1
   .REG_OUTPUT(1),          // 0-1
   .RST_USED(1),            // 0-1
   .SIM_ASSERT_CHK(1)       // 0-1
)
pulse_cdc_unit (
   .origen_clk(origen_clk),       // Reloj de origen
   .origen_rst(origen_rst),       // Reset de origen (opcional)
   .pulso_origen(pulso_origen),   // Entrada de pulso de origen
   .destino_clk(destino_clk),     // Reloj de destino
   .destino_rst(destino_rst),     // Reset de destino (opcional)
   .pulso_destino(pulso_destino)  // Salida de pulso de destino
);

Parámetros Principales

  • DEST_SYNC_FF (por defecto=2): Número de etapas de registros sincronizadores en el dominio de destino
  • REG_OUTPUT (por defecto=0): Indica si se añade un registro de salida en el dominio de destino
  • RST_USED (por defecto=0): Controla si se uttilizan las señales de reset
  • INIT_SYNC_FF (por defecto=0): Valor inicial de los registros sincronizadores
  • SIM_ASSERT_CHK (por defecto=0): Habilita comprobaciones de aserción durante simulación

Ejemplos de Implementación

Ejemplo 1: Transferencia Básica de Pulso

module transferencia_pulso (
   input  wire reloj_origen,
   input  wire reloj_destino,
   input  wire pulso_entrada,
   output wire pulso_salida
);

xpm_cdc_pulse #(
   .DEST_SYNC_FF(2),        // 2 etapas de sincronización
   .RST_USED(0)             // Sin señales de reset
) sincronizador_pulso (
   .origen_clk(reloj_origen),
   .origen_rst(1'b0),       // Sin reset
   .pulso_origen(pulso_entrada),
   .destino_clk(reloj_destino),
   .destino_rst(1'b0),
   .pulso_destino(pulso_salida)
);

endmodule

Ejemplo 2: Sincronización con Señales de Reset

module sincro_con_reset (
   input  wire clk_fuente,
   input  wire clk_destino,
   input  wire reset_fuente,
   input  wire reset_destino,
   input  wire pulso_disparo,
   output wire pulso_sincronizado
);

xpm_cdc_pulse #(
   .DEST_SYNC_FF(4),        // Mayor confiabilidad con 4 etapas
   .RST_USED(1),            // Uso de señales de reset
   .REG_OUTPUT(1)           // Registro de salida habilitado
) cdc_con_reset (
   .origen_clk(clk_fuente),
   .origen_rst(reset_fuente),
   .pulso_origen(pulso_disparo),
   .destino_clk(clk_destino),
   .destino_rst(reset_destino),
   .pulso_destino(pulso_sincronizado)
);

endmodule

Mecanismo de Funcionamiento

El funcionamiento interno de xpm_cdc_pulse sigue estos pasos:

  1. Detección del pulso de origen: El módulo detecta el flanco ascendente del pulso en el dominio de origen
  2. Conversión a nivel: El pulso se convierte a una señal de nivel estable
  3. Sincronización cruzada: La señal de nivel se pasa al dominio de destino mediante una cadena de registros sincronizadores
  4. Regeneración de pulso: En el dominio de destino, se detecta el cambio de nivel para regenerar un pulso de un solo ciclo

Casos de Aplicación Práctica

1. Sincronización de Señales de Inicio

module sincro_senal_inicio (
   input  wire clk_configuracion,
   input  wire clk_procesamiento,
   input  wire iniciar_configuracion,
   output wire iniciar_procesamiento
);

xpm_cdc_pulse cdc_inicio (
   .origen_clk(clk_configuracion),
   .origen_rst(1'b0),
   .pulso_origen(iniciar_configuracion),
   .destino_clk(clk_procesamiento),
   .destino_rst(1'b0),
   .pulso_destino(iniciar_procesamiento)
);

endmodule

2. Propagación de Solicitudes de Interrupción

module sincro_interrupcion (
   input  wire clk_periferico,
   input  wire clk_cpu,
   input  wire peticion_irq,
   output wire irq_sincronizada
);

xpm_cdc_pulse #(
   .DEST_SYNC_FF(3),
   .REG_OUTPUT(1)              // Salida limpia y estable
) cdc_interrupcion (
   .origen_clk(clk_periferico),
   .origen_rst(1'b0),
   .pulso_origen(peticion_irq),
   .destino_clk(clk_cpu),
   .destino_rst(1'b0),
   .pulso_destino(irq_sincronizada)
);

endmodule

3. Disparo entre Múltiples Dominios de Reloj

module disparo_multidominio (
   input  wire clk_lento,       // Reloj lento (ej. configuración)
   input  wire clk_rapido,      // Reloj rápido (ej. procesamiento)
   input  wire disparo_lento,   // Disparo en dominio lento
   output wire disparo_rapido   // Disparo en dominio rápido
);

xpm_cdc_pulse #(
   .DEST_SYNC_FF(4)           // Máxima seguridad
) cdc_disparo (
   .origen_clk(clk_lento),
   .origen_rst(1'b0),
   .pulso_origen(disparo_lento),
   .destino_clk(clk_rapido),
   .destino_rst(1'b0),
   .pulso_destino(disparo_rapido)
);

endmodule

4. Sincronización de Señales de Depuración

module sincro_debug (
   input  wire clk_pruebas,
   input  wire clk_sistema,
   input  wire disparo_debug,
   output wire pulso_debug_sistema
);

xpm_cdc_pulse cdc_debug (
   .origen_clk(clk_pruebas),
   .origen_rst(1'b0),
   .pulso_origen(disparo_debug),
   .destino_clk(clk_sistema),
   .destino_rst(1'b0),
   .pulso_destino(pulso_debug_sistema)
);

endmodule

Configuración Completa de Parámetros

xpm_cdc_pulse #(
   .DEST_SYNC_FF(3),        // Etapas de sincronización en destino
   .INIT_SYNC_FF(0),        // Valor inicial de registros
   .REG_OUTPUT(1),          // Registro de salida (0=desactivado, 1=activado)
   .RST_USED(1),            // Uso de reset (0=no, 1=sí)
   .SIM_ASSERT_CHK(1)       // Comprobaciones en simulación
)

Características de Temporalización

Comportamiento del Pulso

  • Pulso de origen: Debe ser de un solo ciclo en el dominio de origen
  • Pulso de destino: Genera un pulso de un solo ciclo en el dominio de destino
  • Espaciado mínimo: Los pulsos de origen deben tener un espaciado suficiente para evitar pérdidas

Atraso Típico

Pulso origen → [1 ciclo reloj origen] → Inicio sincronización → [DEST_SYNC_FF ciclos reloj destino] → Pulso destino

Comportamiento con Reset

Cuando RST_USED = 1

xpm_cdc_pulse #(.RST_USED(1)) cdc_con_reset (
   .origen_clk(reloj_a),
   .origen_rst(reset_a),      // Reset de origen, asíncrono o síncrono
   .pulso_origen(pulso_entrada),
   .destino_clk(reloj_b),
   .destino_rst(reset_b),     // Reset de destino, asíncrono o síncrono
   .pulso_destino(pulso_salida)
);

Uso en Vivado

Reconocimiento Automático

Vivado identifica automáticamente los módulos XPM CDC y aplica las restricciones de temporización apropiadas.

Sugerencias de Restricciones

# Configurar grupos de reloj asíncronos
set_clock_groups -asynchronous \
   -group [get_clocks reloj_a] \
   -group [get_clocks reloj_b]

# Establecer restricciones de retraso máximo si es necesario
set_max_delay -from [get_cells pulso_origen_reg] \
              -to [get_cells xpm_cdc_pulse_inst/*sincro*] \
              -datapath_only 1.2

Ventajas

  1. Fiabilidad: Específicamente optimizado para señales de pulso
  2. Integridad: Garantiza que cada pulso de origen genere un pulso correspondiente en destino
  3. Simplicidad: Elimina la necesidad de implementar manualmente lógica CDC compleja
  4. Configurabilidad: Parámetros ajustables para diferentes requisitos

Precauciones de Uso

Implementación Correcta

// Correcto: Pulso de un solo ciclo con espaciado adecuado
reg generador_pulso;
always @(posedge reloj_origen) begin
   if (condicion) generador_pulso <= 1'b1;
   else generador_pulso <= 1'b0;
end

xpm_cdc_pulse cdc_correcto (
   .origen_clk(reloj_origen),
   .pulso_origen(generador_pulso),  // Pulso de un ciclo
   .destino_clk(reloj_destino),
   .pulso_destino(pulso_salida)
);

Errores Comunes

// Error 1: Pulso de múltiples ciclos
wire pulso_multiple_ciclo = condicion;  // Puede durar múltiples ciclos

// Error 2: Pulsos consecutivos (posible pérdida)
always @(posedge reloj_origen) begin
   generador_pulso <= ~generador_pulso;  // Pulsos rápidos consecutivos
end

// Error 3: Entrada asíncrona
wire pulso_asincrono = senal_externa;  // Debe sincronizarse primero al reloj de origen

Requisitos de Espaciado

Espaciado mínimo = DEST_SYNC_FF + 2 ciclos del reloj de origen
// Ejemplo: DEST_SYNC_FF=2 → espaciado mínimo de 4 ciclos del reloj de origen

Otros Módulos XPM CDC Relacionados

  • xpm_cdc_single: Transferencia de señales de un solo bit
  • xpm_cdc_handshake: Transferencia de datos múltiples con protocolo de handshake
  • xpm_cdc_gray: Transferencia de contadores usando código Gray

La macro xpm_cdc_pulse es la solución ideal para transferir señales de pulso de un solo ciclo entre dominios de reloj diferentes, especialmente útil en aplicaciones como disparos de inicio, solicitudes de interrupción y transmisión de comandos.

Etiquetas: Verilog Xilinx XPM CDC FPGA

Publicado el 6-23 05:38