domingo, 31 de agosto de 2014

Microprocesador de 4 bits en FPGA con VHDL

El microprocesador hace parte del microcontrolador, el cual es practicamente un computador en un chip, pues dispone de microprocesador (CPU), sensores y actuadores. 

Las características principales del microprocesador son su UNIVERSALIDAD y su PROGRAMABILIDAD, lo que le dan el caracter de versatilidad, lo cual lo hace como el elemento inteligente o cerebro en diversas aplicaciones que van desde un computador personal hasta sistemas de encendido en vehículos, instrumentos electromedicos,etc,

La función de un microprocesador se define a través de un prograna, que consta de una serie de ordenes  o instrucciones relacionadas, ejecutadas secuencialmente (una a la vez) por el microprocesador y que pueden implicar operaciones lógicas o aritmeticas. Las instrucciones se especifican a través de  un código especial que constituye el lenguaje del microprocesador.  

Esencialmente un microprocesador en su Hardware o parte física es un circuito de alta escala de integración  conpuesto de circuitos mas sinples cono flip flops, contadores, registros, decodificadores, ALU,etc. Por otro lado los programas o software determinan el comportamiento del microprocesador adaptándolo a un campo especifico de aplicación.

Antes de estudiar la programacion y aplicacion de un microcontrolador conercial como el Atmel del Arduino, por fines didacticos es muy conveniente diseñar e inplementar un microprocesador de 4 bits en la FPGA Spartan de la tarjeta Digilent Basys 2. Esto permite un conocimiento nas profundo y detallado de las partes de un microprocesador y por consiguiente del microcontrolador comercial.

El diagrama en bloques del microprocesador se muestra a continuación:



A continuación se describen cada una de las partes que forman el microprocesador:

GENERADOR DE CICLO DE  MAQUINA (GCM). Este circuito es el que marca el paso del procesador; su función es sincronizar el sistema por medio de señales de control que van a todos los registros o sea al contador de programa para incrementarlo cuando se requiere, al registro de instrucciones, al registro de datos, al acumulador temporal y al acunulador principal. El GCM es alimentado por una señal de reloj proveniente de un oscilador de onda cuadrada. 




Por el momento vamos a considerar la GCM  como una caja negra con una entrada de reloj maestro proveniente del oscilador y cinco salidas de señal  A,B,C,D y E, desfasadas una respecto a la otra como se observa en el siguiente diagramas de tiempos.


Estas señales de control sincronizan la operación de cada uno de los registros en la forma siguiente:

- El contador del programa se incrementa en cada flanco de bajada de la señal E.

- El registro de instrucciones retiene la información proveniente de la memoria cuando la señal A pasa de 1 a   0.
 El registro de datos  retiene la información proveniente de la memoria cuando la señal B  pasa de 1 a   0

- El acumulador temporal guarda la función generada en la ALU cuando la señal C pasa de 1 a 0.

- El acumulador principal almacena la información que sale del acumulador temporal en el flanco de bajada     de la señal D.

El programa en VHDL del Generador de Ciclos de Máquinas GCM es el siguiente:

Se debe verificar que no hay error de sintaxis y que al sintetizarlo  funciona correctamente en la tarjeta Basys 2, antes de continuar.

Además del BLOQUE GCM que genera las señales de control del microporocesador otro bloque muy importante en el funcionamiento del microprocesador es la Unidad Aritmético Lógica ALU, cuyo programa en VHDL consideramos a continuación:


Luego se debe trabajar el CONTADOR DEL PROGRAMA.  En VHDL queda así:


Luego seguimos con la Memoria del Programa.  En nuestro caso de acuerdo a lo deseado como ejercicio de aplicación  para verificar en la tarjeta y teniendo en cuenta las funciones lógicas y aritméticas propias de la ALU podría ser como se muestra a continuación:


En la memoria, se toman las SALIDAS de la misma en parejas, o sea en una dirección va una INSTRUCCIÓN de la ALU y luego el DATO asociado a o la instrucción.
 Por ejemplo, cuando el Contador del PROGRAMA direcciona 0000 en la memoria, esta está grabada con 0000 en la salida, y luego al incrementar mediante la señal E el contador, la memoria señala 1100 en la salida.  En la dirección 0000 de acuerdo a la ALU se tiene la instrucción F <= B, lo cual se debe entender como cargar el acumulador con el Dato de 4 bits indicada en la dirección siguiente, o sea 1100. Se busca que en 8 periodos de reloj,llamado UN CICLO DE MÁQUINA,  se decodifique y ejecute la INSTRUCCIÓN: "CARGAR EL ACUMULADOR CON EL DATO INMEDIATO 1100".

Luego en las siguientes direcciones de memoria ( 2 y 3) la instrucción se refiere a "SUMAR LO QUE TIENE EL ACUMULADOR CON EL DATO INMEDIATO" que para este caso es el 2 en decimal. O sea se pide al microprocesador que efectúe la suma del 12 con el 2, y el acumulador guardará el 14, en las 2 instruccciones que ha ejecutado.
o
Sigue, en las direcciones 4 y 5, la instrucción "RESTAR DE LO QUE TIENE EL ACUMULADOR EL DATO INMEDIATO" que en este caso es el 5, luego el microprocesador debe hacer la Resta 14 - 5 = 9.

Luego, en las direcciones 6 y 7, la instrucción es :"EFECTUAR UNA OR ENTRE LO QUE TIENE EL ACUMULADOR Y EL DATO INMEDIATO" que en esta ocasión es el 3. La OR bit a bit entre el 9 y el 3 nos da ( 1001 OR  0011  = 1011), con lo que el Acumulador queda guardado con el 11.

En las direcciones 8 y 9 de la memoria, está pidiéndose al microprocesador "EFECTUAR UNA XOR ENTRE LO QUE TIENE EL ACUMULADOR CON EL DATO INMEDIATO", o sea el 5 en este caso. La XOR entre 1011 y 0101 da 1110, con lo cual el Acumulador queda almacenado con el 14 (1110).

En las direcciones 10 y 11, la instrucción "HACER UNA AND ENTRE ACUMULADOR Y DATO INMEDIATO" obliga al procesador a guardar el 10, al hacer la operación ( 1110 AND 1011 = 1010).

En las direcciones 12 y 13, la instrucción es "RESTAR DEL SIGUIENTE DATO INMEDIATO LO QUE HAY EN EL ACUMULADOR", o sea se efectúa la resta 15 - 10 = 5, por ser 1111 el dato que aparece en  la dirección 13, estando guardado el 1010 en el acumulador.

Finalmente en las direcciones de la memoria 14 y 15, se pide nuevamente sumar al acumulador el 3 como dato inmediato, lo cual hace que el acumulador en este caso quede guardado con el 8 = 5 + 3.

Como el contador está cíclico, mientras no se cambie el contenido de la memoria las anteriores operaciones aritmético lógicas se repetirán.

Una vez entendido completamente lo que se está diseñando se continúa con el REGISTRO DE INSTRUCCIONES, REGISTRO DE DATOS; ACUMULADOR TEMPORAL y el ACUMULADOR.

Sus programas en VHDL son idénticos.

Veamos,por ejemplo el del REGISTRO DE INSTRUCCIONES:


Una vez se tengan los programas en VHDL de cada uno de los bloques se procede a integrarlos a través del  PORT MAP, trabajando cada uno como componentes de un programa principal, y teniendo en cuenta las señales internas de interconexión, indicadas de COLOR ROJO, en el diagrama en Bloques del microprocesador:
Repetimos el Diagrama en Bloques para facilidad en su estudio.

El programa  final se indica a continuación:


Las salidas van a 4 LEDS de la tarjeta Digilent  Basys 2 para poder observar el comportamiento del microprocesador implementado en la FPGA Spartan 3E de acuerdo al Programa cargado en la memoria.

El microprocesador diseñado e implementado responde a la  arquitectura de von Neumann que es una familia de arquitecturas de computadoras que utilizan el mismo dispositivo de almacenamiento tanto para las instrucciones como para los datos (a diferencia de la arquitectura Harvard que utiliza dos memorias: una para las instrucciones y otra memoria para los datos).

La mayoría de las computadoras modernas están basadas en esta arquitectura, aunque pueden incluir otros dispositivos adicionales (por ejemplo, para gestionar las interrupciones de dispositivos externos como ratón, teclado, etcétera).
Las computadoras con esta arquitectura constan de cinco partes: La unidad aritmético-lógica (ALU), la unidad de control (UC), la memoria (RAM), un dispositivo de entrada/salida y el bus de datos que proporciona un medio de transporte de los datos entre las distintas partes.
Una computadora con esta arquitectura realiza o emula los siguientes pasos secuencialmente:
  1. Enciende la computadora y obtiene la siguiente instrucción desde la memoria en la dirección indicada por el contador de programa y la guarda en el registro de instrucción.
  2. Aumenta el contador de programa en la longitud de la instrucción para apuntar a la siguiente.
  3. Decodifica la instrucción mediante la unidad de control. Ésta se encarga de coordinar el resto de componentes del ordenador para realizar una función determinada.
  4. Se ejecuta la instrucción. Ésta puede cambiar el valor del contador del programa, permitiendo así operaciones repetitivas. El contador puede cambiar también cuando se cumpla una cierta condición aritmética, haciendo que el ordenador pueda 'tomar decisiones', que pueden alcanzar cualquier grado de complejidad, mediante la aritmética y lógica anteriores.
Para mas detalles el lector puede consultar el enlace:  http://es.wikipedia.org/wiki/Arquitectura_de_von_Neumann

Como ya se dijo en la arquitectura Harvard se hace uso de dos memorias, una para las instrucciones y otra para los datos,tal como se muestra en la gráfica siguiente:


Se  recomienda consultar: http://es.wikipedia.org/wiki/Arquitectura_Harvard    


ENSAMBLADORES Y PROGRAMACIÓN: 
Para escribir un programa que va a ser ejecutado por un microprocesador existen básicamente tres alternativas: lenguaje de máquina, lenguaje ensamblador de bajo nivel y lenguaje de alto nivel. Sólo los programas escritos en lenguaje de máquina pueden ser ejecutados directamente por el microprocesador. Los lenguajes escritos en ASSEMBLER o lenguaje ensamblador, o los de alto nivel como en C, C++,  tienen que ser traducidos primero a lenguaje de máquina a fin de que puedan ser ejecutados.

Un programa en lenguaje de máquina es simplemente una secuencia de instrucciones y datos en código binario, tal como el que utilizamos en nuestro microprocesador implementado:


Las desventajas del lenguaje de máquina son obvias: los programas son difíciles de leer, escribir, entender y corregir.

El lenguaje ASSEMBLER, utiliza mnemónicos para representar los códigos de operación de las instrucciones y símbolos alfanuméricos para representar las direcciones y datos del programa.

Por ejemplo LD A, ( 3 hex), significa cargar (Load)  el acumulador con el dato inmediato 0011.

Así mismo ADD A, (C hex), significa Sumar a lo que hay en el acumulador el dato inmediato 1100 = C hex, guardándose el resultado de la adición de los dos números en el acumulador.

Los lenguajes de alto nivel como el C o el  C++,  permiten la escritura del programa en una forma más relacionada con el algoritmo a ser aplicado, y no tanto con las características del microprocesador.  Generalmente cada instrucción en lenguaje de alto nivel equivale a varias instrucciones en ASSEMBLER.

Sin duda, el tiempo invertido en diseño y codificación de un programa en alto nivel es mucho menor, sin embargo requieren de un traductor que convierta las instrucciones de alto nivel en lenguaje de máquina. A este programa traductor se le conoce como COMPILADOR

Uno de los problemas de los compiladores es que requieren de mucha memoria y por consiguiente son más lentos que los ensambladores. Sin embargo cada día se abre camino la programación de los microcontroladores con lenguajes de alto nivel. Es el caso del Arduino.

ARDUINO: Arduino es una plataforma de hardware libre, basada en una placa con un microcontrolador y un entorno de desarrollo, diseñada para facilitar el uso de la electrónica en proyectos multidisciplinares.
El hardware consiste en una placa con un microcontrolador Atmel AVR y puertos de entrada/salida. Los microcontroladores más usados son el Atmega168, Atmega328, Atmega1280, ATmega8 por su sencillez y bajo costo que permiten el desarrollo de múltiples diseños. Por otro lado el software consiste en un entorno de desarrollo que implementa el lenguaje de programación Processing/Wiring y el cargador de arranque que es ejecutado en la placa.
Arduino se inició en el año 2005 como un proyecto para estudiantes en el Instituto IVREA, en Ivrea (Italia). En ese tiempo, los estudiantes usaban el microcontrolador BASIC Stamp, cuyo costo era de 100 dólares estadounidenses, lo que se consideraba demasiado costoso para ellos. Por aquella época, uno de los fundadores de Arduino, Massimo Banzi, daba clases en Ivrea.
El nombre del proyecto viene del nombre del Bar di Re Arduino (Bar del Rey Arduino) donde Massimo Banzi pasaba algunas horas. En su creación, contribuyó el estudiante colombiano Hernando Barragán, quien desarrolló la tarjeta electrónica Wiring, el lenguaje de programación y la plataforma de desarrollo. Una vez concluida dicha plataforma, los investigadores trabajaron para hacerlo más ligero, más económico y disponible para la comunidad de código abierto (hardware y código abierto). El instituto finalmente cerró sus puertas, así que los investigadores, entre ellos el español David Cuartielles, promovieron la idea. Banzi afirmaría años más tarde, que el proyecto nunca surgió como una idea de negocio, sino como una necesidad de subsistir ante el inminente cierre del Instituto de diseño Interactivo IVREA. Es decir, que al crear un producto de hardware abierto, éste no podría ser embargado.
Posteriormente, Google colaboró en el desarrollo del Kit Android ADK (Accesory Development Kit), una placa Arduino capaz de comunicarse directamente con teléfonos móviles inteligentes bajo el sistema operativo Android para que el teléfono controle luces, motores y sensores conectados de Arduino

jueves, 21 de agosto de 2014

Memoria EEPROM 28C64

En el estudio de la arquitectura del microprocesador es muy importante analizar el comportamiento de la memoria donde se guarda el programa que se va a ejecutar. Podemos hacer la analogía con el papel que desempeña la memoria dentro del cerebro del. ser humano.

Memoria EEPROM 2864

EEPROM o E²PROM son las siglas de Electrically Erasable Programmable Read Only Memory  (ROM programable y borrable eléctricamente). Es un tipo de memoria  que puede ser programada, borrada y reprogramada eléctricamente, a diferencia de la EPROM que ha de borrarse mediante luz ultravioleta. Son memorias no volátiles.
Aunque una EEPROM puede ser leída un número ilimitado de veces, sólo puede ser borrada y reprogramada miles de veces.
Una memoria EEPROM muy usada es la 28C64. ATMEL produce la AT28C64( AT quiere decir que ATMEL es el fabricante, 28 identifica el tipo de memoria, en este caso EEPROM; la C significa que la tecnología usada es C-MOS, o sea con base en transistores Mosfet canal P y canal N en modo complementario,  y el 64 es la capacidad: 64 Kilobits, o sea 8192 palabras de 8 bits cada una, lo que es lo mismo que 8 Kbytes)


Otra empresa que produce EEPROM es MICROCHIP, fabricante de la 28C64A, cuya configuración de pines es similar a la de ATMEL. La programación se realiza con el superpro Z, estableciendo las direcciones y los datos en Hexadecimal.

Internamente la memoria dispone de un DECODIFICADOR DE DIRECCIONES.
Para lograr las 8192 palabras se requiere de 13 entradas de dirección ( A0...A12: Addresses Inputs) ( 2 elevado a la 13 es igual a 8192).
El siguiente esquema muestra la arquitectura básica de una ROM con dos entradas de dirección y cuatro salidas, que nos permite comprender lo esencial en la programación:
La capacidad de esta pequeñísima memoria sería de solo 16 bits ( 4 palabras de 4 bits).
Vamos a suponer que en las 4 direcciones  deseamos programar 4 palabras así:
DIRECCION                  DATOS
A1        A0                   00000
 0           0                     1   0   1   0
 0           1                     0   1   0   1
 1           0                     0   1   1   1
 1           1                     1   1   1   1 


Al fijar A1 = 0, A0 = 0, en las salidas de las compuertas AND del decodificador se tiene:"0" = 1,
 "1" = 0,   "2" = 0,   "3" = 0. 
El primer fusible, situado a a la izquierda en cada compuerta OR, se "quema" si el dato a grabar es un CERO, y "no se quema" si el dato a grabar en esa dirección es un UNO.Para nuestro caso se queman los fusibles de las OR correspondientes a las salidas O2 y O0, y no se queman en las OR de las salidas O3 y O1.

Cuando se tiene A1 =0, A0= 1:  "0" = 0, "1" = 1,   "2" = 0,   "3" = 0.  En este caso, los fusibles de O3 y O1 se queman, y los de O2 y O0 no se queman (para que pueda pasar el UNO)

Cuando se tiene A1 =1, A0= 0: "0" = 0, "1" = 0,   "2" = 1,   "3" = 0.  En este caso, solo el  fusible de O3  se quema.

Por último, para A1 =1, A0= 1: "0" = 0, "1" = 0,   "2" = 0,   "3" = 1.  En este caso, ningún fusible se debe quemar.

El programa en hexadecimal que es el exigido por el programador es:

                             Dirección     Dato
                                 0                A
                                 1                5
                                 2                7
                                 3                F  

EJERCICIO DE APLICACIÓN:  Elaborar las tablas de multiplicar del 0 al 15.  Los números X y Y  se introducen en binario de 4 bits, y el resultado de la multiplicación se establece en BCD en Decenas y Unidades. Las Centenas se omiten. Utilizar dos decodificadores BCD a  7 Segmentos 74LS47  para visualizar el resultado de la multiplicación
en dos displays de 7 segmentos Ánodo común.

Ayuda:  Para elaborar las tablas hay que trabajar las DIRECCIONES y los DATOS.

Por ejemplo, veamos la multiplicación de  9 por 8 = 72, y   de  14    por   5 = 70

    A7     A6     A5     A4     A3     A2     A1    A0      I/O7    I7O6     I/O5    I/O4    I/O3     I/O2     I/O1    I/O0
    1       0        0       1       1        0       0      0         0         1            1        1        0         0          1         0
    1      1         1       0       0        1       0      1         0         1            1        1        0         0          0         0

Hay que convertir a Hexadecimal así:
     DIRECCiÖN DE LA MEMORIA                          DATO A  PROGRAMAR
                     9 8                                                              72
                     0E                                                              70
Los datos en Hexadecimal hay que escribirlos en la EEPROM 28C64 en las direcciones adecuadas para después poderlos leer. Es lo mismo que hacemos  con las hojas de un cuaderno.Tener seguridad en que número de hoja voy a escribir,  para luego en esa hoja buscar lo que deseo leer.
Para este propósito en el laboratorio de la UAN,Bogotá, disponemos de un programador Universal SUPERPRO Z.

Se debe una vez que el programador USB  sea reconocido  por el computador,  seleccionar dispositivos EEPROM,
el fabricante, por ejemplo ATMEL y  la referencia específica de la memoria, por ejemplo puede ser AT28C64B. Luego se
procede a elaborar el programa HEXADECIMAL  y  se da la orden de PROGRAMAR.

Hay que tener en cuenta que la EEPROM dispone de 13 entradas, de tal manera que las entradas A13,A12,A11,A10,
A9 y A8, fueron programadas con CEROS lógicos. Esto hace que cuando se va a leer, estan entradas deben estar
conectadas a TIERRA para que la Lectura sea correcta. Las entradas al aire en tecnología CMOS pueden ser leidas
como UNOS lógicos y esto presentaría error en la lectura.

El programador conecta el Chip Enable a tierra para habilitarlo, lo mismo que el Write Enable, y el Out Enable en
nivel ALTO para deshabilitarlo. El usuario debe para leer, debe habilitar el Chip Enable y el Out enable, y deshabilitar
el Write enable.