Estoy creando un diseño usando Verilog en un Xilinx Spartan-3E (XC3S500E) que usa múltiples RAM de bloque de doble puerto, todas creadas a través de primitivos Verilog como RAMB16_S18_S18
. Estoy usando un puerto para leer y escribir (usando habilitación de escritura) y el segundo para solo lectura (estableciendo WEB
en 0). Ambos puertos comparten el mismo reloj. El bloque de memoria RAM se establece en ancho de 18 bits, pero ignoro los datos de paridad (es decir, no uso su valor de salida y siempre escribo ceros en 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 temporización agresiva y / o la síntesis física no tuvieron una diferencia con respecto a este problema)
Tengo restricciones de tiempo para mi único reloj de la red, y es consistente con la señal de reloj real que se está introduciendo (la restricción es para 50MHz, hay un reloj de 50MHz en la placa de desarrollo que estoy usando y el el informe de temporización indica que la frecuencia máxima para mi diseño es de 64,7 MHz. El reloj funciona a través de un mutliplexor de reloj que se utiliza como reloj habilitado, antes de pasar a la totalidad de mi lógica.
En mi código, tengo una máquina de estados que tiene tres estados (transición en el flanco ascendente del mismo reloj de 50MHz que usa el bloque de memoria RAM):
- Escriba la dirección en un registro conectado a las entradas de dirección de los puertos A y B.
- Lea los datos, realice algunas operaciones lógicas en él y escríbalos en un
reg[15:0]
que esté conectado a DIA (datos en A) en la RAM del bloque (sin cambiar la dirección). Active el permiso de escritura para el puerto A. - Lea algunos pines IO en registros no relacionados. Desactivar la habilitación de escritura del bloque RAM.
Esto siempre es exitoso en una simulación de comportamiento en ISim, y (aunque tuvo menos pruebas que el simulador) tiene un éxito constante en el puerto A. El puerto B tiene una lógica idéntica (simplemente corte de bits para la dirección, y la misma configuración para SSR, SRVAL, INIT) pero no logra leer durante este ciclo de un reloj. Simplemente agregando un estado adicional entre 1 y 2 (lo que da un tiempo de configuración de más de un ciclo de reloj completo para la dirección) el diseño funciona, aunque como aprendiz de desarrollo de FPGA me gustaría saber por qué y cómo evitarlo.
De acuerdo con hoja de datos de Xilinx DS312 y los diagramas de tiempo, esta debería ser una forma aceptable de utilizando el bloque de memoria RAM. En la misma hoja de datos se dan los tiempos de configuración y de espera, pero las herramientas ISE ya deberían conocerlas y aplicarlas durante el análisis de tiempo, si no me equivoco. Además, he vuelto a leer la sección RAM del bloque de UG331 (Spartan-3 Generation User Guide) varias veces y no he podido encontrar ninguna incoherencia entre las instrucciones y mi uso de la RAM del bloque.
La lista de informes de tiempo de las rutas más lentas misteriosamente no enumera ninguna ruta que vaya al puerto RAM ofensivo.
Si alguien pudiera hacer una recomendación, se agradecería, ya que he pasado bastante tiempo en la depuración de este problema y temo que pueda estar cometiendo el error de algunos principiantes. Si necesita información adicional, avíseme para poder proporcionarla.