¿Cómo cruzar dominios de reloj eficientemente?

0

Tengo una pregunta sobre el envío de una señal de corta duración de un dominio de reloj más rápido a un dominio de reloj más lento. Estoy intentando implementar un búfer de marco dual en una memoria RAM de doble puerto (reloj dual). Una vez que se ha almacenado un Frame completo, el lado del reloj de escritura afirma el registro FrameFull. Al final de cada marco de visualización actual, la pantalla solicita un nuevo marco, que si está disponible, establece el puntero de lectura para la RAM en consecuencia y también se usa para volver a colocar la señal FrameFull para que se pueda cargar un nuevo marco mientras se muestra el más reciente.

El lado de lectura está operando a 50 MHz.
El lado de escritura está operando a 27 MHz.

Para sincronizar la señal FrameFull desde el dominio de escritura, he leído que es mejor usar un par de flip flops de sincronización y como FrameFull permanece activo hasta que se cambia el búfer, creo que esto no es muy problemático ( porque la señal FrameFull no se puede perder). La señal SwitchSuccesful se afirma en el dominio de reloj de lectura cuando se solicita un nuevo Frame y FrameFull es 1, lo que indica el intercambio de búfer. Ahora, este SwitchSuccesful debe ser muestreado por el dominio de escritura para que FrameFull pueda restablecerse a 0 y luego pueda comenzar a almacenar un nuevo marco. Lo pensé y decidí usar un registro de desplazamiento de 16 bits que, cuando se cambian los búferes, se restablecerá a 16'hFF y luego se desplazará a la izquierda con un cero concatenado. resultado del bit a bit O con Flip Flops en el dominio de escritura antes de muestrear la señal. ¿Será esto suficiente para evitar perder el interruptor de éxito y la metastabilidad?

CÓDIGO:

always @ (posedge read_clock)
begin
    if(SwitchRequest) begin
          case (Frame_FullSync1, Frame_Read) 
          2'b00 : begin rd_ptr <= /*Some Value*/ Frame_Read <= 0; end           //Restore to Previous 0.
          2'b01 : begin rd_ptr <= /*Some Value*/ Frame_Read <= 1; end           //Restore to Previous 1.
          2'b10 : begin rd_ptr <= /*Some Value*/ Frame_Read <= 1; LE <= 1; end  //Load new ----- 0 to 1.
          2'b11 : begin rd_ptr <= /*Some Value*/ Frame_Read <= 0; LE <= 1; end  //Load new ----- 1 to 0.
          endcase
    end
    if(LE) LE <= 0;
end

always @ (posedge read_clock)  begin 
    //Frame Full Synchronization from write domain to read domain
    Frame_FullSync1 <= Frame_FullSync0;
    Frame_FullSync0 <= FrameFull;
    //LE was asserted for 1 clock cycle when buffer switch was succesful
    if(LE) Sync <= 16'hFF;
    else   Sync <= Sync {Sync[15 : 1],1'b0};
end

assign SwitchSuccesful = |Sync;

always @ (posedge write_clock) begin
    //Synchronization of bitwise OR
    SwitchSuccesfulSync0 <= SwitchSuccesful;
    SwitchSuccesfulSync1 <= SwitchSuccesfulSync0; 
end
    
pregunta Ahmed Ali Abbasi

3 respuestas

3

Suponiendo que los datos de interés cambian en el flanco descendente del reloj de 27Mhz y se muestrean en el flanco ascendente, la aproximación con un retraso mínimo sería tener una división de dos por el reloj de 27MHz cuya salida cambia en el borde ascendente, alimente la salida de eso a un sincronizador doble que muestrea el borde descendente del reloj de 50MHz, y capture todo lo demás en el borde ascendente del reloj de 50MHz.

Si dos flancos descendentes consecutivos del reloj de 50Mhz informan estados opuestos para la salida de división por dos, eso implica que el borde real debe haber ocurrido en algún lugar dentro de ese intervalo. Los datos se habrán muestreado en un momento a medio camino entre esos eventos de reloj de 50MHz, dentro de aproximadamente 10 ns de cuando ocurrió el reloj de 27MHz.

El muestreo de todo en el mismo borde del reloj de 50MHz puede no ser suficiente para permitir una decodificación confiable de eventos. Considere los siguientes dos escenarios, con la primera línea que representa los eventos de reloj de 50MHz y la última que representa los eventos de reloj de 30MHz (los mismos principios se aplicarían en 27); ambas líneas tienen una escala de 3.3 ns por carácter

|-----|-----|-----|-----|-----|--  -- 50Mhz clock rising edges
-|---------|---------|---------|-  -- 30Mhz clock rising edges
_x---------x_________x---------x_  -- 30MHz/2, changing on rising edges
______x---------x_________x------  -- 30MHz/2, changing on falling edges
000000x111111111x222222222x333333  -- Data words, changing on 30Mhz fall

Las muestras consecutivas de los relojes de 30 MHz divididos y las palabras de datos producirían:

_-__--_--_  30MHz/2, changing on rising edges, then sampled @50Mhz rising
_x-__-x_--  30MHz/2, changing on falling edges, then sampled @50Mhz rising
0x1223x455  Data, sampled @50Mhz rising

No hay ningún punto en relación con los bordes observados en ninguna de las formas del reloj de 30MHz donde se garantizará que la salida esté limpia. Por otro lado, si el La señal de "30Mhz / 2 ascendente" se muestrearon en los bordes descendentes del reloj de 50Mhz, que daría, en relación con los datos:

--_x-__-x_  30Mhz/2, changing on rising edges, sampled @50Mhz falling
0x1223x455  Data, sampled @50Mhz rising

Si un reloj de 30Mhz coincidiera con un flanco descendente del reloj de 50Mhz, puede haber una incertidumbre equivalente a la diferencia de cuándo se produjo el borde, pero los mismos datos estarían presentes en los ciclos antes y después, por lo que tal incertidumbre no t importa.

    
respondido por el supercat
1

No podría seguir exactamente todo el escenario que describiste, pero si la pregunta se reduce a "cuál es una buena manera de pasar un solo pulso de ciclo de reloj a un dominio de reloj diferente", considera esto: en lugar de generar un pulso , simplemente alternar la señal. Pase esta señal conmutada al otro dominio de reloj usando registros de metaestabilidad. En el otro dominio del reloj, implemente un circuito de detección de bordes que genere un solo impulso de ciclo de reloj en los cambios de nivel. Eso es todo, pulso pasado. Esto solo funcionará de manera confiable si la señal cambia con poca frecuencia (yo diría que una frecuencia máxima de una vez cada 4 de los ciclos de reloj más lentos) para permitir que los registros de metaestabilidad se establezcan.

    
respondido por el user2913869
0

Como la persona que formuló la pregunta original aclaró que la memoria RAM puede usar relojes independientes para escribir y leer, me gustaría sugerir un buen enfoque para pasar eventos entre dominios de reloj: construya un anillo de flip flops, con dos o tres en cada dominio, una inversión que gira alrededor del anillo y una habilitación de bloqueo en uno de los flops en el dominio de envío. Algo como:

simular este circuito : esquema creado usando CircuitLab

(Utilicé un flop D y un mux para simular un flop D con control habilitado con pestillo).

READY será alto cuando el dispositivo esté listo para un evento en el dominio de origen. Después de un ciclo de reloj de dominio de origen donde STROBE y READY están en alto, READY se pondrá bajo y permanecerá bajo hasta que el evento haya sido procesado y confirmado. La señal de SALIDA en el dominio del reloj de destino será alta para exactamente un ciclo de reloj en ese dominio después de que se active un evento. Tenga en cuenta que incluso si el reloj de origen se detuviera en el ciclo después de que STROBE y READY estuvieran altos, el evento se propagaría al dominio de destino. El circuito podría hacerse para permitir un tiempo de respuesta más rápido en los eventos, alimentando REG1 de REG5 en lugar de REG6, y moviendo REG2 a la salida de XOR2 (para evitar la metastabilidad, debe haber dos flops basados en CLK1 entre la señal REG6 y la LISTA Salida, pero uno de ellos podría ser después del XOR). Creo que el comportamiento del circuito tal como está dibujado es probablemente menos confuso. El dominio izquierdo mostrará "listo" si una luz estroboscópica sería efectiva en el ciclo siguiente , y no estará lista nuevamente hasta que el dominio de la derecha haya tenido un ciclo de reloj en el que el nivel de SALIDA fue alto.

    
respondido por el supercat

Lea otras preguntas en las etiquetas