7-Caracter y texto en LCD Xilinx CPLD




Este proyecto es una modificación de la entrada anterior 

“Mensaje LCD Xilinx CPLD”.


Para poder realizarlo necesitaremos hacer primero el mensaje en el LCD.

 

AVISO: Este programa ha sido pensado en un principio para un FPGA, consecuentemente vamos a tener que reducir los caracteres de nuestro nombre en el LCD para poder programarlo en el CPLD XC9500. Si no lo hacemos nos avisará el propio Xilinx diciéndonos que estamos utilizando demasiadas macrocélulas. 

 

En el ejercicio anterior hemos introducido directamente  códigos de la tabla ASCII en una serie de estados.





Lo que ahora haremos será crear un caracter que no exista en la tabla ASCII.

Por el motivo de la capacidad del CPLD he reducido el texto anterior a

 “ Jose ”.




 

La transición desde el State13 quedaría de la siguiente manera:

 

A State18:

[Q0_D='1' & Q1_D='0' & Q2_D='0' & Q3_D='0' & Q4_D='0' ] : J




A State15:

[Q0_D='0' & Q1_D='1' & Q2_D='0' & Q3_D='0' & Q4_D='0' ]: o




A State16:

[Q0_D='1' & Q1_D='1' & Q2_D='0' & Q3_D='0' & Q4_D='0' ] : s




A State17:

[Q0_D='0' & Q1_D='0' & Q2_D='1' & Q3_D='0' & Q4_D='0' ]: e




A State14:

[Q0_D='1' & Q1_D='0' & Q2_D='1' & Q3_D='0' & Q4_D='0'] :

Espacio


A State31:

[Q0_D='0' & Q1_D='1' & Q2_D='1' & Q3_D='0' & Q4_D='0'] : Caracter




En este estado introducimos la dirección DDRAM donde se creará en carácter
 “ 00000000 ”.

Desde State14, State15, State16, State17 y State18 pasaremos al State38 sin condición, como en el ejercicio anterior, dado que pertenecen al código ASCII.





Una vez hecho esto, la parte de “Jose “ ya está organizada y nos centraremos en el State31 que nos enviará hacia la creación del carácter.






Desde el State31 pasamos al State41 sin condiciones.

En este estado ponemos la salida del reloj a “ 1 ” para aumentar el contador de datos.

Pasamos al State44 sin condiciones.




En este estado habilitamos el LCD y lo ponemos en modo lectura.

Pasamos al State45 sin condiciones y permanecemos en el hasta que el LCD deje de estar ocupado.





Pasamos al State46 si :” D7_I='0' “



Desde el State46 a State47 si:
[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']



En el State48 ponemos el LCD en modo “registro” y vamos seleccionando cada una de las filas.


Con las mismas condiciones que hemos llegado al State48 vamos pasando a los estados correspondientes a cada fila, es decir, desde el State49 hasta el State56.

State49:

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

State50:

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

State51:

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

State52:

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

State53:

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

State54:

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

State55:

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

State56:

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

En estos estados habilitamos el LCD y comunicamos el puerto “D” del autómata con el del LCD poniendo ” THREE_STATE=’1’ “.
Direccionamos CGRAM en cada estado:
State49 à dirección 40 à 01000000
State50 à dirección 41 à 01000001
State51 à dirección 42 à 01000010
State52 à dirección 43 à 01000011
State53 à dirección 44 à 01000100
State54 à dirección 45 à 01000101
State55 à dirección 46 à 01000110
State56 à dirección 47 à 01000111

Una vez hecho esto, estos 8 estados pasaran al State65 sin condiciones.




En el State47 ponemos el LCD en modo “dato” y vamos pasando los códigos para formar nuestro carácter.


Ahora es el momento de decidir qué caracter vamos a crear, podemos ayudarnos de aplicaciones aunque se puede hacer fácilmente sin necesidad de utilizarlas.

En mi caso he hecho una especie de cara.



Los números binarios que aparecen son los valores que pondremos en “Dx_0”, por ejemplo “ 01010 “ será “ D1_O=’1’ ;D3_O=’1’; “.

Es altamente recomendable no repetir estados iguales por motivos de espacio, en este caracter concretamente hay 4  filas que son iguales .



Asique pasaremos 4 veces por el mismo estado y nos ahorramos 3 estados.



Del State47 :

A State57:
[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='0' & Q3_C='1' & Q4_C='0']
[Q0_C='0' & Q1_C='0' & Q2_C='0' & Q3_C='0' & Q4_C='1']


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


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


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


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




Desde estos 5 estados pasamos al State65 sin condiciones.


Desde el State65 pasamos al State42 sin condiciones.

Una vez estemos en el State42 deshabilitamos el LCD y pasamos al State41 hasta completar el carácter, después pasaremos al State43.

De State42:

A State41:
[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']
[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']




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



En este estado Habilitamos el LCD e introducimos el código de ‘dirección DDRAM’ ‘11000110’.

Desde el State43 pasamos al State39 con la siguiente condición:

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



Podemos reducir el número de transiciones entre el State39 y el State10 en comparación con el esquema del mensaje largo en el LCD dado que solo escribimos en 6 espacios del.



Del State39 al State10 si:
[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']


También podemos suprimir el State8 para ganar espacio dado que solo vamos a escribir en una linea.



Una vez hecho esto, todo lo demás de la máquina de estados podemos dejarlo como en el proyecto anterior.

Como no nos preocupa mucho la velocidad del CPLD, vamos a configurarlo por área para ganar espacio, lo haremos siguiendo estos pasos.



Ahora, para ver que no tiene fallos de diseño, vamos a “STATE BENCH” para hacer una simulación.




En este caso, debido al tamaño del esquema, vamos a hacer una simulación automática para comprobar si pasa por todos los estados.

Damos a “Automatic Testbench” y comprobamos que llega al 100% y no da errores.




Una vez hecho esto creamos el VHDL en “Generate HDL”.



Nos mostrará una ventana con estadísticas como las líneas de código, la memoria utilizada, el tiempo que ha tardado en compilar, estados, transiciones… y a continuación nos aparecerá el VHDL.




Una vez creado el VHDL podemos cerrar el entorno StateCAD.

En el diseño esquemático también podemos aprovechar muchas partes del proyecto anterior.

Es necesario añadir un nuevo contador CB8CE para controlar la creación del caracter y también cambiar el componente de la máquina de estados.

Copiamos la carpeta del proyecto anterior “Mensaje LCD Xilinx CPLD” en otro lugar para realizar las modificaciones necesarias  adaptándolo al caracter y así conservar el otro.

Abrimos el ISE de la copia de “Mensaje LCD Xilinx CPLD”.




Aquí tenemos el esquemático, el VHDL y el UCF con los pines.

Clicamos botón derecho del ratón en el esquemático y añadimos el nuevo VHDL que acabamos de crear.





Seleccionamos el nuevo VHDL y damos a “Create Schematic Symbol”.





Las diferencias entre la nueva máquina de estados y la anterior son muy pequeñas, solo cambiaran las conexiones para añadir el nuevo contador CB8CE.



Deshacemos la máquina de estados del esquema.


Añadimos el nuevo contador al esquema.




Introducimos el símbolo de la nueva máquina de estados.




En resumen, solo habremos modificado el símbolo de la máquina de estados y habremos añadido un contador.


Cerramos el esquemático y guardamos los cambios.
El archivo .UCF con los pines es idéntico asique mantenemos el anterior.


Terminamos creando el “ .JED “  en “Generate Programming File”.






Comprobación en tarjeta: