compilación de código VHDL en el quartus II

3

Mira este fragmento de código (voltea la imagen en X)

PROCESS(iCLK) 
BEGIN
  IF (rising_edge(iCLK)) THEN 
    -- Mise en mémoire du pixel
    ram(640*IdxC + PixX) <=  PIXIN; 
    -- Choix traitement
    IF (SWITCH='1') THEN
      PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
    ELSE
      PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
    END IF; 
  END IF;   
END PROCESS;

Cuando lo compilo, el proyecto general toma aproximadamente el 15% de los elementos lógicos y el 13% de los bits de memoria total (QuartusII en el ciclón III). Si cambio el código a

PROCESS (iCLK)
BEGIN
  IF(rising_edge(iCLK)) THEN 
    -- Mise en mémoire du pixel
    ram(640*IdxC + PixX) <=  PIXIN; 
    -- Choix traitement
    IF (SWITCH='1') THEN
      PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
    ELSE
      IF (PixX > 1 AND PixX < 640) THEN
        PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
      ELSE
        PIXOUT <= x"111";
      END IF;
    END IF; 
  END IF;   
END PROCESS;

me sale

Error (276003): Cannot convert all sets of registers into RAM megafunctions when creating nodes. The resulting number of registers remaining in design exceeds the number of registers in the device or the number specified by the assignment max_number_of_registers_from_uninferred_rams. This can cause longer compilation time or result in insufficient memory to complete Analysis and Synthesis

Parece que ya no puedo encajar el diseño. Yo no creo esto. ¿Hay algún error en el compilador o estoy haciendo algo mal?

Tengo la edición web de Quartus II

Simplemente poniendo algunos comentarios -- en las líneas como esta y compila nuevamente:

PROCESS (iCLK)
BEGIN
  IF (rising_edge(iCLK)) THEN
    -- Mise en mémoire du pixel
    ram(640*IdxC + PixX) <= PIXIN;
    -- Choix traitement
    IF (SWITCH='1') THEN
      PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
    ELSE
   -- IF (PixX > 1 AND PixX < 640) THEN
        PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
   -- ELSE
   --   PIXOUT <= x"111";
   -- END IF;
    END IF;
  END IF;
END PROCESS;

Este código funciona con el puerto Megafunction RAM 2:

PROCESS (iCLK)
BEGIN
  IF rising_edge(iCLK) THEN     
    -- Ecrire linéairement dans la RAM le pixel de la cam
    RAMWRITE <= TO_UNSIGNED(640*IdxC + PixX - 1, 11);
    -- Choix traitement
    IF (SWITCH='1') THEN
      RAMREAD <= TO_UNSIGNED(640*((IdxC + 1) mod 2) + PixX - 1, 11);
      PIXOUT <= PIXMEM;
    ELSE
      RAMREAD <= TO_UNSIGNED(640*(2-IdxC) - PixX, 11);
      IF (PixX > 1 AND PixX < 640) THEN
        PIXOUT <= PIXMEM;
      ELSE
        PIXOUT <= x"FFF";
      END IF;
    END IF;     
  END IF;                       
END PROCESS;
    
pregunta Olivier Monnom

1 respuesta

5

No diría que es un error, es más una limitación, y en cierto modo tiene sentido total. Si desea que deduzca un ram de doble puerto, el compilador desea inferir un ram de doble puerto, sin embargo, el proceso en el fragmento de problema no describe correctamente la entrada de dirección del puerto de lectura del ram, ya que no todas las rutas están cubiertas, por lo que Tendría que inferir un pestillo, mientras que lo que realmente quieres es que no te importe. Así que básicamente lo estás haciendo difícil para el compilador.

Tenga en cuenta que para inferir el ariete, también debe inferir algunas señales y sus valores, uno de los cuales es la entrada de dirección. En el proceso síncrono, el valor de esta señal inferida no se define para el caso que termina en PIXOUT < = x "111". Así que tendría que inferir un pestillo y la advertencia sería un incómodo "bloqueo de inferir en la señal de dirección inferida de ram inferida". Termina siendo un poco demasiado, por lo que probablemente se rinda, pero la solución alternativa no se ajusta al dispositivo. No estoy diciendo que esta sea la razón exacta por la que se da por vencido, pero debería estar claro que el compilador tendrá dificultades para completar los espacios en blanco para el ram inferido, dada la forma en que se codificó este proceso.

Todas las soluciones que funcionan cubren todos los casos para la señal de dirección, deducidos o no. Podría probar a declarar la señal y luego codificarla de la misma manera para que tenga que inferir un latch, e incluso puede compilarse porque ahora al menos tendría una señal declarada explícitamente a la que se puede referir.

Los estilos de codificación para inferir bloques ram para Altera se pueden encontrar en enlace

Esta es una de las razones por las que se recomienda encarecidamente que, si desea utilizar bloques de hardware existentes, cree una instancia como tal para evitar ambigüedades, o siga los estilos de codificación adecuados para que se pueda inferir de forma fácil y adecuada.

También tenga en cuenta que un simulador no tendría que lidiar con esto, porque no tendría que inferir un bloqueo de RAM per se y lidiar con el ambiguo no importa vs latch de esta señal fantasma, porque en la simulación no existe.

    
respondido por el apalopohapa

Lea otras preguntas en las etiquetas