Búfer FPGA VGA. ¿Cómo leer y escribir?

Tengo una placa Altera DE2 y trato de dibujar sprites. Tengo algunos problemas para implementar un búfer de pantalla.

Tengo una entidad de visualización que a una velocidad de 25 MHZ genera píxeles para la visualización vga.

Tenía la esperanza de implementar un búfer en SDRAM. La idea original era cargar píxeles al siguiente píxel a una velocidad de 25 MHz desde la SDRAM. Esto funciona, pero no puedo escribir píxeles en la SDRAM a esta velocidad ni borrar la pantalla lo suficientemente rápido para cada cuadro nuevo. Me toma 2 relojes escribir datos y mi placa funciona a 50 MHz, por lo que tengo el tiempo justo para hacer una lectura completa.

Asumiría que estoy haciendo algo terrible, terriblemente mal. ¿Cómo se implementa normalmente un lienzo de dibujo de este tipo en VHDL?

Lo más parecido que pude encontrar es usar un esquema de color 2-3-3 (RGB) para recuperar cada píxel y escribir en el ram del lienzo durante el tiempo VGA de "porche" (supresión). Esto significa que en cada uno de los relojes de 25 mhz solo puedo actualizar el 15% de la pantalla y de alguna manera necesito que mi circuito sepa qué 15% está actualizando.

No puedo descifrar cómo usar el doble búfer porque no puedo descifrar cómo escribir datos en la memoria mientras leo. ¿Hay alguna manera de evitar el bit-banging del protocolo? ¿Cómo lo hace este tipo?

ingrese la descripción de la imagen aquí

@davidcary, con algunos detalles sobre cómo abordar el doble almacenamiento en búfer, ha respondido la pregunta. Me doy cuenta de que lleva tiempo y no puedo tirar piedras, ya que a menudo da una broma rápida como comentario para ayudar al usuario con su problema hasta que alguien pueda escribir una respuesta de alta calidad.
Cuando dice "¿Hay alguna manera de evitar el bit-banging del protocolo?", Supongo que eso significa que no ha escrito el controlador SDRAM usted mismo. Recomiendo hacerlo, es un buen ejercicio y comprenderá más sobre cómo funciona SDRAM y cómo explotar sus tiempos.

Respuestas (2)

Un par de enfoques que pueden ser útiles para algunos estilos de visualización es dividir el panel de visualización en mosaicos y

  1. restringir cada mosaico para usar un pequeño conjunto de colores, lo que permite el uso de menos de 8 bits por píxel, o
  2. use uno o dos bytes de cada mosaico para seleccionar una ubicación desde la cual leer datos de mapa de bits.
El primer enfoque podría reducir la velocidad a la que se tenían que leer los datos de la memoria de la pantalla. Por ejemplo, si uno usa mosaicos de 16x16 y cada uno puede tener cuatro colores elegidos de un conjunto de 256, entonces sin usar RAM adicional en el FPGA, uno podría reducir el número de lecturas de memoria por 16 píxeles a ocho (cuatro valores de color, más cuatro bytes para el mapa de bits). Si se agregaran 160 bytes de almacenamiento en búfer/RAM(*) a la FPGA, se podría reducir el número de lecturas de memoria por 16 píxeles a cuatro, utilizando 160 lecturas adicionales cada 16 líneas de escaneo para leer el siguiente conjunto de colores de mosaico. Si uno quisiera 16 colores por mosaico, el segundo enfoque requeriría 640 bytes adicionales de RAM a menos que se impusieran algunas restricciones en la cantidad de paletas diferentes que podrían existir en una línea.

El segundo enfoque probablemente aumentaría en lugar de reducir el ancho de banda de memoria total requerido para producir una pantalla, pero reduciría la cantidad de memoria que tendría que actualizarse para cambiar la pantalla; uno podría cambiar un byte o dos para actualizar un 8x8 o 16x16 área de la pantalla. Dependiendo de lo que intente mostrar, puede ser útil usar este estilo de enfoque para usar un dispositivo de memoria para mantener las formas de los mosaicos y otro para mantener la selección de mosaicos. Uno podría, por ejemplo, usar una RAM rápida de 32Kx8 para almacenar un par de mapas de mosaicos de 80x60 con dos bytes por mosaico. Si la FPGA no tuviera almacenamiento en búfer, tendría que leer un byte cada cuatro píxeles; incluso con una RAM estática de 40 ns, eso dejaría mucho tiempo para que la CPU actualice la pantalla (una pantalla completa solo ocuparía 9600 bytes).

Por cierto, si uno no quisiera agregar una RAM de 32Kx8 pero pudiera agregar 320 bytes de almacenamiento en búfer/RAM(**) a la FPGA, podría usar un enfoque de mapa de mosaico pero hacer que la CPU o DMA alimente 160 bytes a la mostrar cada 8 líneas de exploración. Eso cargaría un poco al controlador incluso cuando no cambiara nada en la pantalla, pero podría simplificar el circuito.

(*) El búfer podría implementarse como RAM o como una secuencia de 32 registros de desplazamiento de 40 bits de longitud más una pequeña lógica de control.

(**) El búfer podría implementarse como dos RAM de 160 bytes o como dos grupos de dieciséis registros de desplazamiento de 80 bits.

Los sprites normalmente no se hacen con un búfer de cuadros (según tengo entendido la palabra). En su lugar, compara las coordenadas x e y con xmin,ymin y xmax,ymax del sprite. Si la posición de escaneo actual cae dentro del sprite, extraiga el color relevante de la memoria del sprite.

Si está tratando de mostrar un búfer de cuadros, anímese. Este fue mi primer proyecto importante de FPGA. SDRAM no debería ser un problema a 100 MHz (lo hice por primera vez hace una década, y el silicio es mucho más rápido ahora), así que multiplique su reloj de 50 MHz. Escribir tu propio controlador será educativo :)

Eso le da mucho ancho de banda para jugar, luego puede duplicar el búfer, no hay problema. VGA de 60 Hz necesita un promedio de 18 megapíxeles/seg. Si tiene un dispositivo de 16 bits de ancho, tiene 200 MBytes/seg de ancho de banda máximo. Incluso si solo logra tener un 50% de eficiencia (lo que debería ser factible), eso es 100 megapíxeles/seg a 16 bits por píxel o 50 megapíxeles/seg a 32 bits por píxel.

Por ejemplo, puede ser que su RAM necesite 60 ns para configurar una lectura, pero luego puede dividir 8 palabras en 80 ns; eso es 8 bytes en ~ 140 ns. SI puede hacer que su RAM haga ráfagas más largas, eso ayudaría a amortizar el costo de configurar la lectura.

Basado en su comentario de que es una memoria RAM de bytes, eso es un poco más de 50 MBytes/seg, solo 16 megapíxeles/seg a 24 bits por píxel :( Simplemente no tiene suficiente ancho de banda para hacer una pantalla de color verdadero, incluso en VGA. podría hacer 8 bits por píxel con bastante facilidad, pero eso es solo 2 o 3 bits por color, lo que puede estar bien para su aplicación, no lo sé. O podría hacer una tabla de búsqueda de 256 colores como en los viejos tiempos, después Al leer del búfer de cuadros, luego usa el valor para buscar en un reloj RAM interno para obtener los 24 bits (o 18 bits, que encajarían muy bien en un BRAM) de color para enviar al monitor.

El doble almacenamiento en búfer todavía funciona:

Muestre un cuadro desde la dirección 0 (simplemente lea todos los píxeles por turno, deteniendo las lecturas durante los intervalos de borrado).

Escribe tu siguiente cuadro en otra ubicación. Para este doble almacenamiento en búfer, su controlador DRAM tendrá que priorizar entre las demandas competitivas de los canales de lectura y escritura. Sugerencia, priorice las lecturas ya que son críticas en el tiempo :)

¿En general, es mejor priorizar las lecturas, o es mejor leer datos en un FIFO, dar prioridad a las escrituras cuando hay una cierta cantidad de datos en el FIFO y dar prioridad a las lecturas cuando el nivel FIFO es demasiado bajo? Descubrí que, al menos cuando se manejan pantallas LCD que tienen una señal de reloj, es útil permitir que el tiempo de lectura sea bastante 'relajado' siempre que todos los datos se desplacen a tiempo.
Gracias por tu publicación, podría echarle un vistazo al almacenamiento en búfer. Pero creo que me toma 2 relojes (1/50 MHz) para leer datos y también tengo un dispositivo de 8 bits de ancho.
@supercat: sí, esa es una solución más avanzada que podría ser necesaria si se presiona el ancho de banda.
@Misha: lleva un tiempo configurar una lectura de datos, pero puede leer grandes cantidades a la vez.