Fallo de restricción de tiempo interno de FPGA

Actualmente estoy tratando de implementar un IP-Core en un sistema FPGA-HPS Cyclone V 5CSEBA6U23I7 usando Altera Quartus II y TimeQuest Analyzer.
El código Verilog pegado a continuación produce un problema de temporización, a saber, la asignación fifo_wdata_289[255:0] <= {fifo_out,fifo_wdata_289[255:16]};, que escribe la salida de un FIFO en otra matriz de registros FIFO.
Los FIFO en uso son asíncronos, pero las señales utilizadas están en el mismo dominio de reloj.
Esto se coloca en el chip con un sesgo de reloj de -2.255 ns , que es un poco menos que un período completo ( reloj de 288 MHz => 3.47 ns ), y hace que TimeQuest se queje de que se están violando las restricciones.
La recomendación de TimeQuest es Reducir los niveles de lógica combinacional para el camino(Emitir ruta combinada larga ) con niveles adicionales de lógica combinacional = 1.

El reloj de 288 MHz se genera a través de PLL y estoy usando archivos de restricción de tiempo (sdc) con los comandos derivar_pll_relojes y derivar_reloj_incertidumbre.

Mi pregunta ahora es cómo resolver este problema, ya que solo tengo una capa de lógica combinacional (Demuxer y enrutamiento, como lo sugiere la asignación) y, por lo tanto, no tengo idea de cómo reducir eso. ¿Hay alguna otra manera de asegurarme de que se cumpla el requisito de tiempo, o hay una mejor manera de programar esta máquina de estado?
Gracias por tu ayuda.

            case(stateProc)
                2'b00:
                begin
                    if(~fifo_empty&~fifo_full_289)
                    begin
                        fifo_wdata_289[255:0] <= {fifo_out,fifo_wdata_289[255:16]};
                        fifo_wdata_289[287:256] <= {2'b11,fifo_wdata_289[287:258]};
                        if(imgSize >= maxImgSize - 32'd2)//image done, transmit data and fire irq
                        begin
                            fifo_wdata_289[288] <= 1;
                            stateProc <= 2'b01;
                            imgSize <= 32'd0;
                        end
                        else if(fifo_wdata_289[258])//process transfer without irq //258 high means that 256 has been written in this cycle and 258 in the previous cycle
                        begin
                            fifo_wdata_289[288] <= 0;
                            stateProc <= 2'b01;
                            imgSize <= imgSize + 32'd2;
                        end
                        else//accumulate more data
                        begin
                            fifo_wdata_289[288] <= 0;
                            stateProc <= 2'b00;
                            imgSize <= imgSize + 32'd2;
                        end
                    end
                    else
                    begin
                        fifo_wdata_289 <= fifo_wdata_289;
                        imgSize <= imgSize;
                        stateProc <= 2'b00;
                    end
                end
                2'b01:
                begin
                    fifo_wdata_289 <= fifo_wdata_289;
                    imgSize <= imgSize;
                    stateProc <= 2'b11;
                end
                2'b11:
                begin
                    fifo_wdata_289 <= 0;
                    imgSize <= imgSize;
                    stateProc <= 2'b00;
                end
            endcase

EDITAR:

Las rutas fallidas de TimeQuest se ven principalmente así:
Slack:
-3.178

Desde el nodo:
soc_system:u0|CamConnector:camconnector_0|FIFO_289:FIFO_inst_289|dcfifo:dcfifo_component|dcfifo_6up1:auto_generated|wrptr_g[0]

Hasta el nodo:
soc_system:u0|CamConnector:camconnector_0 |fifo_wdata_289[267]

EDIT2:
actualmente estoy usando celdas MLAB como almacenamiento FIFO, que están clasificados para 290 MHz.
Ambos FIFO son asincrónicos y tienen una configuración de sincronización de 3.
Las recomendaciones de cierre de tiempo de TimeQuest informan los dos problemas siguientes:

  1. Lógica Combinacional Desequilibrada
  2. Camino combinacional largo

Respuestas (2)

ya que solo tengo una capa de lógica combinacional (Demuxer y enrutamiento, como lo sugiere la asignación)

No, no tienes eso. También está la compensación en stateProc==2'b11. Pero supongo que las LUT de Cyclone son lo suficientemente grandes como para abarcar una puerta AND adicional al mismo tiempo.

Pero le sugiero que también publique la ruta fallida según lo informado por la herramienta. Porque algo no cuadra aquí. La ruta para fifo_wdata_289[288] es más compleja y usted dice que pasa el tiempo. No me sorprendería si las señales de control mux: fifo_empty, fifo_full_289, stateProc, etc. también están en la ruta de temporización fallida junto con el árbol de transmisión, ya que controla muchos FF desde una señal.

Si no, solo puedes correr a una velocidad más baja. No sirve de nada jugar con el reloj ya que el circuito usa sus propias señales ( fifo_wdata_289 [255:0] <= {fifo_out, fifo_wdata_289[255:16] };) Por lo tanto, si sesga o invierte el reloj, fifo_wdata_289[255: 16] saldrá más tarde y, por lo tanto, volverá a fallar en el tiempo. Puede tener suerte y el fifo_out llega tarde y provoca el error de tiempo, pero vuelva a mirar el informe de tiempo de la ruta fallida.

De todos modos, sesgar un reloj es algo que se puede hacer en un ASIC, pero no lo intentaría en un FPGA. No creo que tenga el control fino para sesgar un reloj ~ 300ps contra otro. Pero no tengo ciclones, así que tal vez....


Actualización:
justo lo que esperaba: la ruta comienza en wrptr_g ... Supongo que es el puntero de escritura que probablemente se compara con el puntero de lectura que hace que las banderas fifo_full/empty controlen el mux.

La mejor manera de deshacerse del problema de tiempo es hacer una versión registrada de las banderas de lleno/vacío. Eso puede significar que tiene que rediseñar parte del resto del circuito.

Si el FIFO es síncrono, hay un truco para generar banderas síncronas de lleno/vacío. Verifica si el nivel es UNO y en una lectura pero no en una escritura síncrona establece el indicador 'vacío'. Vea aquí un código de ejemplo gratuito de FIFO que tiene esa característica. Desafortunadamente, eso no funciona con FIFO asíncronos.

Eché un vistazo al esquema RTL posterior al ajuste y aparentemente las LUT son lo suficientemente grandes como para implementar esto como una operación de bloque lógico único, pero aparentemente debería haber leído las advertencias más de cerca. Las principales rutas que fallan comienzan desde un registro FIFO interno (FIFO_289:FIFO_inst_289|dcfifo:dcfifo_component|dcfifo_6up1:auto_generated|wrptr_g[0]) y se propagan a la matriz fifo_wdata_289. Realmente no sé por qué esta no es una ruta falsa, ya que la señal de origen se alimenta en un bloque de ram registrado. Tal vez sea seguro ignorarlo (con suerte).
Tampoco estoy seguro de si alguna de las rutas mencionadas no falla. Si fallan, no fallan tanto como las rutas que se muestran (TimeQuest tiene un límite de visualización/análisis): D. Tal vez también sea relevante tener en cuenta que la RAM es un bloque M10K.
Gracias por tu actualización. Cambié el tipo de celda de memoria de M10K a MLAB y reduje la velocidad del reloj a 288 MHz, porque aparentemente las celdas de almacenamiento no pueden manejar más que eso. Lamentablemente, los problemas no desaparecieron, el sesgo solo disminuyó en amplitud, ya que la frecuencia del reloj disminuyó. Estoy usando FIFOs asincrónicos, porque necesito hacer CDC y por eso uso 3 etapas de sincronización, es decir, que las señales de lleno/vacío se registran dentro del FIFO.

Si ambos FIFO están siendo alimentados con la misma fase de reloj, entonces se están violando los tiempos de configuración y espera para el segundo FIFO, como si llegara demasiado pronto. Su programa está insinuando que necesita ralentizar algo, a saber, su reloj.

Puede agregar un inversor para bloquear el segundo FIFO en el flanco descendente mucho después de que los datos se hayan asentado. Una mejor opción si su software puede hacer esto es mover la línea del reloj antes de que llegue al segundo FIFO. Software como Specctra puede hacer los cálculos para esto.

A falta de algo mejor, una resistencia de bajo valor en serie con el reloj hasta el segundo FIFO creará un retraso natural. Averigüe la capacitancia del pin del reloj y calcule lo que se necesita para un retraso de algunos nS. Creo que 100 ohmios como máximo, pero más de 10 ohmios.

Gracias por esa sugerencia, pero no usaría una resistencia, incluso si fuera un circuito analógico, porque esto introducirá ruido y no quiero ni pensar en la EMC, cuando pones un reloj de 360 ​​MHz en un FPGA pin y use una resistencia para retroalimentar la señal. Los FIFO también están bloqueados en el borde invertido, mientras que los datos se cambian en el otro borde, por lo que esperaba que los datos fueran estables en el tiempo de bloqueo de los FIFO.