2021/06/03

Para estudiar Designing Video Game Hardware in Verilog


El libro cuenta la evolución inicial de los video juegos, desde la nada de un generador de barrido y unos simples circuitos digitales hasta una CPU de 16 bits, pasando por sprites por hardware y video juegos hechos completamente sin CPU.

Para hacer los ejemplos tiene una plataforma de emulación online excelente https://8bitworkshop.com/ muy muy buena, que permite no tener que saber casi nada y concentrarse en la esencia del libro que no es FPGA ni Verilog.

Si hiciste la transición de programación (no)estructurada a objetos, esta es la inversa, partís de objetos, la pelotita del pong son unos circuitos, no unos valores abstractos en memoria.

 

Ejemplos

 

Como en otras ocasiones, hago la adaptación a Vivado 2018 con Nexys4ddr y algún bonus si se me ocurre. Uso testbenchs, que el framework de la plataforma ofrece implícitamente. Todos los ejemplos que están para CRT y algunos para VGA a 25MHz. Yo hago todo con VGA, así hay algunas adaptaciones extra.



Todo versionado en github.

 

Capítulo 7, clock divider

 

Divisor de reloj
Divisor de reloj



Sin dificultades, salvo que hay que inicializar los valores de los divisores para que funcione en el emulador.

 

Capítulo 8, binary counter


Contador binario
binary counter


Nada especial, con elegir en el bus de salida del contador "waveform style" -> "analog" se consigue esa formita de dientes de sierra.

 

Y gracias a la recomendación del Colo, una visualización mas fidedigna cambiando los settings de analog con "hold" en lugar de "interpolate":

 
Con "hold"
Con "hold"

 

Capítulo 9, video sync generator

 

Acá hay que usar VGA@25Mhz en el selector de plataforma y usar estilo "analog" en vsync y hsync.



hsync se vé, vsync apenas
hsync se vé, vsync apenas



hsync no se distingue, pero si siete frames en vsync
hsync no se distingue, pero si siete frames en vsync

 

Capítulo 10, test pattern 

 

La magia del framework provisto resuelve la frecuencia del clock de base, hay que meter un divisor para la realidad. Siendo de 25MHz y mi placa 100MHz aunque me llevó un rato darme cuenta, con dividir el reloj por cuatro estamos ok, así que tomo prestado el prescaler que ya había tomado prestado de antes y miro que las frecuencias estén ok o pruebo directo con el monitor de descarte que ya está bastante roto de todos modos.

Tiene que dar

  • vsync 57.8 Hz
  • hsync 30 kHz

Capítulo 11, digits


Desde mi punto de vista este es el más importante pues hace algo que no termino de entender y a la vez hay que adaptar a VGA, por que lo que sale en la pantalla apesta:

Klingon
Klingon


Tuve que pasar de tres bits (RGB) a seis bits (RGGGGB) para prender al máximo el verde. La evolución fue:



assign GREEN   = display_on && bits[~xofs];


Siendo GREEN el pin VGA_G[0]

Luego, cambié a los nombres del xdc y asigné de modo repetido

assign VGA_G[0] = display_on && bits[~xofs];
assign VGA_G[1] = display_on && bits[~xofs];
assign VGA_G[2] = display_on && bits[~xofs];
assign VGA_G[3] = display_on && bits[~xofs];


y finalmente lo hice bien:

assign VGA_G = {4{display_on && bits[~xofs]}};

Y post finalmente volví a RED, GREEN, BLUE y generé un módulo de adaptación, al cual tambien moví los pines para ver hsync y vsync en el osciloscopio, así queda limpio el módulo.


  assign HS_probe = hsync;
  assign VS_probe = vsync;
  assign VGA_R    = {4{RED}};
  assign VGA_G    = {4{GREEN}};
  assign VGA_B    = {4{BLUE}};


Y me facilita levemente el próximo paso, que es ejecutar una simulación y su salida pasarla por un programa que me muestre el render, pues esto de estar regenerando todo lleva mucho tiempo.

De paso, me ocurrió que comenzaron a haber errores incomprensibles relativos a los constraints, seleccionando explícitamente el top module se corrigió.

 

Retroceso táctico

 

Para diagnosticar mejor me propuse simular y no me funcionaba para nada la simulación. Entonces volví al ejemplo anterior, tampoco.

La corregí agregando un bloque initial donde puse todos los reg a cero, pero no en el testbench sino en el módulo mismo, video_sync_generator.v.

Teniendo entonces un ejemplo que funciona y su simulación tambien, le puse un $strobe para obtener en ???.sim/sim_1/behav/xsim/simulate.log
los valores y poder hacer un render por software.

 always @(*)
   $strobe("%b %b %d", simul_hsync, simul_hvync, GREEN );


Son cerca de 30 MB por frame.


Lo que necesito es un programita que lea el log y me muestre lo que hubiese aparecido en la pantalla, ya sea un frame o una secuencia de frames, incluso que pueda conectarlo a tail -f y verlo en vivo.



El programa es muy sencillo, toma el standard input y  lo parsea y lo comento en VGA Renderer

 

Capítulo 11, digits, otra vez

 

Teniendo el renderer la situación es esta:


VGA_G undefined
VGA_G undefined


Esas franjas verde claras son XX:


tail -F .../simulate.log | tr "x" "7" | wish render.tcl

Mirando la waveform:


En rojo VGA_G undefined
En rojo VGA_G undefined




Comento de paso con respecto al VGA Renderer que lo bueno de usar tail en lugar de un archivo es que se puede ir cambiando la simulación y para patrones repetitivos como lo que ha habido hasta ahora se hace render parcial:


Resultado de ir cambiando los bits de xofs
Resultado de ir cambiando los bits de xofs

Si fuera por la adaptación de resolución de CRT a VGA la simulación online debería estar ok, no? No sé como poner el waveform para este ejemplo, así que lo simulé localmente y...

Green undefined en el original
Green undefined en el original



...hay XXs en el ejemplo original.

No logré entender cómo arreglarlo ni si tiene relación con el resultado real, por el momento sigo con el próximo.

 

Capítulo 11, bitmaps

 

En la simulación anda ok salvo que sigue generando undefineds, todo el fondo verde claro.


Mal fondo
Mal fondo


En la FPGA, horrible, ni vale la pena mostrarlo.


En https://8bitworkshop.com/v3.4.2/?platform=verilog-vga&file=chardisplay.v

 

Capítulo 12, Ball Motion

 

Falló horriblemente, me rendí un poco, dejé de hacer la adaptación y me concentré en comprender.

 

Final


Uno de los temas trata de una CPU de 8 bits que se programa con su propio assembly, claro, con el compilador en el simulador online, no recuerdo si había manera de compilar afuera. Luego una CPU de 16 bits, etc, mirá el libro, vale la pena.

Llegue hasta el capítulo 28 creo y abandoné un año, lo retomé y sorprendentemente entré en sintonía muy rápido y terminé el libro.

Algo muy interesante es que sugiere utilizar el icestick para los ejemplos, lo cual implica que la edu-ciaa-fpga es más que suficiente. Con respecto al video el clock le dá si usas (si conseguís) un CRT, pero para VGA se complica.

 

Este termina básicamente con dos frases:

In our simulator, control inputs are simply bit values sent to a module. The real world is a bit more messy.

Y otra que no tengo la paciencia de buscar parecida:

Al trasladar a una FPGA real pueden haber errores de sincronización que el emulador ignora.

¡Qué bueno que abandoné en ese momento! Sabiendo este detalle, dejo de confiar ciegamente en el código del libro y uno de estos días (meses, años) lo retomo.












No hay comentarios:

Publicar un comentario