Estoy creando un diseño usando Verilog en un Xilinx Spartan-3E (XC3S500E) que usa múltiples RAM de bloque de puerto dual, todas instanciadas a través de primitivos de Verilog como RAMB16_S18_S18
. Estoy usando un puerto para leer y escribir (usando la habilitación de escritura) y el segundo solo para leer (configurándolo WEB
en 0). Ambos puertos comparten el mismo reloj. El bloque de RAM está configurado en 18 bits de ancho, pero estoy ignorando los datos de paridad (es decir, no uso su valor de salida y siempre escribo ceros en los bits de paridad)
Estoy usando Xilinx ISE 13.4 y sintetizando/implementando usando el flujo de trabajo de la GUI con la configuración predeterminada. (las configuraciones no predeterminadas, como la optimización de tiempo agresiva y/o la síntesis física, no tuvieron una diferencia con respecto a este problema)
Tengo restricciones de tiempo hechas para mi única red de reloj, y es consistente con la señal de reloj real que se está poniendo (la restricción es para 50 MHz, hay un reloj de 50 MHz en la placa de desarrollo que estoy usando, y el informe de tiempo indica que la frecuencia máxima para mi diseño es de 64,7 MHz. El reloj pasa por un multiplexor de reloj utilizado como habilitación de reloj, antes de pasar a la totalidad de mi lógica.
En mi código, tengo una máquina de estado que tiene tres estados (transición en el flanco ascendente del mismo reloj de 50 MHz que usa el bloque de RAM):
reg[15:0]
que está conectado a DIA (datos en A) en el bloque RAM (sin cambiar la dirección). Active la habilitación de escritura para el puerto A.Esto siempre tiene éxito en una simulación de comportamiento en ISim y (aunque tuvo menos pruebas que el simulador) siempre tiene éxito en el puerto A. El puerto B tiene una lógica idéntica (simplemente división de bits para la dirección y la misma configuración para SSR, SRVAL, INIT ) pero no logra leer durante este ciclo de reloj. Simplemente agregando un estado adicional entre 1 y 2 (dando así un tiempo de configuración de más de un ciclo de reloj completo para la dirección), el diseño funciona, aunque como estudiante de desarrollo de FPGA me gustaría saber por qué y cómo evitarlo.
De acuerdo con la hoja de datos DS312 de Xilinx y los diagramas de tiempo que contiene, esta debería ser una forma aceptable de usar el bloque de RAM. Hay tiempos de configuración y espera en esa misma hoja de datos, pero las herramientas ISE ya deberían conocerlos y aplicarlos durante el análisis de tiempo, si no me equivoco. Además, he vuelto a leer la sección de RAM en bloque de UG331 (Guía del usuario de Spartan-3 Generation) varias veces y no pude encontrar ninguna inconsistencia entre las instrucciones y mi uso de la RAM en bloque.
La lista de informes de tiempo de las rutas más lentas misteriosamente no enumera ninguna ruta que vaya al puerto RAM infractor.
Si alguien pudiera hacer una recomendación, sería apreciada, ya que he pasado bastante tiempo depurando esto y temo que podría estar cometiendo un error de principiante. Si necesita información adicional, hágamelo saber para que pueda proporcionársela.
Los datos recién escritos en el flanco ascendente están disponibles directamente después de este flanco solo en el mismo puerto. En realidad, la entrada de datos se reenvía internamente a la salida de datos del mismo puerto RAM. También llamado WRITE_FIRST
modo.
Pero nunca se reenvía a la salida del otro puerto RAM, independientemente del archivo WRITE_MODE
. Estará disponible para lectura (por supuesto, en otro flanco ascendente) después de que se haya completado la escritura interna en la memoria. En su ejemplo, es solo el siguiente flanco ascendente del reloj, porque el tiempo de escritura interno siempre es más pequeño (más rápido) que el período de reloj mínimo permitido.
Este comportamiento se describe en XAPP 463 Uso de Block RAM en FPGA de generación Spartan-3 en la sección Conflictos y resolución de RAM de puerto dual. El ejemplo dado allí usa diferentes relojes, pero también se aplica cuando se usa el mismo reloj para ambos puertos.
Este comportamiento sigue siendo el mismo en los FPGA actuales de Xilinx y Altera.
El reenvío al otro puerto RAM debe realizarlo el suyo con la lógica circundante.
Paebbels
nanofaradio
nanofaradio
usuario_1818839
nanofaradio
usuario_1818839
usuario_1818839
nanofaradio
nanofaradio
usuario_1818839
nanofaradio
nanofaradio