[Math] Cálculos sencillos para las FPGAs.

284 views
Skip to first unread message

Democrito

unread,
Jan 31, 2020, 6:50:08 PM1/31/20
to FPGAwars: explorando el lado libre
Hola,

Abro este hilo para comentar cómo voy resolviendo pequeños cálculos. En la medida que vaya aprendiendo lo iré poniendo por aquí y ya sabéis que estáis invitados a participar, que es de lo que se trata, de compartir experiencias (buenas y malas). Desearía que este hilo fuese esencialmente práctico de cosas que hayamos probado y funcionan, o lo que podemos evitar por no ser lo más óptimo.

Estoy ideando en mi cabeza cómo poner píxeles independientes [ en plan "setPixel(x,y)" ] en la pantalla Oled. Todo ello para, en el futuro, poder hacer gráficos como líneas y circunferencias (con la inestimable ayuda de Mr. Bresenham). Pero todavía estoy en la fase de hacer equivalente los ejes de coordenadas (x,y) con direcciones específicas de la memoria para activar el píxel adecuado. En mi cabeza está resuelto, falta comprobar si funciona. Y mientras buscaba la manera más eficaz (evitando consumir demasiados recursos) me di cuenta que, pese a que iba por buen camino, existía un camino más sencillo, en este caso se trata de multiplicar y es lo que voy a comentar.

Todos sabemos que para multiplicar usaríamos el desplazamiento a la izquierda, donde un desplazamiento a la izquierda significa multiplicar por 2, dos desplazamientos significa multiplicar por 4, tres desplaza.... todo eso que conocéis sobre la base 2. Mi lógica para hacer este tipo de operaciones era utilizar un registro de desplazamiento, pero de lo que no me había percatado era que un simple cableado de bits te hace esa misma operación sin ciclos de reloj. Seguramente muchos de vosotros ya lo sabréis, pero en concreto este post va dirigido a las personas que no lo sabían, como yo hasta hace unas horas.

En vez de usar un registro de desplazamiento lo que haremos es re-cablear con buses.

cableado para multiplicar x8.PNG


Esta imagen es un ejemplo de cómo sería la multiplicación x8, añadiendo tres 0s en los bits más bajos. Lo he usado para multiplicar (en mi caso concreto) por 16 en la pantalla Oled (con 4 desplazamientos) y me ha funcionado sin problemas.

En otra parte del circuito necesito multiplicar por 9. Se resuelve de una manera muy parecida y con cierta añadidura. Se trata de multiplicar por 8 y a ese resultado se le suma la entrada, la salida da como resultado multiplicar por 9. Y todo esto sin ciclos de reloj (estoy obviando la velocidad de propagación de las puertas lógicas, en este caso del sumador).

Multiplicar por 9 eficientemente.PNG


Pese a que esta operación (en aquella época lo pensaba con registros de desplazamiento y sumador) ya lo conocía, la primera persona en comentar este método en este foro fue José Picó.


Lo he usado y aplicado dentro de la Oled y nuevamente ha funcionado sin problemas.


Todas las cosillas que vaya aprendiendo y comprobando lo iré poniendo en este hilo. Se trata de resolver cosas puntuales, pequeñas operaciones. Si usas Verilog (como lo estaba haciendo últimamente) te resuelve todo esto con una simple descripción, pero lo interesante es conocerlo de antemano. He comparado el consumo de LUTs y PLBs y no hay mucha diferencia, simplemente se invierte los consumos (si uno aumenta el otro disminuye y viceversa, según el método empleado), pero el resultado final es muy parecido en consumo de recursos generales, al menos en los casos que acabo de comentar aquí.


Saludos.

charli va

unread,
Feb 1, 2020, 1:23:41 AM2/1/20
to fpga-wars-explora...@googlegroups.com
Hola democrito! Voy a intentar hacer algún tutorías paso a paso de icecrystal porque ahí están resueltos este tipo de problemas.

Hay un bloque para calcular la posición de memoria lineal de una coordenada xy por ejemplo .

Mírate los ejemplos y verás un bloque que tiene un icono de una matriz con una posición subrayada.

Este finde voy a ver si me pongo con la oled para poder aportar mi granito al proyecto que está avanzando súper bien!!



--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/fpga-wars-explorando-el-lado-libre/c73999b6-d96f-41d1-b504-4aeb713e59cf%40googlegroups.com.

charli va

unread,
Feb 1, 2020, 2:34:37 AM2/1/20
to fpga-wars-explora...@googlegroups.com
Y por cierto... gracias por compartir todo esto!! Tus explicaciones están geniales! 

Democrito

unread,
Feb 1, 2020, 4:22:44 AM2/1/20
to FPGAwars: explorando el lado libre

charli va

unread,
Feb 1, 2020, 5:23:26 AM2/1/20
to fpga-wars-explora...@googlegroups.com
Nada si es por si te ayuda! Hay otros módulos que son conceptos en sí pero que igual te pueden ayudar . 

Como andas motivado con esto por eso te comenté si te apetecia participar en la colección porque sería genial que fuéramos ampliándola en displays y bloques comunes a cualquier tema gráfico.

Un abrazo!

El El sáb, 1 feb 2020 a las 10:22, Democrito <spo...@gmail.com> escribió:
--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.

Democrito

unread,
Feb 1, 2020, 5:34:55 AM2/1/20
to FPGAwars: explorando el lado libre
Poco a poco lo conseguiremos!

Democrito

unread,
Feb 2, 2020, 12:08:09 AM2/2/20
to FPGAwars: explorando el lado libre
Dejo una imagen de cómo he resuelto: dado dos ejes x e y, obtener la posición de memoria (dirección) y dato a guardar en ella. No está terminado porque me falta hacer una OR al dato que guardo para que no machaque lo que ya existía en ese byte.

byte_position_and_data.PNG

La traducción matemática es esta:

calculos.PNG

Nota: "mod" significa que en vez de dividir quieres el resto de esa división.

La división es entera y como es en base 2, son desplazamientos, todo lo demás son sumas y restas. Me consume un sólo PLB y cero LUTs. Lo he probado aparte con leds y parece ser que funciona perfecto. En los próximos días veré como meter todo esto y gestionarlo para que también pueda hacer el barrido de toda la memoria y sacarla como imagen en la Oled.

Este método sólo sirve para la pantalla Oled que estamos manejando, por la forma particular que tiene de funcionar de enviar 8 bits (píxeles) verticales. Las constantes 128 es el número de píxeles máximo de anchura, y el 8 de los 8 píxeles verticales.

La intención de mostrar esto es para comprobar que podemos hacer cálculos sencillos (gracias a que todo se maneja en base 2) para resolver problemas muy concretos.

Saludos.

charli va

unread,
Feb 2, 2020, 1:58:35 AM2/2/20
to fpga-wars-explora...@googlegroups.com

Estas optimizaciones están muy bien! Gracias democrito!

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.

Democrito

unread,
Feb 2, 2020, 7:34:01 AM2/2/20
to FPGAwars: explorando el lado libre
He metido la pata hasta el fondo. No funciona. No sé cómo leches hice las comprobaciones anoche para hacerme pensar que iba bien.

charli va

unread,
Feb 2, 2020, 7:50:33 AM2/2/20
to fpga-wars-explora...@googlegroups.com

Ja jaja cuidado que la noche confunde!

El El dom, 2 feb 2020 a las 13:34, Democrito <spo...@gmail.com> escribió:
He metido la pata hasta el fondo. No funciona. No sé cómo leches hice las comprobaciones anoche para hacerme pensar que iba bien.

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.

Democrito

unread,
Feb 2, 2020, 8:44:56 AM2/2/20
to FPGAwars: explorando el lado libre
La madre que me parió! Como son píxeles en vertical en grupos de 8 me hago unos líos tremendos para verificar que estoy dando con el byte que realmente se corresponde. He vuelto a mirar el funcionamiento y en fin, que sí que parece que funciona, pero me lío en los cambios de enfoque. Voy a ponerme manos a la obra e integrar ese diseño y ver si va o no.

Perdonad tanta confusión! Adjunto un ejemplo de cómo hago las pruebas.
Memory_Nbyte_Nbit_XY.ice

Democrito

unread,
Feb 3, 2020, 7:00:09 PM2/3/20
to FPGAwars: explorando el lado libre
He conseguido hacer un circuitillo demo que hace un putPixel hardware. Las mates que puse en un post anterior funcionan y el error que comenté después no existe, tuve un lapsus al volver a comprobar la fórmula (estaba recién levantado) y me lancé alarmado a avisar...

putPixel.PNG

Se trata de subir el circuito sólo para comprobar de que funciona realmente las mates que comenté; dada una configuración, que puedes modificar como entradas (x,y) donde lo indica, el resultado sale a la vista. Una vez subido, en las "Alhambras" se pulsa primero sw1 (escribir en memoria) y después se pulsa sw2 (mostrar lo que hay en memoria) y sale dicho punto (píxel) donde se espera.

Para los que miren dentro del circuito, decir que tengo pensado simplificar más la parte de gestión de la memoria (si fuese posible). Tomé una versión de bootloader de Obijuan y a partir de ahí comencé a simplificar poco a poco hasta llegar al ICE que adjunto (dentro del módulo "BITMAP"), pero como comentaba, creo que se puede más, pero lo sabré conforme vaya experimentando.

Todo comienza con un punto (es la base donde comienza todo lo demás), espero con el tiempo lograr líneas y círculos.

Adjunto ICE.

Saludos.
putPixel.zip

Democrito

unread,
Mar 4, 2020, 6:12:48 PM3/4/20
to FPGAwars: explorando el lado libre
Adjunto en este post un algoritmo de Bresenham para dibujar líneas, pero de momento sólo muestra en los leds la sucesión de números en binario, sólo eso. Estos días voy con el tiempo justo y más adelante intentaré explicar algo muy curioso que tiene este algoritmo, además de dibujar líneas puede servir para otras cosas (al menos para una más, pero que se puede derivar en otras).

A veces, antes de ponerme con un diseño electrónico trato de hacer un programa para ayudarme a comprender el problema que quiero sacar. En este caso es muy evidente, es un algoritmo y lo único que he hecho ha sido traducirlo a Verilog. Así que hay cálculos que por ser electrónica se ejecutan en un mismo tiempo y otras requieren secuenciación porque hay registros (variables) que se transforman en la medida que transcurre el tiempo.

Este post es sólo una mini-introducción de lo que estoy trabajando ahora. El ICE que adjunto es el algoritmo de Bresenham para ser visualizado con leds. Se ha de poner el punto inicial donde lo indica (xo, yo) y el punto final en (x1, y1) que ya viene por defecto con valores que he ido probando. Al pulsar sw1 (en las alhambras) se pondrá en marcha y por defecto se verá la salida que da 'x', y si se pulsa sw2 permite ver lo que sucede en el eje 'y'.

El algoritmo que he utilizado está muy optimizado. Tenía de hace años otro que no era tan "corto" por así decirlo, esta nueva versión me ha encantado. Lo que verás en el ICE es una traducción. En próximos post daré más detalles sobre esto.

Está pensando para ser implementado en una pantalla Oled. Espero no demorar mucho en hacerlo.

Las entradas sólo acepta números en el rango de -128 hasta 127 (esto son 8 bits, el último bit es de signo), si te sales de ese rango seguramente observarás incoherencias. De hecho este módulo ya lo tengo diseñado como módulo y está limitado (por cuestiones de buses) de 0 hasta 127 (aunque sigue siendo una entrada de 8 bits). En las operaciones internas puede haber cálculos con resultado negativo (esto significa un bit más) y si multiplico por 2 (existe esa operación dentro del algoritmo) necesito otro bit más. Por eso los registros están "signados", así al sintentizar tendrá presente ese tema, y el número de bits total que usaré es de 10 bits (8 bits + uno de signo y otro para la operación de por 2).

Si consigo dibujar líneas en la pantalla Oled, luego me pondré con las circunferencias. Terminado estos dos temas gráficos lo aparcaré y pasaré a documentar todos los proyectos realizados hasta ahora, desde escribir texto hasta dibujar esas dos primitivas gráficas.

Mensaje para Charliva: Todavía no he subido los proyectos a Icecrystal, pero lo haré cuando termine esta parte del proyecto y lo pueda documentar. Con este proyecto he ido aprendiendo muchas cosas, que necesito corregir y optimizar de proyectos anteriores, que sepas que no me olvido y que no es descuido.

Saludos.

Ejemplo_Bresenham.ice

Democrito

unread,
Mar 4, 2020, 6:25:27 PM3/4/20
to FPGAwars: explorando el lado libre
Bueno, como siempre me pasa, me doy cuenta de errores justo después de postear. Adjunto el ICE corregido. Tiene el mismo nombre.
Ejemplo_Bresenham.ice

Democrito

unread,
Mar 4, 2020, 6:32:53 PM3/4/20
to FPGAwars: explorando el lado libre
Otra cosita más, se ejecuta en 4 ciclos, sin embargo es posible ser ejecutado en 3 pasos. Las optimizaciones lo dejaré cuando termine de implementar las dos primitivas gráficas.

charli va

unread,
Mar 5, 2020, 1:29:09 AM3/5/20
to fpga-wars-explora...@googlegroups.com
Fantástico trabajo Demócrito! y no te preocupes yo tengo muchas cosa atascadas xD el tiempo por desgracia es finito y da para lo que da.

De echo yo tengo pendiente ponerme a ver las tripas en detalles de lo que has hecho ya que me interesa mucho en general y espero poder aportar cosas.

¡Un abrazo y ánimo!

El jue., 5 mar. 2020 a las 0:32, Democrito (<spo...@gmail.com>) escribió:
Otra cosita más, se ejecuta en 4 ciclos, sin embargo es posible ser ejecutado en 3 pasos. Las optimizaciones lo dejaré cuando termine de implementar las dos primitivas gráficas.

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.

Democrito

unread,
Mar 5, 2020, 4:45:03 AM3/5/20
to FPGAwars: explorando el lado libre
Acabo de conseguir implementar el algoritmo de bresenham en la Oled, eso significa que el algoritmo en verilog funciona. Todo está en plan "sucio" y hay mucho trabajo por hacer para unirlo a los módulos que permiten escribir y otras funciones.

Pongo un vídeo demo, pero explico lo que sucede. Hago que se imprima píxel a píxel cada 20 ms, porque quería ver si era capaz de tomar un sentido dentro de la trayectoria (en el futuro esto puede servir para posicionar motores y el sentido es importante). La línea comienza en la esquina inferior derecha a propósito por lo que comentaba antes, y termina en el lado opuesto.


Adjunto la demo.

Saludos!
Oled_DrawLine.zip

Obijuan

unread,
Mar 5, 2020, 10:47:16 AM3/5/20
to FPGAwars: explorando el lado libre
Woala!!! Me encanta!!!! ¡Gracias! :-)

En cuanto pueda lo prueba con la Oled

Saludos, Obijuan

charli va

unread,
Mar 5, 2020, 12:40:23 PM3/5/20
to fpga-wars-explora...@googlegroups.com
Súper divertido democrito !! No se si será mi oled o que hay algún bug pero la línea cambia de color!! Jajaja

Fantástico! Ya investigaremos!

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
IMG_0777.MOV

Democrito

unread,
Mar 5, 2020, 4:33:17 PM3/5/20
to FPGAwars: explorando el lado libre
Jejeje, Charliiiii!!! tu pantalla es bicolor! No significa que pueda dar dos colores, es reclamo publicitario en la que yo también caí cuando me compré una Oled SPI cuando no tenía idea de estos tema y sólo quería experimentar. La parte de arriba (los primeros 8 píxels) es de color anaranjado y el resto es azul.

Te pongo varias imágenes de la pantalla "bicolor" SPI que tengo que reconvertí a I2C (luego doy más info sobre esto).

IMG_20200305_220108.jpg


IMG_20200305_220354.jpg


En tu caso es cláramente una pantalla I2C porque tiene 4 pines, pero es "bicolor", y lo dicho, no es bicolor, es simplemente que los 8 píxels de arriba son de otro color.

Sobre pasar de SPI a I2C y vice-versa (aunque no creo que siempre se pueda, eso depende del fabricante) dejo este documento que está genial:


Dejo una imagen de la pantalla Oled SPI que modifiqué para convertirla en I2C.

IMG_20200305_220807.jpg


Un fuerte abrazo Charli!

Democrito

unread,
Mar 5, 2020, 4:36:14 PM3/5/20
to FPGAwars: explorando el lado libre
Corrijo un detalle: No son 8 píxeles de la zona de arriba, sino 16.

charli va

unread,
Mar 6, 2020, 12:42:30 AM3/6/20
to fpga-wars-explora...@googlegroups.com

Que bueno!! Gracias por la aclaración!! No tenía ni idea!! Probare otras que tengo por ver si son monocromo también.

Un abrazo!

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.

Democrito

unread,
Mar 7, 2020, 9:54:48 AM3/7/20
to FPGAwars: explorando el lado libre
He conseguido hacer circunferencias pero tiene algunos problemas. Si te sales de los márgenes puede hacer cosas raras. He tratado de poner condiciones pero aún así no he conseguido solventar esos problemas.

Pongo un vídeo para ver en "lentitud humana" cómo "fabrica" la circunferencia. Es un algoritmo de Bresenham para circunferencias y lo que hace es calcular un cuadrante y el resto de los cuadrantes se crean con sumas y restas equivalentes para esos cuadrantes . Es por eso que en vídeo veréis que a la vez se forman 4 curvas que terminan uniéndose. He puesto para crear la circunferencia más grande posible en el centro de la pantalla Oled, en el ICE que adjunto está ese mismo ejemplo y que puedes modificar a tu antojo.


Los dos algoritmos optimizados (línea y circunferencia) en lenguaje C los he tomado de esta página: http://members.chello.at/~easyfilter/bresenham.html y los convertí a Verilog. El Verilog de circunferencias es menos evidente porque para optimizar recursos lo pensé lo más "electrónicamente" posible, aún así consume muchos recursos, pero sirve como ejemplo ya sea para Icestudio, Apio, u otra aplicación hardware.

Aparco aquí el tema gráfico. En los próximos días crearé un tutorial sobre I2C de sólo escritura hasta llegar a la Oled. Terminado ese tutorial lo pasaré a GitHub.

Saludos.
Oled_Circle.zip

Obijuan

unread,
Mar 11, 2020, 3:09:39 AM3/11/20
to FPGAwars: explorando el lado libre
Increible Demócrito. Muchísimas gracias :-)

Esto tiene un valor docente increible. Todos estos cálculos además se pueden utilizar para pintar en la VGA

Saludos, Obijuan
Reply all
Reply to author
Forward
0 new messages