Usando ambos bordes de reloj en un diseño FPGA

Entonces, después de recibir algunos consejos de algunas buenas personas aquí, logré armar mi primer (muy modesto) diseño de FPGA. Básicamente son solo unos pocos registros y contadores, y solo se ejecuta a unos pocos MHz, pero pude sintetizarlo e implementarlo sin advertencias, y las señales reales que salen parecen hacer lo que la simulación me hizo pensar que harían. Aprendí algunas cosas en el camino.

Ahora quiero aprender a establecer restricciones de tiempo y ejecutar análisis de tiempo. Así que estoy leyendo el documento de Xilinx UG612 y veo en la parte superior de la página 205:

"Usar solo un borde del reloj"

Mmm. Parece que infringí la ley. Parte de mi diseño es un registro de cambio de carga en paralelo: utilicé el margen del último ciclo del reloj para cargarlo (desde un contador que se marcó en el margen anterior). Un boceto rápido:

cronometraje y carga

Por supuesto, no estoy usando directamente el negedge aquí, pero la señal de carga se deriva de él. Pensé que esto era bueno, pero Xilinx me dice: no hagas eso.

¿Me equivoco? Si es así, ¿por qué? ¿Qué debo hacer en su lugar?

¿El error que te da xilinx es sobre un reloj cerrado?
no, mi diseño se compila de forma completamente limpia, sin advertencias ni errores. Me refiero a los consejos dados en el documento vinculado (número de página en el texto anterior).
Puede mezclarlos, pero desde una perspectiva de sincronización, eso significa que las rutas de configuración/mantenimiento se vuelven la mitad de largas y la sincronización se vuelve más difícil de cumplir. ¿De qué se deriva SRCLK?
SRCLK es un reloj de 2 MHz, el reloj principal de mi diseño. (Hay un oscilador de cristal de 100 MHz en la placa de desarrollo, usé un contador síncrono para obtener los 2 MHz). Me imagino que en estas frecuencias es poco probable que haya un problema, pero me gustaría saber cuál es la "mejor práctica" y por qué. .
La salida de su contador no es un reloj de 2 MHz . Es una señal cuadrada con 2 MHz pero sin señal de reloj (real) . En general, la mayoría de los FPGA no admiten relojes lentos por debajo de 10 MHz. Debe operar su circuito con 100 MHz y generar una señal de habilitación de reloj con una frecuencia de 2 MHz.
Los relojes BiPhase son útiles para reducir la latencia en un 50 %, pero si se cumplen los requisitos de tiempo de configuración/retención, la frecuencia de entrada asíncrona se puede duplicar usando el mismo borde
Los FPGA no admiten técnicas DDR (que funcionan en ambos bordes del reloj) para flip-flops internos. Esto solo se admite para bloques de entrada/salida (IOB). Si tiene un reloj de sistema de 100 MHz, use la técnica de habilitación como se describe anteriormente. Esto le permite utilizar hasta 50 versiones desplazadas de su señal de 2 MHz en lugar de una versión desplazada (orden 25).
Gracias a todos por sus comentarios y consejos. Paebbels: en realidad, no estoy sincronizando ningún dispositivo con ambos bordes; sin embargo, estoy usando un reloj negedge en algunos dispositivos. ¿Tiene algún vínculo con la técnica CE? Y cuando dice "la mayoría de los FPGA no admiten relojes lentos por debajo de 10 MHz", ¿qué significa eso realmente? ¿Cuáles son las (posibles) consecuencias? y ¿cuándo exactamente una onda cuadrada se convierte en un "reloj propiamente dicho"?
@Paebbels "la mayoría de los FPGA no admiten relojes lentos por debajo de 10 MHz" Entiendo que es posible que el PLL no pueda generar relojes lentos, pero ¿qué evitaría que el FPGA avance a esta velocidad lenta si el reloj se genera externamente (o incluso usando internamente alguna lógica de divisor de frecuencia)? ¿Tiene referencias para esta restricción?
Los relojes reales no se enrutan con recursos lógicos de usuario, sino con rutas dedicadas (de reloj), las llamadas redes de reloj. Por lo tanto, debe alimentar el reloj generado en un BUFG, BUFH, BUFR, ... No puede usar un reloj combinatorio de este tipo para ningún bloque modificador de reloj (CMB) como entrada. A continuación, debe especificar nuevas restricciones en el sistema para notificar al análisis de tiempo estático que esta señal tiene una frecuencia, un ciclo de trabajo y quizás una relación de fase. Normalmente, tales restricciones se infieren automáticamente.
Nunca he visto a ningún estudiante o ingeniero haciendo todo esto cuando usan la forma sucia de crear relojes derivados. Ok, siguiente problema, la lógica de usuario (contador) utilizada para generar el reloj introduce una alta fluctuación en la señal. Por lo tanto, nuevamente es necesario especificar las restricciones de tiempo, pero se desconoce la fluctuación máxima en los FPGA para esta técnica. También depende mucho de la temperatura y el voltaje (carga de trabajo). Los ingenieros que utilizan este método sucio para diseños lentos utilizarán la misma técnica para frecuencias más altas o en diseños de transceptores de varios gigabits. Así que hay una regla de diseño muy simple: ¡no lo hagas!
Esto también se puede encontrar en las pautas de diseño de HDL de los proveedores...
Creo que ISE es consciente de que estas son señales de reloj: "1 entradas de reloj: i_clk_100MHz Redes de reloj de 4 hojas: clk_div/o_clk_BUFG i_clk_100MHz_BUFGP" - gracias por sus comentarios. Como digo, estoy aprendiendo.
Entonces, descubrí que al usar el asistente de reloj en ISE puedo generar un reloj de 4 MHz a partir de 100 MHz, lo cual está bien, usando los recursos de reloj internos. (Lo más bajo que puede llegar desde 100 MHz clk in es un poco más de 3 MHz; si mi reloj externo fuera de 20 MHz, podría generar fácilmente 2 MHz internos, por supuesto). Por supuesto, esto es mejor que lo que estaba haciendo, otra cosa que aprendí. También miré la hoja de datos y no veo ninguna especificación para la frecuencia de reloj mínima en ningún lugar. Un montón de Fmax, no Fmin. Por supuesto, si alguien sabe de tal requisito en los datos de Xilinx Spartan 6, me interesaría saberlo.

Respuestas (3)

"Usar solo un borde del reloj"

No sé por qué dirían eso. Puede usar flancos de reloj ascendentes y descendentes en el diseño y el analizador de tiempo lo tendrá en cuenta.

Por lo tanto, un reloj de 200MHz le dará 5 ns desde el flanco ascendente hasta el flanco ascendente, pero solo 2,5 ns desde el flanco ascendente hasta el flanco descendente. Hice un pequeño ejemplo usando valores de 16 bits:

always @(posedge clk)
   result1 <= counter + hold;
always @(negedge clk)
   result2 <= counter + hold;

A continuación se muestra una captura de pantalla del análisis de tiempo de ISE. Es para un reloj de ciclo de trabajo del 50% de 5ns.

El texto trata sobre una ruta fallida desde el bit 3 counterhasta el bit 15 de result2. Como puede ver, utiliza el flanco ascendente como fuente y el flanco descendente como destino.

ingrese la descripción de la imagen aquí

Creo que lo dicen para evitar más multas por SR... y porque KISS es mejor de todos modos. Pero, sí, completamente válido para usar diferentes bordes, y sus herramientas de sincronización pueden manejarlo.
Gracias. De hecho, parece que se puede hacer, pero como Photon señala a continuación, eso no significa que deba serlo.

Los elementos lógicos en la FPGA generalmente se diseñan con tiempo de espera cero , específicamente para permitirle diseñar con solo un borde de reloj.

En su ejemplo, esto significa que tanto la señal CTR INC como la señal SR LOAD se ven como afirmadas en el borde 0, y ninguna se ve como afirmada en el borde 15. El valor que se carga en el registro de desplazamiento será el que está en el contador antes del borde 0. El efecto de incrementar el contador no se verá en el registro de desplazamiento hasta la próxima vez que se afirme SR LOAD.

Si hizo que la señal SR siguiera la misma forma de onda que CTR INC, esto seguiría siendo cierto y el comportamiento del circuito sería el mismo.

Bien. Esto es muy útil, porque aquí es donde no estaba pensando con claridad. Cuando hice esto, me preocupaba que el SR saltara un conteo si usara la misma señal. Esto no sucederá ya que los flip flops de FPGA aún no pueden predecir el futuro. tranquilizador!

No está equivocado, solo está haciendo su vida más difícil de lo que debe ser... especialmente en lo que respecta al cierre de tiempo (desarrollar restricciones precisas es más difícil). Puede hacer que este diseño funcione fácilmente solo en el borde ascendente.

Me parece que si desea cargar cuando contador = 0, podría tener alguna lógica combinatoria que: assign load = (counter==15)(o similar). Esto cambiará su señal de carga hacia atrás 1/2 ciclo de reloj, y se verá en el borde ascendente de edge0 como se afirma. Sin embargo, hay muchas maneras de hacer esto (utilizando todos los FF con reloj de flanco ascendente), y probablemente un poco de google será de gran ayuda.