[icestudio][VGA][iPxs] Bloque "PxsCharacter", BRAM y otras cosillas.

587 views
Skip to first unread message

Juanma Rico

unread,
Apr 24, 2018, 12:31:07 PM4/24/18
to FPGAwars: explorando el lado libre

Buenas a todos/as,

En ratos sueltos que tengo sigo con los bloques iPxs, la VGA y viendo las posibilidades de la colección de Sergio.

En estos días echaba en falta leer texto en la pantalla y un proyecto de Luke con la TinyFPGA (TinyFPGA Sneakes) me ha animado a hacer una serie de pruebas rápidas... como siempre a costa del SAV de otros proyectos que tengo siempre a la vista... ;).

Para poner texto se necesitan unos "glifos", he optado por seguir el ejemplo de Luke y utilizar "glifos" de 8x8 píxeles. He buscado los más básicos y al menos unos que tengan la "ñ". Estos son...


Como se ve están agrupados de 16 en 16 (256 glifos) con lo que es más fácil seleccionarlos utilizando los códigos ASCII y dividendo el byte en dos nibbles. Los he pasado con Matlab a un fichero binario (*.list) mediante el mismo método que utilicé en "screen-logo".


La cuestión es que para acceder a los glifos y representarlos en pantalla se necesita "fijarlos" en la FPGA a modo de mapa de memoria, para esto se utilizan todos los recursos de la propia FPGA y es en el sintentizado cuando se decide cómo y dónde guardar esta memoria.


Al hacerlo en la iceZum Alhambra, únicamente he conseguido meter las seis primeras filas de glifos, pero a partir de ahí el integrado se queda sin recursos.



Como véis tenemos también como bloque el módulo UART de recepción de @Obijuan (Gracias como siempre... ;)) y en el ejemplo se trata de que el byte ASCII recibido por el puerto serie de la iceZum Alhambra se represente en pantalla mediante su glifo correspondiente.


El tamaño y el color de este glifo se puede cambiar mediante unos parámetros constantes del bloque "PxsCharacter". Con estas seis filas de glifos llegamos a los símbolos, los número y las mayúsculas, suficiente para unas pruebas rápidas.


Aquí podéis ver un vídeo del funcionamiento del ejemplo.


Os dejo abajo el código por si lo queréis probar. Para probarlo, descomprimir y abrir el fichero "iPxs-Text-icezum.ice", sintetizarlo y grabarlo en la iceZum Alhambra.

Una vez descargado se quedará la pantalla en negro (con un puntito rojo al final... Hay que corregir eso... ;-) ) y en cuanto reciba un byte desde el puerto serie mostrará el glifo en pantalla.

¿Cómo se envía el byte por el puerto serie? Con cualquier terminal que abra el puerto de comunicaciones (a 115200 baudios) de la iceZum Alhambra. Una vez abierto el puerto y desde la terminal, se pulsa el teclado y aparecerá el glifo representativo del código ASCII enviado. Muy chulo... :)))


La cuestión es que para probar he sintetizado el mismo ejemplo (un poco modificado) para la TinyFPGA-B2 incluyendo los 256 glifos completos y me lanza un total de 2167 LUT necesarios (lógico que no entre en la 1K).



En ambos casos, tanto para la iceZum Alhambra como para la TinyFPGA-B2, sobran FF y BRAM... La pregunta es fácil... ¿Por qué diablos el sintetizador no utiliza estos recursos y peta por falta de LUT en la iceZum Alhambra? :)))


Ahí dejo la pregunta... también es verdad que el código en sí del "PxsCharacter" consume muchos recursos... (está hecho a piñón repitiendo el código para cada línea del glifo), pero eso no es óbice (se me notan los años... :-D) para que no los aproveche mejor.


Ya me contáis si llegáis a alguna conclusión. :))))


Saludos

Juan Manuel Rico



iPxs-Text.zip

Alexandre Dumont

unread,
Apr 24, 2018, 1:37:35 PM4/24/18
to FPGAwars: explorando el lado libre
Lo que he visto, hay reglas sobre cómo tienes que poner el Verilog para que se sintétize como Bram y no usando LUTs. Luego lo busco y te lo paso. Igual alguien es más rápido que yo.

También puedes mirar en los ejemplos de Obijuan en Verilog, busca genrom.v. Hay más reglas pero ese ejemplo funciona rom y se sintetiza en BRAM.

Alexandre Dumont

unread,
Apr 24, 2018, 1:38:26 PM4/24/18
to FPGAwars: explorando el lado libre
Por cierto, mola mucho eso que haces con el VGA menudos avances, enhorabuena!

Juanma Rico

unread,
Apr 24, 2018, 2:07:06 PM4/24/18
to FPGAwars: explorando el lado libre

Buenas Alexandre,

gracias por tus felicitaciones, no hay que olvidar que todo empezó con el MonsterLED de Obijuan... :)))

La verdad es que esto de la VGA, cuando la controlas, es una maravilla, te engancha.
El pensar que con únicamente tres resistencias y un conector VGA reciclado dispones de toda una pantalla para hacer experimentos... te abre todo un mundo... Son 640x480 leds de ocho colores distintos...los LED integrados de la placa, los dispositivos OLED y demás para obtener información ya te saben a poco.

En este caso es donde se ve la verdadera potencia de las FPGA, una tarjeta gráfica integrada... donde a los microcontroladoes les cuesta mucho más llegar.
Además, al estar ya todo integrado en bloques y siguiendo la colección de Sergio, hace la cosa mucho más fácil para usar y probar, aunque no se tenga mucha idea de cómo funciona.

Yo animo a todo el mundo a que lo pruebe... que suelde tres resistencias a un conector VGA y lo conecten a un monitor... ya verán, ya... todos los LED del mundo les sabrá a poco. :)))

Y una vez realizada mi soflama para animar a la gente a usar la VGA.... jajajajajaja, vayamos al lío.

He mirado el ejemplo que me comentas de Obijuan. Lo hice en su tiempo y de hecho cojo muchos conceptos de él (como inicializar la memoria con un fichero externo), pero no veo en ningún momento del código en que se obligue a usar BRAM en lugar de registros o FF... se supone que es automático y el sintetizador utiliza los recursos como mejor cree... ¿o no?

Esa es mi duda...
Yo pensaba que era automático, pero por lo visto no... o al menos hay otras formas de pensar en la red...

Saludos
Juan Manuel Rico

Alexandre Dumont

unread,
Apr 24, 2018, 2:44:30 PM4/24/18
to fpga-wars-explora...@googlegroups.com
Hola, 

Lo puedes forzar tu utilizando primitivas de ice40 (busca por lattice ice technology library  ), o puedes dejar que el sintetizador las genere por ti (verbo inglés infer, no se si sera inferir en castellano?). 

Sobre eso, ahora mismo no encuentro, si es que lo tenía, ningún documento específico de lattice ice40 sobre el tema, pero tengo uno llamado "xst user guide", 
https://www.xilinx.com/support/documentation/sw_manuals/xilinx11/xst.pdf, aunque sea de Xilinx es muy interesante ver las Coding  Technics. Miralo. Hay una sección sobre Rom y Ram, con varios ejemplos single port. Dual port. Sincrono, asynchronous.. De hecho detallan patrones de código, verilog y vhdl, para cada tipo de bloque básicoby no tan básico. Lo encontré muy interesante como referencia. Creo que para bloques genéricos de tipo ram, rom, Mux... Aplicará igual en ice40.




--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/fpga-wars-explorando-el-lado-libre/c8037741-6544-4c8f-b3c2-5f261250a9f8%40googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Alexandre Dumont

unread,
Apr 24, 2018, 3:08:22 PM4/24/18
to FPGAwars: explorando el lado libre
Mas especifico a iCE40 y memoria tambien tienes este: TN1250 Memory Usage Guide for iCE40: http://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/MO/MemoryUsageGuideforiCE40Devices.ashx?document_id=47775 . Espero que te ayude. Creo que tiene que ver el poner un modulo para la rom/ram solo. Y tambien el tamaño de los bloques,... Tambien el proceso sequencial que diseñes, supongo que solo debera de ser dedicado a eso (no mezcles nada en el always @( posedge) (con hacer un modulo solo para eso, como el genrom.v ya lo tienes ;) ).

Single-Port RAM Verilog

module ram (din, addr, write_en, clk, dout);// 512x8
parameter addr_width = 9;
parameter data_width = 8;
input [addr_width-1:0] addr;
input [data_width-1:0] din;
input write_en, clk;
output [data_width-1:0] dout;
reg [data_width-1:0] dout; // Register for output.
reg [data_width-1:0] mem [(1<<addr_width)-1:0];

always @(posedge clk)
begin
if (write_en)
mem[(addr)] <= din;
dout = mem[addr]; // Output register controlled by clock.
end

endmodule


On Tuesday, April 24, 2018 at 8:44:30 PM UTC+2, Alexandre Dumont wrote:
Hola, 

Lo puedes forzar tu utilizando primitivas de ice40 (busca por lattice ice technology library  ), o puedes dejar que el sintetizador las genere por ti (verbo inglés infer, no se si sera inferir en castellano?). 

Sobre eso, ahora mismo no encuentro, si es que lo tenía, ningún documento específico de lattice ice40 sobre el tema, pero tengo uno llamado "xst user guide", 
https://www.xilinx.com/support/documentation/sw_manuals/xilinx11/xst.pdf, aunque sea de Xilinx es muy interesante ver las Coding  Technics. Miralo. Hay una sección sobre Rom y Ram, con varios ejemplos single port. Dual port. Sincrono, asynchronous.. De hecho detallan patrones de código, verilog y vhdl, para cada tipo de bloque básicoby no tan básico. Lo encontré muy interesante como referencia. Creo que para bloques genéricos de tipo ram, rom, Mux... Aplicará igual en ice40.


El mar., 24 abr. 2018 20:07, Juanma Rico <juan...@gmail.com> escribió:

Buenas Alexandre,

gracias por tus felicitaciones, no hay que olvidar que todo empezó con el MonsterLED de Obijuan... :)))

La verdad es que esto de la VGA, cuando la controlas, es una maravilla, te engancha.
El pensar que con únicamente tres resistencias y un conector VGA reciclado dispones de toda una pantalla para hacer experimentos... te abre todo un mundo... Son 640x480 leds de ocho colores distintos...los LED integrados de la placa, los dispositivos OLED y demás para obtener información ya te saben a poco.

En este caso es donde se ve la verdadera potencia de las FPGA, una tarjeta gráfica integrada... donde a los microcontroladoes les cuesta mucho más llegar.
Además, al estar ya todo integrado en bloques y siguiendo la colección de Sergio, hace la cosa mucho más fácil para usar y probar, aunque no se tenga mucha idea de cómo funciona.

Yo animo a todo el mundo a que lo pruebe... que suelde tres resistencias a un conector VGA y lo conecten a un monitor... ya verán, ya... todos los LED del mundo les sabrá a poco. :)))

Y una vez realizada mi soflama para animar a la gente a usar la VGA.... jajajajajaja, vayamos al lío.

He mirado el ejemplo que me comentas de Obijuan. Lo hice en su tiempo y de hecho cojo muchos conceptos de él (como inicializar la memoria con un fichero externo), pero no veo en ningún momento del código en que se obligue a usar BRAM en lugar de registros o FF... se supone que es automático y el sintetizador utiliza los recursos como mejor cree... ¿o no?

Esa es mi duda...
Yo pensaba que era automático, pero por lo visto no... o al menos hay otras formas de pensar en la red...

Saludos
Juan Manuel Rico

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Message has been deleted

Juanma Rico

unread,
Apr 24, 2018, 3:50:54 PM4/24/18
to FPGAwars: explorando el lado libre
Gracias Alexandre y Unai,

No os lo vais a creer, pero al recibir vuestras rápidas y acertadas contestaciones en el móvil se me han saltado las lágrimas... :_)

¡Así da gusto compartir tantas cosas en el grupo! ;-)

Dispongo de poco tiempo, pero a ver si echo un rato esta noche y por deferencia hacia vosotros me lo estudio como un buen alumno. :)

Como siempre Unai sueles acertar... ;)

Me parece muy apropiada la comparación con el HD4478, lo conozco en profundidad pero no se me había ocurrido la asociación con la tarjeta gráfica de una VGA... y el hecho de que hay que diseñar más que programar en HDL me parece más que acertado. Es por eso que me gusta tanto la herramienta icestudio (aunque como ya sabéis estoy completamente en desacuerdo en el formato y la forma en que se lleva el liderazgo del proyecto), y me gusta tanto porque te obliga a diseñar/dibujar el circuito, no dejándote llevar por la secuenciación automática que te surge al escribir código en un fichero de texto... estoy convencido de que si en el mismo icestudio te permitiera modificar los bloques en una estructura top-down el salto de la herramienta sería cuantitativo y cualitativo... pero en fin.

Que me enrollo... daros las gracias y lo dicho... noche de investigación por vuestra culpa. ;p

Gracias.

Saludos
Juan Manuel Rico

Jose Pico

unread,
Apr 24, 2018, 6:00:07 PM4/24/18
to FPGAwars: explorando el lado libre
 Hola a todos:

 La verdad es que no tengo tiempo para nada pero me encanta aunque sea poder dedicar unos minutos a leer vuestras réplicas.
 
 Saludos y Gracias

 Pd:Alexandre, excelente documento de Xilinx.

Sergio Cuenca

unread,
Apr 24, 2018, 6:47:05 PM4/24/18
to FPGAwars: explorando el lado libre
Hola Juanma,
1) en la documentación de Lattice (MemoryUsageGuideforiCE40Devices.pdf  y en iCE40FamilyHandbook.pdf  : Appendix A. Standard HDL Code References) te dice exactamente que utilizando la codificación estándar de memorias en HDL se consigue la síntesis de BRAM (no hace falta instanciar las primitivas directamente). Pero, como bien apunta Unai, te tienes que ceñir al timing y número de puertos soportado por los bloques de Lattice.
Ese estilo es el que utilicé en el core GameTable.v de iPXS.

2) Hay otra forma de más alto nivel de abstracción que consiste en declarar un array y leer y/o escribir en él (sin explicitar las señales de control: clk, write_en)
reg [datawidth-1:0] mem [nwords-1:0];

en ese caso hay que darle pistas al sintetizador para que utilice memoria de bloques:
 a) ver el post de Unai
 b) además ver la respuesta de Clifford en stackoverflow, sobre como trabaja Yosys "In general, Yosys should map something like this to a BRAM in ice40 mode, if that BRAM cell will be utilized by at least 2%"

Este estilo lo puedes en el core PxsLogoPattern.v

3) Echando un vistazo a tu código creo que el problema está en que accedes a varias posiciones de memoria en 1 solo ciclo y los bloques de BRAM sólo disponen de 2 puertos (2 lecturas simultáneas como máximo). La única solución para poder hacer esto es crear un array de registros, por eso se mapea en PLBs
always @(posedge px_clk)

   
RGBStr_o[`RGB] <= font[pcy+0][pcx+7]&&....||font[pcy+1][]&&...||font[pcy+2][]&&...

4) Un posible esquema para lo que quieres hacer (fuentes en una ROM mapeada en BRAM) lo tienes en el ejemplo PxsBouncingSprite.v
En ese caso las fuentes son las distintas vistas de la bola. En tu caso:
reg  [0:0] fonts [n_char*width_char*height_char-1:0];

si escribes las fuentes una detrás de otra (no por filas) son más fáciles de direccionar: 
assign addr=index_char*width_char*height_char+y_img*width_char+x_img;

Pero bueno, de la otra forma también se podrá hacer solo que el cálculo de la dirección será un poco más complicado.
En cualquier caso, sólo se necesita acceder en cada ciclo a una única posición de memoria. 

5) Si a esto le añades una RAM con MxN posiciones, dónde cada posición guarda el código ascii del carácter, ya tienes la PxsTextConsole (El ejemplo SpriteGame101 sigue este esquema)


Saludos


El martes, 24 de abril de 2018, 21:50:54 (UTC+2), Juanma Rico escribió:

Juanma Rico

unread,
Apr 24, 2018, 8:23:43 PM4/24/18
to FPGAwars: explorando el lado libre

Buenas Sergio,

He estado leyendo los enlaces de Alex y Unai y le he estado echando un vistazo a tus comentarios y al código del "PxsBouncingSprite.v" que me sugieres.
Al ver que tu código no es tan difrente del mio y está todo integrado en el mismo módulo, lo primero y más rápido que se me ha ocurrido para probar, es eliminar todos esos accesos repetidos al array que hago en la condición del pixel.

Para ello he vuelto a los orígenes de cuando realimentaba el color del pixel en mi cutre-controladora VGA y le he dado más protagonismo a la posición de escaneo del pixel actual en pantalla, de tal manera que primero compruebo si estamos en los límites del glifo a representar y luego asigno el color del pixel según la posición relativa en la ROM (variable font) y el pixel actual de escaneo.

El código modificado dentro del always queda más conciso y tiene esta pinta:


// Task 2: Draw the pixel.
always
@(posedge px_clk)
begin
   
// Clone VGA stream in a RGB stream.
   
RGBStr_o[`VGA] <= RGBStr_i[`VGA];

   
// Are we inside a character limit?
   
if  (
       
(RGBStr_i[`XC] > pos_x) && (RGBStr_i[`XC] < (pos_x + psw*8)) &&
       
(RGBStr_i[`YC] > pos_y) && (RGBStr_i[`YC] < (pos_y + psh*8))
       
)
       
begin
           
// Ok, look for a pixel font.
           
if (  font[pcy+((RGBStr_i[`YC]-pos_y)>>5)][pcx + 7 - ((RGBStr_i[`XC]-pos_x)>>5)]  )
               
begin
                    px_color
<= color;
               
end
           
else
               
begin
                    px_color
<= RGBStr_i[`RGB]; //TODO: Here you can define a background for a character.
                end
        end
    else
        begin
            px_color <= RGBStr_i[`
RGB];
       
end

   
// Update the pixel in stream output RGB.
   
RGBStr_o[`RGB] <= px_color;
end


Para simplificar divido la posición actual en x e y que nos entrega el stream RGB entre 32 (desplazar 5 bits a la derecha) porque defino el pixel a representar de este tamaño y esto me es más fácil que una división con resto (mod) para calcular la posición del pixel en la ROM.

En definitiva, vamos a lo importante, la cosa es que tal y como está ahora la cosa, funciona y de varios accesos a la variable font en el mismo always he pasado a un único acceso como sugerías en el punto 3, pero aún así el sintetizador no toma la BRAM. :((



Eso sí, el número de LUT ha bajado significativamente. Sé que es una prueba demasiado rápida, así que lo siguiente a probar será cambiar completamente el esquema y separar en un módulo el bloque de ROM, pero ya no se parecería en nada a tu código. Ya por hoy lo tengo que dejar. De todas formas... antes de buscar un hueco para ponerme a ello... ¿Se te ocurre alguna otra prueba rápida que pueda hacer sobre este mismo código?

Un saludo
Juan Manuel Rico

Auto Generated Inline Image 1

1138-4EB

unread,
Apr 24, 2018, 9:10:43 PM4/24/18
to FPGAwars: explorando el lado libre
Hola de nuevo,

Juanma, una BRAM es una array, es decir, una matriz unidimensional. La variable font que estás utilizando tiene dos índices. ¿Cómo se supone que tiene que mapear el sintetizador esa matriz a una array? ¿Por columnas? ¿Por filas? Cualquiera sirve, pero simplemente no sabe hacer la conversión y decide que no puede hacerlo con BRAM. Soluciones:

- Como sugiere Sergio, guarda cada caracter como un vector de 64 elementos. En un ciclo de reloj lees todo el caracter y en el siguiente decides en cual de las líneas fijarte, mediante un multiplexor 8:1.
- Utiliza ocho BRAM en paralelo, que cada una guarde una fila. Es equivalente al anterior, pero más explícito. Puedes decidir leer todas a la vez, o de forma secuencial, ya que no necesitas acceder a todas las filas de un caracter al mismo tiempo. Si lo secuencias, puedes hacer un pipeline o escalera: cuando estés leyendo la última fila de un caracter de la última BRAM, lees la cuarta del siguiente en la BRAM anterior, lees también el de dos caracteres después en la tercera BRAM, etc. Así, en cada ciclo estás leyendo cinco filas, pero cada una corresponde a un caracter diferente.
- Haz tu la conversión a row-major o column-major. Esto implica leer 8 palabras de la BRAM para tomar una sola decisión. Así, para no afectar al throughput, el reloj de lectura de la BRAM debe ser ocho veces más rápido que el del stream.
- Mezcla algunas de las soluciones anteriores. Por ejemplo: dos BRAM en paralelo, conteniendo cada una cuatro filas (medio caracter), y dos multiplexores 4:1 además de un multiplexor 2:1.

Dicho lo anterior, vuelvo a mi libro... Es muy difícil que te imagines un circuito que represente esta línea:


font[pcy+((RGBStr_i[`YC]-pos_y)>>5)][pcx + 7 - ((RGBStr_i[`XC]-pos_x)>>5)]

Eso es indicativo de que "te has pasado". Frena un poco ;). Al mismo tiempo, intenta no mezclar descripciones secuenciales y combinacionales. ¿Quieres leer el contenido de la BRAM en un ciclo de reloj y después utilizar otro para definir px_color (dos ciclos de latencia en total)? ¿O quieres dedicar un ciclo a leer de la BRAM (porque es necesario) y generar px_color sin latencia adicional? Independientemente de cual sea la opción que quieras, ¿puedes garantizar que el trozo de código que has puesto se va a sintetizar de una de las dos formas? ¿puedes garantizar que el comportamiento en un simulador va a ser igual que el circuito sintetizado? Así definiría yo ambas opciones de forma inequívoca:

process(clk) begin if rising_edge(clk) then
 
if rst then
    Q
<= (others=>'0');
 
elsif RD then
    Q
<= font(address);
end if;

address
<= pcy+((RGBStr_i[`YC]-pos_y)>>5);
pixel <= Q( pcx + 7 - ((RGBStr_i[`
XC]-pos_x)>>5 );

process
(clk) begin if rising_edge(clk) then
 
if rst then
    rRD
<= '0';
 
else
    rRD
<= RD;
end if;

process
(clk) begin if rising_edge(clk) then
 
if rst then
    px_color
<= RGBStr_i[`RGB];
  elsif rRD then
    px_color <= color when pixel else RGBStr_i[`
RGB];
end if;


process(clk) begin if rising_edge(clk) then
 
if rst then
    Q
<= (others=>'0');
 
elsif RD then
    Q
<= font(address);
end if;

address
<= pcy+((RGBStr_i[`YC]-pos_y)>>5);
pixel <= Q( pcx + 7 - ((RGBStr_i[`
XC]-pos_x)>>5 );
px_color
<= color when pixel else RGBStr_i[`RGB];

He mezclado Verilog y VHDL. Pero lo relevante es qué señales están dentro de procesos, y por lo tanto son registros, y cuáles están fuera y son combinacionales.
No es el código más compacto, pero resulta muy evidente de qué componentes básicos se componen. El segundo, por ejemplo, de arriba abajo: una BRAM, dos sumadores/restadores, dos sumadores/restadores y un multiplexor 8:1, un multiplexor 2:1 (o una puertas and y or, ya que px_color es un solo pixel). Se ve también que la latencia es de un sólo ciclo. Y se puede intuir que la frecuencia de trabajo se puede ver limitada por que hay dos sumadores encadenados a un multiplexor, encadenado a otro multiplexor. De hecho, el primer ejemplo, aunque ocupe más código, permite frecuencias de operación mayores, porque hay un registro en medio de esa cadena.

Recuerda que en aplicaciones de tipo stream la latencia es tu amiga. No importa cuantos registros encadenes, siempre que una vez echado a andar todos ellos avancen al mismo ritmo. Puedes aprovechar esto para dividir tu circuito en etapas y simplificar cada una de ellas. ¡Divide y vencerás!

Saludos

Juanma Rico

unread,
Apr 25, 2018, 5:31:13 AM4/25/18
to FPGAwars: explorando el lado libre

Buenas Unai,

Esta mañana no tengo mucho tiempo, pero he sacado unos minutos porque al menos quería contestarte. Ya con calma investigaré todo lo que proponéis, por otra parte agradecer a Alex sus ideas de esta mañana y disculparme por haber sido tan poco comunicativo, pero me pilló en mal momento... :(

El miércoles, 25 de abril de 2018, 3:10:43 (UTC+2), 1138-4EB escribió:
Hola de nuevo,

Juanma, una BRAM es una array, es decir, una matriz unidimensional. La variable font que estás utilizando tiene dos índices. ¿Cómo se supone que tiene que mapear el sintetizador esa matriz a una array? ¿Por columnas? ¿Por filas? Cualquiera sirve, pero simplemente no sabe hacer la conversión y decide que no puede hacerlo con BRAM. Soluciones:

- Como sugiere Sergio, guarda cada caracter como un vector de 64 elementos. En un ciclo de reloj lees todo el caracter y en el siguiente decides en cual de las líneas fijarte, mediante un multiplexor 8:1.

Lo voy a intentar con calma. La prueba rápida que he hecho es dejar todo la matriz unidimensional


reg [0:0] font [0:(fh*fw)-1];


 Pero tampoco se lo traga. No lo genera como una BRAM.

- Utiliza ocho BRAM en paralelo, que cada una guarde una fila. Es equivalente al anterior, pero más explícito. Puedes decidir leer todas a la vez, o de forma secuencial, ya que no necesitas acceder a todas las filas de un caracter al mismo tiempo. Si lo secuencias, puedes hacer un pipeline o escalera: cuando estés leyendo la última fila de un caracter de la última BRAM, lees la cuarta del siguiente en la BRAM anterior, lees también el de dos caracteres después en la tercera BRAM, etc. Así, en cada ciclo estás leyendo cinco filas, pero cada una corresponde a un caracter diferente.
- Haz tu la conversión a row-major o column-major. Esto implica leer 8 palabras de la BRAM para tomar una sola decisión. Así, para no afectar al throughput, el reloj de lectura de la BRAM debe ser ocho veces más rápido que el del stream.
- Mezcla algunas de las soluciones anteriores. Por ejemplo: dos BRAM en paralelo, conteniendo cada una cuatro filas (medio caracter), y dos multiplexores 4:1 además de un multiplexor 2:1.

Dicho lo anterior, vuelvo a mi libro... Es muy difícil que te imagines un circuito que represente esta línea:

font[pcy+((RGBStr_i[`YC]-pos_y)>>5)][pcx + 7 - ((RGBStr_i[`XC]-pos_x)>>5)]

Eso es indicativo de que "te has pasado". Frena un poco ;).

Sí, te doytoda la razón. Lo iba escribiendo y me daba cuenta que estaba liándolo un poco... pero como funcionó... es lo que tienen las pruebas rápidas... que ni piensas... :)
 

Tu código me hace reflexionar sobre una forma de describir el circuito que he visto que también hace Sergio y que yo veo como equivalente y a lo mejor estoy equivocado y tiene su sentido...

Cuando haces algo como esto:


always @(posedge clk)
begin
     
(...task_1... );
end

always
@(posedge clk)
begin
     
(...task_2... );
end


¿Qué sentido tiene?¿No es lo mismo que esto?


always
@(posedge clk)
begin
     
(...task_1... );
     
(...task_2... );
end


 
No es el código más compacto, pero resulta muy evidente de qué componentes básicos se componen. El segundo, por ejemplo, de arriba abajo: una BRAM, dos sumadores/restadores, dos sumadores/restadores y un multiplexor 8:1, un multiplexor 2:1 (o una puertas and y or, ya que px_color es un solo pixel). Se ve también que la latencia es de un sólo ciclo. Y se puede intuir que la frecuencia de trabajo se puede ver limitada por que hay dos sumadores encadenados a un multiplexor, encadenado a otro multiplexor. De hecho, el primer ejemplo, aunque ocupe más código, permite frecuencias de operación mayores, porque hay un registro en medio de esa cadena.

Recuerda que en aplicaciones de tipo stream la latencia es tu amiga. No importa cuantos registros encadenes, siempre que una vez echado a andar todos ellos avancen al mismo ritmo. Puedes aprovechar esto para dividir tu circuito en etapas y simplificar cada una de ellas. ¡Divide y vencerás!

Saludos

Me encanta la facilidad que tienes para ver los componentes según el código... (de mayor quiero ser como tú... :-D), pero a mi todo esto se me escapa un poco.
Estoy muy limitado por el px_clock, no sé si tengo que hacerlo todo en este mismo clock de reloj, un ciclo perdido de este reloj es un pixel perdido en pantalla.

A ver si saco más tiempo y puedo estudiar (y probar) todas vuestras propuestas... disculpadme si esta semana no lo consigo (pensaréis que hago saltar la liebre y luego no le disparo... jejejejeje)

Muchas gracias a todos.

Saludos
Juan Manuel Rico

Sergio Cuenca

unread,
Apr 25, 2018, 8:05:54 AM4/25/18
to FPGAwars: explorando el lado libre
Hola Unai y Juanma,
Unai muy buena explicación. 
El código iPXS está pensado de esa forma un pipeline de operaciones simples de forma que se pueda trabajar a la frecuencia del pixclk.
Juanma, fíjate que en el código p. je de PxsLogoPattern.v el dibujo del pixel en el stream se realiza en 2 etapas (stages) donde el resultado de la primera es consumido por la segunda etapa. El sintetizador genera un pipeline con un registro intermedio (pixel), además de esta forma la salida de la memoria está registrada lo que permite al sintetizador utilizar memoria BRAM.
// 2 stages pipeline
 assign addr
={VGAStr_i[`addy],VGAStr_i[`addx]};
 
// Stage0: read pixel
 always
@(posedge px_clk)
   
begin
 
AuxStr1[`HS]<=VGAStr_i[`HS]; AuxStr1[`VS]<=VGAStr_i[`VS];
 
AuxStr1[`XC]<=VGAStr_i[`XC]; AuxStr1[`YC]<=VGAStr_i[`YC];
 
AuxStr1[`Active]<=VGAStr_i[`Active];
 pixel
<= logo [addr];
 
end
 
// Stage1: draw Logo pattern
 always
@(posedge px_clk)
   
begin
 
RGBStr_o[`HS]<=AuxStr1[`HS]; RGBStr_o[`VS]<=AuxStr1[`VS];
 
RGBStr_o[`XC]<=AuxStr1[`XC]; RGBStr_o[`YC]<=AuxStr1[`YC];
 
RGBStr_o[`Active]<=AuxStr1[`Active];


 
if(AuxStr1[`Active])
 RGBStr_o[`
RGB]<= pixel? ink: background;
 
else
 
RGBStr_o[`RGB]<=black;
 end


 respondiendo a tu pregunta, un always @(posedge clk) con 2 operaciones encadenadas necesita de un reloj más lento para poder realizar ambas operaciones (tiene que hacerlas una detrás de otra en el mismo ciclo). Si lo divides en dos always@ puedes utilizar un clk que será más rápido Tclk= maxT{task1, task2}, y los dos bloques always trabajan en paralelo (aunque sobre distintos datos). Esto es, que  mientra dibujas el pixel_i (etapa1) estás leyendo de memoria el pixel_i+1 (etapa0). El típico pipeline.


Conclusión: utiliza un ciclo para leer la memoria y registra la lectura, en el ciclo siguiente utilizas el pixel para hacer lo que quieras. Si el cálculo de la dirección a partir de CX, CY es muy complejo podrías incluso utilizar una etapa más para calcular la dirección (en lugar de utilizar un assign combinacional)

always @ //calculo dirección y la registro
 reg addr
<= ....


always
@ // leo memoria
 reg pixel
<= fonts[addr]


always
@ // dibujo pixel
 
RGBStr[] <= ....


Vamosssssss
Message has been deleted

1138-4EB

unread,
Apr 25, 2018, 5:07:20 PM4/25/18
to FPGAwars: explorando el lado libre
Hola Sergio,

Simplemente agradecerte la valoración y felicitarte por haber contribuido esa librería. No la he probado personalmente, porque me paso el día con HDL y al terminar el cuerpo me pide algo diferente. Pero me parece muy valioso que en el contexto de FPGAwars haya colecciones/librerías especialmente bien pensadas y que apliquen técnicas de diseño contemporáneas. Lo que he leído del código es una gozada.

Un saludo

Sergio Cuenca

unread,
Apr 26, 2018, 3:24:02 AM4/26/18
to FPGAwars: explorando el lado libre
Hola Unai,
muchas gracias. Tus comentarios son realmente acertados y se nota la experiencia de años con el VHDL. 
Ya que trabajas en temas de procesado de vídeo a ver si te animas a hacer algún aporte a iPXS aunque sea en forma de sugerencia/comentario, seguro que tienes mucho que aportar.
Además en la siguiente versión me gustaría incluir algo de procesado de imagen..... ahí lo dejo ;-)

Respecto del código, hace bastante tiempo que sólo trabajo con HLS (en los últimos años VivadoHLS), así es que procuro escribir un Verilog  muy básico para no meter la pata. Estoy en proceso de re-aprendizaje :-)
Un saludo

Juanma Rico

unread,
Apr 26, 2018, 8:24:13 AM4/26/18
to FPGAwars: explorando el lado libre

Buenas Unai,

Te lo he dicho muchas veces, pero una vez más, espero que no moleste... de verdad, es una gozada leerte... :)))
Aunque reconozco que tus post a veces los tengo que leer dos y hasta tres veces sólo para tener una ligera idea de lo que comentas... pero como dicen por ahí: "sarna con gusto no pica"... además, para colmo, destilan profesionalidad y rigor, cosa que a los makers como yo, beber de ese elixir, no nos viene mal de vez en cuando... (sin emborracharnos, ¿ehhh? :-P)

Ando a tope estos días y tengo que reprimir el SAV (muy a mi pesar), así que no he podido probar nada de las sugerencias que me habéis hecho, a ver si el fin de semana puedo dedicarle un poco más de tiempo para hacer al menos una prueba rápida y poder comentarla con el grupo.
¡El día que consiga usar a propósito la BRAM va a ser todo un triunfo! jejejejejejeje

Agradecerte tus consejos y el hecho de que te pases por aquí de vez en cuando y nos abras los ojos... ¡Esto de los lenguajes HDL es todo un mundo! jejejejeje

Saludos
Juan Manuel Rico


Juanma Rico

unread,
Apr 26, 2018, 8:37:49 AM4/26/18
to FPGAwars: explorando el lado libre

Gracias Sergio,

A ver si saco un rato. Tus consejos es lo primero que quiero probar (además de ponerme al día con los conceptos que me habéis comentado del pipeline y el throughput).

Tengo también pendiente los pull-request de los bloques y ejemplos para tu colección iPxs.
Espero solucionar pronto los temas de BRAM e incluir el bloque PxCharacter para que se puedan escribir letras en la colección, creo que eso animaría a las personas a usar la biblioteca, aunque sea para utilizar el monitor VGA como un gran LCD para mostrar información relevante... :)

Ya nada más el hecho de tomar el bloque Serie de Obijuan como hice y ver como tecleando aparece una gran letra en pantalla, me pareció una pasada... Así que cuando se disponga de una consola completa en un único bloque Pxs de tipo Overlay y se pueda añadir las letras al stream RGB...¡Guauuhh!... es posible que hasta para el MOC de juegos que tenéis pensado pueda servir. :)))

jajajajajaja... Se me vuelve a disparar la imaginación... tengo que contenerme... muchas ideas y poco tiempo... jajajajaja

Saludos
Juan Manuel Rico


Alexandre Dumont

unread,
Apr 26, 2018, 9:00:21 AM4/26/18
to fpga-wars-explora...@googlegroups.com
Estuve anoche haciendo pruebas para de inferir y sintetizar Bram, y descubrí una cosa: no sólo depende del módulo en sí, sino también de las entradas que le conectas. Me refiero a que si diseñas una rom de 8K pero en entrada le pones un valor fijo, solo por probar algo... Al final se da cuenta que no van a usarse las direcciones enteras y no lo sintetiza como Bram. Si pones solo unos pocos bit de direcciones respecto a todo lo ancho de direcciones posibles,idem genera una Bram más pequeña (4K por ejemplo).

Tenlo en cuenta, yo ayer me volví loco.


--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.

Juanma Rico

unread,
Apr 26, 2018, 2:14:07 PM4/26/18
to FPGAwars: explorando el lado libre
Gracias Alex,

Lo tendré en cuenta. Lo curioso es que a Sergio, en sus ejemplos de animación de la colección iPxs, le sintetiza como BRAM y no lo tiene como un bloque aparte, usa la misma estructura que uso yo (en realidad yo uso la misma que él), es decir, definir un conjunto de registros del tipo «reg [registro] variable [dirección]» y con eso ya le funciona... pero a mi no... y eso es lo que me trae loco. :)

Está claro que no es únicamente por la definición en un módulo... hay algo más y como sugieren Unai y el propio Sergio, puede ser debido al «timming» que yo utilizo... (a ciegas, porque ni sabía que afectaba tanto a la síntesis, ni sé utilizarlo como es debido).

¡La verdad es que esto es todo un reto... y apasionante! :))

Si descubres algo más no dejes de compartirlo... ;)))

Si podemos crear una ROM en la BRAM con los 256 glifos, nuestra icezum Alhambra podrá hablar en un monitor VGA... :)))

¡Al final lo conseguiremos! Jejejeje ;))

Saludos
Juan Manuel Rico

Alexandre Dumont

unread,
Apr 26, 2018, 3:19:20 PM4/26/18
to fpga-wars-explora...@googlegroups.com
Creo que el hecho de ponerlo en un módulo separado no es necesario (a mi me ayuda a entenderlo mejor), pero una cosa que menciono, no se si Unai o Sergio, es que solo puedes leer una dirección font[addr] en el bloque always@. Creo que eso es clave. 

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar una entrada en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.

1138-4EB

unread,
Apr 27, 2018, 1:13:33 AM4/27/18
to FPGAwars: explorando el lado libre
Hola,

@Sergio, en realidad no me dedico a procesamiento de vídeo, sino a clasificación de imágenes multi/hiperespectrales. Se utilizan protocolos similares para transferir la información, porque proviene de una cámara, pero el tipo de algoritmos que se aplican son diferentes porque el procesamiento es principalmente espectral y no tanto espacial. Es decir, mi trabajo se centra en dos dimensiones de un cubo, y solo una de ellas es compartida con lo que entendemos por procesamiento de imagen.

Por otro lado, para justificar la utilización de FPGAs, el volumen de información tiene que ser lo suficientemente pesado de forma que una CPU no sea capaz de gestionarlo. Esto es un problema en el contexto de FPGAwars, si nos limitamos a las mal llamadas FPGAs libres. Sencillamente, no hay BRAM suficiente para cualquier procesamiento un poco serio, y tampoco hay ninguna memoria externa pensada como RAM (SDRAM). Hacerlo con la memoria SPI es un ejercicio interesante, y muy didáctico, pero nada útil en "tiempo real". Por ejemplo, para hacer un filtrado espacial con una ventana de 5x5, se tienen que almacenar temporalmente 4 filas de la imagen: 4x640x16b = 40kb. Eso es más del 60% de la Alhambra, y es sólo uno de los buffer necesarios en un sistema que tiene que recibir y enviar información. Cierto es que con la HX4K mejorable a HX8K cambiarán las perspectivas. Y también que se pueden utilizar sólo 8 bits (para reducirlo a 20kb), teniendo cuidado con las operaciones aritméticas. De hecho, mi interés en disponer de un stack Alhambra II + Arduino/ARM es utilizar la CPU y/o la RAM conectada a la misma como buffer del acelerador descrito en la FPGA. O para que la CPU reciba/transfiera la información y que eso no deba ir en la FPGA. En cualquier caso, la optimización necesaria no es baladi. Si hablamos de procesamiento de vídeo propiamente dicho, acabose: tres frames, son 3x640x480x16b = 14mb.

No obstante, sí me gustaría poder contribuir, aunque sea facilitando referencias/explicaciones a quien, como Juanma, se mete en el fregado; a fin de hacer su tránsito lo menos accidentado posible. Adicionalmente, creo que una parte muy importante es el pre/post procesamiento y la (re)ordenación de la información, y en eso sí puedo aportar algo de código, porque las funciones genéricas/parametrizadas lo mismo sirven para resoluciones HD que para imágenes de 28x28 pixeles. De hecho, quiero aprovechar para sugerirte que hagas uso de las issues en GitHub, y de la posibilidad de etiquetarlas, con el objetivo de dar visibilidad a los TODO. Si hay una lista explícita de tareas, catalogadas según dificultad, área, lenguaje y/o tiempo de dedicación estimado, es más fácil ponerse a ello en una tarde o finde libre. Por ejemplo, relacionado con el TODO sobre conversión de BMP a texto, he escrito el script (octave) adjunto: lee el mapa de caracteres que puso Juanma en el primer mensaje y crea BRAM_8.list (2048x8) y BRAM_64.list (256x64). Estaría bien disponer de una issue donde discutir/comentar si quieres/queremos añadir este tipo de scripts al repo (dónde), si usar otro lenguaje (Python?), y cómo extenderlo para gestionar imágenes a color. Otra issue que me parece interesante es darle la vuelta al sistema: leer la salida de la simulación del circuito y crear los frames en PNG, de forma que se pueda testear el sistema sin necesidad de FPGA ni monitor. Pero creo recomendable que seas tú como mantenedor el que des un poco de vida inicial a las issues, para que el resto entendamos cuál es la forma de comunicación que esperas. Actualmente, parece ser Twitter, lo cual es bastante limitante.

Por último, con respecto al lenguaje, es bastante desesperante la situación. Aprendí VHDL por razones geosociales que ya conoces, pero actualmente el soporte de las herramientas comerciales para VHDL2008 es limitado, muy limitado o pésimo. Y las perspectivas para VHDL2018 o VHDL2020 no son mejores. Tenemos nuestras esperanzas puestas en Tristan (GHDL), lo cual es muy triste como comunidad. He estado varias veces tentado a aprender VivadoHLS, o SDAccel, pero me echa atrás que sean "lenguajes" específicos para Xilinx y muy pensados para quienes vienen del software. En cuanto a SystemVerilog, veo que se utiliza mucho para verificación, pero no he visto que sea realmente ventajoso para diseño RTL. Verilog en sí... me cuesta mucho ver claramente la diferenciación entre qué es secuencial y qué es combinacional. En general, me parece que es más fácil acabar escribiendo código que se sintetiza y funciona, pero sin saber explicar qué hardware se ha generado. VHDL es muy pesado/quejica, pero si sintetiza es muy posible que el resultado sea lo que querías. En este panorama, confio en que en algún momento GHDL pueda utilizarse para convertir cualquier VHDL en VHDL 2002 o VHDL 1993, de forma que yosys y/o Vivado lo acepten. Mientras tanto, tengo el ojo en SpinalHDL, Chisel y System-C.

@Juanma Supongo que el script que adjunto es parecido al que tú has utilizado. Pero no lo he encontrado/visto, para poder comparar y, en su caso, proponer modificaciones. Échale un ojo a ver qué te parece.

@Alexandre, efectivamente, la inferencia depende del ancho de palabra, la longitud del array, si se lee y escribe, solo se lee o solo se escribe... Primero se analiza, y si es necesario se optimiza, todo lo anterior, y después se decide si es BRAM o no. De hecho, si declaras que es un array para variables de 16 bits, pero en algún punto anterior del circuito resulta que eran sólo 8 bits y los otros ocho son siempre cero, la BRAM inferida será de tamaño byte.

Sin embargo, esto tiene un condicionante, y es que las BRAM son módulos físicos, son parte del silicio, y tienen un tamaño fijo. En el caso de las ICE40, son 4k. Concretamente, como se indica en la página 6 de uno de los PDF que enlazaste, soporta los siguientes modos: 256x16, 512x8, 1024x4, 2048x2. Por lo tanto, si la variable que quieres inferir, después de todas las optimizaciones, se queda en 300x8 (2400b), se requerirá un solo bloque, 4k. Si es de 500x8 (4000b), también. Sin embargo, si es de 200x9 (1800b), se van a necesitar dos bloques (8k), cada uno configurado como 256x16. ¿Es mejor eso que declarar 200x8 y 200x9, de forma que se utilicen una sola BRAM y 300 registros de los CLBs? Depende de la aplicación.

Otro caso que puede multiplicar el número de BRAMs son los puertos de lectura. Los bloques de las ICE40 sólo permiten utilizar un puerto para lectura. Por lo tanto, si queremos leer dos direcciones al mismo tiempo, la solución es que se infieran dos BRAM que comparten puerto de escritura. Así, para almacenar 100x8 y leer dos direcciones a la vez, se requieren dos BRAM de 4k cada una. Pero, el sintetizador no siempre sabe hacer esto. A veces hay que describirlo explícitamente.

En resumen, diga lo que diga el sintetizador, las BRAM siempre son de 4k en las ICE40. Puede ser sólo un bloque, o pueden ser varios bloques. Pero físicamente no hay BRAMs de 12k, aunque lo indique.

Saludos
bmp2bram.m

Juanma Rico

unread,
Apr 27, 2018, 5:30:43 PM4/27/18
to FPGAwars: explorando el lado libre

Buenas Unai,

Te contesto en esta rama del mensaje por alusiones...
Veo que tu script de Matlab usa funciones básicas, me lo guardo. :)))
Yo uso funciones de la tool-box de image procesing, con dos líneas tengo el fichero listo.

img = imread('FPGA_WARS-binario-80x96.png');    % Carga la imagen en la matriz 'img'.
dlmwrite('logo.list',img,'delimiter','');       % Pasa la matriz a texto.

La explicación exacta del proceso está aquí.

Saludos
Juan Manuel Rico

Juanma Rico

unread,
Apr 27, 2018, 6:11:31 PM4/27/18
to FPGAwars: explorando el lado libre

Buenas chicos/as,

Ya lo conseguí, no es como me hubiera gustado pero ya he conseguido que me sintetice utilizando la BRAM, con lo que ya podemos disponer de un conjunto completo de caracteres ASCII en nuestra iceZum Alhambra. :)))

Os comento un poco el proceso, lo primero que hice es intentarlo con el timing, separando el proceso en tres escenarios como me recomendaba Sergio.
Este primer intento (por lo que fuera) no funcionó y seguía sin usar las BRAM al sintetizar.

Tras muchas vueltas y ya deseperado (cambiando tamaño de palabra, de direcciones y demás) lo intenté separando el módulo de la ROM, pero nada... luego eché un vistazo al ejemplo de Sergio del SpriteGame101 que sí sintetiza en la BRAM, con tan mala fortuna que tomé como ejemplo el pacma.list, donde se guarda la ROM de los sprites y no me fijé en el bloque TableGame, con lo que desesperado al no funcionarme descarté el ejemplo (más tarde, cuando ya me funcionaba el mio, me di cuenta que el que sintetiza en BRAM es este bloque TableGame, no el otro de los Sprites... pero bueno, una mala decisión la tiene cualquiera).

Así que me fui a las fuentes y tomé como módulo de ejemplo, para instanciar una RAM de 512x8, de uno de los PDF de Lattice.


Generé un módulo de prueba para el módulo de ROM, hice un copy-paste lo adapté un poco y efectivamente se lo tragó. :)))



Vemos como sintetiza finalmente usando la BRAM y el uso de 4 tiene su sentido. (Do the math!)

son 256 glifos de 8x8 bits... luego 256x8x8 = 16384Kb y si se usan 512x8x4 tenemos los mismos 16384Kb... Aprovechamiento máximo de la BRAM... :)))


Lo siguiente es ver si generando un nuevo bloque PxsCharacter la cosa mejora... el esquema que seguí es mantener, en la medida de lo posible, el fichero list tal y como estaba y tal y como se generaba desde Matlab, es decir 16 glifos de 8x8 por fila con 16 columnas de glifos, por tanto, la ROM nos devuelve por cada dirección una fila completa del glifo direccionado por pcx y pcy (8bits). Se complica un poco el cálculo de la dirección de la ROM, pero se gana en tiempo de edición del fichero list.


El bloque entonces se compone de otros dos bloques DynCharacter.ice (con su DynCharacter.v correspondiente) y fontROM.ice (con su código en verilog correspondiente), el primer bloque, según la posición indicada externamente y la obtenida del flujo RGB, pide a la ROM el valor de cada línea del glifo y así interpreta los píxeles a dibujar.


Me ha sido relativamente fácil echarlo a andar porque esto mismo hice hace muuucho tiempo con el logo de FPGAwars y más o menos me acordaba, pero claro, sin usar la BRAM, como todo... "a ciegas y a lo loco"... con lo que en el logo iba muy justito de LUTs y menos mal que sólo rebotaba por la pantalla... siempre se aprende algo en esto de las FPGA... ;))


En definitiva, este es el aspecto final del bloque PxsCharacter.ice



Como véis es una ROM porque no hay posibilidad de habilitar la escritura... un cero patatero a piñón fijo.... :)))

Una vez construido el PxsCharacter queda probarlo introduciéndolo en un stream RGB de prueba. Como el primero que hice sin BRAM, se utiliza el puerto serie para mostrar el código ASCII recibido en pantalla.



Y listo... ¡¡Funciona!! ¡¡Conseguidoooooo!! :))

Vemos como se utilizan 4 bloques BRAM y nos deja libre más de la mitad de los LUTs... Ahora a por la consola de texto... ¡Que ya cabe!... jejejejejeje :)))


Saludos

Juan Manuel Rico



Auto Generated Inline Image 1
Auto Generated Inline Image 2
Auto Generated Inline Image 3

Alexandre Dumont

unread,
Apr 27, 2018, 7:09:57 PM4/27/18
to FPGAwars: explorando el lado libre
Mola Juan Ma!! :)

1138-4EB

unread,
Apr 27, 2018, 7:52:52 PM4/27/18
to FPGAwars: explorando el lado libre
Hola Juanma,

En primer lugar, muchas felicidades! Me alegro de que hayas podido echarlo a andar!

Como sugerencia de mejora:


Se complica un poco el cálculo de la dirección de la ROM, pero se gana en tiempo de edición del fichero list.

En general, no es razonable que se complique el circuito para ahorrar tiempo en la edición del fichero. Al fin y al cabo, el fichero sólo hay que editarlo una vez, y por mucho tiempo que lleve hacerlo el resultado se obtiene antes de poner el circuito en marcha. Sin embargo, toda la complejidad que añadas al circuito son recursos adicionales que requieres, que significa coste y/o consumo.

De hecho, fijate un poco mejor en mi script. Utiliza las dos mismas funciones que tú (imread en la línea 6, y dlmwrite en las líneas 34 y 64). Lo que hago en medio con "funciones" básicas es manipular/reordenar el contenido para guardarlo "a mi gusto", no como aparecen en el GIF. También hay algunas subplot y imagesc para mostrar gráficamente qué se está haciendo; estas sólo funcionan cuando verbose es 1.

Tal como está ordenada la información en BRAM_8.list, por ejemplo, cada caracter ocupa 8 direcciones de memoria consecutivas. Eso quiere decir que construir la dirección para leer una fila de un caracter es tan sencillo como concatenar dos índices: <char_index> & <line_index>, donde char_index tiene 8 bits y line_index tiene 3 bits. En el caso de BRAM_64.list, se pueden utilizar los mismos índices, pero char_index se utiliza para leer la memoria y line_index para el multiplexor.

Saludos y felicidades de nuevo

Jose Pico

unread,
Apr 27, 2018, 11:39:35 PM4/27/18
to FPGAwars: explorando el lado libre
Enhorabuena!
Un gran paso...

Saludos y Gracias

Juanma Rico

unread,
Apr 28, 2018, 3:36:18 AM4/28/18
to FPGAwars: explorando el lado libre

Buenas Unai,

Tienes toda la razón del mundo... Vi tantos "for" anidados que me echó para atrás y pensé... "Este Unai... complicándome la cosa con lo sencillo que es,... y a mi sin funcionarme todavía lo de la BRAM, que es lo que necesito ahora mismo" jejejejejeje... Prepotencia de aprendiz... Lo siento Sensei, no volverá a ocurrir... ;))

Lo he ejecutado y funciona de maravilla. Voy a ver si modifico y optimizo el módulo para eliminar esas multiplicaciones en el cálculo de la dirección como me aconsejas... Me gusta como has hecho que se vaya viendo el proceso de descomposición del glifo, muy ilustrativo.... :)))



Ya calmado un poco el SAV que me daba la desesperación de la BRAM seguiré con el intento de terminar la consola de texto y generar un bloque usable con ella. En teoría no es más que otra memoria en BRAM, pero veremos. También tengo que releer todo lo que me escribisteis sobre el pipeline ahora que lo tengo un poco más claro para asimilarlo. Creo que el tema de la consola no me va a costar tanto porque es más o menos lo que tiene ya hecho Sergio en su TableGame, pero voy a intentar y ver si soy capaz de no copiarlo para pensarlo a "mi manera"... ya veremos qué sale.

Muchas gracias por toda vuestra ayuda (aunque me habéis dado una semana de SAV que para mí se queda... ;P)

Saludos
Juan Manuel Rico


Auto Generated Inline Image 1

Juanma Rico

unread,
Apr 28, 2018, 12:02:48 PM4/28/18
to FPGAwars: explorando el lado libre

Gracias Alexandre,

La verdad es que sí que mola,... y mola mucho... :))
Estoy ya loco (el SAV se dispara) por tener unos minutos y ponerme con la memoria de vídeo para terminar la consola de texto.
He hecho una pequeña prueba rápida con un array de 4 bytes como memoria de vídeo y eso de teclear y que aparezca en pantalla... moooola mucho... :))

He hecho un pequeño vídeo con la prueba, lo puedes encontrar aquí.

Es una prueba rápida... pero para que veáis lo simple que quedan los bloques, tiene este aspecto.



He añadido la posibilidad de cambiar el tamaño y el color de los caracteres desde fuera del bloque (PxsCharacter). El código que toma el dato del puerto serie y actualiza la memoria de vídeo está escrito directamente en un bloque de código, además he incluido un cursor de prueba (PxsCursor) que tendré que ir afinando. :))

Por cierto @Unai, ya he corregido el direccionamiento como me recomendaste, usando la BRAM_8.list que genera tu script de Matlab se hace todo mucho más sencillo. Para prueba un botón.


// Cálculo del direccionamiento en la ROM con 'font.list'
addr_rom
<= pcy*fw + glyph_y*gc + pcx;

// Cálculo del direccionamiento en la ROM con 'BRAM_8.list'
addr_rom
<= {character,glyph_y};


La diferencia como véis es brutal, se eliminan dos multiplicaciones y dos sumas y se puede prescindir de la separación del byte "character" en "pcx" y "pcy".
Gracias Unai... Ahora va mucho más rápido, ¿Qué no?... yo ya noto la diferencia de Megahercios... jejejejejejeje :))

Saludos
Juan Manuel Rico




Auto Generated Inline Image 1

Obijuan

unread,
Apr 29, 2018, 5:20:49 AM4/29/18
to FPGAwars: explorando el lado libre

Esto es un gran avance! ¡Muchas gracias Juanma!

Todavía me queda para llegar, pero en los tutoriales mostraré también lo básico de las VGAs y la iPxs. Todo esto será tremendamente útil!

¡Muchas gracias!

Saludos, Obijuan

Juanma Rico

unread,
Apr 29, 2018, 6:21:49 AM4/29/18
to FPGAwars: explorando el lado libre

¡¡Noooo por Dios!!
¡¡Gracias a ti SIEMPRE!!.
Tú eres la semilla de todo lo que pasa en el grupo. ¿Cómo olvidar eso? :)))

Desgraciamente tengo completamente olvidados tus tutoriales, te pido disculpas. Empecé pero no los seguí, creo que me quedé en "aspirante a cadete", cuatro míseros bitpoints... ni cadete siquiera, aspirante... ni para una pegatina me da con los bitpoints que tengo.... jejejeje
Quería retomarlos pero no me daba el tiempo, además por aquel entonces estabas a tope y así te liberaba un poco de tanta corrección. Ya creo que llego tarde (y sigo sin tiempo.... jejejeje). :)))

Me muero de curiosidad por ver como afrontas el tema de la VGA en un tutorial... pasaron muchas cosas y muchos fallos (por mi parte) hasta que llegó Sergio con su colección iPxs... ¡y lo que queda por avanzar!

Yo encantado de poder aportar a la comunidad en la medida de mis posibilidades. No son muchas, de momento creo que recibo más que aporto... pero algo es algo... ;))

Quizás nos veamos en Granabot... a ver si me puedo escapar esa mañana y dar un salto a Granada. :))))

Saludos
Juan Manuel Rico

1138-4EB

unread,
Apr 29, 2018, 10:32:28 AM4/29/18
to FPGAwars: explorando el lado libre
Hola Juanma!


Tienes toda la razón del mundo... Vi tantos "for" anidados que me echó para atrás y pensé... "Este Unai... complicándome la cosa con lo sencillo que es,... y a mi sin funcionarme todavía lo de la BRAM, que es lo que necesito ahora mismo" jejejejejeje... Prepotencia de aprendiz... Lo siento Sensei, no volverá a ocurrir... ;))

Que ocurra, que ocurra muchas veces más. Esa también es una forma de aprender. A menudo no sirve que alguien te diga cómo funciona algo, tienes que creertelo.


Por cierto @Unai, ya he corregido el direccionamiento como me recomendaste, usando la BRAM_8.list que genera tu script de Matlab se hace todo mucho más sencillo. Para prueba un botón.
// Cálculo del direccionamiento en la ROM con 'font.list'
addr_rom
<= pcy*fw + glyph_y*gc + pcx;

// Cálculo del direccionamiento en la ROM con 'BRAM_8.list'
addr_rom
<= {character,glyph_y};
La diferencia como véis es brutal, se eliminan dos multiplicaciones y dos sumas y se puede prescindir de la separación del byte "character" en "pcx" y "pcy".

Me alegro de que te resultara sencillo ;). Pero, ten en cuenta que este "truco" sólo se puede utilizar cuando 'glyph_y' es una potencia de dos (en este caso 8). Si utilizaras caracteres de 5x7 o 5x10, tendrías dos opciones:

- Alinear cada caracter a la potencia de dos inmediatamente superior: 5x8 y 5x16, respectivamente. Al hacerlo, añades filas vacias entre caracteres, por lo que desaprovechas parcialmente la RAM/ROM. Pero te permite mantener el mismo hardware.
- Utilizar sumadores y multiplicadores como hacías/haces con 'font.list'.

Por lo tanto, guarda ambas implementaciones. No deseches la primera, aunque en este caso en concreto no sea óptima.
 
Gracias Unai... Ahora va mucho más rápido, ¿Qué no?... yo ya noto la diferencia de Megahercios... jejejejejejeje :))

¿Has visto diferencia en los resultados de frecuencia máxima después de síntesis, o es una forma de expresar júbilo?

Saludos

Juanma Rico

unread,
Apr 29, 2018, 11:07:18 AM4/29/18
to FPGAwars: explorando el lado libre

Buenas Unai,

Me guardo tus consejos... ya por experiencia, seguro que los voy a necesitar... :)))

La verdad es que no... no he mirado los tiempos ni las frecuencias, para este nivel en el que estoy ya es una proeza que la descripción HDL haga lo que yo quiero que haga y no siempre lo hace... por tanto... sí, se podría decir que es una forma de expresar júbilo... :)))

¿Cómo se haría?¿Con icetime? :)))

Saludos
Juan Manuel Rico

Alexandre Dumont

unread,
Apr 29, 2018, 7:24:40 PM4/29/18
to FPGAwars: explorando el lado libre
Hola Juan-Ma


En el Stage 0, entiendo que guardas el estado del stream RGBStr_i en AuxStr1, pero en el Stage 1, ya no lo haces.

Creo que eso hace que en el Stage 2 acabas con un desfase de 1 ciclo de px_clk entre RGBStr_o[`VGA]  y RGBStr_o[`RGB] .

Creo (igual me equivoco, espero que alguien pueda confirmar o corregirme) que deberias de poner otro AuxStr2 <= AuxStr1; en tu Stage 1 y asi en el Stage2 podras usar AuxStr2 que estara "alineado" (con los 2 ciclos de reloj de tu pipeline).

(no se si me explico bien)

Juanma Rico

unread,
Apr 29, 2018, 7:46:20 PM4/29/18
to FPGAwars: explorando el lado libre
Buenas Alex,

Me has pillado despierto, enciendo el "cacharro" y lo pruebo... :)))
Pero no me extrañaría que fuera algo de eso. Tengo un lío ya con el pipeline que no veas... son casi 30 años programando secuencialmente y con escasos conocimientos de HDL, me cuesta... la verdad es que pensar en "paralelo" (o para tontos como es mi caso) me cuesta, me cuesta bastante... los conceptos de pipeline, throughput y demás son nuevos para mi... :)))

Lo pruebo... ¿El SAV qué?¿Mejor? jejejeje :)))

Saludos
Juan Manuel Rico




Juanma Rico

unread,
Apr 29, 2018, 8:07:15 PM4/29/18
to FPGAwars: explorando el lado libre

Pues así, con una prueba rápida, no ha dado resultado... :((((

Tengo que sentarme con calma, hago las cosas "a rachas" y es complicado acordarse de lo que hiciste cuando lo dejaste la última vez... hay muchos bloques implicados ya y es difícil acordarse de la interacción entre ellos.
Además he de estudiarme bien el tema del pipeline y hacerme un esquema pausado de las distintas etapas y qué quiero que hagan cada una de ellas... aún no lo tengo claro... ¿Alguien conoce algún libro sobre cómo aplicar esta técnica del pipeline? ;))

¿Has podido descargarte el código? ¿Lo has sintetizado? ¿Lo has probado? Habrás visto que está todo muy desordenado... si te sirve para calmar el SAV, perfecto, pero como te digo lo voy haciendo todo a rachas y modifico muchas cosas a la vez, no esperes un código muy pensado y estructurado... voy aprendiendo cosas nuevas mientras lo escribo, así que no te preocupes en ser todo lo crítico que quieras con el código (gracias por esta última sugerencia), a ver si conseguimos echarlo a andar un día de estos...  :)))

Saludos
Juan Manuel Rico


Alexandre Dumont

unread,
Apr 29, 2018, 8:40:02 PM4/29/18
to FPGAwars: explorando el lado libre
No he podido descargarlo, pero eso es lo que he pensado mirando tu codigo. Pero no te creas que se me ha ocurrido asi por las buenas jaja.

Se me ha ocurrido pensar en eso desde que lei algo parecido en un libro (FPGA Prototyping By Verilog Examples), donde decian (p. 347)

There is subtle timing issue in this circuit. Because of the block RAM implementation,
the font ROM's output suffers a one-clock-cycle delay. However, since the p i x e l - t i c k
signal is asserted every two clock cycles, the p i x e l x signal remains unchanged within
this interval and the corresponding bit (i.e., f o n t - b i t ) can be retrieved properly.

se me encendio la bombilla como en los dibujos animados jaja. 

Es que justo en mi proyecto cellular automaton VGA me he dado cuenta que me tenia que estar pasando algo parecido: esta noche he intentado aplicar eso que comentaba Unai del pipeline, aplicando como has hecho tu, los "Stages", pero si en el stage1 me custa 1 ciclo de reloj recuperar el valor del pixel, en el siguiente ciclo, el stream VGA (hsync, vsync,... x,y) tambien ha pasado al siguiente valor (el pixel de al lado!)... eso no lo tenia en cuenta. No se si es percibible en la pantalla, pero siendo estricto supongo que hay que tenerlo en cuenta.

No se vosotros, pero el SAV no se pasa nunca :p

Juanma Rico

unread,
Apr 30, 2018, 4:47:06 AM4/30/18
to FPGAwars: explorando el lado libre

Buenas Alex... no, ya te digo yo que no se pasa. El SAV se aprende a sobrellevarlo, pero pasarse, no se pasa... jejejejejeje

Voy a buscar ese libro a ver si lo encuentro... parece interesante... jejejejeje  ;-P

Mientras me leo un par de libros y encuentro el problema con el pipeline, para rebajar el SAV, he hecho una prueba rápida de consola.
Muy cutre,... apenas tiene funcionalidad, pero da el "pego" a la hora de escribir en pantalla.

Aquí he subido un vídeo.

Aunque es código tecleado al "tuntún" en un bloque de código, he subido el commit a github, por si te sube mucho el SAV. ;))
El aspecto de los bloques de esta última prueba es este.



Aunque en esta prueba la dinámica del cursor está en un bloque de código aparte, la idea es que esté todo integrado en el bloque PxsConsole y sea mucho más fácil y limpio usarlo. El código de prueba recibe un byte por el puerto serie y según el código recibido, se encarga de actualizar la posición del cursor o de escribir el código ASCII en pantalla (escribiendo directamente en la RAM de vídeo según la posición del cursor actual).

Para que el bloque de la dinámica de consola no se complicara internamente con un multiplexor, y como la BRAM del ice40 lo permite, he creado un módulo nuevo con una RAM Dual (videoDualRAM.ice y su correspondiente videoDualRAM.v), que permite separar la dirección de lectura (que se usa para representar los caracteres en pantalla) de la de escritura (usada para escribir en la posición del cursor el carácter recibido).



Ese pequeño bloque de código que genera la dirección de escritura en RAM se tendrá que integrar con el código externo y generar un nuevo bloque (posiblemente DynCursor) que integre la dinámica del cursor, eliminando las entradas externas del bloque de la posición del cursor (pos_x y pos_y) y de escritura (write), dejando únicamenete como entradas las del "stream RGB" (px_clk y RGBStr_i), la del carácter de entrada (character) y a lo mejor se necesita de un bit que indique que el código introducido no es un carácter imprimible, sino un código de control... ya veremos... paso a paso. :)))

Y eso es todo el SAV por hoy.
Me retiro que tengo que repasarme unos cuantos post de Unai, revisar código de Sergio, ver unos cuantos vídeos propuestos y leer algún que otro libro para ver como funciona esto del "pipeline"... que hay que afinar la consola y los conocimientos... jejejejeje

Saludos
Juan Manuel Rico


Auto Generated Inline Image 1
Auto Generated Inline Image 2
Message has been deleted

Jose Pico

unread,
Apr 30, 2018, 10:47:11 AM4/30/18
to FPGAwars: explorando el lado libre
Juanma:

Una vez llegado hasta aquí.....

Como todo sistema, con sus pegas...pero...

Ya Amas a Icestudio?
Jejejejej

Saludos

Juanma Rico

unread,
Apr 30, 2018, 11:19:53 AM4/30/18
to FPGAwars: explorando el lado libre

Nooooooo, Jose, no, no me mal interpretéis cuando opino sobre el tema... jajajajajajajajaja

No Jose, no, de verdad que no, todo lo contrario... :))))

Además creo que lo he dicho más de una vez en varios mensajes, icestudio me encanta (sino no lo usaría). Me obliga a "dibujar los pensamientos" y me separa de "programar" en un fichero de texto (que por vicio o deformación tiendo a pensar en una lista de órdenes secuenciales)... con la ventaja de que ahora, con los "includes" me permite concretar sobre un fichero de código las partes que "no me puedo imaginar" como circuito...

Lo digo una vez más, por si hubiera dudas: me encanta icestudio. :)))

Incluso seguro que no hay problema en tomarme una cerveza con Jesús si algún día paso por Madrid y se da el caso... es decir, no es nada personal, no es eso... de verdad que no...  de hecho se podría decir que es todo lo contrario...

Tanto me gusta icestudio que no estoy en nada de acuerdo con la estructura y la forma del liderazgo del proyecto. Está demasiado personalizado en Jesús, lo que evita que se pueda desarrollar por una amplia mayoría de la comunidad, se corre un riesgo de que el proyecto no avance a la velocidad de la comunidad y que el proyecto finalmente no crezca como algo "de todos"... solo de unos pocos... e incluso que, por una decisión personal, quede abandonado.

Además, por mi experiencia, al estar tan personalizado, cualquier sugerencia o crítica al programa se personaliza en el desarrollador mayoritario del proyecto (y además él se lo toma así, claro) y lo peor... no veo que haya intención de cambiar... :(((

Es solo eso, una crítica a la forma de liderar un proyecto, solo eso... simplemente creo que no es la adecuada para fomentar una implicación de todos en un proyecto libre, solo eso, de verdad... "De verdad de la buena"...  "sin acritud", como diría el otro... jejejejeje  :))))

Saludos
Juan Manuel Rico


Jose Pico

unread,
Apr 30, 2018, 11:30:50 AM4/30/18
to fpga-wars-explora...@googlegroups.com
Ya lo sabía... y lo tenía claro... te entiendo perfectamente y realmente sería una pena que se llegase a diacontinuar ( que miedo ! )...solo es que a veces  me sale una vena pícara 😂😂.


--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.

Juanma Rico

unread,
Apr 30, 2018, 11:33:25 AM4/30/18
to FPGAwars: explorando el lado libre

Gracias Unai  ;)))

Me pongo a estudiar y seguro que buscando el "bug" del "pipeline" aprendo otro par de "cositas" interesantes... :)))

Saludos.
Juan Manuel Rico

Juanma Rico

unread,
May 1, 2018, 10:26:03 AM5/1/18
to FPGAwars: explorando el lado libre

Buenas chicos/as,

Como Alexandre es como es y él tiene el SAV subido estos días... no se le ocurre otra cosa que, esta mañana, subírmelo a mi... ¡Con la de cosas que tengo que hacer! :)))

Yo había aparcado de momento el tema del bloque PxConsole para hacer otras cosas, pero hemos estado charlando el tema del pipeline y ha sido una conversación muy interesante. Me doy cuenta que hay muchas formas de pensar y por tanto, de afrontar los problemas. No siempre mi forma es la más apropiada para los circuitos digitales. :)))

Personalmente he llegado a la conclusión de que (seguramente por deformación profesional) tiendo a cerrar lazos de control por "todos lados" (ya me pasó con la controladora VGA y el pixel de color en su día, hasta que vino a salvarme Sergio con su colección iPxs) y me está pasando ahora también con este proyecto en algunos bloques.

Con esta forma de resolver los problemas lo que hago es crear "realimentaciones de información", provocando un retraso en el pipeline (el propio flujo de la información, en este caso de la información del stream RGB). Al combinar bloques en icestudio con código puro y duro, estos retrasos son difíciles de detectar en el código Verilog si uno no lo tiene en cuenta cuando lo está escribiendo y, como pasa en las realimentaciones de control real, los retrasos en el lazo de control hace que las cosas sean inestables si no se tiene el suficiente cuidado.

Para ilustrar este hecho esta mañana hice este dibujillo...



Como véis la realimentación es clara en el bloque DynCharacter. Esto hace que, si no se quiere trabajar con información desfasada, se deba resolver en el interior del bloque que es realimentado con un registro auxiliar (AuxStr1) en el código. El uso de esta variable auxiliar hace que se retrase el pipeline con la información RGB al pasar por el código del bloque (el RGBStr_o de salida del bloque está retrasado un pixel respecto al RGBStr_i de entrada).

Problema... que este bloque del dibujo es el PxsCharacter, que a su vez es usado por el PxsConsole, que a su vez tiene sus propias realimentaciones y sus propios bloques... :(((

Bueno, pues hay que resolver estas "realimentaciones de bloque internas", saber cuanto retrasa el flujo de información y, además, los distintos bloques que componen el PxsConsole, deben estar sincronizados para obtener un stream RGB coherente (hay bloques que retrasan un pixel, otros dos...etc).

Bueno pues a falta de un estudio más exhaustivo de todo los retrasos y realimentaciones de los bloques en su conjunto (utilizaré la técnica propuesta por Unai)... para apaciguar el SAV he estado toqueteando por aquí y por allá con un cálculo "intuitivo" de los retrasos y sincronías en el ejemplo de la consola (Test-PxsConsole.ice) y la cosa ha mejorado muchísimo, el logo se ve mucho más estable y lo mismo pasa con los caracteres: todo es más estable. Aún así hay un pixel que se me escapa en la sincronización, pero realmente no hay color en lo referente a la estabilidad. Imagino que cuando lo estudie todo con calma quedará listo, mostrando todos los píxeles de los glifos correctamente y preparado para ser integrado en la colección iPxs. :)))
 
De momento he actualizado el proyecto en GitHub por si queréis probar esta nueva versión más estable.

Un saludo
Juan Manuel Rico

Auto Generated Inline Image 1

Alexandre Dumont

unread,
May 1, 2018, 10:59:01 AM5/1/18
to fpga-wars-explora...@googlegroups.com
Eso que comentas :

"y, además, los distintos bloques que componen el PxsConsole, deben estar sincronizados para obtener un stream RGB coherente (hay bloques que retrasan un pixel, otros dos...etc)." 

 también lo estaba pensando yo, aun no he probado las IPXS pero según los ciclos de reloj que se van "consumiendo" en cada bloque, supongo que al final, antes de multiplexarlos y obtener el stream final,  habrá que poner algunos registros para realinear/resincronizar bien los streams (si por un lado se retrasa de 1 ciclo por acceso a BRAM por ejemplo) el otro lado se tendrá que retrasar también de 1 ciclo. Si no, estaríamos mezclando streams desalineados. (o eso creo yo). 

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

1138-4EB

unread,
May 1, 2018, 11:34:04 AM5/1/18
to FPGAwars: explorando el lado libre
Hola Juanma y cía,

Juanma Rico:
Con esta forma de resolver los problemas lo que hago es crear "realimentaciones de información", provocando un retraso en el pipeline (el propio flujo de la información, en este caso de la información del stream RGB). Al combinar bloques en icestudio con código puro y duro, estos retrasos son difíciles de detectar en el código Verilog si uno no lo tiene en cuenta cuando lo está escribiendo y, como pasa en las realimentaciones de control real, los retrasos en el lazo de control hace que las cosas sean inestables si no se tiene el suficiente cuidado.

Me alegra ver que estáis dándole vueltas a los "ciclos perdidos" o glitches, que son bugs/correcciones propias del diseño hardware. Sin embargo, creo que estás pensando demasiado, y al introducir el término "realimentación" puede que estés complicando su comprensión, en vez de facilitarlo. Más concretamente, no creo que sea adecuado usar terminología de teoría de control en un circuito de tipo stream o data-flow. En control, una realimentación no es sólo una señal que se dibuja de derecha a izquierda en el diagrama; es también una variable a regular, que se compara de una u otra manera con una o varias consignas (otras señales de entrada).

En este caso, no es una variable controlada, es un simple acceso a un módulo que requiere un ciclo de latencia. Esto quiere decir que si decidieras dibujar el bloque de la parte inferior derecha dentro del bloque central, desaparecería la "realimentación" del circuito. En verilog es cortar de un fichero y pegar en otro, pero supongo que en icestudio tendrás que crear un nuevo fichero ice.
 
Bueno, pues hay que resolver estas "realimentaciones de bloque internas", saber cuanto retrasa el flujo de información y, además, los distintos bloques que componen el PxsConsole, deben estar sincronizados para obtener un stream RGB coherente (hay bloques que retrasan un pixel, otros dos...etc).

Independientemente de que sea una "realimentación" o no, es necesario saber cuánto se retrasa el flujo en cada bloque y cómo deben interactuar para producir un resultado coherente. Tal como sugiere Alexandre.
 
Bueno pues a falta de un estudio más exhaustivo de todo los retrasos y realimentaciones de los bloques en su conjunto (utilizaré la técnica propuesta por Unai)... para apaciguar el SAV he estado toqueteando por aquí y por allá con un cálculo "intuitivo" de los retrasos y sincronías en el ejemplo de la consola (Test-PxsConsole.ice) y la cosa ha mejorado muchísimo, el logo se ve mucho más estable y lo mismo pasa con los caracteres: todo es más estable. Aún así hay un pixel que se me escapa en la sincronización, pero realmente no hay color en lo referente a la estabilidad. Imagino que cuando lo estudie todo con calma quedará listo, mostrando todos los píxeles de los glifos correctamente y preparado para ser integrado en la colección iPxs. :)))

Va a ser muy difícil arreglar estos "bugs" mirando la pantalla directamente. Hay muchos resultados incoherentes que tu ojo es incapaz de percibir. O que los percibe y se te cansa la vista, pero no eres capaz de apreciar el origen. Para depurarlo debidamente es imprescindible hacer simulaciones y analizar la waveform. Por eso, en el diseño HDL son tan o más importantes las técnicas de simulación y verificación. No sé si es más razonable exportar el diseño ice a verilog para después simularlo, o trabajar directamente en verilog para este análisis tan concreto.
 
Saludos

Juanma Rico

unread,
May 1, 2018, 3:29:19 PM5/1/18
to FPGAwars: explorando el lado libre

Buenas Unai...

vaya, me has chafado un poco la moral y el Ego... :((

Yo pensando que había tenido una idea original y genial al buscarme un símil al que agarrarme con la teoría de control y resulta que ha sido un desastre de símil por mi parte...  ¡Tanto que aprender!  jejejejeje :)))

De momento tengo que aparcar el tema, pero tengo alguna idea que quizás esta vez sí sea original para estudiar estos "gliches" (o igual no es tan original como creo y resulta que también tengo que descartarla... jejejejejeje).

Seguramente al final acabe teniendo que aprender técnicas de simulación y optar por una simulación como dices (que no me apetece nada, la verdad... ), pero bueno... mientras tanto, como "Engué Endomo" de "Amanece que no es poco", voy haciendo eses por la calle porque así se difruta más del camino.... :)))

Pido disculpas si llego a desesperar dando tantos bandazos "a mi modo" por la calle... jejejejejeje ;))

A ver si dispongo de una tarde seguida para dedicarle, lo investigo, encuentro el fallo, aprendemos y terminamos de afinar la consola. ;))

Saludos
Juan Manuel Rico


Alexandre Dumont

unread,
May 1, 2018, 3:40:29 PM5/1/18
to fpga-wars-explora...@googlegroups.com
Juanma, lo de la simulación y testbench no te creas que no mola (bueno, a mi sí que me mola ver las waveforms esas en el gtkwave. Todo depende de la hora jaja, à las 02:00 ya son más abstractas jaja). 

Suelo revisar mis bloques con eso, para asegurarme que van bien como deben). (ya ves, aun así  no siempre pillo los glitches...) 

Claro que con VGA puede ser más complicado porque... No se. Pero, te permite detectar que las cosas, a veces, no están alineadas/sincronizadas como te creias.

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

1138-4EB

unread,
May 1, 2018, 4:27:18 PM5/1/18
to FPGAwars: explorando el lado libre
Juanma, está bien que busques tus propias explicaciones, y tires para ello de referencias que te son cercanas. Sólo que en este caso en concreto es importante identificar qué es y no sólo qué parece. Una flecha de derecha a izquierda no es una realimentación per se, aunque muchas veces sí cumpla esa función.


Seguramente al final acabe teniendo que aprender técnicas de simulación y optar por una simulación como dices (que no me apetece nada, la verdad... ), pero bueno... mientras tanto, como "Engué Endomo" de "Amanece que no es poco", voy haciendo eses por la calle porque así se difruta más del camino.... :)))

Sobre técnicas de simulación, en realidad son solo un par de comandos: http://inf-server.inf.uth.gr/~konstadel/resources/Icarus_Verilog_GTKWave_guide.pdf Lo "pesado" es, una vez abierto gtkwave con el resultado de la simulación, colocar/agrupar y dar formato (color, tipo de representación -binaria, decimal, hexadecimal...-) a las señales que quieres analizar. La primera media docena de veces es llevadero, pero luego se hace un insoportable. En el caso de ModelSim/QuestaSim, por ejemplo, se puede proveer un fichero .do que cargue automáticamente las señales, de forma que es más fácil hacer cambios en el código y recompilar/resimular iterativamente. De hecho, con VUnit se puede recompilar/resimular sin cerrar la GUI del simulador. Sin embargo, no estoy seguro de que exista esta posibilidad con verilog + iverilog + gtkwave.
 
Como comenta Alexandre, ver una waveform dar la respuesta que esperas es tan válido y gratificante como ver el resultado en la VGA. Tanto, que a veces no merece la pena el esfuerzo de hacer el prototipo físico por el coste que conlleva.

Pero, sobre todo, es una cuestión de tiempo. A veces es más rápido compilar y simular 10ms o 1s de ejecución, que sintetizar el circuito y programar la placa. Especialmente cuando el diseño está sin optimizar y puede no caber en la placa todavía.

Juanma Rico

unread,
May 2, 2018, 3:58:03 AM5/2/18
to FPGAwars: explorando el lado libre
Sí, me doy cuenta... :)))

Es mucho más sencillo simular.
Voy a ver si en un hueco lo hago... igual hasta me gusta.

La última vez que simulé fue para el proyecto del 4004 y fue porque aún no tenía la icezum Alhambra en mis manos...

Igual es por eso que no me atrae... lo asocio con la impotencia de «no poder hacer otra cosa».

Va siendo hora de retomar el «gtkwave»... :)))

Muchas gracias por todos vuestros consejos.

Un saludo.
Juan Manuel Rico

1138-4EB

unread,
May 2, 2018, 9:30:22 AM5/2/18
to FPGAwars: explorando el lado libre
Jajajaja, es gracioso porque yo asocio la impotencia con tener que trabajar en hardware físico, ya que en una simulación puedes ver decenas o cientos de señales a la vez, y físicamente estás muy limitado por los periféricos (nº de leds) o por el número de sondas que tengas en el analizador/osciloscopio. Acabo escribiendo casi tanto hardware de debug como hardware útil, para poder ver qué está pasando. Y eso a pesar de comprobar previamente que la simulación sea impecable.

Pero tienes razón en que en estas demos que estás haciendo, centradas en la VGA, pasar a la simulación puede dar pereza.
Message has been deleted

Juanma Rico

unread,
May 3, 2018, 7:26:13 AM5/3/18
to FPGAwars: explorando el lado libre

¡Jobá! La primera vez que me pasa... me ha borrado el servidor un mensaje que ya tenía redactado... :(((

En fin, lo repito...

-----------------------------------------------

Buenas chicos/as,

Pues resulta que como soy tan "pesao", que antes de simular me he puesto a hacer pruebas con el bloque PxsCharacter y al acercarlo a la pantalla y usar una reijlla inversa de referencia (PxsGrid, que ya incluiré en la colección) me he encontrado esto...


Pues sí, el propio bloque PxsCharacter tiene un glich que no había visto antes al probarlo por separado, así que me he decidido por empezar casi de cero y eliminar la "realimentación" (lo pondré entre comillas hasta que encuentre un nombre mejor) que tantos quebraderos de cabeza me da con la VGA. Para que sea mejor sincronizar con el resto de bloques al integrarlo, he separado los escenarios (stages) en otros bloques distintos... así de un vistazo se ve el flujo del "stream RGB", ahora tiene una pinta como esta:



La cuestión es que en una prueba rápida he conseguido obtener esto otro...


Sí, el glicht de momento se ha corregido... :)))

Ahora toca integrarlo en el PxsConsole y sincronizarlo con él para tener un bloque en la colección iPxs "usable" y sin fallos (aparentes)... las optimizaciones, si son necesarias, vendrán después.... :)))

Saludos
Juan Manuel Rico
Auto Generated Inline Image 1
Auto Generated Inline Image 2
Auto Generated Inline Image 3

Juanma Rico

unread,
May 3, 2018, 8:43:11 AM5/3/18
to FPGAwars: explorando el lado libre

Buenaaaaassss... :)))

Confirmado, una integración rápida y una sincronización del flujo RGB con el bloque de acceso a la RAM de vídeo en el bloque PxsConsole y "glitches" desaparecidos también en PxsConsole.... :))))



Ahora a ponerle un lacito y dejarlo a disposición de todos... :)))

Saludos
Juan Manuel Rico
Auto Generated Inline Image 1

Jose Pico

unread,
May 3, 2018, 9:09:42 AM5/3/18
to FPGAwars: explorando el lado libre
Enhorabuena!
Eres un fiera!
Gracias por tu esfuerzo.

Saludos

Juanma Rico

unread,
May 4, 2018, 4:55:43 AM5/4/18
to FPGAwars: explorando el lado libre

Buenas a todos/as,
(Gracias Jose Pico... ;))

He creado una rama "desarrollo" en el proyecto de iPxs-Text (aunque la "master" está tanto o más en desarrollo, pero bueno... :-D).
He estado creando en ella el bloque PxsConsole para que quede todo un poco más organizado y sea más fácil aprender su funcionamiento para luego poder modificarlo si os apetece. El aspecto actual interno del bloque es el siguiente...



El bloque únicamente tiene como entrada la señal de recepción y el dato recibido, además del flujo RGB de la VGA y la salida del mismo. La dinámica del cursor se encuentra en "DynConsole.v". Está redactada de forma muy básica y necesita quizás de una FSM para que el comportamiento del cursor sea el adecuado... (el comportamiento del cursor no es intuitivo en absoluto y hace "cosas extrañas"). El cursor se puede controlar enviando caractares de control con Ctrl (más i, j, k ,l).

En el fichero de prueba con el logo de FPGAwrars rebotando (Test-PxsConsole.ice) tiene este aspecto.



Como véis el uso de las BRAM están a tope... y eso hace que con el tamaño mínimo del carácter (8 bits) el espacio de la RAM direccionado actualmente no da para completar la pantalla... se necesitarían (640/8)x(480/8) = 80x60 = 4800 bytes, pero 4 BRAMs son para los glifos, luego disponemos de 16 - 4 = 12 BRAMs para la memoria de vídeo... eso nos da en teoría 512x12 = 6144 bytes, pero resulta que para direccionar estos se necesitan 13 bits... total... que realmente ahora son 2^12 = 4096 bytes direccionables exactos... con lo que la RAM se termina repitiendo...



Los números de la imagen son los 16 bytes que sobran de la línea completa (80x51 = 4080  -> 4096 - 4080 = 16 bytes)... para aprovechar el resto de la memoria habrá que incluir un bit más a la RAM de vídeo. Como he estado haciendo pruebas con el tamaño de 16 bits no me había dado cuenta del detalle... intentaré modificar ese bit para aprovechar mejor las BRAMs...  próximamente en sus pantallas. :)))

De momento ya podéis descargar las últimas pruebas.

Saludos.
Juan Manuel Rico

Auto Generated Inline Image 1
Auto Generated Inline Image 2
Auto Generated Inline Image 3

Alexandre Dumont

unread,
May 4, 2018, 5:11:13 AM5/4/18
to fpga-wars-explora...@googlegroups.com
Muchas gracias Juanma,

Supongo que habra casos en los que no es necesario toda la fuente de los  256 glifos. Por ejemplo, si es un contador de puntos, con tener los numeros, e igual algun signo podria ser suficiente.  En otros casos ASCII 7 bits seguro que basta y ya seria la mitad (2 BRAM en vez de 4).

Asi se puede ahorra BRAM, por dos razones: la BRAM de fuentes se reduce, y al ser menos caracteres su direccionamiento tambien baja (ancho de direcciones) por lo que el "Tile Memory" tambien bajara.

Tambien, depende el caso, puede que no necesitamos mapear caracteres en toda la pantalla (80x60), sino solo una region (contador, zona de texto (por ejemplo, 10 lineas...). Y se puede usar zoom, (x2 --> reduce /4 la BRAM necesaria para mapear los caracteres en la pantalla).

(Este thread mola! estoy enganchado!)

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Juanma Rico

unread,
May 4, 2018, 6:08:54 AM5/4/18
to FPGAwars: explorando el lado libre

¡De nada Alexandre!

Me alegra ver que estás enganchado... yo ya avisé.... ¡la VGA engancha!... jejejejejeje :)))

He estado probando añadir un bit más a la dirección de la vídeo RAM, pero no es posible... se intenta completar la memoria completa que pueden direccionar esos 13 bits de la dirección con BRAM... y claro, no tiene suficiente... así que lo dejaremos así, en 80x51 para 8 bits de tamaño (ya probaré con la TinyFPGA la pantalla completa).

De momento a ver si de alguna forma consigo filtrar las filas para que en estos casos no se muestre la pantalla entera y no se vean repetir los caracteres en la pantalla.

¡Claro Alexandre! Eso es lo bueno de las FPGA que te construyes tu propia tarjeta de vídeo a medida... :)))

De hecho en el "screen-numbers" que he actualizado últimamente en BRAM tienes solo los números... y los dibujé yo mismo desde GIMP, así que el tipo de letra tampoco es problema en las FPGA... no estás condicionado por nada... ¡eres libre en todos los sentidos!  :))))

Matthew estaba intentando hacer un contador con el proyecto "screen-numbers" sin necesitar icestudio ni iPxs... es un reto ideal para ti que te manejas con el make... échale unas líneas a ver como lo lleva si te apetece integrarte en su proyecto... yo os puedo ayudar. ;))

Por otra parte es interesante tener un "visualizador" de números en VGA lo más simple posible, esto te permitiría obtener datos internos del valor de los registros de la FPGA. :))

Saludos
Juan Manuel Rico


1138-4EB

unread,
May 4, 2018, 10:13:31 AM5/4/18
to FPGAwars: explorando el lado libre

Juanma Rico:
He estado probando añadir un bit más a la dirección de la vídeo RAM, pero no es posible... se intenta completar la memoria completa que pueden direccionar esos 13 bits de la dirección con BRAM... y claro, no tiene suficiente... así que lo dejaremos así, en 80x51 para 8 bits de tamaño (ya probaré con la TinyFPGA la pantalla completa).

Puedes hacerlo "a mano". Primero describes una BRAM con 12 bits de direccionamiento. Después otra con 11 bits de direccionamiento. Por último, coges una señal de 13 bits, y utilizas el MSB como select entre las dos BRAM. Tamaño de memoria final: 2^12 + 2^11 = 4096 + 2048 = 6144. En la práctica obtienes una BRAM de 13 bits de la cual sólo son usables los primeros 3/4.

Juanma Rico

unread,
May 4, 2018, 10:44:19 AM5/4/18
to FPGAwars: explorando el lado libre

Hummmmmm.... interesante, interesante... :))))

Ahora mismo ando con otro "glich" que he encontrado y me tiene loco. Está relacionado con la posición de un pixel de color en la posición 0,0. Por ahora lo he esquivado... pero no acabo de solucionarlo... parece que es "algo más profundo" dentro de las bibliotecas, porque se produce tanto en el PxsCursor como en el PxsCharacter...

Lo de la BRAM habrá que probarlo... para el diploma de honor en inferencia en BRAM creo que te lo piden... jejejejejeje

Gracias Unai. ;)))

Saludos
Juan Manuel Rico

Message has been deleted

Sergio Cuenca

unread,
May 4, 2018, 3:45:54 PM5/4/18
to FPGAwars: explorando el lado libre
Hola Juanma, Unai y demás locos del FPGAWars,
os dejo una semana y mirad la que montáis!!!! jajajaja!!!
Solo pediros disculpas por no poder contribuir más, no tengo ni tiempo de leer los mensajes pero tenéis todo mi apoyo moral ;-)

@Juanma. Este fin de semana echo un vistazo a tu código a ver si encuentro la causa del glitch ¿puedes subir una imagen?

@Unai cojo el guante de las issues de GitHub (primero tengo que ver que es eso.... ) . Cualquier código de pre/post procesamiento de los datos me parece muy útil, el único requisito que pondría es que no haya que instalarse más herramientas, por ejemplo se pueden crear plugins para Gimp2 pero eso supone instalarse el Gimp más un tutorial de como utilizar los plugins, lo mismo pasa con código matlab/octave. Lo ideal sería fuentes C/python y proporcionar también el ejecutable para no tener ni que compilarlo. Pero vamos que cualquier solución es bienvenida.
Efectivamente, se nota que llevas tiempo con procesado de imágenes, yo también había pensado en un postprocesado de las simulaciones VGA de forma que se generasen las imágenes/videos a partir de las señales simuladas, pero como digo no tengo tiempo ni para leer. Si alguien se anima y lo hace tendrá un lugar en mi corazoncito.  

Saludos desde el lado oscuro


1138-4EB

unread,
May 4, 2018, 4:39:26 PM5/4/18
to FPGAwars: explorando el lado libre
Hola Sergio,


@Unai cojo el guante de las issues de GitHub (primero tengo que ver que es eso.... ).

Es un especie de "miniforo", donde puedes crear hilos para tratar mejoras, correcciones, sugerencias... Permite etiquetar cada hilo/issue, y referenciarlo con #<numero>. Es muy cómodo porque puedes cerrar issues directamente desde otras issues, o desde commits. Y cada vez que mencionas una issue en otra, se refleja la relación. Simplemente accede a:

https://github.com/sergicuen/collection-iPxs/issues

Más info: https://guides.github.com/features/issues/
 
Cualquier código de pre/post procesamiento de los datos me parece muy útil, el único requisito que pondría es que no haya que instalarse más herramientas, por ejemplo se pueden crear plugins para Gimp2 pero eso supone instalarse el Gimp más un tutorial de como utilizar los plugins, lo mismo pasa con código matlab/octave. Lo ideal sería fuentes C/python y proporcionar también el ejecutable para no tener ni que compilarlo. Pero vamos que cualquier solución es bienvenida.

Creo que es inevitable instalar cualquier herramienta, salvo que sea C, porque gcc es una dependencia de iverilog, yosys, ghdl, etc. Sin embargo, no creo que C sea adecuado, porque dificulta la modificación del código sobre la marcha, al requerir la recompilación del mismo. Para este tipo de tareas, y para facilitar que los usuarios puedan cacharrear, creo que es mejor un lenguaje interpretado. En este sentido, entre python y matlab/octave, encuentro la segunda opción mucho más robusta desde un punto de vista numérico.

Saludos

Juanma Rico

unread,
May 4, 2018, 6:11:54 PM5/4/18
to FPGAwars: explorando el lado libre

Buenas Sergio,

Te pierdes lo mejor... ¡Estamos reinventando las tarjetas gráficas! (¡y lo que estamos aprendiendo!)... jejejeje :)))

Realmente no te puedo pasar una foto del fallo porque no es un glitch estático... Pero puedes reproducirlo si te bajas el proyecto y apuntas la copia de trabajo al siguiente commit de la rama master (en el siguiente de la misma rama ya está "trampeado").


commit
272d71bd27c0d736e50fd263f2131b1a5c9ef61b (HEAD -> master)
Author: Juan Manuel Rico <juanmard@gmail.com>
Date:   Fri May 4 08:58:05 2018 +0200

   
Repetición de memoria e integrado.


Nada más descargar el bitstream verás que el cursor, al estar en el punto (0,0) es como si se "dispersase" por la parte superior de la imagen y baja la intensidad en la imagen completa. Al mover el cursor (con Ctrl y las teclas i j k l, o bien con un mismo Enter) la dispersión desaparece, pero lo mismo ocurre si escribes un carácter en esa posición que use el bit (0,0), entonces, al mover el cursor el error permanece.

Creo que tengo localizado el error, pero no el porqué y no sé como solucionarlo... Se produce en ambos bloques y creo que es debido a una misma estructura que utilizo en ambos. En PxsCursor.v es esta parte del código:


assign cursor
= (
               
(RGBStr_i[`XC] >= abs_x) && (RGBStr_i[`XC] < (abs_x + size)) &&
               
(RGBStr_i[`YC] >= abs_y) && (RGBStr_i[`YC] < (abs_y + size))
               
) ? 1 : 0;


Y en el bloque PxsConsole en el fichero DynCharacterS3.v es esta:

   

   
// Are we inside a character limit?
   
if  (
       
(RGBStr_i[`XC] >= posx_i) && (RGBStr_i[`XC] < (posx_i + psw*gw)) &&
       
(RGBStr_i[`YC] >= posy_i) && (RGBStr_i[`YC] < (posy_i + psh*gh))
       
)
       
begin
           
RGBStr_o[`RGB] <= gline[glyph_x] ? color_fg : ( alpha ? RGBStr_i[`RGB] : color_bg);
       
end


Si evito el punto con una condición de mayor que cero se elimina el error... pero claro, me quedo sin líneas superior e izquierda. Es como si comparara con números negativos y se intentara dibujar fuera de los píxeles visibles, he intentado con RGBStr_i[`Active], pero no funciona.

Sigo buscando,.. es lo único que me queda corregir para dejarlo listo para la colección (bueno, eso y probar lo de la BRAM que me indica Unai), por lo demás, que es el comportamiento del cursor y la edición que provoca, creo que es menos importante en un principio y tampoco le quiero dedicar demasiado tiempo.

Si dieras con la clave del fallo no dudes en decírmelo... ;))

Saludos
Juan Manuel Rico


Alexandre Dumont

unread,
May 4, 2018, 7:55:31 PM5/4/18
to FPGAwars: explorando el lado libre
Hola Juanma,

No se si tiene que ver con el glitch tuyo en el 1er pixel (0), yo tambien detecte glitches con la columna de pixeles 0. Mirando las waveform de tu vga_sync, he visto algo que me choco. Fijate en el pantallazo, en la señal activevideo (en amarillo) y la x_px (en naranja):


Ves que cuando se activa activevideo a 1, se queda x_px a 0 durante 2 ciclos de reloj? Creo que deberia ser solo 1. x_px esta retrasado de 1 ciclo.

Creo que es porque lo actualizas en un bloque secuencial:

// Generate sync pulses (active low) and active video.
assign hsync = (hc >= hfp && hc < hfp + hpulse) ? 0:1;
assign vsync = (vc >= vfp && vc < vfp + vpulse) ? 0:1;
assign activevideo = (hc >= blackH && vc >= blackV) ? 1:0;
// Generate color.
always @(posedge px_clk)
begin
// First check if we are within vertical active video range.
if (activevideo)
begin
x_px <= hc - blackH;
y_px <= vc - blackV;
end
else
// We are outside active video range so display black.
begin
x_px <= 0;
y_px <= 0;
end
end


He modificado el bloque para que sea combinacional:

// Combinational
always @(*)
begin
// First check if we are within vertical active video range.
if (activevideo)
begin
x_px <= hc - blackH;
y_px <= vc - blackV;
end
else
// We are outside active video range so display black.
begin
x_px <= 0;
y_px <= 0;
end
end

Y ahora mira la waveform resultante:


Ahora sí que x_px se queda a 0 1 ciclo. Se aprecia tambien la diferencia en el pixel x = 639 que ahora sí que esta en el activevideo a 1.


Otra cosa, he añadido unas directivas alrededor del bloque SB_PLL40_CORE para poder simular. No deberia impactar en la sintesis, aunque no lo he podido probar aun.

Juanma Rico

unread,
May 5, 2018, 12:58:12 AM5/5/18
to FPGAwars: explorando el lado libre
A raiz de mi comentario... Matthew lo ha hecho... ¡y ya lo tiene funcionando!

https://github.com/mattvenn/2bit-pmod-vga

¡Es una maravilla! Me gusta hasta el «font» de las letras que ha elegido... ¡puto amo! Jejejejeje ;))

https://twitter.com/matthewvenn/status/992475395411906560

Ha cogido mi idea y la ha potenciado como mil veces... ¡Así da gusto compartir! ;))

Saludos
Juan Manuel Rico

Juanma Rico

unread,
May 5, 2018, 6:42:32 AM5/5/18
to FPGAwars: explorando el lado libre

Buenas Alexandre,

No se lo digas a nadie pero al final me he escapado (delinquiendo por bajar el #SAV...¡A lo que hemos llegado! jajajajajaja)

He probado tu modificación en la consola... y no, el glitch no se ha ido, pero no descarto que sea una combinación de ambas cosas.

La cuestión es que ahora incluso dudo de que la señal RGBStr_i[`Active] esté funcionando... (esta señal se transmite al stream RGB directamente desde la señal "activevideo" que tú estás usando en la controladora vga_sync.v). La he intentado usar como condición extra en la estructura que da problemas y es como si nunca se activara (y eso no es posible).

Habrá que seguir buscando, de todos modos esa modificación que has hecho habrá que tenerla en cuenta para futuros desarrollos.
Gracias por pelearte con ese lío de señales en la simulación de los sincronismos de la VGA... :))

Juanma Rico

unread,
May 12, 2018, 11:20:58 AM5/12/18
to FPGAwars: explorando el lado libre

Buenas a todos/as,

Buscando el glitch en la consola PxsConsole, he encontrado un par de problemas un poco más generales...

Uno es el motivo del porqué la señal `Active en el stream VGA parecía no funcionar y es que, en algún momento, se han mezclado dos ficheros distintos en formato Verilog al que hace referencia el bloque PxsSyncGen (posiblemente cuando lo modifiqué para que fuera compatible con la TinyFPGA), en este caso he encontrado dos distintos (VgaSyncGen.v y VGASyncGen.v) en uno estaba definida la salida "activevideo" y en otro no (aparece una salida "endframe"), con lo que los bloques de icestudio se los "tragaba" puesto que la interfaz era la misma al realizar una instanciación por posición en el bloque de código que lo referenciaba (señal de salida de un bit en ambos casos), pero la señal no era la que se suponía debería ser.

Y os preguntaréis... ¿Cómo ha podido pasar?
Si fuera al único al que le ha pasado podría entender que es cosa mía, mi torpeza y ya está, pero resulta que esto mismo le ha pasado a Sergio en su colección... y es que algunos ejemplos no tienen el mismo fichero Verilog asociado al bloque que en la propia colección de bloques (véase el caso del PxsConstant y su color como parámetro... a ver si busco un hueco y te hago un pull-request, Sergio) y dichos bloques fallan en su comportamiento al intentar utilizarlos.

Bueno, os explico el motivo de tanto error entre ficheros referenciados para que tengáis las precauciones oportunas... cuando icestudio encuentra un fichero referenciado (no sólo en los "includes" del bloque de código, sino también a lo largo del propio código aunque esté comentado), hace una copia allá donde se encuentre el fichero ICE que lo referencia, con lo que a partir de ese momento aparecen dos copias del mismo fichero y si no tienes las precauciones oportunas... modificas uno, pero queda otro sin modificar...  y claro, tras muchas pruebas, aparecen muchas copias... y pasa lo que pasa. :(((

Así que tened cuidado con este hecho sobre todo si usaís con asiduidad (como es el caso de la collección de iPxs) los ficheros referenciados dentro de icestudio.

Dicho esto y teniendo centrado el problema de la señal activevideo del bloque generador del stream VGA (PxsSyncGen.ice), veamos como funciona el asunto...

Esta señal (activevideo) indica que el pixel que se está tratando es un pixel "visible" en pantalla, es decir, la señal de reloj con la que se dibuja el pixel (px_clk) también se usa para sincronizar las líneas verticales y horizontales del monitor VGA, por eso se habla de "píxeles de sincronismo" que no se ven y no son visibles (en analogía serían como caracteres de control en un documento de texto); como nosotros, precisamente al dibujar en la VGA, modificamos estos píxeles, deberíamos saber cuales son visibles (modificables) y cuales no. De esto se encarga esta señal. :))

Pues bien, por las pruebas que he hecho, es precisamente esta señal la que provoca dicho glich al inicio del frame, al parecer no se está generando como debería y hace que los primeros píxeles del cuadro (frame) estén a veces activos y otras no-activos, dessincronizados con la posición que entrega la propia controladora (x_px y y_px).

Por ahora no tengo la solución exacta del problema (creo que es debido a una resta extraña que aparece por ahí...), pero quería avisaros por si os basáis en este bloque para generar el stream VGA y véis que os hace cosas raras, no desesperéis que no es cosa vuestra... que es un error más profundo, es cosa mia... es cosa de la controladora VGA. ;)))

En cuanto tenga la solución actualizo el bloque para que no aparezcan estos glich en el inicio, mientras tanto se puede utilizar sin problemas, claro... llevamos casi un año ya utilizándola... ¡Y la de cosas que hemos hecho con ella!  :)))

Un cordial saludo.
Juan Manuel Rico

Juanma Rico

unread,
May 12, 2018, 2:31:59 PM5/12/18
to FPGAwars: explorando el lado libre

Buenas de nuevo,

Pues buscando, buscando... lo he encontrado. :)))

Resulta que estaba relacionado no con la controladora en sí, sino en como se genera el stream VGA a partir de las señales que vienen de la controladora. A parte de la señal activevideo ya comentada, al principio me echaba yo la culpa por posibles errores de novato en la controladora, pero viendo que la controladora a Alexandre le funcionaba tal cual, sin necesidad de iPxs ni de icestudio y le funciona muy bien, me he puesto a pensar si no estaría ahí el problema, aún así, he echado un repaso a la controladora para recordar y la he cambiado un poco para confirmar...

Finalmente he vuelto a los orígenes y he tomado el bloque PxsCourt de mi iPxs-Pong que es lo más simple que tengo (a parte del PxsConstant) para generar el stream RGB a partir del stream VGA.

Para visualizar el glitch he cambiado el color de fondo que entrega por un color rojo y el de las líneas por uno azul... aquí está la visualización del error en la representación de este bloque.



Como véis un error un tanto extraño... cuando el fondo es negro lo que se veía es que la línea superior era gris... y está claro el porqué, porque se mezclaba en la parte superior con el color de fondo que entregaba el bloque.

Tras varias vueltas veo que el bloque de salida en la VGA (PxsVGAComp) es una asignación directa a los pines de salida, sin comprobar si el pixel es visible o no, con lo que se "me ilumina la bombilla"... ¿No será que está fluctuando el valor de esos pines cuando no hay visualización de los mismos?

Y efectivamente, compruebo que el bloque PxsCourt que genera el stream RGB, no fija el valor cero al RGB cuando es un pixel no visible, con lo que podría fluctuar a lo largo del "pipeline"... Fijándolo a un valor cero el error se soluciona y deja de aparecer esta "mezcla" extraña entre fondo y pixel.



¡¡Corregido!! El fondo aparece estable... Tras la emoción previa me pongo a pensar...  ¿No será esto lo que está pasando en el bloque PxsConstant que utilizo como fondo para la consola? Lo compruebo... y efectivamente no se está fijando el valor cero cuando el pixel es de "control", así que fijo el valor de RGB a cero cuando el pixel no es visible y me aseguro de no cambiarlo en el flujo del pipeline en los bloques del carácter y del cursor (simplemente con una condición extra para que el pixel sea visible para modificarlo)... y ¡tachaaaaannnnn!




¡¡El glitch ha desaparecido!!... ya se puede mostrar la letra E y el cursor en las líneas extremas de la pantalla sin que se vuelva loco el sincronismo... ¡Toda una victoria!  :)))

Así que ya está todo funcionando "decentemente"... podéis encontrar la prueba corregida en la rama "desarrollo" en el fichero Test-PxsConsole.ice. Quedan algunas modificaciones para el bloque, entre ellas, cambiar el parámetro size por el de zoom que me gusta más e intentar generar en BRAM la memoria de vídeo suficiente para una resolución de 80x60 (y que quepa en la icezum Alhambra)... pero en líneas generales el bloque ya es utilizable sin grandes errores de visualización. :)))
Auto Generated Inline Image 1
Auto Generated Inline Image 2
Auto Generated Inline Image 3

Alexandre Dumont

unread,
May 12, 2018, 7:25:45 PM5/12/18
to fpga-wars-explora...@googlegroups.com
Que guay!

Creo que yo ese glitch no lo tenia, porque en a la hora de determinar el valor del RGB, por defecto lo pongo a un valor fijo (3'b 000). Y (redundante), si activevideo es 0, tambien lo fijo  a 000:


always @(*) begin
rgb <= 3'b000;
if (activevideo3) begin
if ( font_bit )
rgb <= 3'b010;
else if (px_y3 == 0 || px_y3 == 479 || px_x3 == 0 || px_x3 == 639 )
rgb <= 3'b001;
else
rgb <= 3'b000;
end
else
rgb <= 3'b000;
end


Ademas, al no usar iPxs, mi activevideo si era correcto.

Sobre lo que comentabas en el mail anterior, te recomiendo siempre instanciar los bloques indicando los nombres de los puertos. Asi evitaras ese problema / efecto segundario.

Sobre lo de que te quepa la tile mem de 80x60 (x8 bit), no te cabe?? 80x60x8 son 38400 bit, es menos que 10x4Kb. Son 10 bloques de BRAM.

En esta version mia, si que sintetiza en 10 bloques de BRAM (+4 para la Font), si quieres mirar (no la he probado en el VGA aun):

After placement:
PIOs       14 / 96
PLBs       82 / 160
BRAMs      14 / 16


Happy #SAV


--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Juanma Rico

unread,
May 13, 2018, 6:29:30 AM5/13/18
to FPGAwars: explorando el lado libre

Buenas Alexandre,

El domingo, 13 de mayo de 2018, 1:25:45 (UTC+2), Alexandre Dumont escribió:
Que guay!

Creo que yo ese glitch no lo tenia, porque en a la hora de determinar el valor del RGB, por defecto lo pongo a un valor fijo (3'b 000). Y (redundante), si activevideo es 0, tambien lo fijo  a 000:


always @(*) begin
rgb <= 3'b000;
if (activevideo3) begin
if ( font_bit )
rgb <= 3'b010;
else if (px_y3 == 0 || px_y3 == 479 || px_x3 == 0 || px_x3 == 639 )
rgb <= 3'b001;
else
rgb <= 3'b000;
end
else
rgb <= 3'b000;
end


Ademas, al no usar iPxs, mi activevideo si era correcto.

Efectivamente, esa era la clave... :))
 

Sobre lo que comentabas en el mail anterior, te recomiendo siempre instanciar los bloques indicando los nombres de los puertos. Asi evitaras ese problema / efecto segundario.

Sí, en eso estoy... aunque no me gusta como queda en el bloque de código de icestudio, la verdad... confunde mucho más que aclara... :((
 

Sobre lo de que te quepa la tile mem de 80x60 (x8 bit), no te cabe?? 80x60x8 son 38400 bit, es menos que 10x4Kb. Son 10 bloques de BRAM.

Sí, debería... es casi seguro que es porque estoy haciendo las pruebas con el logo de FPGwars rebotando...y seguro que algún bloque de BRAM consume... imagino que todo al mismo tiempo no se puede... :(((  Probaré quitando el logo a ver. :))


En esta version mia, si que sintetiza en 10 bloques de BRAM (+4 para la Font), si quieres mirar (no la he probado en el VGA aun):

After placement:
PIOs       14 / 96
PLBs       82 / 160
BRAMs      14 / 16


Happy #SAV


Genial, tendré que actualizar para probarlo... :))

Saludos.
Juan Manuel Rico

Alexandre Dumont

unread,
May 13, 2018, 7:37:30 AM5/13/18
to fpga-wars-explora...@googlegroups.com
Si quieres, puedes ahorrar dos BRAM de Font usando el ASCII 7 bits en vez de 8 bits (tienes la mitad de caractères claro, de 0 a 127). Pero ganas dos bloques 😀

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Juanma Rico

unread,
May 13, 2018, 7:43:55 AM5/13/18
to FPGAwars: explorando el lado libre

Buenas Alexandre,

He quitado el logo y nada... sigue haciéndome falta 20 bloques de BRAM, creo que sé porqué.

He sincronizado tu código y lo he probado (por cierto, en la rama devel te falta un `define FONT_WIDTH 8 en el fichero font.v para que sintetice sin errores).

Resulta que definimos de forma diferente la RAM de vídeo, mi memoria de vídeo está definida para aprovechar al máximo el direccionamiento, es decir define tanta cantidad de memoria como puede direccionar, es decir, con 12 bits de dirección 2^12 = 4096bytes que se me queda corta para 80x60 = 4800bytes, luego tengo que incrementar un bit la dirección, pero 2^13 = 8192bytes y entonces se dispara a 20 BRAMS (16 de vídeo + 4 de los font). Ahí está el problema... necesito 13 bits de dirección, pero no definir la memoria completa, sino simplemente los bytes que necesito, como tú lo haces...

Así que en cuanto encuentre un hueco actualizo mi vídeo RAM "copiando" tu implementación y seguro que funciona... jejejejeje :P

Saludos
Juan Manuel Rico

Alexandre Dumont

unread,
May 13, 2018, 8:19:49 AM5/13/18
to fpga-wars-explora...@googlegroups.com
Claro el problema tuyo es ese... si aprovechas a tope el direccionamiento por bits, 2^13 es MUCHO mas de lo que realmente necesitas. Yo pase al metodo direccionamiento tuyo! (y veo que tu al mio antiguo jaja).

El `define FONT_WIDTH 8 sí esta, en el const.vh que se incluye desde el top.v, por eso me sintetiza, pero si , tendria que asegurarme que esta definido en el font.v. cierto... lo cambiare :)


--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/flgb6Y64v3o/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Juanma Rico

unread,
May 13, 2018, 8:27:59 AM5/13/18
to FPGAwars: explorando el lado libre

Buenas de nuevo...

Ya está listo... :))
(Lo sé, lo sé, el SAV me puede... tengo que ser más fuerte. :)) )

Con la modificación "robada" a Alexandre de la RAM de vídeo ya se puede aprovechar más los bloques de la BRAM (no así el direccionamiento, pero eso en este caso no importa ;) ). Este es el resultado



¡Ya funciona la consola de 80x60 en la icezum Alhambra!. :)))

He generado dos pruebas con el antes (Test-PxsConsole.ice) y el después (Test2-PxsConsole.ice) y las he subido a la rama de desarrollo, para aquellos que lo quieran probar rápido para bajar el SAV (o no dispongan del entorno de icestudio preparado como Alexandre), he generado dos nuevos bitstreams que podéis descargar directamente en la icezum Alhambra (con el iceprog, por ejemplo). Recordad que para escribir directamente en el monitor conectado a la icezum Alhambra solo hay que enviar las letras tecleando en un terminal conectado al puerto serie a 115200 baudios. En las pruebas de icestudio hay un bloque de código sin conectar que si se conecta al PxsConsole envía caritas sonrientes simplemente pulsando los botones... sin necesidad de conectarlo al PC. :)))

Queda limpiar un poco e incluir el bloque de la consola en la colección iPxs. (próximamente)

Saludos
Juan Manuel Rico


Auto Generated Inline Image 1

Juanma Rico

unread,
May 13, 2018, 8:31:54 AM5/13/18
to FPGAwars: explorando el lado libre

Me lo imaginé... pero entonces tienes que modificar el Makefile para que incluya el fichero en la síntesis... o bien incluirlo también en font.v donde se utiliza.
Tú decides... jejejejeje :)))

Saludos
Juan Manuel Rico
Reply all
Reply to author
Forward
0 new messages