domingo, 1 de enero de 2012

Mostrar un carácter en el LCD con Xilinx

Muy buenas a todos, en esta entrada os voy a explicar cómo elaborar nuestro propio carácter y hacer que éste se nos muestre en nuestra pantalla LCD. Como en el ejercicio anterior, nuestra práctica se lleva a cabo en una FPGA, y utilizamos un LCD alfanumérico 2x16.
Para aclarar, crear un carácter significa elaborar un elemento que no aparezca en la tabla ASCII. Es decir, esta que os muestro a continuación.


Bien, a partir de aquí procederemos a elaborar nuestro propio carácter. Para eso he utilizado un programilla muy útil el cual, tras marcar cada punto, me dice el código que debería meter.




Arriba a la izquierda os muestro el nombre del programa y el cuadro de la derecha muestra el código. La “A”, es el carácter que voy a sacar en el LCD, perdonadme pero ahora mismo no recuerdo si era exactamente así, no tengo ninguna placa para probarlo, pero creo que era así, de todas formas ya mostraré en vivo y en directo el mensaje.
No me voy a entretener mucho en el inicio del proyecto puesto que es exactamente igual que la entrada anterior de mostrar un mensaje en el LCD. Aquí os muestro lo que es el inicio.
Pero no me pararé a explicarlo porque ya lo hice en la entrada anterior.


Bien, una vez hemos habilitado el LCD a través de las tres instrucciones y demás, es momento de empezar a mostrar las cosas por el LCD. En primer lugar, mi práctica tiene que mostrar primero mi nombre “Gabi”, seguido del carácter. En este caso, aproveché lo que hice en la anterior práctica y simplemente me limité a copiar como se creaba la “G”,”a”,”b” y la ”i”, con esto escribí en primer lugar “Gabi”. El inicio del nuevo programa empieza más o menos a partir del estado 13.





Es importante mencionar una cosa, el motivo de que solo ponga gabi, no es por el simple hecho de ahorrarme molestias, sino porque por culpa de esto, xilinx no era capaz de generarme el fit, el problema que me daba era algo así como “Imposible compilar, exceso de macrocélulas”, es decir, estaba utilizando más de las que debía, y por eso no me dejaba.

Estas son las transiciones que hay a partir del estado 13 a los siguientes.

Del 13 al 18 : Q0_D='1' & Q1_D='0' & Q2_D='0' & Q3_D='0' & Q4_D='0'
Del 13 al 15 : Q0_D='0' & Q1_D='1' & Q2_D='0' & Q3_D='0' & Q4_D='0'
Del  13 al  16: Q0_D='1' & Q1_D='1' & Q2_D='0' & Q3_D='0' & Q4_D='0'
Del 13 al 17: Q0_D='0' & Q1_D='0' & Q2_D='1' & Q3_D='0' & Q4_D='0'
Del 13 al 31: Q0_D='0' & Q1_D='1' & Q2_D='1' & Q3_D='0' & Q4_D='0'

El estado 31 contiene la dirección DDRAM, yo he puesto la dirección 00000000, cada uno puede ponerla donde quiera, aunque aconsejo poner esta porque es fácil identificar a lo que se refiere.
Los  4 primeros estados anteriormente mencionados pasarán al estado 38 sin condición. Como os enseño en la imagen.




Si os fijais solo los verdes van al 38, sin embargo el 31 (el carácter), no pasa por él, sino que va a otro, que es el 41, para que os situéis, la transición marcada con una X es la que conecta con el estado 31.



En el estado 41 activamos el “reloj_carácter” incrementando así el contador de datos.
Del 41 pasamos al 44 sin condiciones. En éste activamos el LCD y lo ponemos en lectura.
Como os muestro a continuación.


Del 44 pasamos al 45 sin condiciones, éste estado es exactamente igual  al 44, solo que le colocamos un “else”, de tal manera que no saldrá de ese estado hasta que el LCD deje de estar ocupado.
Después pasamos al state 46 si D7_I =0.
Y a partir del 46, pasamos al 47 con las siguientes condiciones, que son unas cuantas.

Q0_C='0' & Q1_C='1' & Q2_C='0' & Q3_C='0' & Q4_C='0'
Q0_C='0' & Q1_C='0' & Q2_C='1' & Q3_C='0' & Q4_C='0'
Q0_C='0' & Q1_C='1' & Q2_C='1' & Q3_C='0' & Q4_C='0'
Q0_C='0' & Q1_C='0' & Q2_C='0' & Q3_C='1' & Q4_C='0'
Q0_C='0' & Q1_C='1' & Q2_C='0' & Q3_C='1' & Q4_C='0'
Q0_C='0' & Q1_C='0' & Q2_C='1' & Q3_C='1' & Q4_C='0'
Q0_C='0' & Q1_C='1' & Q2_C='1' & Q3_C='1' & Q4_C='0'
Q0_C='0' & Q1_C='0' & Q2_C='0' & Q3_C='0' & Q4_C='1'
Desde el State46 a State48 si:

[Q0_C='1' & Q1_C='0' & Q2_C='0' & Q3_C='0' & Q4_C='0']

[Q0_C='1' & Q1_C='1' & Q2_C='0' & Q3_C='0' & Q4_C='0']

[Q0_C='1' & Q1_C='0' & Q2_C='1' & Q3_C='0' & Q4_C='0']

[Q0_C='1' & Q1_C='1' & Q2_C='1' & Q3_C='0' & Q4_C='0']

[Q0_C='1' & Q1_C='0' & Q2_C='0' & Q3_C='1' & Q4_C='0']

[Q0_C='1' & Q1_C='1' & Q2_C='0' & Q3_C='1' & Q4_C='0']

[Q0_C='1' & Q1_C='0' & Q2_C='1' & Q3_C='1' & Q4_C='0']

[Q0_C='1' & Q1_C='1' & Q2_C='1' & Q3_C='1' & Q4_C='0']

Esta sería la imagen de los estados anteriores y todas sus transiciones, el estado 47 a la izquierda y el estado 48 a la derecha.





En el estado  47  activamos el “RS”, es decir, ponemos el LCD en modo registro. Y en el estado 48 lo ponemos a 0.




Las condiciones que debíamos poner para pasar del estado 46 al 48, vamos a copiarlas, es decir, las transiciones que salen del estado 48 son las que salieron del 46. Cada transición finalizará en un nuevo estado, que va desde el 49 al 56. Como os muestro en la imagen.




Cada estado representa a una línea del carácter, por eso son 8. En todos ellos mantenemos habilitado el “THREE STATE”, para  direccionar CGRAM en cada estado.Una vez hecho esto, empezaremos a crear el carácter.

Finalmente todos ellos pasarán sin condiciones al último estado, el 65, que a su vez volverá al estado 42 del diagrama, para que se repita en un bucle constante.

Como os enseé un poco más arriba, del estado 46, pasamos al 47 y 48, bien, en el estado 47 dijimos que tendría que estar activado el registro, para que podamos ir pasando los datos de nuestro carácter.
Una vez llegados a este punto, tendremos que tener ya pensado nuestro carácter, yo os lo enseñé al principio del programa, pero lo volveré a meter para que lo veais.


Como veis, es simplemente una “A”, como carácter queda bastante bien en el LCD, además al ser el fondo negro crea una especie de “marco”. IMPORTANTE, aprovecharos de las líneas que sean iguales!, por qué digo esto?, pues porque yo he sufrido en mis propias carnes el no poder compilar por culpa de overflow de espacio. Lo que os comenté de las macrocélulas algo más arriba. Por eso, prestad atención a la siguiente imagen, en ella me limito a hacer grupos de mismas líneas.



Como veis aquí, hay 3 líneas diferentes, por lo que en vez de hacer uno por cada línea, simplemente ponemos 1 y hacemos que cada línea vaya a dicho estado, ahorrándonos así bastante espacio.
Con esta siguiente imagen lo entenderéis bien.




Cada círculo representa a un grupo, como os mostré en el carácter. Las transiciones son las siguientes, entendiendo que todas llegan del estado  47.
Es decir:

Del 47 al 57:
Q0_C='0' & Q1_C='1' & Q2_C='0' & Q3_C='0' & Q4_C='0'
Q0_C='0' & Q1_C='0' & Q2_C='0' & Q3_C='0' & Q4_C='1'

Del 47 al 19:
Q0_C='0' & Q1_C='0' & Q2_C='1' & Q3_C='0' & Q4_C='0'

Del 47 al 14:
Q0_C='0' & Q1_C='1' & Q2_C='0' & Q3_C='1' & Q4_C='0'
Q0_C='0' & Q1_C='1' & Q2_C='1' & Q3_C='0' & Q4_C='0'

Del 47 al 59:
Q0_C='0' & Q1_C='0' & Q2_C='0' & Q3_C='1' & Q4_C='0'
Q0_C='0' & Q1_C='0' & Q2_C='1' & Q3_C='1' & Q4_C='0'
Q0_C='0' & Q1_C='1' & Q2_C='1' & Q3_C='1' & Q4_C='0'

Después, los 4 estados van al 65 sin ninguna condición.




Y justo después del estado 65 lanzamos una transición hacia el estado 42, que va sin condiciones.
Como veis, del estado 42 salen una gran cantidad de transiciones hacia el 41, estas son:

[Q0_C='1' & Q1_C='0' & Q2_C='0' & Q3_C='1' & Q4_C='0']
[Q0_C='0' & Q1_C='1' & Q2_C='0' & Q3_C='1' & Q4_C='0']
[Q0_C='1' & Q1_C='1' & Q2_C='0' & Q3_C='1' & Q4_C='0']
[Q0_C='0' & Q1_C='0' & Q2_C='1' & Q3_C='1' & Q4_C='0']
[Q0_C='1' & Q1_C='0' & Q2_C='1' & Q3_C='1' & Q4_C='0']
[Q0_C='0' & Q1_C='1' & Q2_C='1' & Q3_C='1' & Q4_C='0']
[Q0_C='1' & Q1_C='1' & Q2_C='1' & Q3_C='1' & Q4_C='0']
[Q0_C='1' & Q1_C='0' & Q2_C='0' & Q3_C='0' & Q4_C='0']
[Q0_C='0' & Q1_C='1' & Q2_C='0' & Q3_C='0' & Q4_C='0']
[Q0_C='1' & Q1_C='1' & Q2_C='0' & Q3_C='0' & Q4_C='0']
[Q0_C='0' & Q1_C='0' & Q2_C='1' & Q3_C='0' & Q4_C='0']
[Q0_C='1' & Q1_C='0' & Q2_C='1' & Q3_C='0' & Q4_C='0']
[Q0_C='0' & Q1_C='1' & Q2_C='1' & Q3_C='0' & Q4_C='0']
[Q0_C='1' & Q1_C='1' & Q2_C='1' & Q3_C='0' & Q4_C='0']
[Q0_C='0' & Q1_C='0' & Q2_C='0' & Q3_C='1' & Q4_C='0']






Del estado 42 al 43 con la condición:

Q0_C='0' & Q1_C='0' & Q2_C='0' & Q3_C='0' & Q4_C='1'





Este estado es importante, habilitamos el LCD, lo primero, y después, introducimos el código de la DDRAM. Que es 11000110.

Después pasamos del 43 al 38 sin condición.

Subimos un poquito más y nos vamos al estado 39, que va hacia el 10 mediante estas transiciones:

Q0_D='1' & Q1_D='0' & Q2_D='0' & Q3_D='0' & Q4_D='0'
Q0_D='0' & Q1_D='1' & Q2_D='0' & Q3_D='0' & Q4_D='0'
Q0_D='1' & Q1_D='1' & Q2_D='0' & Q3_D='0' & Q4_D='0'
Q0_D='0' & Q1_D='0' & Q2_D='1' & Q3_D='0' & Q4_D='0'
Q0_D='1' & Q1_D='0' & Q2_D='1' & Q3_D='0' & Q4_D='0'
Q0_D='0' & Q1_D='1' & Q2_D='1' & Q3_D='0' & Q4_D='0'
Q0_D='1' & Q1_D='1' & Q2_D='1' & Q3_D='0' & Q4_D='0'

Ya con esto lo esencial ya estaría para hacer funcionar nuestro carácter en el LCD. Me dijeron que existía una manera de “optimizar” el proyecto dándole desde el stateCAD a donde pone “optimize” en la parte superior, mi problema es que cuando le doy, me desaparece el diagrama entero, como su fuera una especie de error grave, y no puedo usarlo. Aún no sé el motivo, disculpad.

Después como siempre, podemos utilizar el statebench, para probar que se puede pasar por todos los estados y no nos genera ningún problema. Para esto utilizamos la opción “automatich Testbench” y el propio stateCAD viaja a través del diagrama buscando fallos o errores. Aquí veréis a lo que me refiero.



Tras verificar que todo está correcto y al 100% podremos realizar el proceso de creación de VHDL, como siempre, dándole en la parte superior a “Generate VHD”.

Una vez tengamos el código VHD generado será el momento de crear un esquemático, en este caso, bastante parecido a la entrada de “crear un mensaje en el LCD con xilinx”, solo que he tenido que hacer unos pequeños retoques, como cambiar la máquina de estados y demás, claro.
Es algo así.



El esquemático es muy similar al anterior, éste tiene incorporado un contador binario de 4 bits y 2 contadores binarios de 8 bits. Además de la máquina de estados, claro.

Cuando tengamos creado el esquemático, pasaremos al PACE, para meter los pines, y por ultimo generaremos el .JED, como hacemos siempre.


Una vez tengamos acabado todo esto y utilicemos el JTAG para simularlo en la placa entrenadora tendremos nuestro caracter listo, como os enseño a continuación:





Y ya tendríamos nuestra máquina que muestra un carácter en el lCD. Espero que os haya servido de ayuda, un saludo y feliz año!

No hay comentarios:

Publicar un comentario