Primeros programas en VHDL

Antes de que me lleguen los CPLDs de 5V he empezado a hacer el programa del controlador VGA, a ver qué tal. Las primeras versiones del programa me han ocupado demasiado como para caber en el dispositivo –algunas veces me quedaba sin registros (macroceldas), y otras veces la lógica que debía implementarse para una señal en concreto no cabía en los recursos posibles para generar una señal.


He ido reduciendo la complejidad del circuito (y las prestaciones) hasta que me ha cabido, y me he quedado con dos versiones posibles. Las dos se basan en una comunicación serie desde el microcontrolador hacia el CPLD, tipo SPI, es decir con un reloj mandado por el micro, pero con un bus de datos de 8 bits desde el micro a la memoria. Otra señal adicional, wrUc, se usa para decir que el micro quiere escribir (en la vram).


En ambos circuitos el microcontrolador accede al bus de datos de la VRAM a través de un latch controlado por el CPLD. Un latch es un registro que puede guardar 8 bits de datos y su salida puede ser puesta en alta impedancia para permitir a otros dispositivos usar el bus de datos. En este caso la memoria puede ser escrita desde este latch del microcontrolador, o puede ser leída, volcando ella entonces su contenido en el bus, hacia otro latch de salida (hacia el DAC qe genera las señales analógicas R, G y B para la VGA).


En ambos circuitos se trata de un controlador bastante burdo y sencillo, ya que mientras el microcontrolador está escribiendo en la VRAM, no se está generando señal de VGA (al menos no el RGB, las señales de sincronía hsync y vsync sí se generan, para que el monitor sufra menos) Mientras se escribe en la VRAM, probablemente se verá ruido o porciones de la pantalla en patrones extraños, ya que se verá lo que se está escribiendo pero a una frecuencia completamente distinta. Intenté al principio usar ambos flancos del reloj (ascendente y descendente), en el ascendente pretendía leer la memoria y generar el RGB, y en el descendente escribir en memoria, de forma que se haría entrelazado transparente. Pero no ha podido ser porque no es posible usar ambos flancos en estos CPLD o en FPGAs en general.


La diferencia entre los dos circuitos es lo que se comunica por la interfaz serie.


En el primero se envía una dirección de memoria a escribir vía esta interfaz serie. En concreto usa 19 ciclos del reloj del microcontrolador, más uno final en el que se hace la escritura de lo que haya en el bus de datos (el microcontrolador maneja la señal wrUc, clkUc, dataUc y el bus de datos controlando la comunicación, pero es el CPLD el que permite la entrada de datos del latch a la memoria).


En el segundo no se envían datos (no hay señal dataUc, sino otra señal resetUc). Por el contrario, el microcontrolador reinicia un contador de memoria que se encuentra programado en el CPLD, mediante la señal resetUc. Tras esto, en cada ciclo (flanco ascendente) de clkUc, el contador del CPLD se incrementa en 1, y se escribe en memoria el valor que habrá cargado el micro en el bus de datos, apuntado por la dirección de memoria indicada por el contador.


El segundo circuito permite una comunicación más rápida (un rellenado más rápido de la pantalla), y utiliza menos recursos del CPLD (éste se queda “menos lleno”), pero tiene la desventaja de que el acceso a la memoria no es aleatorio. Como sobran algunos recursos del CPLD (en concreto sobran más registros de las macroceldas porque no se usa el contador estadoComunicacion de cinco bits), es posible que intente implementar la lectura de la memoria desde el microcontrolador en este segundo circuito, ya veremos si lo consigo.


Una cosa interesante es que en ambos circuitos he usado un gated clock, es decir que el reloj pasa a través de una combinación de puertas lógicas mezclándose con otras señales. Ésta es la línea en concreto donde lo hago:

clkGated <= ( clk and not wrUc ) or ( clkUc and wrUc );



Esta línea de VHDL define la señal clkGated con tres señales: dos relojes (el externo de 25.175 MHz para generar la señal VGA, y el que viene del microcontrolador), y la señal wrUc, que también la controla el microcontrolador. La ecuación hace que clkGated sea igual a clk o a clkUc, respectivamente cuando wrUc vale 0 o 1.


Esto del gated clock lo he necesitado porque si no, algunas señales como la dirección de memoria se tenían que modificar de acuerdo a un reloj en un caso y a otro reloj en otro caso, y no era posible implementar las ecuaciones –el programa no se sintetizaba (análogo de compilar). Usando la detección del flanco ascendente de este reloj y posteriormente comprobando el valor de wrUc, puedo manejar los casos de lectura o escritura de memoria con el reloj correspondiente en cada caso.


Aquí os dejo los dos programas en VHDL, del primer y segundo circuito:


Circuito 1 y 2


Nada más, hasta la próxima!