UNIVERSIDADE DE VIGO ESCOLA TÉCNICA SUPERIOR DE ENXEÑEIROS DE TELECOMUNICACIÓN PROYECTO FIN DE CARRERA DESARROLLO DE UN MICROPROCESADOR DIDÁCTICO MEDIANTE FPGAs Autor: Álvaro García Varela Tutor: Luis Jacobo Álvarez Ruiz de Ojeda Curso 2003/2004 EL TRIBUNAL NOMBRADO PARA EL PRESENTE PROYECTO DE FIN DE CARRERA, COMPUESTO POR: PRESIDENTE: VOCAL: SECRETARIO: ACUERDAN OTORGARLE LA CALIFICACIÓN DE: Vigo, a de de 2003 A miña filla Inés, para que a partir de agora, teñamos máis tempo para pintar “tríngulos” e ver “calículas”. Agradecimientos Terminan aquí, cuatro años de intensivo trabajo después de once años apartado del mundo universitario. Desde el momento en que tomé la decisión de volver a las aulas, varias han sido las personas que, de alguna manera, me han ayudado a la hora de alcanzar este objetivo a las cuales quiero manifestar mi agradecimiento. En principio, agradecer a mi amigo Javier Fariñas el haberme animado en su momento a matricularme. A la directora de la Biblioteca Universitaria de Santiago de Compostela, Mariví Pardo, por su sensibilidad, humanidad y comprensión a la hora de compatibilizar mi trabajo en este servicio con la obligaciones propias del estudio. A aquellos profesores, que sin renunciar a las exigencias propias de las asignaturas, han sabido entender mi situación laboral y me han facilitado las cosas. Dentro de este grupo quiero recordar especialmente a Áurea Martínez Varela, Antonio García Pino, Fernando Aguado Agelet , Fernando Pérez Fontán y a Jacobo Álvarez Ruíz de Ojeda. Tengo una especial deuda con José Lino Monteagudo Pereira, amigo desinteresado donde los haya, donde siempre he encontrado a alguien dispuesto a echar una mano en lo que hiciese falta. Hago extensivo este agradecimiento, a toda su familia que siempre se han preocupado por mi evolución como si fuese uno más de la familia. Finalmente, agradecer a mi mujer Sole y mi hija Inés todos estos años de renuncia. Resumen En este Proyecto Fin de Carrera, se aborda el estudio de la viabilidad del diseño e implementación de un procesador con fines didácticos, con el objeto de poder ser incluido como parte práctica de una asignatura de la especialidad de electrónica, dentro del currículum de un Ingeniero de Telecomunicaciones. Para ello, se han desarrollado todos los pasos que debería acometer el alumno desde su inicio, consistente en la definición del juego de instrucciones y arquitectura del procesador, hasta su consecución final con la implementación del mismo en un dispositivo programable del tipo FPGA1. El diseño del procesador se ha complementado con el desarrollo de dos herramientas software de apoyo. Palabras Clave: Microprocesador. Juego de instrucciones. Dispositivos programables FPGA Spartan-II. Ensamblador. Puerto paralelo. 1 FPGA: Field Programmable Gate Array “Computers in the future may weight no more than 1.5 tons” (Las computadoras del futuro puede que no pesen más de tonelada y media) Popular Mechanics, Marzo de 1949 “I think there is a world market for maybe five computers” (Pienso que la demanda mundial de ordenadores será de no más de 5 máquinas). Thomas Watson. CEO de IBM (1943) Índice General 1. Introducción ............................................................................................................... 1 1.1. Objetivo ................................................................................................................. 2 1.2. Estructura de la memoria ....................................................................................... 3 2. Fundamentos sobre Microprocesadores................................................................... 7 2.1. Perspectiva histórica .............................................................................................. 7 2.2. La arquitectura de Von Neumann .......................................................................... 9 2.3. Estructura básica de una CPU.............................................................................. 10 2.3.1. La Unidad de Control ............................................................................... 11 2.3.2. El registro de instrucción (IR) .................................................................. 12 2.3.3. La Unidad Aritmético Lógica (ALU) ....................................................... 13 2.3.4. El registro de estado (STATUS)............................................................... 14 2.3.5. La unidad de direccionamiento................................................................. 14 2.3.6. Registros auxiliares................................................................................... 15 2.4. La memoria .......................................................................................................... 16 2.5. Instrucciones ........................................................................................................ 16 2.5.1. Modos de direccionamiento...................................................................... 17 2.5.1.1. Direccionamiento implícito ......................................................... 18 2.5.1.2. Direccionamiento inmediato........................................................ 18 2.5.1.3. Direccionamiento directo............................................................. 18 2.5.1.4. Direccionamiento indirecto.......................................................... 18 2.5.1.5. Direccionamiento relativo............................................................ 18 I 2.5.1.6. Direccionamiento indexado..........................................................18 2.5.2. Clasificación de las instrucciones .............................................................19 2.6. Temporización de las instrucciones .....................................................................20 2.7. Interrupciones.......................................................................................................20 3. Introducción al diseño con dispositivos programables (FPGAs). .........................21 3.1. Introducción a los circuitos digitales configurables.............................................21 3.2. Fases en el diseño de circuitos con FPGAs..........................................................24 4. Desarrollo del microprocesador didáctico ERIC ...................................................27 4.1. Especificaciones generales ...................................................................................28 4.2. El juego de instrucciones......................................................................................28 4.2.1. Modos de direccionamiento ......................................................................29 4.2.2. Clasificación de las instrucciones .............................................................29 4.2.2.1. Transferencias de datos ................................................................30 4.2.2.2. Operaciones aritméticas ...............................................................30 4.2.2.3. Operaciones con banderas............................................................30 4.2.2.4. Operaciones lógicas......................................................................31 4.2.2.5. Flujo de programa ........................................................................31 4.2.3. Formato de las instrucciones .....................................................................32 4.3. Implementación física de Eric..............................................................................36 4.4. Estructura del microprocesador............................................................................38 4.4.1. Organización de la memoria .....................................................................40 4.4.2. El corazón del procesador .........................................................................43 4.4.2.1. El acumulador y el registro auxiliar B .........................................45 4.4.2.2. El registro de instrucción (IR)......................................................45 4.4.2.3. El registro de estado (STATUS) ..................................................45 4.4.2.4. El contador de programa (PC)......................................................46 4.4.2.5. El registro de direccionamiento de memoria (MAR)...................47 4.4.2.6. Multiplexores y bufferes triestado................................................49 4.4.2.7. La Unidad Aritmético Lógica (ALU)...........................................50 4.4.2.8. La Unidad de Control (UC)..........................................................53 II 4.4.2.8.1. Descripción de las señales .......................................... 55 4.4.2.8.2. El diagrama de estados ............................................... 57 4.4.2.8.3. El registro de gestión de interrupciones (IER)............ 60 4.4.2.8.4. El detector de flancos.................................................. 60 4.4.2.8.5. El generador de ciclos de espera................................. 62 4.4.2.9. El Sniffer...................................................................................... 65 4.4.3. El decodificador de 7 segmentos .............................................................. 68 4.5. ERIC y la XSA-50 ............................................................................................... 69 4.6. Ejecución de las instrucciones ............................................................................. 72 4.6.1. Temporización de las señales ................................................................... 72 4.6.2. Las interrupciones..................................................................................... 74 4.6.3. La ruta de datos......................................................................................... 74 4.6.3.1. Ejemplo: MOVX A,@B .............................................................. 75 4.6.3.2. Ejemplo: ACALL addr12 ............................................................ 78 5. Desarrollo del software de soporte .......................................................................... 83 5.1. EricMON ............................................................................................................. 83 5.1.1. Descripción general del programa ............................................................ 85 5.1.2. Modo LOAD............................................................................................. 86 5.1.3. Modo RUN ............................................................................................... 89 5.1.4. Modo STEP............................................................................................... 90 5.1.5. Implementación ........................................................................................ 92 5.1.5.1. El puerto paralelo en modo SPP .................................................. 93 5.1.5.2. Arquitectura software de las XSTOOLS ..................................... 94 5.1.5.3. La clase PPORT........................................................................... 96 5.1.5.4. La clase EricPORT ...................................................................... 97 5.1.5.5. La librería Console..................................................................... 100 5.1.6. Compatibilidad........................................................................................ 100 5.2. EricASM ............................................................................................................ 102 5.2.1. Descripción general del programa .......................................................... 103 5.2.2. Implementación ...................................................................................... 103 5.2.2.1. PARSER.Y ................................................................................ 105 III 5.2.2.2. SYMBOL.C................................................................................105 6. Prueba final..............................................................................................................107 6.1. Instalación de la prueba......................................................................................107 6.2. Conexión del LCD al ERIC ...............................................................................108 6.3. Ejecución de la prueba .......................................................................................109 7. Conclusiones y líneas futuras .................................................................................111 7.1. Conclusiones ......................................................................................................111 7.2. Líneas futuras .....................................................................................................115 8. Presupuesto ..............................................................................................................117 Referencias...................................................................................................................119 Contenido del CD ........................................................................................................121 A. Juego de instrucciones (ISA) del ERIC ................................................................123 A.1. Registros internos ..............................................................................................123 A.2. Memoria ............................................................................................................123 A.3. Modos de direccionamiento ..............................................................................124 A.4. Reset ..................................................................................................................124 A.5. Interrupciones....................................................................................................124 B. Microinstrucciones .................................................................................................137 C. Manual del monitor EricMON..............................................................................141 C.1. Requisitos previos..............................................................................................141 C.2. Instalación del software .....................................................................................142 C.3. Ejecución de la aplicación .................................................................................142 C.3.1. Modo LOAD...........................................................................................143 C.3.2. Modo RUN .............................................................................................145 IV C.3.3. Modo STEP............................................................................................ 146 D. Manual del ensamblador EricASM...................................................................... 147 D.1. Comando ........................................................................................................... 147 D.2. Opciones del comando ...................................................................................... 147 D.3. Instrucciones ..................................................................................................... 149 D.4. Directivas .......................................................................................................... 149 D.5. Sintaxis del lenguaje ......................................................................................... 150 D.5.1. Generalidades......................................................................................... 150 D.5.2. Comentarios ........................................................................................... 150 D.5.3. Números................................................................................................. 150 D.5.4. Cadena de caracteres.............................................................................. 151 D.5.5. Símbolos ................................................................................................ 151 D.5.6. Expresiones ............................................................................................ 151 D.6. Ejemplo de un fichero fuente ............................................................................ 152 E. El entorno de desarrollo ISE WebPACK............................................................. 153 E.1. Descripción HDL o esquemáticos ..................................................................... 155 E.2. Síntesis............................................................................................................... 156 E.3. Posicionamiento y enrutado .............................................................................. 156 E.4. Simulación......................................................................................................... 156 E.5. Generación del bitstream y programación......................................................... 157 E.6. Tabla de prestaciones ........................................................................................ 158 F. La tarjeta de desarrollo XSA-50. .......................................................................... 159 F.1. Descripción de la tarjeta .................................................................................... 160 F.1.1. Los dispositivos programables: .............................................................. 160 F.1.2. El reloj programable ............................................................................... 161 F.1.3. La RAM dinámica .................................................................................. 161 F.2. La RAM FLASH ............................................................................................... 162 F.2.1. El visualizador de 7 segmentos .............................................................. 162 F.3. Puerto VGA y PS2............................................................................................. 163 V F.3.1. Banco de interruptores DIP y pulsador ...................................................163 F.3.2. El puerto paralelo ....................................................................................164 F.4. Las utilidades XSTOOLS ..................................................................................166 F.4.1. GXSTEST (XSTEST).............................................................................166 F.4.2. GXSSETCLK (XSSETCLK)..................................................................166 F.4.3. GXLOAD(XSLOAD).............................................................................167 F.4.4. GXPORT(XSPORT)...............................................................................167 F.5. Listado de conexiones ........................................................................................168 G. FPGAs de la familia SPARTAN II DE XILINX. ................................................171 G.1. Arquitectura.......................................................................................................172 G.2. Bloques de entrada/salida (IOBs)......................................................................173 G.3. Bloques lógicos configurables (CLBs)..............................................................173 G.3.1. Tablas de consulta LUT (Look-Up Table) .............................................174 G.3.2. Lógica de acarreo (Carry Logic) ............................................................175 G.3.3. Amplificadores (BUFTs)........................................................................175 G.3.4. Lógica adicional .....................................................................................175 G.4. Bloques de memoria (BRAM) ..........................................................................175 G.5. Matriz de interconexión programable ...............................................................176 G.6. Caminos de interconexión local ........................................................................176 G.6.1. Caminos de interconexión de propósito general ....................................177 G.6.2. Caminos de interconexión globales........................................................178 G.7. DLL (Delay-Locked Loop) ...............................................................................178 G.8. Exploración periférica (boundary scan) ............................................................178 H. LCD PowerTIP 1602-H. ........................................................................................179 I. Intregración del proyecto en un IDE. ....................................................................181 J. Listados y esquemas ................................................................................................185 VI Índice de Figuras Figura 1: Computador elemental según Von Neumann.................................................... 9 Figura 2: Diagrama de bloques genérico de una CPU.................................................... 10 Figura 3: Informaciones de entrada de la Unidad de Control......................................... 11 Figura 4: La Unidad Aritmético Lógica (ALU).............................................................. 13 Figura 5: Estructura matricial de una FPGA de Xilinx .................................................. 23 Figura 6: Fases del diseño de un circuito mediante FPGAs ........................................... 25 Figura 7: Fases de desarrollo del entorno WebPACK de Xilinx.................................... 26 Figura 8: Estructura de campos del primer byte de una instrucción............................... 32 Figura 9: Tarjeta XSA-50 de la casa XESS utilizada en este proyecto .......................... 37 Figura 10: Tarjeta D2XL de la casa DIGILENT también probada en este proyecto ..... 37 Figura 11: Diagrama principal de bloques del ERIC (TOP.SCH).................................. 39 Figura 12: Esquema de la memoria del ERIC según el modelo de FPGA ..................... 41 Figura 13: Primitiva RAMB4_S8 utilizada como base de los módulos de memoria ..... 42 Figura 14: Esquema de bloques del corazón del procesador (CPU_CORE.SCH) ......... 44 Figura 15: El acumulador ............................................................................................... 45 Figura 16: El contador de programa ............................................................................... 46 Figura 17: El registro de direccionamiento de memoria................................................. 47 Figura 18: Relación de MAR con otros bloques del circuito ......................................... 48 Figura 19: Multiplexor tipo MUX2_8Z.......................................................................... 49 Figura 20: Unidad Aritmético Lógica............................................................................. 50 Figura 21: Diagrama de una máquina de estados tipo Mealy......................................... 53 Figura 22: La Unidad de Control del ERIC.................................................................... 54 I Figura 23: Diagrama de estados de la Unidad de Control...............................................59 Figura 24: Registro de gestión de interrupciones............................................................60 Figura 25: Estructura interna de la Unidad de Control (CONTROL_UNIT.SCH) ........61 Figura 26: Subunidades del bloque de estados de espera (WAIT_STATES.SCH) ........63 Figura 27: Cronograma del generador de ciclos de espera asociado a la ROM..............64 Figura 28: Bloque SNIFFER...........................................................................................65 Figura 29: Decodificador binario a 7 segmentos ............................................................68 Figura 30: Adaptación de las señales del ERIC a la tarjeta XSA-50 ..............................71 Figura 31: Fase FETCH de la instrucción MOVX A,@B ..............................................76 Figura 32: Fase DECODE de la instrucción MOVX A,@B...........................................76 Figura 33: Fase EXECUTE de la instrucción MOVX A,@B.........................................77 Figura 34: Fase STORE de la instrucción MOVX A,@B ..............................................77 Figura 35: Fase FETCH de la instrucción ACALL addr12 ............................................80 Figura 36: Fase DECODE de la instrucción ACALL addr12.........................................80 Figura 37: Fase EXECUTE de la instrucción ACALL addr12.......................................81 Figura 38: Fase SUBR1 de la instrucción ACALL addr12.............................................81 Figura 39: Fase SUBR2 de la instrucción ACALL addr12.............................................82 Figura 40: Fase SUBR3 de la instrucción ACALL addr12.............................................82 Figura 41: Proceso a seguir desde el fichero fuente a la carga en el ERIC.....................87 Figura 42: Ejemplo de una sesión en modo LOAD ........................................................88 Figura 43: Ejemplo de una sesión en modo STEP ..........................................................91 Figura.44: Vista general del entorno de programación Visual C++ ...............................94 Figura.45: Esquema jerárquico de los objetos de las utilidadaes XSTOOLS.................95 Figura 46: Ventana en MS-DOS para invocar el programa EricMON .........................142 Figura 47: Menu principal del programa EricMON......................................................143 Figura 48: Submenú del modo LOAD del programa EricMON...................................143 Figura 49: EricMON mostrando un mensaje de error en modo LOAD........................144 Figura 50: Volcado de datos en memoria en el modo LOAD del programa EricMON144 Figura 51: Submenú del modo RUN del programa EricMON......................................145 Figura 52: Submenú del modo STEP del programa EricMON.....................................146 Figura 53: Ejemplo de un fichero fuente para el ensamblador EricASM .....................152 Figura 54: Ventana del Project Manager del entorno WebPACK ................................153 II Figura 55: Esquema organizativo del entorno WebPACK ........................................... 154 Figura 56: Ventanas del simulador ModelSIM de la casa Mentor ............................... 157 Figura 57: Tarjeta XSA-50 de Xess.............................................................................. 159 Figura 58: Esquema general de la tarjeta XSA-50 ....................................................... 160 Figura 59: Conexión de la FPGA y la DRAM enana XSA-50..................................... 161 Figura 60: Conexión entre la FPGA, el CPLD y la FLASH en la XSA-50.................. 162 Figura 61: Detalles de las conexiones VGA y PS2 de la XSA-50 ............................... 163 Figura 62: Detalles de la conexión del la XSA-50 con el puerto paralelo.................... 165 Figura 63: Conexionado entre el puerto paralelo y distintas partes de la XSA-50....... 165 Figura 64: Ventana de dialogo de GXSTEST .............................................................. 166 Figura 65: Ventana de diálogo de GXSSETCLK......................................................... 166 Figura 66: Ventana de diálogo de GXLOAD ............................................................... 167 Figura 67: Ventana de diálogo de GXPORT ................................................................ 167 Figura 68: Esquema interno de una FPGA de la familia Spartan-II............................. 172 Figura 69: Diagrama de bloques de los IOBs de una FPGA Spartan-II ....................... 173 Figura 70: Diagrama de bloques de un SLICE de una Spartan-II ................................ 174 Figura 71: Tamaño de los bloques RAM según el modelo de Spartan-II..................... 175 Figura 72: Enrutado local de una Spartan-II................................................................. 176 Figura 73: Líneas de interconexión de propósito general en una Spartan-II ................ 177 Figura 74: Vistas anterior y posterior del LCD PowerTIP 1602 .................................. 179 Figura 75: Características mecánicas y diagrama de bloques del LCD-1602H ........... 180 Figura 76: Vista general del editor ConTEXT utilizado como IDE ............................. 181 Figura 77: Ejemplo de configuración de F9 para que ejecute EricASM ...................... 182 Figura 78: Ejemplo de configuración de F10 para que ejecute EricMON ................... 183 Figura 79: Ejemplo de configuración de F11 para que ejecute el XSLOAD ............... 184 III Índice de Tablas Tabla 1: Instrucciones de transferencia de datos ............................................................ 30 Tabla 2: Instrucciones aritméticas .................................................................................. 30 Tabla 3: Instrucciones de manipulación de banderas ..................................................... 30 Tabla 4: Instrucciones lógicas......................................................................................... 31 Tabla 5: Instrucciones de control de flujo de programa ................................................. 31 Tabla 6: Formato de los campos según el tipo de instrucción ........................................ 34 Tabla 7: Mapa de distribución de las instrucciones del ERIC........................................ 35 Tabla 8: Bloques BRAM disponibles según el modelo de FPGA.................................. 40 Tabla 9: Configuraciones posibles de un bloque BRAM de una Spartan-II .................. 40 Tabla 10: Tabla de operaciones de la ALU .................................................................... 51 Tabla 11: Asignación de registros a la entrada del multiplexor del SNIFFER............... 67 Tabla 12: Códigos visualizados en función del estado de la UC.................................... 68 Tabla 13: Asignación de las señales del ERIC a lo terminales (pines) de la XSA-50.... 69 Tabla 14: Descripción del vector de señales (SV).......................................................... 73 Tabla 15: Resumen de los pasos necesarios para ejecutar MOVX A,@B ..................... 75 Tabla 16: Resumen de los pasos necesarios para ejecutar ACALL addr12 ................... 79 Tabla 17: Descripción de las señales del puerto paralelo y su relación con ERIC......... 93 Tabla 18: Conexiones entre el LCD y la XSA-50 ........................................................ 108 Tabla 19: Resumen del juego de instrucciones del ERIC............................................. 125 Tabla 20: Microinstrucciones de las instrucciones del tipo MOV................................ 137 Tabla 21: Microinstrucciones de las instrucciones del tipo MIX ................................. 138 Tabla 22: Microinstrucciones de las instrucciones de carga e interrupción ................. 138 I Tabla 23: Microinstrucciones de las instrucciones del tipo ALU .................................139 Tabla 24: Microinstrucciones de las instrucciones del tipo JMP ..................................140 Tabla 25: Prestaciones de los distintos productos software de Xilinx ..........................158 Tabla 26: Listado de las conexiones de la tarjeta XSA-50 ...........................................169 Tabla 27: Tipos de dispositivos de la familia Spartan-II ..............................................171 Tabla 28: Configuraciones posibles de los bloques RAM ............................................176 II Capítulo 1 Introducción Tradicionalmente, los planes de estudio de carreras técnicas han abarcado el estudio de los fundamentos de la computación desde dos puntos de vista bien diferenciados y complementarios. Un punto de vista teórico, donde se realiza el estudio genérico de un procesador particularizado posteriormente en el estudio de un microprocesador comercial. Otro punto de vista más práctico, consistente en la realización de programas en ensamblador que posteriormente son probados, simulados y depurados sobre alguno de los procesadores estudiados en la fase teórica. Habitualmente, los profesores evidencian en los alumnos una desconexión entre los conceptos sobre arquitectura, estudiados en la fase teórica, y el funcionamiento de los programas que se prueban en el laboratorio. Para superar esta limitación, en algunos centros de enseñanza, es común observar prácticas orientadas a que el alumno diseñe su propio procesador, simulando su comportamiento a partir de lenguajes de alto nivel. No obstante, para los docentes afines al área de la electrónica, la opinión es que estas prácticas no resuelven la laguna formativa, convirtiéndose al final en un estudio casi teórico de arquitecturas. Por este motivo, el presente proyecto propone como solución, el diseño e implementación de un procesador por parte del alumno, basado en el uso de dispositivos programables tipo FPGAs. 1 2 Introducción 1.1. Objetivo El objetivo principal de este proyecto, ha sido el analizar la viabilidad de introducir esta tarea como parte práctica de una asignatura de la especialidad de electrónica dentro del currículum de un Ingeniero de Telecomunicaciones. Para ello, se han llevado a cabo todos aquellos pasos que debería realizar el alumno, desde la definición del juego de instrucciones, pasando por el diseño del procesador y su posterior implementación en un dispositivo programable tipo FPGA, mediante el uso de las herramientas CAD adecuadas. De este modo, se han podido obtener conclusiones sobre la dificultad de cada uno de los pasos, y generar de paso material y documentación útil para la labor formativa del personal docente. La labor desarrollada en este proyecto, ha dado lugar al desarrollo de un procesador con fines didácticos que hemos querido bautizar con el nombre de ERIC (Educational Reduced Instruction set Computer), resultado de la combinación de dos conceptos manejados a lo largo del libro: procesador educativo y juego reducido de instrucciones. A los objetivos anteriores se le han añadido otros, no contemplados inicialmente en el anteproyecto, orientados a facilitar el diseño y la explotación del ERIC por parte del alumno. Estas contribuciones han consistido en la realización de dos aplicaciones: un programa monitor denominado EricMON y un programa ensamblador denominado EricASM. Introducción 1.2. 3 Estructura de la memoria La estructura de la presente memoria está formada por siete capítulos y diez apéndices, cuyo contenido se describe a continuación. Capítulo 1: Introducción. En este capítulo, se realiza una descripción general sobre los objetivos perseguidos con la realización de este Proyecto Fin de Carrera. Capítulo 2: Fundamentos sobre microprocesadores. En este capítulo, se hace un recorrido sobre las bases teóricas que fundamentan los procesadores, describiendo los elementos más relevantes de un microprocesador. Capítulo 3: Introducción al diseño con dispositivos programables (FPGAs). En este capítulo, se hace una breve introducción a los dispositivos programables, centrando la descripción en la estructura interna de las FPGAs. También se describe la metodología de trabajo utilizada en el desarrollo de proyectos basados en este tipo de dispositivos. Capítulo 4: Desarrollo del microprocesador didáctico ERIC. Es el capítulo fundamental de la obra, donde se describe cada uno de los elementos que componen el ERIC. Partiendo de unas especificaciones de inicio y un juego de instrucciones, se va diseñando paso a paso cada uno de los elementos que componen el microprocesador, explicando en cada caso las decisiones adoptadas. Se hace un especial énfasis, en describir las operaciones llevadas a cabo por la CPU en la ejecución de las instrucciones. Capítulo 5: Desarrollo del software de soporte. Este capítulo, describe la motivación que ha conducido al desarrollo de los dos programas de soporte al ERIC. Se explica detalladamente las distintas clases y métodos que sustentan el EricMON. También se describen las partes que conforman el ensamblador EricASM, explicando las labores acometidas en la adaptación del programa a partir del AS31. Capítulo 6: Prueba final. El diseño e implementación del ERIC, concluye con la ejecución de una prueba para comprobar el correcto funcionamiento del sistema. Este capítulo describe los pasos a seguir para acometer dicha prueba. 4 Introducción Capítulo 7: Conclusiones y líneas futuras. En este capítulo se hace una valoración sobre lo conseguido en el presente proyecto. Se analizan los puntos de especial dificultad que puede dificultar su implantación como asignatura. Se proponen soluciones y alternativas para acometer dicha implantación. Capítulo 8: Presupuesto. Este último capítulo, recoge los costes de material y mano de obra de ingeniería invertidos en el desarrollo del presente proyecto. Antes de iniciar la descripción de los apéndices, comentar que se ha dado una especial relevancia a esta parte de la memoria con el objeto de facilitar el desglose de información que, según criterio del profesor, sea preciso proporcionar al alumno para acometer la tarea de desarrollar el procesador. Apéndice A: Juego de instrucciones (ISA) del ERIC. En este apéndice, se hace una descripción detallada de todas las instrucciones soportadas por el ERIC. Apéndice B: Microinstrucciones. Resumen de cada una de las etapas en que se ha divido la ejecución de cada instrucción, así como las señales de control implicadas. Apéndice C: Manual del monitor EricMON. En esta parte, se describen las prestaciones del monitor así como el modo de utilización. Apéndice D: Manual del ensamblador EricASM. Describe las prestaciones del ensamblador así como el modo de usarlo. Apéndice E: El entorno de desarrollo ISE WebPACK. En este apéndice se describe, de una manera muy general, las prestaciones del entorno de trabajo proporcionado por Xilinx, para el desarrollo de diseños basados en dispositivos programables de esta firma. Apéndice F: La tarjeta de desarrollo XSA-50. Este apéndice describe, cada una de las partes que constituyen la tarjeta de desarrollo utilizada en este proyecto. Apéndice G: FPGAs de la familia SPARTAN II de Xilinx. Describe los recursos hardware más relevantes, que proporciona el uso de las FPGAS de la familia Spartan-II. Introducción 5 Apéndice H: LCD Powertip 1602.-H. Describe aspectos mecánicos y físicos del visualizador LCD utilizado en la fase de prueba del sistema. Apéndice I: Integración del proyecto en un IDE. Tanto el procesador, como las aplicaciones software, pueden ser ejecutadas desde un entorno de desarrollo integrado aprovechando la funcionalidad de editores gratuitos. Este apéndice explica como configurar uno. Apéndice L: Listados y esquemas. Este apéndice, recoge todos listados VHDL del diseño así como los esquemas realizados en el entorno WebPACK. Capítulo 2 Fundamentos sobre Microprocesadores 2.1. Perspectiva histórica La idea de un sistema de procesamiento de información, que sea reconfigurable a través de un programa guardado en alguna forma de memoria, es muy antigua, remontándonos a principios del siglo XIX. Charles Babbage [1791-1871] fue quien proyectó el primer computador mecánico, capaz de ejecutar secuencias de operaciones automáticamente, conocido como máquina diferencial. La complejidad de los elementos mecánicos necesarios para su funcionamiento, imposibilitó su construcción dada las limitaciones tecnológicas de la época. Con el nacimiento de la electrónica se volvieron a realizar intentos en la construcción de computadores. En 1941, se inicia la construcción del ENIAC (Electronica Numeral Integrator and Computer) el primer computador funcional de la historia. Esta máquina tenía alrededor de 19.000 válvulas y fue construida por la Escuela de Ingeniería Eléctrica de Moore. Fue puesta en funcionamiento en el año 1945 y se retiró en 1955. Su principal inconveniente, era que debía ser programado manualmente accionando una serie de interruptores, conectando y desconectando cables. En 1945 el matemático húngaro-americano John Von Neumann2 [1903-1957], que ya había formado parte del equipo de desarrollo del ENIAC, publicó un artículo First Draft of a Report on the EDVAC que sentó los principios de construcción de los 2 También conocido porque participó en el diseño de la bomba atómica y de la bomba de hidrogeno. 7 8 Fundamentos sobre Microprocesadores computadores, a pesar de que el EDVAC no llegó a construirse nunca. Dentro de estas ideas, que hoy conocemos como arquitectura de Von Newmann, estaba la de utilizar un programa almacenado en memoria. Tras el ENIAC, vendrían otros computadores basados en válvulas de vacío conocidos como ordenadores de primera generación, caracterizados por su elevado tamaño y baja fiabilidad. La aparición de los transistores en 1947, daría lugar a la segunda generación, subsanando parcialmente los problemas de tamaño, introduciendo el uso de discos magnéticos para guardar la información y memoria basadas en ferritas. La tercera generación, se iniciaría con el advenimiento de los circuitos integrados en 1961, permitiendo con ello una gran reducción de tamaño y un aumento en la complejidad de los computadores. La aparición de los circuitos integrados de gran escala de integración (VLSI), permitió el diseño de un procesador en un solo chip que daría lugar al nacimiento de los microprocesadores. El 4004 de Intel (1971) fue el primer dispositivo de este tipo. Este logro, permitió seguir reduciendo el tamaño y bajar los costes, consiguiendo de este modo una mayor difusión del microprocesador impensable hasta el momento. Desde entonces, los microprocesadores no han dejado de evolucionar, mejorando sus prestaciones según lo han hecho el número de transistores disponibles (Ley de Moore3) En la actualidad, gracias a gran cantidad lógica y a la capacidad de configuración de los circuitos programables del tipo FPGA, cualquier diseñador con cierta experiencia puede realizar su propio procesador. 3 En un chip, la densidad de transistores se duplica cada 18 meses. La arquitectura de Von Neumann 2.2. 9 La arquitectura de Von Neumann Como ya comentamos con anterioridad, Von Neumann desarrolló una arquitectura sobre la estructura interna de un computador que, aún hoy es la base en la que se asientan la mayoría de los procesadores actuales. Esta arquitectura, se caracteriza por una división funcional en bloques tal como se muestra en la siguiente figura: CPU ALU MÓDULO DE E/S MEMORIA UNIDAD DE CONTROL Figura 1: Computador elemental según Von Neumann Los elementos esenciales son la memoria y el procesador. La memoria, es el lugar de almacenamiento donde se guardan instrucciones y los datos de los programas. El procesador, es un intérprete de un juego de instrucciones cuya finalidad es: Extraer la instrucción de memoria y decodificarla. Ejecutar la instrucción. Localizar la siguiente instrucción y volver al primer paso. Este proceso continúa de manera recurrente y de esta forma, el ordenador puede ejecutar cualquier tipo de programa por grande que sea su complejidad. Veamos a continuación, una descripción más detallada de cada uno de estos bloques y su configuración interna. 10 2.3. Fundamentos sobre Microprocesadores Estructura básica de una CPU B U S SEÑALES DE CONTROL REGISTRO B ACUMULADOR ALU REGISTROS AUXILIARES CONTADOR DE PROGRAMA UNIDAD DE DIRECCIONAMIENTO D E D A T O S UNIDAD DE CONTROL REGISTRO DE REGISTRO DE STATUS INSTRUCCIÓN I N T E R N O BUFFER DEL BUS DE DATOS BUS DE DIRECCIONES BUS DE DATOS RELOJ RESET Figura 2: Diagrama de bloques genérico de una CPU BUS DE CONTROL Estructura básica de una CPU 2.3.1. 11 La Unidad de Control El bloque que gobierna y coordina todas las operaciones, que tienen lugar dentro de la CPU, es la Unidad de Control (UC). Se trata, de un circuito secuencial que genera las microinstrucciones que recibirán los elementos operativos como la ALU, registros, etc. Órdenes tales como, que un registro almacene un dato o lo entregue al bus, que un registro se incremente, decremente, que la ALU ejecute una función determinada de su repertorio, todas ellas proceden de la UC. Para que la Unidad de Control pueda desempeñar su función, necesita disponer de dos informaciones de distinta procedencia: La INSTRUCCIÓN, procedente del exterior de la CPU. El STATUS, procedente del interior de la CPU. INSTRUCCIÓN UNIDAD DE MICRO-ÓRDENES CONTROL STATUS RELOJ Figura 3: Informaciones de entrada de la Unidad de Control La instrucción es un valor binario que indica a la CPU la función que debe realizar. La Unidad de Control, interpreta el significado de la instrucción y la descompone en operaciones elementales (microinstrucciones), de tal modo que, los elementos internos de la CPU puedan llevar a cabo la tarea encomendada. Por otro lado, la acción de la unidad de control está condicionada por la historia anterior de la CPU, reflejada en los bits del registro de estado (STATUS), que indicarán 12 Fundamentos sobre Microprocesadores que las operaciones previas han dado como resultado un valor nulo, con acarreo, desbordamiento, etc. En función de esta información, el controlador puede generar microinstrucciones diferentes para una misma instrucción. La Unidad de Control es un circuito síncrono, es decir, que todos sus cambios vienen marcados por un reloj externo utilizado para coordinar el funcionamiento interno del sistema. Cada salida de la Unidad de Control, genera una microinstrucción específica destinada a actuar sobre un elemento de la CPU. Por ejemplo, una de estas señales da lugar a que un dato se escriba en un registro determinado, otra señal activa la salida de un registro cuyo contenido se vuelca en un bus interno, otras indican a la ALU que debe realizar una suma, etc. 2.3.2. El registro de instrucción (IR) La CPU es capaz de ejecutar un número finito de acciones que le vienen señaladas desde la memoria de programa, mediante una combinación binaria que se denomina instrucción. Una instrucción es, por lo tanto, un conjunto de unos y ceros que indicará a la CPU cuál es la operación que debe realizar. La UC es la encargada de desgranar el significado de la instrucción y generar las correspondientes microinstrucciones. Para llevar a cabo esta tarea, la instrucción extraída de la memoria deberá almacenarse momentáneamente durante el tiempo que invierta la UC en ejecutar las microinstrucciones. Esto proceso, se realiza con la ayuda de un registro conocido como registro de instrucción (IR). Dicho registro, tendrá tantos bits como la longitud de palabra del microprocesador. La forma en que la instrucción es extraída de la memoria, no es diferente de cualquier otro proceso de lectura, sin embargo, la CPU debe discernir de algún modo que esta información leída es precisamente una instrucción y no otro dato cualquiera. Por otro lado, dicha instrucción es una combinación binaria que en nada se diferencia de cualquier otra información contenida en memoria. El único hecho diferencial, que permite que esa palabra binaria sea llevada al registro de instrucción, es precisamente que en ese instante la CPU espera una instrucción y no, otro tipo de dato. Estructura básica de una CPU 2.3.3. 13 La Unidad Aritmético Lógica (ALU) Es habitualmente, un circuito combinacional capaz de realizar ciertas operaciones de tipo lógico o de tipo aritmético entre dos operandos, generando un resultado que se almacena en un registro denominado acumulador. Para ello, es preciso que cada uno de los operandos esté situado en la entrada correspondiente de la ALU. Estas variables de entrada determinarán la salida de la ALU de acuerdo con las tablas de verdad a las que responde. Las entradas de control determinarán la operación a realizar. Por ejemplo, 3 líneas de control permiten definir 8 operaciones diferentes que podrían ser: AND, OR, XOR, NOT, NAND, suma binaria y resta binaria. El acumulador, es un registro de carga y salida en paralelo que, recoge el resultado de la operación de la ALU. La orden de memorización del resultado, en el registro acumulador, procede de la UC y deberá llegar después de que los operandos hayan sido memorizados en sus respectivos registros y con el tiempo suficiente de retraso, para que la salida de la ALU haya alcanzado su valor estable. B U S D E ACUMULADOR REGISTRO B STATUS D A T O S CTRL ALU Figura 4: La Unidad Aritmético Lógica (ALU) I N T E R N O 14 Fundamentos sobre Microprocesadores La estructura habitual de una ALU incluye el uso de tres registros: dos registros de operando y un registro acumulador. No obstante, la mayoría de los fabricantes optan por suprimir uno de los registros de operando sustituyéndolo por el propio acumulador, tal como puede verse en la figura anterior. De esta forma, el acumulador cumple dos cometidos: antes de la operación almacena un operando y después almacena el resultado. La ALU, aparte de llevar a cabo operaciones lógico-aritméticas, suele actualizar el estado de los bits de estado en función del resultado de la operación, pudiendo utilizarse esta información en operaciones posteriores. 2.3.4. El registro de estado (STATUS) El registro de estado, también llamado registro de códigos de condición, está formado por un conjunto de biestables independientes, denominados comúnmente como banderas (flags). Cada uno de ellos, está destinado a memorizar un determinado suceso que ha tenido lugar dentro de la CPU. Los sucesos que suelen estar señalados mediante banderas son habitualmente los siguientes: El resultado de una operación ha sido nulo (Zero o Z). El resultado de una operación ha generado acarreo (Carry o C). El resultado de una operación desborda la capacidad de un registro (Overflow o OV). El estado de las banderas, es consultado por la UC y condicionará su modo de funcionamiento en el desarrollo de algunas instrucciones, normalmente los saltos condicionados. 2.3.5. La unidad de direccionamiento Para poder acceder, tanto a las instrucciones como a los datos, la CPU a de tener capacidad de direccionamiento de la memoria. Con esta finalidad, la CPU dispone tanto de un bus de datos como de un bus de direcciones. El número de líneas de estos Estructura básica de una CPU 15 buses, definen la capacidad máxima de memoria soportada, así como, la longitud de la instrucción que va a manejar el computador. Cuando la CPU se dirige a la memoria, para encontrar instrucciones del programa que está ejecutando, suele hacerlo en posiciones consecutivas. En este caso, el circuito interno de la CPU que se encarga de presentar su contenido en el bus de direcciones, es el llamado contador de programa (PC). El número de bits de este registro síncrono, está en relación con el tamaño del bus de direcciones. Pero el programa, no siempre se ejecuta de forma estrictamente consecutiva, sino que pueden producirse saltos o rupturas de secuencia, lecturas o escrituras de datos en posiciones de memoria completamente aleatorias, saltos a posiciones relativas al contenido del PC, etc. Para ello, la CPU debe disponer de capacidades adicionales de direccionamiento, que le permitan llevar a cabo estas tareas, que se traducen en operaciones como el cambio del contenido del PC, calcular direcciones relativas a la actual, guardar o cargar una dirección a partir de los datos procedentes del bus de datos, etc. Normalmente, toda esta funcionalidad no es posible con la ayuda de un único registro, por lo que se hace necesaria la ayuda de registros auxiliares (MAR), sumadores, multiplexores, etc. 2.3.6. Registros auxiliares Para la ejecución de determinadas instrucciones, a veces, se hace necesario el uso de registros auxiliares internos, inaccesibles por el usuario, que permitan llevar estas tareas. Su función, aunque hay muchas posibles, podría decirse que es la de almacenamiento temporal sin necesidad de acudir a la memoria externa, y la de ayuda a la generación de direcciones de memoria. Dentro de estos registros auxiliares, requiere una atención especial un registro que suelen incluir todos los procesadores: el STACK POINTER o puntero de pila. 16 Fundamentos sobre Microprocesadores 2.4. La memoria La memoria es uno de los módulos fundamentales de un procesador. Es el lugar donde se guarda la información sobre el programa a ejecutar, así como los datos que se vayan generando. Aunque existen varias modalidades de memoria, clasificadas según la tecnología con la que se fabrican, todas ellas pueden catalogarse en memorias: ROM De solo lectura, orientadas al almacenamiento de programas ya que mantienen su contenido en ausencia de alimentación. RAM De lectura/escritura de acceso aleatorio, orientadas al almacenamiento de datos o de programas de manera temporal. No mantiene su información en ausencia de alimentación. Independientemente del tipo, un módulo de memoria, es un conjunto de celdas de almacenamiento con circuitos asociados, que permiten la transferencia de información entre el interior de la memoria y el mundo exterior. 2.5. Instrucciones Una instrucción, es una información elemental que se suministra a la CPU en forma de combinación binaria, a partir de la cual la CPU desarrolla una secuencia de acciones, que le permiten llevar a cabo una determinada manipulación de la información. El conjunto de instrucciones que soporta una CPU se conoce como juego de instrucciones, y determina las capacidades del procesador. La asignación de los códigos binarios, a cada una de las instrucciones, no se realiza de forma aleatoria, sino que, es el resultado de un estudio detallado, con el objeto de simplificar las labores de decodificación por parte de la unidad de control. Los bits de la combinación binaria que constituyen la instrucción, se dividen en grupos denominados campos. Los campos más comunes, que se encuentran en los distintos formatos de instrucciones, son los siguientes: Instrucciones 17 Un campo de código de operación, que especifica la operación que se debe realizar. Un campo de dirección, que designa una dirección de la memoria o un código para elegir un registro del procesador. Un campo de modo, que especifica la forma en que se interpretará el campo de dirección. El código de operación de una instrucción, es un grupo de bits que definen diversas operaciones del procesador, como puede ser: la adicción, la sustracción, complemento, etc. Los bits que definen el campo de modo, especifican diversas alternativas para escoger los operandos del campo de dirección. La longitud de la instrucción es variable; así, podemos encontrarnos instrucciones codificadas en una única palabra como otras que pueden ocupar dos, tres o más palabras. Todo dependerá de la complejidad de la instrucción, del número de operaciones, de la diversidad de los modos de direccionamiento, etc. La elección de un juego de instrucciones extenso o reducido ha dado lugar a dos tipos de concepción sobre la arquitectura de los procesadores, conocidos como CISC4 o RISC5. Se dice que un juego de instrucciones es ortogonal, si cada operación se puede realizar con cualquier tipo de operando y cualquier modo de direccionamiento. 2.5.1. Modos de direccionamiento Los datos necesarios para que se ejecute una instrucción, y que son especificados por el operando, pueden ser accesibles de diferentes formas, llamados modos de direccionamiento. De este modo, se añade versatilidad a las operaciones que es capaz de realizar la CPU, facilitando la realización de programas o acelerando la ejecución de los mismos. Los modos de direccionamiento disponibles en una CPU pueden ser muy variados, incluyendo en muchos casos, combinación de varios en una misma instrucción. En cualquier caso, existen ciertos modos que, aunque puedan variar de nombre, obedecen a una misma forma de operar. Estos modos son: 4 CISC: Complex Instruction Set Computer 5 RISC: Reduced Instruction Set Computer 18 Fundamentos sobre Microprocesadores 2.5.1.1. Direccionamiento implícito También llamado inherente. Es el modo en el que no se hace ninguna referencia a memoria. Se aplica a aquellas instrucciones que se ejecutan en la CPU, sin necesidad de intercambiar datos con memoria. Las instrucciones no tienen operando. 2.5.1.2. Direccionamiento inmediato En este modo, las instrucciones necesitan un dato que está contenido en la propia instrucción, en el campo de dirección. 2.5.1.3. Direccionamiento directo También llamado absoluto. El dato necesario para la instrucción, está contenido en una posición de memoria. El operando es precisamente la dirección de memoria en donde se encuentra ese dato. 2.5.1.4. Direccionamiento indirecto El dato necesario para la instrucción, está contenido en una posición de memoria denominada dirección efectiva. El operando es una dirección de memoria que actúa como dirección intermedia. El contenido de esta posición es la dirección efectiva. 2.5.1.5. Direccionamiento relativo Localiza el dato en una posición de memoria que se encuentra distanciada un cierto número de posiciones con relación al contador de programa. Esta distancia u offset, es el número indicado por el operando y suele ir codificado en complemento a dos, dando lugar, a una dirección positiva (adelante) o negativo (atrás). La dirección efectiva se calcula, sumando la dirección actual al offset. 2.5.1.6. Direccionamiento indexado Este modo requiere que la CPU tenga un registro auxiliar, denominado índice. La dirección efectiva, se encuentra sumando, el contenido de este registro con el operando de la instrucción. Puede haber múltiples variantes de este modo. Instrucciones 2.5.2. 19 Clasificación de las instrucciones Es posible, realizar una clasificación de las instrucciones de un procesador tomando como base, la función que realizan. Así, podemos encontrar instrucciones: Aritméticas. Son aquellas instrucciones que operan con la ALU. Lógicas. Realizan operaciones lógicas y modifican el registro de estado. De bifurcación. Modifican la secuencia normal de ejecución de un programa. Puesto que la secuencia de ejecución la controla el contador del programa, estas instrucciones actúan sobre este registro. Algunas instrucciones pueden verificar el estado de alguno de los flags del registro de estado. Si es así, las instrucciones son de salto condicionado. Si el salto se realiza en cualquier caso se les conoce como incondicionales. Transferencia de datos. Mueven datos de un sitio a otro, sin modificar el valor de éste, ni el registro de estado. Las instrucciones de entrada/salida, son un caso especial de instrucciones de transferencia. De bit. Tiene como función modificar un solo bit, o leer su estado. Son típicas, aquellas que modifica alguno de las banderas del registro de estado. Otras instrucciones. Existen otras instrucciones que no se pueden clasificar en ninguna de las categorías anteriores. Algunas de ellas, controlan la operación del microprocesador; como son las de parada del procesador, o las que no ejecutan ninguna operación. 20 2.6. Fundamentos sobre Microprocesadores Temporización de las instrucciones Cuando un código de operación llega al registro de instrucciones de la CPU, la unidad de control desarrolla una secuencia de acciones preestablecidas, hasta completar su ejecución. Como se ha dicho anteriormente, el controlador es un subsistema secuencial síncrono, que va cambiando de estado, en función de una señal de reloj externa. Cada una de las acciones elementales (microinstrucciones) necesarias, para la ejecución de una instrucción, tarda un ciclo de reloj en completarse. El número total de microinstrucciones, y por tanto, de ciclos de reloj, dependerá de la complejidad de la instrucción. La velocidad de ejecución de un microprocesador, depende fundamentalmente de la máxima frecuencia de reloj que admite, condicionada por razones tecnológicas. Pero juega también un papel importante, la habilidad que hayan desarrollado sus diseñadores para acortar el número de ciclos de reloj necesarios para cada instrucción. La técnica denominada pipelining, permite acortar tiempos, haciendo que la unidad de control efectúe varias operaciones en paralelo, en lugar de hacerlo consecutivamente. 2.7. Interrupciones Las interrupciones, constituyen quizá, el mecanismo más importante para la conexión del microprocesador al mundo exterior, sincronizando la ejecución de los programas con los acontecimientos externos. El funcionamiento de las interrupciones, es similar al de las subrutinas, de las cuales se diferencian del procedimiento con que se ponen en marcha. Del mismo modo, que las subrutinas se ejecutan cada vez que en el programa aparece la instrucción de llamada, las interrupciones se ponen en marcha, al activarse un terminal de entrada de la CPU, es decir, mediante un mecanismo hardware. Capítulo 3 Introducción al diseño con dispositivos programables (FPGAs). 3.1. Introducción a los circuitos digitales configurables El continuo avance de la microelectrónica a finales de los años 70, dio como resultado la creación de circuitos de muy gran escala de integración VLSI6. Este hecho, permitió el desarrollo de diferentes tipos de circuitos y sistemas electrónicos digitales como fueron: las matrices lógicas programables PLA7, las matrices lógicas Y-programables PAL8, los circuitos integrados semimedida, etc. A pesar de estos avances, los dispositivos mencionados, no proporcionaron una solución claramente satisfactoria a la resolución de determinados problemas prácticos; si se utilizaban dispositivos custom las prestaciones eran elevadas pero, a un coste prohibitivo, si se recurría a las lógicas programables, sus prestaciones eran reducidas y en ambos casos, su capacidad de reprogramación era nula. Según la tecnología lo fue permitiendo, surgió el interés por desarrollar circuitos integrados cuyo comportamiento hardware pudiese ser modificado tantas vece, como fuese necesario, del mismo modo, que se hace con un programa software. 6 VLSI: Very Large Scale of Integration 7 PLA: Programmable Logia Array 8 PAL: Programmable Array Logic 21 22 Introducción al diseño con dispositivos programables (FPGAs). Esto dio lugar, al nacimiento de los dispositivos programables, que se caracterizaron por disponer de un elevado número de recursos lógicos y de interconexión, definibles por el usuario, de modo parecido a lo que se podía hacer hasta el momento con las MPGA9, pero sin la necesidad de implementar las interconexiones mediante una máscara metálica, sino, por medio de interruptores programables. Estos circuitos, se clasifican habitualmente en dos tipos: los Dispositivos Lógicos Programables (PLD10) y los Conjuntos Configurable de Puertas (FPGA11). Las FPGAs se diferencian básicamente de los PLD en su mayor nivel de integración, debido a una arquitectura más compleja, tanto a nivel de recursos lógicos como de interconexión. Como el presente proyecto está fundamentado en el uso de la FPGAs, vamos a destacar las características más relevantes de este tipo de dispositivos. Aunque es obvio, que un dispositivo hecho a medida siempre dispondrá de mayores prestaciones que uno configurable, el uso de las FPGAs, está recomendado para aquellas aplicaciones, donde el número de unidades a producir no justifica el desarrollo de un ASIC. Por otro lado, la facilidad del prototipado, permite disponer de unidades funcionales mucho antes que con los ASICs; reduciendo de este modo los tiempos de desarrollo. Otras de sus ventajas, es su capacidad de reconfiguración en cualquier instante, lo que se traduce en que, dentro de una misma tarjeta una FPGA puede desempeñar distintas funciones, dependiendo de la configuración cargada. Por ejemplo, en el momento de arranque de una tarjeta, la FPGA puede ser programada para realizar un chequeo de todo el circuito, para posteriormente ser reconfigurado y comportarse como un microprocesador. A nivel de arquitectura, todas las FPGAs se caracterizan por disponer sus recursos lógicos en forma matricial, unidos por medio de líneas de interconexión horizontales y verticales. 9 MPGA: Mask Programmable Gate Array 10 PLD: Programmable Logic Device 11 FPGA: Field Programmable Gate Array Introducción a los circuitos digitales configurables 23 Figura 5: Estructura matricial de una FPGA de Xilinx Básicamente, están formadas por un núcleo con múltiples Bloques Lógicos Configurables (CLB12), recursos de interconexión controlados por las Matrices de Conmutación (MC), y una periferia de bloques de entrada/salida configurables (IOB13). Por último, debemos mencionar que las tecnologías de fabricación de las FPGAs están en su totalidad basadas en transistores MOS, siendo posible tres técnicas a la hora de programar el comportamiento de los interruptores programables. La más empleada en la actualidad, es la SRAM (memoria estática de acceso aleatorio), donde cada bit define el comportamiento de un interruptor. Su mayor ventaja es la posibilidad de su reconfiguración, pero precisa de circuitos adicionales para almacenar la configuración de forma permanente, dada su volatilidad. 12 CLB: Configurable Logic Block 13 IOB: Input Output Block 24 Introducción al diseño con dispositivos programables (FPGAs). 3.2. Fases en el diseño de circuitos con FPGAs Las etapas básicas del diseño y realización de un sistema digital mediante FPGAs, son comunes al diseño con cualquier otro tipo de circuitos (semimedida, totalmente a medida, etc.), aunque existen diferencias en la forma de realizarlas con cada circuito. En primer lugar, es necesario distinguir dos fases en la realización de un sistema: el diseño y la implementación. El diseño consiste, en la descripción abstracta y general de un circuito, definiendo su comportamiento, que debe ajustarse a la realización de las tareas dictadas por las especificaciones. La implementación, es la fase en que este diseño abstracto se materializa físicamente en los circuitos elegidos. El diseño y realización de un circuito mediante FPGAs, puede dividirse en las siguientes etapas: Descripción del diseño. En esta fase se especifica la función del sistema digital. Verificación del diseño. En esta fase se verifica el correcto funcionamiento del diseño descrito anteriormente. Compilación e implementación del diseño. En esta fase, se transforma el diseño que se ha descrito, de forma que sea posible su implementación física en el dispositivo físico escogido. Aunque el orden del proceso, es básicamente el descrito en los puntos anteriores, existen interrelaciones entre las fases, tal como se pueden observar en la figura siguiente, dando lugar a un progresivo refinamiento del diseño mediante las sucesivas iteraciones de estos tres pasos fundamentales. Fases en el diseño de circuitos con FPGAs 25 Especificaciones Lista de conexiones DESCRIPCIÓN DEL Retro-anotación DISEÑO Lista de conexiones VERIFICACIÓN DEL DISEÑO Datos del diseño enrutado IMPLEMENTACIÓN DEL DISEÑO Figura 6: Fases del diseño de un circuito mediante FPGAs La fase de descripción del diseño consiste en, detallar el circuito que se ha obtenido a partir de las especificaciones iniciales. Esta descripción, puede hacerse básicamente de dos modos: Descripción estructural. Consistente en, la realización de las interconexiones entre los diferentes elementos que componen el circuito, por medio de esquemas realizados con herramientas CAD. Descripción de comportamiento. Consistente en, expresar el funcionamiento del circuito con la ayuda de algún Lenguaje de Descripción Hardware (HDL14) del tipo VHDL, Verilog, etc. Lo más habitual, es realizar la descripción del diseño mediante la combinación de ambas formas. Una vez realizado el diseño del sistema, y antes de proceder a la implementación del mismo, debe realizarse una verificación de este mediante las apropiadas simulaciones funcionales y temporales. 14 HDL: Hardware Description Language 26 Introducción al diseño con dispositivos programables (FPGAs). El proceso de diseño concluye con la compilación de proyecto sobre el dispositivo elegido, dando como resultado un fichero de programación de la FPGA. Dependiendo de la herramienta CAD elegida, variará la denominación y el número de etapas antes descritas, aunque, la filosofía del trabajo sigue siendo la misma. En la siguiente figura, podemos ver las distintas fases de desarrollo de la herramienta WebPACK de Xilinx. Figura 7: Fases de desarrollo del entorno WebPACK de Xilinx Capítulo 4 Desarrollo del microprocesador didáctico ERIC El punto de partida, en el diseño de cualquier procesador, es fijar las prestaciones que queremos que realice. Estas especificaciones quedan reflejadas por una parte en el juego de instrucciones o ISA15, y por otro lado, en las capacidades a nivel de direccionamiento de memoria, soporte de dispositivos de E/S, manejo de interrupciones, etc. Ambas partes están íntimamente relacionadas. A la hora de determinar las prestaciones del procesador, se ha tenido en mente ante todo, el valor didáctico de las mismas y por otro lado, el ajustando calendario de tiempo disponible por parte del alumno para su implementación. Por estas razones, se a huido intencionadamente de arquitecturas extensas a nivel de instrucciones, con múltiples modos de direccionamiento o con ejecuciones en un ciclo de reloj, por el contrario nos hemos conformado con una buena combinación entre complejidad y valor pedagógico. La combinación de dos ideas: por un lado, la implementación de un procesador con un juego de instrucciones reducido RISC, y por otro lado, el objetivo didáctico del mismo, dio lugar al nombre del procesador que denominamos ERIC (Educational Reduced Instruction set Computer), y que pasamos a describir. 15 Instruction Set Architecture 27 28 Desarrollo del microprocesador didáctico ERIC 4.1. Especificaciones generales A continuación, se resume esquemáticamente las prestaciones de ERIC: Arquitectura Von Neumann. Juego de instrucciones reducido (RISC). Bus de datos de 8 bits. Bus de direcciones de 12 bits. Bus de entrada/salida de 4 bits. Memoria ROM de 4096 bytes. Memoria RAM de 256 bytes. Pila de 64 bits. Soporte de una interrupción. 4.2. El juego de instrucciones El juego de instrucciones de ERIC se encuadra dentro de la filosofía RISC, esto es, un conjunto reducido de instrucciones. Esta decisión se fundamenta únicamente en la simplicidad a la hora de ser implementadas, lo que se traduce en una mayor sencillez a la hora de ser decodificadas, y en un menor consumo de los recursos de la FPGA. Otros aspectos inherentes a la filosofía RISC, como el uso intensivo de registros internos, la facilidad para implementar instrucciones en un ciclo de reloj, reducción de los accesos a memoria externa, etc., no han sido contemplados en este proyecto por lo que en este sentido ERIC, no es un autentico RISC. En cualquier caso, lo que se ha buscado es un repertorio representativo de las instrucciones que podemos encontrar en cualquier procesador, tanto RISC, como CISC, siendo el 8051 el modelo que ha inspirado gran parte de las instrucciones del ERIC. El juego de instrucciones 4.2.1. 29 Modos de direccionamiento Con el fin, de que el alumno se familiarice con los distintos modos de direccionamiento que finalmente podrán encontrar en cualquier procesador comercial, se ha decido incluir los siguientes modos: Implícito Instrucciones que no precisan de campo de dirección (CD). Registro Instrucciones que hacen referencia al registro en el CD. Inmediato La instrucción va acompañada del operando que precisa. Directo El CD hace referencia a una posición de memoria donde se encuentra el operando. Indirecto El CD hace referencia a una posición de memoria o registro, donde se encuentra la dirección, que a su vez hace referencia al operando. Relativo Instrucciones que hacen referencia a una dirección relativa en el CD. 4.2.2. Clasificación de las instrucciones Ateniéndonos a su funcionalidad, es posible clasificar las instrucciones en diferentes grupos. A continuación, se resume todas las instrucciones disponibles con información relevante como: Hex Valor en hexadecimal de la instrucción. Nemotécnico Nombre de la instrucción. Descripción Operación que realiza. C1, C2, C3 Campos en que ha sido dividida la instrucción para su posterior tratamiento por parte de la Unidad de Control. C, Z, O Banderas afectadas en cada operación (Carry, Zero, Overflow). Modo Modo de direccionamiento. 30 Desarrollo del microprocesador didáctico ERIC 4.2.2.1. Transferencias de datos HEX NEMOCTÉCNICO DESCRIPCIÓN (A) <- (addr4) 2# IN A,addr4 (addr4) <- (A) 3# OUT addr4, A 03 PUSH A 13 POP A 04 PUSH B 14 POP B 05 PUSH F 15 POP F C0 C1 D0 D1 D2 D3 E1 E2 F# MOV A,#dato MOV B,#dato MOV A,addr8 MOV B,addr8 MOV addr8,A MOV addr8,B MOV A,@B MOVX A,@B MOVX A,addr12 ((SP)) <- (A) (SP) <- (SP) + 1 (SP) <- (SP) - 1 ((SP)) <- (A) ((SP)) <- (B) (SP) <- (SP) + 1 (SP) <- (SP) - 1 ((SP)) <- (B) ((SP)) <- (Flags) (SP) <- (SP) + 1 (SP) <- (SP) - 1 ((SP)) <- (Flags) (A) <- dato (B) <- dato (A) <- (addr8) (B) <- (addr8) (addr8) <- A (addr8) <- B (A) <- ((B)) (A) <- ((B)) (A) <- (addr12) C1 00 00 C2 10 11 C3 C Z O xxxx xxxx BYTES MODO 1 1 INMEDIATO 00 00 0011 1 IMPLICITO 00 01 0011 1 IMPLICITO 00 00 0100 1 IMPLICITO 00 01 0100 1 IMPLICITO 00 00 0101 1 IMPLICITO 00 01 0101 1 IMPLICITO 11 11 11 11 11 11 11 11 11 00 00 01 01 01 01 10 10 11 0000 0001 0000 0001 0010 0011 0001 0010 xxxx 2 2 2 2 2 2 1 1 2 INMEDIATO INMEDIATO INMEDIATO DIRECTO DIRECTO DIRECTO DIRECTO INDIRECTO INDIRECTO DIRECTO Tabla 1: Instrucciones de transferencia de datos 4.2.2.2. HEX 40 41 42 43 54 55 Operaciones aritméticas NEMOCTÉCNICO DESCRIPCIÓN (A) <- (A) + (B) + (C) ADDC A,B (A) <- (A) - (B) - (C) SUBC A,B (A) <- (A) + 1 INC A (A) <- (A) - 1 DEC A (B) <- (B) + 1 INC B (B) <- (B) - 1 DEC B C1 01 01 01 01 01 01 C2 00 00 00 00 01 01 C3 C Z O 0000 x x x 0001 x x x 0010 x 0011 x 0100 x 0101 x BYTES MODO 1 1 1 1 1 1 REGISTRO REGISTRO REGISTRO REGISTRO REGISTRO REGISTRO Tabla 2: Instrucciones aritméticas 4.2.2.3. HEX 7D 7E 7F 01 02 Operaciones con banderas NEMOCTÉCNICO DESCRIPCIÓN (C) <- 0 CLR C (C) <- 1 SET C (C) <- /(C) CPL C (IEN) <- 1 ION (IEN) <- 0 IOF C1 01 01 01 00 00 C2 11 11 11 00 00 C3 1101 1110 1111 0001 0010 C Z O 0 1 x Tabla 3: Instrucciones de manipulación de banderas BYTES MODO 1 1 1 1 1 REGISTRO REGISTRO REGISTRO IMPLICITO IMPLICITO El juego de instrucciones 4.2.2.4. HEX 46 47 48 49 4A 31 Operaciones lógicas NEMOCTÉCNICO DESCRIPCIÓN (A) <- (A) * (B) AND A,B (A) <- (A) v (B) OR A,B (A) <- (A) A (B) XOR A,B (A) <- 0 CLR A (A) <- /(A) CPL A 4B RLC A 4C RRC A (An + 1) <- (An) (A0) <- (C) (C) <- (A7) (An) <- (An + 1) (A7) <- (C) (C) <- (A0) C1 01 01 01 01 01 C2 00 00 00 00 00 C3 C Z O 0110 x 0111 x 1000 x 1001 1 1010 x BYTES MODO 1 1 1 1 1 REGISTRO 01 00 1011 x 1 REGISTRO 01 00 1100 x 1 REGISTRO BYTES MODO REGISTRO REGISTRO REGISTRO REGISTRO Tabla 4: Instrucciones lógicas 4.2.2.5. Flujo de programa HEX NEMOCTÉCNICO DESCRIPCIÓN 80 JZ rel 81 JNZ rel 82 JC rel 83 JNC rel 84 JO rel 85 JNO rel 88 SJMP rel 90 RET 91 RETI A# ACALL addr12 B# 00 0F AJMP addr12 NOP HALT (PC) <- (PC) + 2 si (A) = 0 entonces (PC) + rel (PC) <- (PC) + 2 si (A) != 0 entonces (PC) + rel (PC) <- (PC) + 2 si (C) = 1 entonces (PC) + rel (PC) <- (PC) + 2 si (C) = 0 entonces (PC) + rel (PC) <- (PC) + 2 si (OV) = 0 entonces (PC) + rel (PC) <- (PC) + 2 si (OV) != 0 entonces (PC) + rel (PC) <- (PC) + rel (SP) <- (SP)-1 (PCl) <- ((SP)) (SP) <- (SP)-1 (PCh) <- ((SP)) (SP) <- (SP)-1 (PCl) <- ((SP)) (SP) <- (SP)-1 (PCh) <- ((SP)) ION <- 1 ((SP)) <- (PCh) (SP) <- (SP) + 1 ((SP)) <- (PCl) (SP) <- (SP) + 1 (PC) <- addr12 (PC) <- addr12 (PC) <- (PC) + 1 (PC) <- (PC) C1 C2 C3 C Z O 10 00 0000 2 RELATIVO 10 00 0001 2 RELATIVO 10 00 0010 2 RELATIVO 10 00 0011 2 RELATIVO 10 00 0100 2 RELATIVO 10 00 0101 2 RELATIVO 10 00 1000 2 RELATIVO 10 01 0000 1 IMPLICITO 10 01 0001 1 IMPLICITO 10 10 xxxx 2 DIRECTO 10 00 00 11 00 00 xxxx 0000 1111 2 1 1 DIRECTO IMPLICITO IMPLICITO Tabla 5: Instrucciones de control de flujo de programa Aunque la funcionalidad de mayoría de las instrucciones son evidentes, es posible disponer de una información más detallada en el Apéndice: Juego de Instrucciones del ERIC. 32 4.2.3. Desarrollo del microprocesador didáctico ERIC Formato de las instrucciones Cada instrucción codificada en binario, contiene un número de campos que ofrecen la información pertinente que necesita la Unidad de Control, para ejecutar la instrucción en la CPU. Normalmente, el número de campos, la anchura en bits y el nombre que recibe cada uno, suele variar de instrucción a instrucción. En el caso de ERIC, y buscando la máxima simplicidad, se ha estructurado cada instrucción en un número de campos fijos y de ancho fijo que se han denominado C1, C2 y C3. Por otro lado, es posible encontrar instrucciones de 1 ó 2 bytes. La siguiente figura resume la estructura del primer byte: C2 7 6 C1 5 4 3 2 1 0 C3 Figura 8: Estructura de campos del primer byte de una instrucción El significado de cada uno de los campos es variable, dependiendo en cada momento del contexto de la instrucción que estemos interpretando. Esto es debido, a lo limitado del número de bits disponibles para codificar, no siendo posible establecer significados de carácter general y por lo tanto, es necesario ir cambiando el significado de cada campo según el caso. Veamos en cualquier caso, ciertas ideas de carácter general que se han aplicado a la hora de establecer los códigos al juego de instrucciones. El juego de instrucciones 33 El campo C1 (2 bits) es utilizado para realizar una primera división de las instrucciones en grupos funcionales: 11 (MOV) Instrucciones de transferencias de datos con memoria. 10 (JMP) Instrucciones de control del flujo del programa, es decir, todas aquellas que tenga que ver con saltos, llamadas a subrutinas, etc. 01 (ALU) Instrucciones que en su ejecución utilizan la ALU. En este grupo se incluyen las instrucciones lógicas, aritméticas y de manipulación de banderas vistas con anterioridad. 00 (MIX) Instrucciones de transferencias de datos con el exterior, con la pila y algunas otras, que no pueden catalogarse en alguno de los grupos anteriores. Al lado de cada valor posible del C1, se ha añadido un nemotécnico que define el sentido de cada grupo de instrucciones (MOV para las de transferencia, JMP para las de salto, ALU para las que tiene relación con la ALU y MIX al grupo de las misceláneas). Vemos por lo tanto que C1, se comporta como una parte del código de operación. El campo C2 (2 bits) es el campo de significado más variable. En algunos casos se comporta como campo de destino, otras como indicador de modo de dirección, otras como ampliación del código de operación. El campo C3 (4 bits), normalmente indica un código de operación, o bien, alguna parte de una dirección en los modos directo, o la totalidad, en el modo inmediato. Veamos a continuación el significado de cada uno de los campos, según la instrucción o grupo de instrucciones: 34 Desarrollo del microprocesador didáctico ERIC BYTE 1 C1 C2 11 Tipo MOV 00 01 10 11 10 01 00 BYTE 2 C3 Modo Inmediato Modo Directo Modo Indirecto (Reg B) Ext. Cod. Operación xxxx xxxx xxxx xxxx Cod. Operación Cod. Operación Cod. Operación addr12(11:8) #dato addr8(7:0) addr12(7:0) Tipo JMP 00 Modo Relativo 01 Modo Implícito 10 Ext. Cod. Operación xxxx Cod. Operación xxxx Cod. Operación xxxx addr12(11:8) rel 00 Registro Destino A 01 Registro Destino B 1X No hay registro destino. xxxx Cod. Operación xxxx Cod. Operación xxxx Cod. Operación - 0X Ext. Cod. Operación 10 Ext. Cod. Operación 11 Ext. Cod. Operación xxxx Cod. Operación xxxx addr4(3:0) xxxx addr4(3:0) - addr12(7:0) Tipo ALU Tipo MIX Tabla 6: Formato de los campos según el tipo de instrucción De la tabla anterior, solo comentar el significado y la manera de codificar algunas de las informaciones. addr4 Dirección de 4 bits. Va codificada en los bits de menor peso de la instrucción. addr8 Dirección de 8 bits. Va codificadas en el segundo byte. addr12 Dirección de 12 bits. Los bits más significativos de addr12 van codificados en los bits de menor peso de la instrucción. El resto va en el segundo byte. rel Dirección relativa. Va codificada en el segundo byte. #dato Va codificado en el segundo byte. ION 7 8 JNZ rel JC rel JNC rel 0110 SJMP rel F E D C 0000 0001 MOV B, #dato MOV B, addr8 MOVX A,@B MOV addr8,A MOV addr8,B 0010 0011 0100 0101 Tabla 7: Mapa de distribución de las instrucciones del ERIC 0111 1000 MOVX A, addr12 AJMP addr12 MOV A, #dato MOV A, addr8 MOV A,@B B RETI ACALL addr12 RET 9 JNO rel A JZ rel 8 JO rel XOR A,B 1001 CLR A 1010 CPL A A 1011 RLC A B 1100 RRC A C CLR C D SET C E CPL C HALT F 0101 0100 0011 0010 0001 0000 1101 1110 1111 1111 1110 1101 1100 1011 1010 1001 1000 0111 OR A,B 9 7 DEC B AND A,B 6 0110 INC B POP F PUSH F 5 6 5 4 DEC A POP B PUSH B 4 OUT addr4, A POP A PUSH A 3 3 INC A IOF 2 IN A, addr4 ADDC A,B SUBC A,B NOP 1 2 1 0 0 El juego de instrucciones 35 36 4.3. Desarrollo del microprocesador didáctico ERIC Implementación física de Eric Para la realización práctica del diseño, se seleccionó inicialmente la tarjeta de desarrollo de Xess XSA-50. Dicha tarjeta posee como corazón una FPGA del tipo Spartan-II XC2S50 de 50.000 puertas. Además, dispone de otra serie de dispositivos como una memoria DRAM de 8 Mbytes, una memoria FLASH de 128 Kbytes, un CPLD, etc. Para más información sobre las características de la tarjeta consultar el apéndice: La tarjeta de desarrollo XSA-50. El entorno de desarrollo utilizado ha sido el WebPack 5.1, de la casa Xilinx. El WebPack viene acompañado de una versión de evaluación del simulador ModelSim de la casa Mentor Graphics, que también ha sido utilizado. Para más información sobre el ISE WebPack consultar el apéndice: El entorno de desarrollo ISE WebPACK. El diseño del procesador se ha realizado casi totalmente en VHDL16, por entender que los lenguajes HDL, aceleran los tiempos de desarrollo, aunque sea a costa de perder algo de objetividad sobre lo que realmente se sintetiza. Por otra parte, el lenguaje VHDL es de estudio obligatorio dentro de la titulación de Ingeniero de Telecomunicación, por lo que esta decisión no debería acarrear ningún problema. Además, el uso del VHDL como lenguaje de síntesis, pone de relieve ciertas limitaciones del lenguaje que no se manifiestan hasta que se acomete un trabajo real, por lo que, es posible aprovechar este trabajo para profundizar en el estudio del lenguaje. Aunque es posible una descripción completa del procesador en VHDL, se han incluido numerosos esquemáticos, con el fin de favorecer la comprensión de la interacción de los distintos componentes que conforman el procesador. También se ha recurrido a los esquemáticos a la hora de implementar las memorias por su inmediatez, a partir de las primitivas. 16 VHSIC Hardware Description Language Implementación física de Eric Figura 9: Tarjeta XSA-50 de la casa XESS utilizada en este proyecto Figura 10: Tarjeta D2XL de la casa DIGILENT también probada en este proyecto 37 38 Desarrollo del microprocesador didáctico ERIC 4.4. Estructura del microprocesador Cuando se decidió acometer la idea de desarrollar este proyecto, se tenía en mente el implementar un microprocesador utilizando como memorias del mismo, alguna de las disponibles en la tarjeta XSA-50. Tras analizar las particularidades de cada una de ellas, se decidió descartar esta idea por la dificultad que entrañaba. Por un lado, la memoria DRAM necesita que se implemente un controlador de memoria dinámica en la propia FPGA y por otro lado, la memoria FLASH comparte gran parte de sus terminales de acceso con el puerto paralelo, complicando enormemente su gestión. Dado que las FPGAs de tipo Spartan-II poseen bloques específicos de memoria (BRAM), se optó por explotar este recurso e incorporar la memoria RAM y ROM al propio diseño del procesador. Con esta decisión, se ha conseguido por una parte simplificar el diseño y por otra parte, no depender de las posibilidades hardware de la tarjeta de desarrollo, por lo que se facilita la movilidad del diseño a tarjetas equipadas únicamente con la FPGA pertinente. En este sentido, durante la ejecución de este proyecto surgió la posibilidad de probar el proyecto en una tarjeta de la casa Digilent, demostrando lo acertado de la decisión al funcionar sin problemas. El diseño del microprocesador se ha realizado de manera modular, siguiendo la metodología top-down. En la siguiente página, podemos observar la estructura en bloques del nivel más alto del diseño, es decir el top. Como se puede observar en la figura, ERIC está formado por cuatro bloques claramente diferenciados: La memoria RAM. La memoria ROM. El corazón del procesador. Un conversor binario a 7 segmentos. que pasamos a desarrollar a continuación. Estructura del microprocesador Figura 11: Diagrama principal de bloques del ERIC (TOP.SCH) 39 40 4.4.1. Desarrollo del microprocesador didáctico ERIC Organización de la memoria Dependiendo del modelo de FPGA Spartan-II utilizada, es posible disponer de un número variables de bloques BRAM, tal como se muestra en la siguiente tabla: Tabla 8: Bloques BRAM disponibles según el modelo de FPGA Comentar que, cada bloque tiene una capacidad de 4096-bits y que es posible configurarlo de múltiples maneras, variando el tamaño de la memoria y la anchura del bus de datos. Independientemente de la configuración elegida, siempre se consume la totalidad del bloque, siendo posible agrupar bloques para formar memorias con mayores capacidades. La memoria puede ser de simple o doble puerto y siempre es síncrona. Para más información sobre las prestaciones de las FPGAs Spartan-II consultar el apéndice: FPGAs de la familia SPARTAN II DE XILINX Tabla 9: Configuraciones posibles de un bloque BRAM de una Spartan-II Según esto, veamos cuantos bloques especificaciones de memoria del ERIC. necesitamos para implementar las Estructura del microprocesador ROM 41 Con un tamaño igual a 4096 bytes, necesitamos por lo tanto 8 bloques. RAM Aunque de tamaño igual a 256 bytes, consumiremos igualmente un bloque de 4096 bits. STACK Con un tamaño igual a 64 bytes necesitamos un bloque. Resumiendo, necesitamos 10 bloques para disponer de las especificaciones máximas, o lo que es lo mismo, una Spartan-II XC2S100 (100.000 puertas). Dado que la tarjeta XSA-50 está equipada con una XC2S50 de 8 bloques, no es posible implementar la totalidad del esquema de memoria. Para poder seguir trabajando con la XSA-50, y con otras tarjetas de menor capacidad (Digilent D2XL) se optó por reducir la ROM a la mitad de sus especificaciones iniciales, es decir 2048 bytes. Con esta nueva configuración sólo son necesarios 6 bloques, siendo suficiente una XC2S30. De este modo, la organización de la memoria según el tipo de FPGA utilizada, queda tal como se muestra en la siguiente figura: Memoria de Memoria de Programa (ROM) Datos (RAM) 0xFF 0xFFF FPGA XC2S100 0x00 0x7FF Memoria de FPGA XC2S30 Stack 0x3F 0x002 0x000 RESET Salto a la rutina de INTERRUPCIÓN 0x00 Figura 12: Esquema de la memoria del ERIC según el modelo de FPGA 42 Desarrollo del microprocesador didáctico ERIC Aunque hasta ahora hemos estado hablando de ROM y de RAM, es obvio que el único tipo de memoria que se puede realizar es de tipo RAM. Aun así, vamos a seguir utilizando esta denominación, como sinónimo de memoria de programa (no modificable) y de memoria de datos (modificable). A nivel de diseño, todos los módulos de memoria han sido realizados por medio de esquemáticos a partir de la primitiva RAMB4_S8 (512x8 bits). Esta memoria es de simple puerto y síncrona, lo que implica ciertas diferencias a tener en cuenta respecto a las memorias asíncronas, tradicionalmente usadas con microprocesadores. La primera diferencia radica, en el desglose del bus de datos en dos: uno para la entrada y otro para la salida. La otra diferencia, es el momento a partir del cual podemos disponer de los datos, puesto que una vez aplicada una dirección deberemos esperar al siguiente flanco de subida del reloj, para disponer de los datos. Figura 13: Primitiva RAMB4_S8 utilizada como base de los módulos de memoria Los esquemas ROM.SCH, RAM.SCH y STACK.SCH reflejan la manera en que han sido implementadas las distintas unidades de memoria. Hay que destacar, que el diseño de la ROM es fácilmente ampliable puesto que el decodificador utilizado ya contempla la totalidad de lo bloque posibles, aunque en este caso solo direccione la mitad. A todas las memorias, se han añadido bufferes triestado a sus salidas para posibilitar su conexión al mismo bus de datos. Estructura del microprocesador 4.4.2. 43 El corazón del procesador Comúnmente, a la descripción de procesadores en HDL para su implementación en FPGA se les denomina CORES. El bloque que vamos a describir, el más extenso por otra parte, representa el corazón de ERIC de ahí su nombre (CPU_CORE.SCH). Veamos las distintas partes que lo componen: El acumulador y el registro auxiliar B. El registro de instrucciones (IR). El registro de estado. El contador de programa (PC). El registro de direccionamiento de memoria (MAR). La Unidad Aritmético Lógica (ALU). La Unidad de Control (UC). La pila o STACK. El contador de la pila (SC) El bloque SNIFFER. Multiplexores varios. A grandes rasgos, podemos comprobar que están todos los bloques típicos de un microprocesador comercial, con la salvedad del bloque SNIFFER. Este bloque, que se muestra en el esquema siguiente de forma distinta a los demás, no es como tal, una parte del procesador, sino un bloque añadido que posibilita la salida y entrada de datos de ERIC con el mundo exterior. Por otra parte, también podemos comprobar que hay 3 buses de carácter general por los que circula la información entre los distintos módulos del procesador. Lo habitual es encontrar un bus de direcciones y otro de datos. Aquí se ha desglosado el bus de datos en dos: uno de entrada DIN(7:0) para los datos procedentes de la memoria hacia el procesador, y otro de salida DOUT(7:0), para los datos de salida del procesador hacia la memoria. La justificación de este desglose, es que las memorias síncronas utilizadas poseen el bus de de entrada y de salida de datos, de forma independiente. 44 Desarrollo del microprocesador didáctico ERIC Figura 14: Esquema de bloques del corazón del procesador (CPU_CORE.SCH) Estructura del microprocesador 4.4.2.1. 45 El acumulador y el registro auxiliar B La finalidad del acumulador y del registro auxiliar B, es la de servir de buffer temporal de datos. Estos datos pueden proceder de distintas fuentes: las memorias, de la ALU o del exterior. A nivel de diseño hardware, ambos registros han sido descritos en VHDL como un LATCH de 8 bits por flanco de subida, con entradas de LOAD y RESET asíncronas. Figura 15: El acumulador Cuando RST esta activa17 se pone a 0 todo el registro. El circuito, almacenará el dato presente en la entrada durante el flanco de subida de la señal de reloj, siempre que la señal LOAD, esté activa. 4.4.2.2. El registro de instrucción (IR) La finalidad del registro de instrucción, es la de servir de buffer temporal de una instrucción procedente de la memoria de programas. A nivel hardware, es un registro idéntico al acumulador. 4.4.2.3. El registro de estado (STATUS) La finalidad del registro de estado, es la de almacenar las banderas (C, Z y OV) procedentes de la ALU. A nivel hardware, es un registro idéntico al acumulador con la particularidad de ser de 4 bits. 17 Las señales se consideran activas a nivel alto salvo que se indique lo contrario. 46 4.4.2.4. Desarrollo del microprocesador didáctico ERIC El contador de programa (PC) La finalidad del contador de programa, es la de apuntar a la dirección de memoria desde donde se va a extraer la próxima instrucción. Aunque las direcciones son normalmente consecutivas, es posible que existan saltos en esta secuencia. Dichos saltos, pueden ser absolutos o relativos al valor que posea en ese momento el contador. Figura 16: El contador de programa La base para construir este módulo es un contador de 12 bits, es decir, de igual anchura que el bus de direcciones. El contenido del contador aparece en ADDR_OUT(11:0). La cuenta, se realiza en el flanco de subida de la señal de reloj siempre que E_PCUP y UP estén activas. El motivo por el cual existen dos señales de habilitación, tiene su origen en la forma en como se accede a la memoria ROM. Al ser ésta síncrona, se precisa de al menos18, un ciclo de reloj de espera para disponer del dato direccionado. Este hecho, imposibilita el acceder e incrementar el PC en una misma microinstrucción, ya que su duración es superior a un ciclo de reloj y el resultado de la cuenta sería errónea. Para solucionar este problema, se ha dispuesto de dos señales de habilitación: una de UP que utiliza la UC cuando desea incrementar en una unidad el valor del PC, y otra E_PCUP que es controlada por el contador de tiempos de espera, activándose 18 Idealmente un ciclo de espera es suficiente, aunque retardos debido al enrutado puede aconsejar incrementar este valor. Estructura del microprocesador 47 únicamente en el último ciclo de espera. De este modo, el PC sólo contará una unidad independientemente de lo que dure el tiempo de acceso a la ROM. Cuando se produce un salto en la secuencia, es necesario cambiar el contenido del contador. Cuando se trata de un salto absoluto, la señal LD (LOAD) cambia el valor de cuenta por el presente en ADDR_IN(11:0). Si el salto es relativo, se deberá activar la señal REL; esto ocasiona que se realice la suma, en complemento a dos, entre los bits ADDR_IN(7:0) y el valor actual del contador. Todas estas operaciones se realizan de manera síncrona. El contador posee adicionalmente dos señales de RESET asíncronas. RST0 pone el contador a 0x000 y se activa por parte de la UC en el momento de atención a una interrupción. RST2 pone el contador a 0x002 y se activa con la señal de RESET global del procesador. 4.4.2.5. El registro de direccionamiento de memoria (MAR) La finalidad del registro MAR, es la de servir de apoyo al PC en los momentos en que se necesita acceder temporalmente una posición de memoria, que difiere de la disponible en el PC. Este hecho está normalmente asociado, al uso de instrucciones de transferencia. Adicionalmente a esta función, MAR también es utilizado como buffer temporal vinculado al PC. Figura 17: El registro de direccionamiento de memoria Cuando se ejecuta una instrucción de transferencia es posible encontrarnos con varios tipos de direcciones: addr4, add8 y addr12. 48 Desarrollo del microprocesador didáctico ERIC Para comprender bien la relación de MAR, con el resto de los bloques, es importante recordar como vienen codificadas las direcciones antes comentadas: addr4 se debe extraer de IR, addr8 de un segundo byte y addr12 de IR y del segundo byte. Por este motivo, es necesario desglosar el bus de direcciones de entrada en 2 bloques y disponer de 3 señales de carga. Figura 18: Relación de MAR con otros bloques del circuito De este modo si se desea cargar una dirección: addr4 Se activará LD4 y se cargarán los datos presentes en ADDR_H(3:0). addr8 Se activará LD8 y se cargarán los datos presentes en ADDR_L(7:0). addr12 Se activará LD12 y se cargarán los datos presentes en ADDR_H(3:0) y en ADDR_L(7:0) Estructura del microprocesador 49 La carga de estos datos se realiza de manera síncrona. El dispositivo dispone de una señal de RST asíncrona que al ser activada pone el registro a 0. En las instrucciones de salto, MAR también es utilizado para almacenar temporalmente la dirección de salto, que posteriormente se cargará en el PC. 4.4.2.6. Multiplexores y bufferes triestado Para poder controlar el camino que va a seguir los datos en el interior de la CPU, es necesario el uso de multiplexores y bufferes triestado. En este diseño se han incluido los siguientes bloques: BUFT4: Buffer triestado. La entrada es una señal de 4 bits y la salida una de 8 bits. Cuando está activo, los 4 bits de mayor peso son 0 y los de menor peso proceden de la señal de entrada. MUX2_4: Multiplexor de 2 entradas de 4 bits. MUX2_8: Multiplexor de 2 entradas de 8 bits. MUX2_8Z: Multiplexor de 2 entradas de 8 bits con salida triestado. MUX2_12: Multiplexor de 2 entradas de 12 bits. MUX2P_8Z: Multiplexor de 2 entradas, una de 8 bits y otra de 4 bits con salida de 8 bits triestado. En un caso selecciona la señal de 8 bits y en el otro, la señal de 4 bits completándola con 0 en la parte alta. Figura 19: Multiplexor tipo MUX2_8Z 50 4.4.2.7. Desarrollo del microprocesador didáctico ERIC La Unidad Aritmético Lógica (ALU) La finalidad de la ALU es realizar operaciones de tipo lógico o aritmético. Se trata de un circuito combinacional, que realiza una operación utilizando las entradas A(7:0) y B(7:0) obteniéndose el resultado en C(7:0). La operación a realizar se selecciona por medio de las señales de control CTRL(3:0). Algunas operaciones, modifican alguno de las banderas (Carry, Zero y Overflow). En estos casos, el resultado se presenta en FLAGS_OUT(3:0) para su posterior escritura en el registro de estado. Por otra parte, hay operaciones que precisan conocer el registro de estado para ser evaluadas. La entrada de esta información se realiza vía FLAGS_IN(3:0) Figura 20: Unidad Aritmético Lógica Con 4 bits de control es posible realizar 16 operaciones. El código elegido para realizar cada una de las operaciones, está íntimamente relacionado con el código de operación de las instrucciones aritméticos/lógicas. Si analizamos el juego de las instrucciones del grupo lógico, aritmético y de flags correspondientes al tipo ALU, tal como ya comentamos al hablar de los formatos de las instrucciones, veremos que el campo C3 coincide con el código de control de la ALU. De este modo, al decodificar la instrucción por parte de la Unidad de Control, simplemente hay que asignar el contenido del C3 directamente a las líneas de control de la ALU. Estructura del microprocesador 51 Veamos que operaciones realiza la ALU. COD. CTRL 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 NEMOTÉCNICO ALU_OPC_ADDC ALU_OPC_SUBC ALU_OPC_INC_A ALU_OPC_DEC_A ALU_OPC_INC_B ALU_OPC_DEC_B ALU_OPC_AND ALU_OPC_OR ALU_OPC_XOR ALU_OPC_CLR_A ALU_OPC_CPL_A OPERACIÓN CARRY ZERO OVERFLOW C= A+B+CARRY_IN X X X C= A-B-CARRY_IN X X X C= A+1 X C= A-1 X C= B+1 X C= B-1 X C= A AND B X C= A OR B X C= A XOR B X C= 0 1 C= NOT (A) X C(0)=CARRY_IN ALU_OPC_RLC_A X C(7:1)= A(6:0) 1100 ALU_OPC_RRC_A 1101 1110 1111 ALU_OPC_CLR_C ALU_OPC_SET_C ALU_OPC_CPL_C C(7)=CARRY_IN C(6:0)= A(7:1) - X - - 0 1 NOT C - - Tabla 10: Tabla de operaciones de la ALU ALU_OPC_ADDC: Suma el contenido del registro A y B junto con el acarreo disponible en el registro de estado (CARRY_IN). ALU_OPC_SUBC: Resta el contenido del registro B junto con el acarreo disponible en el registro de estado (CARRY_IN), del registro A. ALU_OPC_INC_A: Incrementa el valor de A. ALU_OPC_DEC_A: Decrementa el valor de A. ALU_OPC_INC_B: Incrementa el valor de B. ALU_OPC_DEC_B: Decrementa el valor de B. ALU_OPC_AND: Realiza la operación lógica AND entre A y B. ALU_OPC_OR: Realiza la operación lógica OR entre A y B. ALU_OPC_XOR: Realiza la operación lógica XOR entre A y B. ALU_OPC_CLR_A: Pone el acumulador a 0. ALU_OPC_CPL_A: Invierte el contenido del acumulador. ALU_OPC_RLC_A: Desplaza el contenido del acumulador hacia la izquierda. 52 Desarrollo del microprocesador didáctico ERIC C 7 0 ALU_OPC_RRC_A: Desplaza el contenido del acumulador hacia la derecha. C 7 0 ALU_OPC_CLR_C: Pone la bandera de acarreo a 0. ALU_OPC_SET_C: Pone la bandera de acarreo a 1. ALU_OPC_CPL_C: Invierte el valor de la bandera de acarreo. Tal como vemos en la Tabla 10, algunas operaciones modifican el estado de las banderas. Las banderas existentes son: CARRY: Se pone a 1 si el resultado de la operación genera un acarreo. En el caso de la suma y de la resta, podemos considerar el acarreo como un 9 bit del resultado. ZERO: Se pone a 1 si el resultado de la operación es igual a 0. OVERFLOW: Se pone a 1 si el resultado de la operación genera un rebosamiento. El rebosamiento es útil cuando se realiza operaciones de suma o resta con signo. Se activa, cuando sumando dos números de un signo el resultado es del signo contrario. Algo similar ocurre en la resta cuando debiendo esperar un resultado de un signo, se obtiene el contrario. Estructura del microprocesador 4.4.2.8. 53 La Unidad de Control (UC) La finalidad de la Unidad de Control (UC) es generar las señales de control adecuadas que permitan coordinar las distintas partes de la CPU. El objetivo de estas señales es la ejecución de microoperaciones de procesado de la información, resultado de la interpretación de la instrucción. El núcleo de la UC es una máquina de estados de tipo Mealy. Como toda máquina de estados, dispone de una parte secuencial y una parte combinacional tal como se puede observar en la siguiente figura: Próximo Estado I (NS) N (Combinacional) P NS Estado Actual (CS) RESET (Secuencial) CS U T S Salidas Lógicas (Combinacional) O U T P U T S Figura 21: Diagrama de una máquina de estados tipo Mealy La máquina arranca de un estado inicial marcado por la activación de la señal asíncrona reset. A partir de ahí, y coincidiendo con el flanco de bajada del reloj, la máquina irá pasando de un estado a otro, en función de los valores que vaya tomando la variable próximo estado (NS). El valor de dicha variable, procedente de la parte combinacional, es una función de las entradas externas y del valor de estado actual (CS)19. 19 NS (Next State) y CS (Current State) 54 Desarrollo del microprocesador didáctico ERIC Figura 22: La Unidad de Control del ERIC Estructura del microprocesador 4.4.2.8.1. 55 Descripción de las señales Veamos el significado de cada una de las señales de entrada, que van a condicionar la evolución del a máquina de estados: CLK: Reloj. RST: Reset asíncrono. IR(3:0): Bus procedente del registro de instrucción. FLAGS(3:0): Bus procedente del registro de estado. MODE(1:0): Indicador del modo de funcionamiento. Los tres modos posibles son: ejecutar el programa en modo continuo, paso a paso o bien, proceder a la carga de un programa en la ROM. RISE_STROBE: Procedente del detector del flanco de subida de la señal STROBE. Esta señal permite la sincronización en el modo paso a paso (STEP) con el mundo exterior. La activación de la misma, indica a la UC que debe ejecutar otra instrucción. WAIT_STATE: Indica a la máquina de estados, que debe esperar por algún dispositivo que todavía no ha terminado su trabajo. Estos dispositivos son los de entrada/salida y las memorias. La espera se realiza introduciendo ciclos de espera, repitiendo el estado actual. IER: Señal procedente del registro de control de las interrupciones. Su activación le indica a la UC que hay una solicitud de interrupción. Veamos ahora el significado de las señales de salida manejadas por la UC: IO: Selección de un dispositivo de entrada/salida. RAM_CE: Selección de la RAM. ROM_CE: Selección de la ROM. STACK_CE: Selección del STACK. 56 Desarrollo del microprocesador didáctico ERIC WE: Escritura/lectura. PC_RST: Reset del contador de programa (PC). PC_UP: Incrementar PC en una unidad. PC_LD: Cargar dato en el PC. PC_REL: Sumar la dirección relativa presente en su entrada, con el valor actual del contador. E_PCUP: Habilita la señal PC_UP para que pueda contar. A_LD: Cargar dato en el registro A. B_LD: Cargar dato en el registro B. F_LD: Cargar dato en el registro de FLAGS. IR_LD: Cargar dato en el registro IR. MAR_LD4: Cargar dato en el registro MAR en el modo addr4. MAR_LD8: Cargar dato en el registro MAR en el modo addr8. MAR_LD12: Cargar dato en el registro MAR en el modo addr12. SC_UP: Incrementar el contador del STACK (SC). SC_DOWN: Decrementar el SC. HALT: Indica que el procesador está parado o a ejecutado la instrucción HALT. En cualquier caso, el procesador se encuentra detenido. SNIF_RST: Reiniciar el bloque SNIFFER. ENABLE_IER: Habilita interrupciones. DISABLE_IER: Deshabilita interrupciones. STATE(3:0): Muestra el estado en que se encuentra la UC. ALU_CTRL(3:0): Señal de control de la ALU. S_MUXn: Selección de la señal del multiplexor MUXn E_MUXn: Habilita la salida del multiplexor MUXn en el caso de los multiplexores triestado. E_BUFn: Habilita la salida del buffer BUFn. Estructura del microprocesador 4.4.2.8.2. 57 El diagrama de estados Toda máquina de estados, lleva asociado un diagrama de estados que indica como se va a comportar dependiendo de las señales de entrada. Este diagrama ha de contemplar por un lado la ejecución de las distintas instrucciones y por otro lado, las mejoras que se han introducido al diseño como son, la ejecución paso a paso, continuo y carga de la memoria ROM. Como ya veremos en otro apartado de esta memoria, la ejecución de una instrucción está estructurada en una serie de fases básicas que podemos resumir: FETCH: Fase de búsqueda de la instrucción. La UC genera las señales de control que va a permitir cargar una instrucción procedente de la ROM, en el registro de instrucción. DECODE: Fase de decodificación y lectura de operandos. EXECUTE: Fase de ejecución. Con los datos de IR y la lectura de operandos adicionales se procede a la ejecución de la instrucción, mediante la generación de las señales de control pertinentes. Aunque en la mayoría de los casos, estos tres estados son suficientes, algunas instrucciones por su complejidad precisan de un mayor número de estados. En concreto aquellas instrucciones relacionadas con direccionamientos indexados (MOV/X A,@B), o con tratamiento de subrutinas pertenecen a este tipo (CALL, RET y RETI). Para dar soporte a estas instrucciones, se ha ampliado el grafo con los siguientes estados: STORE: Utilizado por las instrucciones con direccionamiento indexado. SUBR1 … 3: Utilizado por la instrucciones con llamadas y retorno de subrutinas. 58 Desarrollo del microprocesador didáctico ERIC Al margen de la ejecución de las instrucciones, la máquina de estado debe dar soporte a las interrupciones, a los distintos modos de ejecución y a la carga de programas. Ello implica un mayor número de estados: RESET: Estado inicial de arranque al partir del cual se bifurca en función del valor de la señal MODE(1:0). Esta señal va a condicionar o bien, los modos de ejecución o bien pasar a modo de carga de programa en ROM. ERROR: Estado que alcanzará la máquina de estados en el caso de tener que interpretar una instrucción no soportada. STOP: Estado que alcanzará la máquina de estados al interpretar la instrucción HALT. END_CYCLE: Cada vez que una instrucción termina su ejecución pasará a este estado, salvo que se trate de la instrucción HALT. Dependiendo del modo de ejecución, se puede continuar ejecutando instrucciones, o bien esperar por la señal de sincronización STROBE. Si las interrupciones están habilitadas, éstas son procesadas a partir de este punto. INT1 … 4: Estados implicados en la atención a una interrupción. LOAD1 … 6: Si la señal MODE(1:0) esta en modo LOAD, esto le indica a la máquina de estados que debe ponerse en modo carga de programa. La máquina evolucionará a lo largo de todos estos estados hasta terminar la carga, donde la UC deberá ser reiniciada. En cada uno de estos estados, las señales de salida van adoptando distintos valores que permiten la ejecución de las distintas microinstrucciones en que se divide la instrucción, o bien los procesos antes reseñados de carga y ejecución. Dado que este apartado es de vital importancia para entender el funcionamiento del procesador, vamos a posponerlo y representar únicamente, de manera gráfica, la máquina de estado mostrando la interconexión entre los distintos estados, así como, las señales implicadas. Estructura del microprocesador 59 RESET MODE=STEP & STROBE=0 RESET MODE=LOAD MODE=RUN MODE=STEP & STROBE=1 LOAD1 FETCH LOAD2 DECODE STOP EXECUTE ERROR STROBE=0 STROBE=1 LOAD3 LOAD4 STROBE=1 STORE SUBR1 LOAD5 SUBR2 LOAD6 SUBR3 STROBE=0 MODE=RUN MODE=STEP & STROBE=1 END_CYCLE IER=1 MODE=STEP & STROBE=0 INT1 INT2 INT3 INT4 Figura 23: Diagrama de estados de la Unidad de Control 60 4.4.2.8.3. Desarrollo del microprocesador didáctico ERIC El registro de gestión de interrupciones (IER) Dentro de la unidad de control, también es posible encontrar algunos bloques necesarios para una correcta gestión de algunas señales. Uno de estos bloques, es el registro de gestión de interrupciones (IER) que dependiendo de su programación permite o inhibe las interrupciones, controlando de este modo su atención por parte de la máquina de estados de la UC. Figura 24: Registro de gestión de interrupciones Si se activa la señal ENABLE, el registro aceptará interrupciones memorizando en la salida cualquier cambio en positivo que se produzca en la entrada. Si se activa DISABLE, la salida se pone a 0, independientemente de lo que ocurra en la entrada. De este modo, es posible aceptar o rechazar una interrupción, a la vez que se almacena una solicitud para su posterior tratamiento. 4.4.2.8.4. El detector de flancos Otro bloque, que forma parte de la UC es el detector de flancos. Como el propio nombre indica, su función es la de detectar el flanco de subida, en este caso, de la señal STROBE para acondicionarla para su posterior uso por parte de la UC. La duración de esta señal no debe superar la duración de un ciclo, ya que la máquina de estados no funcionaría apropiadamente. Estructura del microprocesador Figura 25: Estructura interna de la Unidad de Control (CONTROL_UNIT.SCH) 61 62 4.4.2.8.5. Desarrollo del microprocesador didáctico ERIC El generador de ciclos de espera Cuando la máquina de estados, accede a partes del circuito más lentos que ella misma, ésta ha de esperar. Dicha demora, se realiza prologando el estado actual a la espera de recibir una señal externa que le indique que puede continuar. Dicha señal externa procede de un bloque, implementado aquí dentro de la propia UC, y que se conoce como el generador de ciclos de espera. La señal externa es WAIT_STATE, ya descrita al comentar las señales de entrada a la máquina de estados. Cuatro, son los dispositivos que precisan que se espere por ellos, que son: los distintos bloques de memoria, es decir, la ROM, RAM y el STACK, así como, los dispositivos de entrada/salida. En el caso de la memoria síncronas, los datos invierten un ciclo de reloj desde que son aceptados hasta la devolución del resultado. Por ejemplo, en el caso de la lectura por parte de la máquina de estados, ésta escribirá la dirección coincidiendo con un flanco de bajada de la señal de reloj. En el flanco de subida siguiente, la memoria aceptará la información y en el siguiente entregará el dato solicitado. Por lo tanto, es preciso introducir un ciclo de espera, valor que puede verse incrementado si a las características intrínsecas de las memorias le añadimos los efectos debidos a los retardos de propagación de las señales, en el interior de la FPGA. La diferencia de velocidad entre la CPU y los dispositivos externos obliga también, a esperar. Esta diferencia puede ser mínima en algunos casos y muy amplia en otros. Para poder configurar independientemente, los ciclos de espera para cada uno de los casos descritos, se ha diseñado este bloque como la suma de cuatro. Cada subunidad está formado por un contador que es disparado por las señales de selección pertinente: RAM_CE, ROM_CE, STACK_CE e IO. Por defecto, cada contador posee un valor de cuenta coincidente con el número de ciclos de espera programado. Cuando se activa la señal, se inicia una cuenta regresiva que finaliza al alcanzar el valor 0. Durante el último ciclo, se activa la señal de WAIT_STATE, indicándole a la máquina de estados que la espera ha terminado, y que puede continuar. Estructura del microprocesador Figura 26: Subunidades del bloque de estados de espera (WAIT_STATES.SCH) 63 64 Desarrollo del microprocesador didáctico ERIC Cuando se describió el contador de programa, se comentó el problema que existía al intentar realizar el incremento conjuntamente con el acceso a la memoria ROM. El problema, consiste en que, no se puede activar la señal de incrementar sin más, ya que el acceso a la memoria ROM precisa de más de un ciclo de reloj, lo que ocasionaría que el contador contase más de una unidad. La solución pasa, por aprovechar el generador de tiempos de espera asociado a la ROM, para proporcionar una ventana temporal al finalizar la espera. Figura 27: Cronograma del generador de ciclos de espera asociado a la ROM En el anterior cronograma, podemos ver que el contador de ciclos de espera, tiene programado un valor de 3. Al activarse ROM_CE, representado aquí como la señal RST, se inicia el decremento activándose la señal WAIT_STATE. Cuando el contador alcanza el valor 0, WAIT_STATE vuelve a su valor inicial indicando que la espera a terminado. E_PCUP, es la señal utilizada por el contador de programa, para incrementar su valor en una unidad. Cuando el valor de cuenta vale 1, es decir un ciclo de reloj antes de que concluya el contador, se genera un pulso. Este pulso, es demorado medio ciclo de reloj, con el fin de hacer coincidir el flanco de subida a la mitad de la ventana temporal, momento en que el contador realizará su incremento. Estructura del microprocesador 4.4.2.9. 65 El Sniffer La finalidad de este bloque, es permitir el acceso al contenido de los registros internos del ERIC desde el mundo exterior. Otra función que realiza, es la de posibilitar la introducción de datos desde el exterior con destino a la memoria ROM. Desde el punto de vista funcional, este bloque no puede ser considerado como parte de un procesador ya que no está involucrado en el procesado de la información, cumpliendo únicamente una función de introducción/extracción de la información interna. Por este motivo, en el esquema, este bloque es mostrado con un color/tono distinto del resto. La información proporcionada, junto con el uso del programa EricMON, es de mucha utilidad, para poder entender y seguir como se va modificando el contenido de los registros, según se va interpretando cada instrucción. También es de mucha utilidad, en la fase de desarrollo, ya que permite analizar una gran cantidad de información. Figura 28: Bloque SNIFFER El diseño de este bloque se ha realizado en dos partes: una dedicada a la captura de la información hacia el exterior, y otra que permite la introducción de la información desde el exterior hacia el bus de datos interno del procesador. 66 Desarrollo del microprocesador didáctico ERIC La parte dedicada a la captura de datos de los registros ha sido realizada con un contador de 7 bits conjuntamente con un multiplexor de 16 entradas de 4 bits. Se ha elegido este número de entradas por ser común divisor de todos los registros, puesto que los hay de 4, 8 y de 12 bits. La lectura, se realiza por medio de una única línea de salida SNIF_DOUT, sincronizada por un reloj externo denominado SNIF_CLK. La ejecución de los pasos precisos para la lectura, es una acción combinada entre la UC, el SNIFFER y el programa EricMON, que son expuestos a continuación: 1. El proceso se inicia con la inicialización del contador por parte de la UC, a través de la señal SNIF_RST. Este evento se producirá, cada vez que la UC inicie la fase FETCH de interpretación de una instrucción, o bien en algún otro caso donde se requiere leer el contenido de los registros, por ejemplo en la carga de datos en modo LOAD. 2. Tras el reset, el contador se posiciona en el valor más alto, multiplexando en este caso la señal de HALT de la UC. Esta señal permite al EricMON conocer cuando el ERIC ha terminado de procesar una instrucción, y proceder a su lectura. 3. Cuando EricMON decide su lectura, va generando pulsos a través de SNIF_CLK, obteniendo el valor de un bit multiplexado por la línea SNIF_DOUT. Se pueden leer hasta 16x4 bits de información, por lo que será preciso generar toda esta cantidad de pulsos y lecturas. EricMON irá agrupando esta información, reconstruyendo los datos originales de los registros. 4. Con la lectura del último bit el proceso concluye. En ese momento, EricMON generará una señal de STROBE, para indicar a la UC que puede continuar con otra instrucción, lo que desencadenará el regreso al paso 1 antes descrito. Reseñar que el proceso de lectura sólo se produce en el modo de ejecución paso a paso (STEP). La siguiente tabla, resume la asignación de los distintos registros a las entradas del multiplexor: Estructura del microprocesador ENTRADA 0 1 2 3 4 5 6 7 8 9 A B C D E F REGISTRO A_REG(7:4) A_REG(3:0) B_REG(7:4) B_REG(3:0) F_REG(3:0) IR_REG(7:4) IR_REG(3:0) PC_ADDR(11:8) PC_ADDR(7:4) PC_ADDR(3:0) MAR_REG(11:8) MAR_REG(7:4) MAR_REG(3:0) SP_ADDR(7:4) SP_ADDR(3:0) STATE(3:0) 67 OBSERVACIONES Acumulador Acumulador Registro B Registro B Registro de estado (FLAGS) Registro de instrucciones Registro de instrucciones Contador de programa Contador de programa Contador de programa Registro MAR Registro MAR Registro MAR Contador del STACK Contador del STACK Estado de la unidad de control Tabla 11: Asignación de registros a la entrada del multiplexor del SNIFFER La parte dedicada a la introducción de datos desde el exterior, ha sido diseñada a partir de un registro de desplazamiento de 8 bits, que hace las funciones de conversor de datos serie-paralelo. Está conversión, sólo se realiza si el SNIFFER detecta, a través de la señales MODE(1:0), que el ERIC se encuentra en modo LOAD. En este modo, el bus de datos interno del ERIC está a disposición del SNIFFER. Veamos los pasos llevados a cabo en este proceso: 1. El proceso se inicia por parte de EricMON programando el modo LOAD a través de las señales MODE(1:0). La UC utilizará la señal de HALT como señal de sincronización, poniendo ésta a nivel activo. La combinación de ambos señales habilita el buffer triestado permitiendo que los datos del conversor vayan a parar al bus de datos interno del ERIC. 2. EricMON escribe bit a bit el dato que quiere enviar. Para ello sincronizará los pulsos de reloj de SNIF_CLK con la introducción de datos a través de SNIF_DIN. Al concluir con el 8 bit, generará un pulso de STROBE a la UC, indicándole que ya ha terminado, repitiéndose de nuevo todo el proceso. Para completar la comprensión sobre la interacción del SNIFFER con el EricMON, se recomienda la lectura del capítulo dedicado a este programa, sección modo LOAD. 68 4.4.3. Desarrollo del microprocesador didáctico ERIC El decodificador de 7 segmentos Para finalizar la descripción del esquema de bloques, solo nos queda por comentar el visualizador de 7 segmentos. Este bloque posibilita la presentación del estado en que se encuentra la UC, a través del visualizador de 7 segmentos disponible en la XSA-50. Figura 29: Decodificador binario a 7 segmentos La implementación se realiza mediante un decodificador, que traslada la codificación binaria del estado de la UC a un código alfanumérico a visualizar. Dicho codificador implementa la siguiente tabla: CÓDIGO 0 1 2 3 4 E H P A U L ESTADO RESET FETCH DECODE EXECUTE STORE ERROR HALT END_CYCLE SUBR1 … 3 INT1 … 4 LOAD1 … 6 Tabla 12: Códigos visualizados en función del estado de la UC ERIC y la XSA-50 4.5. 69 ERIC y la XSA-50 Hasta aquí, hemos visto las distintas partes en que ha sido divido el diseño del ERIC. Esta implementación, finaliza con la asignación de las señales del ERIC a los terminales físicos de la tarjeta elegida, la XSA-50 en este caso. A continuación, vamos a resumir la lista de conexiones relacionando, el número de terminal de la FPGA, el nombre de la señal que sale al exterior y la equivalente del ERIC. PIN P88 P50 P48 P42 P47 P65 P51 P58 P78 P77 P79 P80 P83 P84 P85 P86 P87 P93 P94 P66 P74 P75 P76 P67 P39 P62 P60 P46 P57 P49 P41 XSA-50 XCLK XPPD0 XPPD1 XPPD2 XPPD3 XPPD4 XPPD5 XPPD6 XPPS6 XD0 XD1 XD2 XD3 XD4 XD5 XD6 XD7 XIO XWE20 XADDR0 XADDR1 XADDR2 XADDR3 XLED0 XLED1 XLED2 XLED3 XLED4 XLED5 XLED6 XFLASHCE ERIC CLK RST MODE0 MODE1 STROBE IRQ SNIF_CLK SNIF_DIN SNIF_DOUT D0 D1 D2 D3 D4 D5 D6 D7 IO WE ADDR0 ADDR1 ADDR2 ADDR3 LED0 LED1 LED2 LED3 LED4 LED5 LED6 - OBSERVACIONES Señal de reloj Señal de reset Señal de selección de modo 0 Señal de selección de modo 1 Señal STROBE Señal IRQ Señal de reloj del SNIFFER Señal de datos de entrada del SNIFFER Señal de salida de entrada del SNIFFER Bus de datos D0 Bus de datos D1 Bus de datos D2 Bus de datos D3 Bus de datos D4 Bus de datos D5 Bus de datos D6 Bus de datos D7 Señal de selección de entrada/salida Señal de lectura/escritura (Invertida) Bus de direcciones. ADDR0 Bus de direcciones. ADDR1 Bus de direcciones. ADDR2 Bus de direcciones. ADDR3 Led 0 del visualizador de 7 segmentos Led 1 del visualizador de 7 segmentos Led 2 del visualizador de 7 segmentos Led 3 del visualizador de 7 segmentos Led 4 del visualizador de 7 segmentos Led 5 del visualizador de 7 segmentos Led 6 del visualizador de 7 segmentos Deshabilitación de la FLASH en la XSA. Tabla 13: Asignación de las señales del ERIC a lo terminales (pines) de la XSA-50 20 La señal WE se invierte al salir al exterior, para que sea activa a nivel bajo. 70 Desarrollo del microprocesador didáctico ERIC Para posibilitar la movilidad del diseño, y que pueda ser usado en otras tarjetas, se a diseñado un esquema de bloques por encima del nivel TOP (teóricamente el más alto), donde se relacionan las señales propias del ERIC, mostradas en el nivel TOP, con las particularidades propias de esta tarjeta simbolizadas por el bloque XSA 50 PINOUT. La idea es, que cuando se quiera adaptar el diseño a otra tarjeta sólo sea necesario modificar un único bloque, es este caso el XSA 50 PINOUT, y no tocar nada del resto del diseño. ERIC y la XSA-50 71 Figura 30: Adaptación de las señales del ERIC a la tarjeta XSA-50 (XSA50_PINOUT.SCH) 72 4.6. Desarrollo del microprocesador didáctico ERIC Ejecución de las instrucciones En este apartado, vamos a analizar el proceso interno de interpretación y ejecución de las instrucciones, donde se van ha ver implicados cada uno de los bloques que conforman el procesador. 4.6.1. Temporización de las señales La parte fundamental que coordina a cada uno de los bloques funcionales del procesador, es la UC. La Unidad de Control, va cambiando de estado sincronizadamente con el flanco de bajada del reloj. Por el contrario, el resto de elementos de la CPU realizan operaciones sincronizados por el flanco de subida. La razón de esto, es que la UC pueda activar las señales de control, dando tiempo suficiente para que se propaguen por el interior de la CPU, antes de que los elementos del procesador realicen su función. El tiempo de asentamiento de estas señales, desde que son generadas por la UC hasta que son utilizadas, es por lo tanto, de medio ciclo, diferencia entre el flanco de bajada y el de subida. En consecuencia, el tiempo de propagación de cualquier señal a de ser inferior a la mitad del ciclo de trabajo, limitando de este modo la frecuencia máxima de trabajo del procesador. ERIC funciona a una velocidad de 1 Mhz. Esta frecuencia ha sido elegida con el fin de minimizar los posibles problemas de propagación antes comentados. Se han hecho pruebas a 50 Mhz encontrándose inestabilidades en el diseño originado por estos retardos. Hay que pensar que medio ciclo de reloj a 50 Mhz son 10 ns, tiempo similar al retardo máximo reportado por el WebPACK. Bajando la velocidad a 1 Mhz, el procesador dispone de 500 ns, tiempo más que suficiente para la propagación de señales. El modo de funcionamiento de todo el sistema, salvo los elementos puramente combinacionales, es funcionar sincronizadamente con la señal de reloj. De este modo, la UC va habilitando ventanas temporales, normalmente de un ciclo de reloj de duración, durante el cual los elementos ejecutan su función sincronizadamente con el flanco de subida. Ejecución de las instrucciones 73 Cada grupo de señales de control, generadas durante un estado de la UC, es conocido como microinstrucción y es la base que determina que se realice una cosa y no otra, desglosando de esta manera, la ejecución de una instrucción en unidades más pequeñas. Las señales de control, involucradas en estas microinstrucciones, ya han sido comentadas al tratar la descripción de la UC. Con el fin de facilitar su tratamiento de forma tabular, así como de facilitar su implementación a la hora de definir el comportamiento de la máquina de estados, se han agrupado estas señales en un vector. Dicho vector es conocido como vector de señales (SV21) donde cada bit representa una señal de control. La siguiente tabla nos muestra esta relación: SV 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SEÑAL DE CONTROL IO RAM_CE ROM_CE WE PC_UP PC_LD IR_LD A_LD B_LD F_LD S_MUX1 HALT ENABLE_IER DISABLE_IER MAR_LD8 MAR_LD12 SV 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 SEÑAL DE CONTROL S_MUX2 S_MUX3 E_MUX3 SNIF_RST S_MUX4 S_MUX5 PC_REL STACK_CE SC_UP SC_DOWN E_BUF1 S_MUX6 E_MUX6 S_MUX7 MAR_LD4 PC_RST Tabla 14: Descripción del vector de señales (SV) 21 SV procede de Signal Vector 74 Desarrollo del microprocesador didáctico ERIC 4.6.2. Las interrupciones Aunque el tratamiento de una interrupción, no es una instrucción recogida en el juego de instrucciones de un procesador, a nivel interno es tratada como si lo fuera. La instrucción equivalente es la llamada a subrutina: ACALL addr12. La diferencia con esta instrucción es, que se desactiva el registro IER para que no se produzca ninguna interrupción durante la llamada de atención, y que la llamada es el resultado de un proceso hardware. Dado que a nivel de microinstrucciones es similar a ACALL, y que esta instrucción va a ser analizada en detalle en el apartado siguiente, sólo vamos a realizar una breve descripción de las tareas realizadas en cada estado: INT1: Se guarda la parte alta del PC en el STACK. INT2: Se incrementa el SC. INT3: Se guarda la parte baja del PC en el STACK. INT4: Se incrementa el SC, se deshabilita IER y se reinicia el PC a la posición 0x002. 4.6.3. La ruta de datos Un concepto, que aparece en los textos que tratan aspectos relativos a microprocesadores, es el de la ruta de datos22. Dicho concepto, define el camino seguido por los datos en las distintas fases en la ejecución de una instrucción. La representación gráfica de la ruta de datos, es una buena manera de mostrar como la UC va ejecutando cada una de las microinstrucciones. Con el fin de explicar la manera que tiene el procesador de ejecutar las instrucciones, vamos a elegir dos ejemplos representativos y proceder a analizar las distintas fases de ejecución, las señales de control que se activan, representado en cada caso la ruta de datos que sigue la información. Las instrucciones elegidas son: MOVX A,@B y ACALL addr12. 22 Datapath en inglés Ejecución de las instrucciones 4.6.3.1. 75 Ejemplo: MOVX A,@B Como podemos comprobar, revisando el juego de instrucciones, esta instrucción realiza una lectura de la memoria RAM depositando el dato en el acumulador. El modo de direccionamiento es el indexado, utilizando para ello el registro auxiliar B. Vamos a ver, los pasos implicados en cada una de las 4 fases en que ha sido dividida la instrucción: FETCH: Se va a buscar la instrucción a la ROM, en la posición indicada por el PC. El dato obtenido se guardará en el registro IR. Para ello se activa ROM_CE, IR_LD. Como es principio de instrucción se reinicia el SNIFFER por medio de SNIF_RST y se incrementa el PC con PC_UP. El acceso a ROM dispara el contador de tiempos de espera. DECODE: El contenido del registro B es encaminado hasta la entrada del registro MAR. Para ello, se activa las señales S_MUX3(E1), E_MUX3 y S_MUX4(E1). EXECUTE: Se guarda el dato procedente del registro B en MAR, activando la señal MAR_LD8. STORE: El dato guardado en MAR contiene la dirección donde está el dato que se debe guardar en A. Para proceder a su lectura, se activa S_MUX2(E1) para que la dirección de MAR pase al bus de direcciones, y se activa ROM_CE y A_LD. El acceso a ROM introduce ciclos de espera. INSTRUCCIONES ESTADO MOVX A,@B FETCH DECODE EXECUTE STORE io ram_ ce rom_ ce we pc_u p pc_ld ir_ld a_ld b_ld f_ld s_m ux1 halt en_ie r dis_ ier mar_ ld8 mar_ ld12 s_m ux2 s_m ux3 e_m ux3 snif_ r st s_m ux4 s_m ux5 pc_r el stac k_ce sc_u p sc_d own e_bu f1 s_m ux6 e_m ux6 s_m ux7 mar_ ld4 pc_r st La siguiente tabla resume los pasos antes descritos. 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Tabla 15: Resumen de los pasos necesarios para ejecutar MOVX A,@B VECTOR DE SEÑALES 2 0 0 2 A 0 0 1 0 0 0 0 0 0 2 0 1 6 6 8 0 8 8 0 0 0 0 0 0 0 0 0 76 Desarrollo del microprocesador didáctico ERIC Figura 31: Fase FETCH de la instrucción MOVX A,@B Figura 32: Fase DECODE de la instrucción MOVX A,@B Ejecución de las instrucciones Figura 33: Fase EXECUTE de la instrucción MOVX A,@B Figura 34: Fase STORE de la instrucción MOVX A,@B 77 78 Desarrollo del microprocesador didáctico ERIC 4.6.3.2. Ejemplo: ACALL addr12 La instrucción ACALL addr12 es una instrucción de salto a subrutina. El modo de direccionamiento es el directo, proporcionando la dirección de 12 bits parte codificada en la instrucción y parte en el segundo byte, tal como corresponde a la codificación de addr12. Como toda llamada a subrutina, el procesador ha de salvaguardar el contenido del contador de programa antes de realizar el salto. Vamos a ver los pasos implicados en cada una de las 6 fases en que se ha subdividido la instrucción: FETCH: Se va a buscar la instrucción a la ROM, en la posición indicada por el PC. El dato obtenido se guardará en el registro IR. Para ello, se activa ROM_CE, IR_LD. Como es principio de instrucción, se reinicia el SNIFFER por medio de SNIF_RST y se incrementa el PC con PC_UP. El acceso a ROM dispara el contador de tiempos de espera. DECODE: La UC decodifica la instrucción, analizando para ello los campos C1 y C2 del primer byte. Esto, le indica que debe proceder a la lectura de un segundo byte por lo que procede de nuevo a una lectura en la ROM. Para ello, se activa de nuevo ROM_CE, almacenando el dato entrante en el registro MAR junto a los 4 bits de menor peso de IR, activando para ello MAR_LD12. El acceso a ROM introduce de nuevo ciclos de espera. EXECUTE: Se guarda en el STACK la parte alta del PC, es decir los 4 bits de mayor peso. Para ello se activa S_MUX6(E1) y E_MUX6 del multiplexor M6, consiguiendo encaminar parte del PC por el bus de datos hacia la entrada del STACK. Mediante la activación de STACK_CE y WR se consigue escribir el dato en la pila, en la posición apuntada por el puntero del STACK (SC). El acceso al STACK ocasiona ciclos de espera SUBR1: Se incrementa el valor de SC. Esta instrucción dura exactamente un ciclo de reloj. Ejecución de las instrucciones SUBR2: 79 Se guarda en el STACK la parte baja del PC, es decir los 8 bits de menor peso. Para ello se activa S_MUX6(E0) y E_MUX6, del multiplexor M6 consiguiendo encaminar parte del PC por el bus de datos hacia la entrada del STACK. Mediante la activación de STACK_CE y WR se consigue escribir el dato en la pila, en la posición apuntada por el puntero del STACK (SC). El acceso al STACK ocasiona ciclos de espera SUBR3: Se incrementa el valor de SC y se carga en el PC, en dato previamente almacenado en el MAR, mediante la activación de la señal PC_LD. Esta instrucción también dura un ciclo de reloj. INSTRUCCIONES ESTADO ACALL addr12 FETCH DECODE EXECUTE SUBR1 SUBR2 SUBR3 io ram_ ce rom_ ce we pc_u p pc_ld ir_ld a_ld b_ld f_ld s_m ux1 halt en_ie r dis_ ier mar_ ld8 mar_ ld12 s_m ux2 s_m ux3 e_m ux3 snif_ rst s_m ux4 s_m ux5 pc_r el stac k_ce sc_u p sc_d o wn e_bu f1 s_m ux6 e_m ux6 s_m ux7 mar_ ld4 pc_r st Todo lo comentado con anterioridad, viene recogido en la siguiente tabla: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 VECTOR DE SEÑALES 2 2 1 0 1 0 A 8 0 0 0 4 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 1 8 0 8 0 0 8 0 8 0 Tabla 16: Resumen de los pasos necesarios para ejecutar ACALL addr12 El apéndice Microinstrucciones, recoge una descripción pormenorizada sobre las señales involucradas en cada una de las etapas en que se ha dividido la ejecución de cada una de las instrucciones del ERIC, de manera similar a la tabla anteriormente mostrada. 80 Desarrollo del microprocesador didáctico ERIC Figura 35: Fase FETCH de la instrucción ACALL addr12 Figura 36: Fase DECODE de la instrucción ACALL addr12 Ejecución de las instrucciones Figura 37: Fase EXECUTE de la instrucción ACALL addr12 Figura 38: Fase SUBR1 de la instrucción ACALL addr12 81 82 Desarrollo del microprocesador didáctico ERIC Figura 39: Fase SUBR2 de la instrucción ACALL addr12 Figura 40: Fase SUBR3 de la instrucción ACALL addr12 Capítulo 5 Desarrollo del software de soporte Adicionalmente al diseño e implementación del procesador ERIC, se han desarrollado una serie de programas de apoyo con el fin de facilitar el manejo del mismo. Se trata por un lado, de un programa monitor enfocado a explotar las posibilidades del ERIC de una manera más amigable, y por otro lado, de un ensamblador que permita la creación sencilla de programas. 5.1. EricMON A la hora de diseñar el ERIC, surgió la necesidad de dar solución a una serie de interrogantes sobre la forma de explotar, de una manera sencilla y amigable, las funcionalidades del procesador, en concreto el control de los modos de ejecución y la generación de interrupciones. Tradicionalmente, este control se ha realizado con la ayuda de pulsadores que mediante su activación desencadenan la generación de las señales pertinentes, permitiendo de este modo la ejecución paso a paso de un programa, pasar a modo ejecución continua o generar una interrupción en un momento dado. Aunque la solución, es aparentemente muy sencilla, adolece de una serie de inconvenientes: Precisa que la tarjeta de desarrollo posea pulsadores y en la cantidad adecuada. Este hecho condiciona la tarjeta de desarrollo a utilizar, puesto que las tarjetas más simples no poseen ningún pulsador, por lo que hay que recurrir a hardware 83 84 Desarrollo del software de soporte adicional. Por otro lado, los pulsadores que podemos encontrarnos en estas tarjetas son bastante simples y de bajas prestaciones. Precisa incluir en el diseño, circuitos antirebotes. El diseño del conjunto ERIC más pulsadores lo hace más dependiente de un tipo de tarjeta en concreto, dificultando su emigración a otro tipo de tarjetas. El uso repetitivo de los pulsadores puede llegar a ser tedioso, sobre todo, en el caso de la ejecución paso a paso donde cada paso requiere una pulsación. Adicionalmente a este problema, existía otro sobre que información interna del ERIC se quería visualizar y cómo. Lo común, en estos casos, es la utilización de visualizadores de 7 segmentos conectados a los registros que queremos estudiar. Esta solución, aunque sencilla, padece de serias limitaciones: Es preciso 2 visualizadores de 7 segmentos por cada registro que queremos mostrar ya que cada visualizador muestra 4 bits. Dado lo limitado de este tipo de dispositivos en las placas de desarrollo, que pueden variar desde ninguno hasta 4, la visualización se reduce a mostrar el contenido de 1 o 2 registros como máximo. Normalmente, el registro elegido es el acumulador, por ser uno de los más activos. Esta información es insuficiente para evaluar la evolución interna del procesador. La decodificación, de binario a 7 segmentos, debe ser realizada dentro de la propia FPGA, lo que obliga a incluir en el diseño módulos adicionales ajenos al propio procesador. En el supuesto de disponer de suficientes visualizadores de 7 segmentos, es preciso disponer en la FPGA de un gran número de terminales de salida, no siempre disponibles dependiendo del modelo de FPGA. Puesto que, el sistema de desarrollo de una FPGA obliga necesariamente al uso de un PC conectado a la tarjeta de desarrollo vía puerto paralelo, parece más apropiado para el control del ERIC el uso de estos recursos con la ayuda del software adecuado. Esto, motivó el diseño de un programa monitor al que se le denominó con el nombre de EricMON (Eric MONitor). A partir de las especificaciones ya comentadas, se procedió posteriormente a añadirle alguna funcionalidad más que a continuación se detalla. EricMON 5.1.1. 85 Descripción general del programa EricMON, es una aplicación MS-DOS que puede correr en cualquier máquina que disponga como sistema operativo Windows9x, Windows NT, Windows 2000 o XP. El programa ha sido estructurado en tres partes que controlan los dos modos posibles de ejecución así como la carga de un programa en ROM. En el apéndice Manual del monitor EricMON, podemos encontrar un manual sobre su uso. Cada uno de estos modos de trabajo, han sido denominados: LOAD Permite la carga de un fichero ensamblado en formato .BYTE en la ROM del procesador. RUN Ejecuta un programa en modo continuo (sin pausas entre instrucciones), permitiendo arrancar o detener el programa en cualquier momento. También es posible generar una interrupción durante la ejecución del mismo. STEP Ejecuta un programa en el modo paso a paso, visualizando en cada momento la evolución de la totalidad de los registros internos que conforman el ERIC. Dentro de este modo, es posible variar el número de pasos a realizar en cada interacción. También es posible generar una interrupción en cualquier momento del proceso. El programa ha sido escrito en C++, aunque se ha buscado la máxima sencillez en la programación, evitando intencionadamente las definiciones ininteligibles. En este sentido, el estilo de programación es más propio del C clásico, que de las complejas construcciones propias de las programaciones orientadas a objeto. Sin entrar en demasiadas profundidades, ya que el visionado de los ficheros fuentes son suficientemente explícitos, vamos a comentar las particularidades de cada uno de los modos. 86 5.1.2. Desarrollo del software de soporte Modo LOAD El cometido, de esta parte del programa, es cargar el contenido de un fichero ensamblado en la ROM del ERIC. El fichero deberá estar escrito en formato BYTE. El formato BYTE, es uno de los múltiples formatos de salida del ensamblador EricASM, que también se describe en este capítulo, y que se caracteriza en que cada línea del fichero describe una posición de memoria y el contenido de la misma en formato ASCII. Ejemplo: 0000: B0 0001: 2D 0006: 6F Vamos a ver las distintas etapas llevadas a cabo por el programa: 1. El proceso se inicia mostrando en consola las opciones posibles, lo que se consigue con la función PrintCommandLoad(). 2. A continuación, se le indica al procesador que se desea cargar un programa lo que se consigue con la ayuda de la función LoadMode(). 3. La pulsación de la tecla F, origina que se solicite el nombre de un fichero sin extensión, que deberá estar ubicado en el mismo directorio desde donde se está ejecutando el EricMON. El programa le añade la extensión .BYTE e intenta abrirlo. En el caso de que esta apertura sea fallida, se genera un mensaje de error y se aborta el proceso. 4. En caso afirmativo, se procede a su lectura línea a línea, escribiendo la información obtenida en un array que representa la imagen de la memoria de la ROM. El array es inicializado a 0 antes de proceder a la lectura del fichero. Los pasos 3 y 4 son llevados a cabo por la función ReadByteFile(). 5. El proceso de carga se realiza de manera sincronizada con el procesador, ya que realmente es el procesador el que realiza la escritura/lectura de los datos. La señal de sincronización es la señal HALT del procesador, que deberá estar a nivel alto indicando al programa que se encuentra listo. El programa comprueba esta condición y en el caso contrario el programa genera un mensaje de error y aborta el proceso. EricMON 87 Editor de Texto Ensamblar Fichero .ASM EricASM Cargar Fichero .BYTE EricMON Figura 41: Proceso a seguir desde el fichero fuente a la carga en el ERIC 6. Si todo está correcto, se procede a escribir el primer dato correspondiente a la posición de memoria 0x000, dado que el procesador ERIC se encuentra posicionado en este punto. La escritura se hace en serie, vía pin SNIF_DIN, generando un pulso de reloj de SNIF_CLK por cada bit. Este paso es llevado a cabo por la función Sniffer_Write(). 7. Al finalizar la escritura de un byte, se genera la genera un pulso de STROBE indicando al procesador que hay un dato listo. 8. A partir de esta señal de sincronización, el procesador copia el dato suministrado en el acumulador, y a partir de ahí, efectúa una operación de escritura en la memoria de programa. Una vez escrito, el procesador comprueba que el dato ha sido bien grabado procediendo a su lectura, dejando el resultado en el registro auxiliar B. La finalización de este paso es indicado al programa mediante la señal HALT del procesador. 9. El programa procede a leer el contenido interno de los registros mediante la función DumpLoad(), comprobando que el valor del PC y del registro B son los esperados. En caso negativo, se genera un mensaje de error y se aborta el proceso. 88 Desarrollo del software de soporte 10. Si todo va bien, se imprime la dirección y el dato procesado y se pasa a la siguiente posición del array, repitiendo los pasos del 5 al 10. Por su parte el procesador habrá incrementado en una unidad el valor del PC. Los puntos del 5 al 10 son llevados a cabo por la función Load(). En este apartado, solo queda comentar que la dimensión del array antes mencionado, es de 2048 posiciones, es decir, se corresponde con el tamaño de la ROM en versión reducida. Si se desea trabajar con otro tamaño de ROM, es necesario modificar el parámetro TAM_ROM23 y volver a compilar el programa. Figura 42: Ejemplo de una sesión en modo LOAD 23 Las variables y definiciones de EricMON se encuentran en EricPort.h EricMON 5.1.3. 89 Modo RUN El cometido de esta parte de la aplicación, es controlar el modo de ejecución del programa existente en memoria. En este modo, la ejecución se realiza de manera continuada sin la inserción de pausas entre la ejecución de instrucciones. Una vez cargado el programa, e introducidos en este modo, la ejecución se inicia mediante la pulsación de la tecla RETURN. Cada vez que se pulsa la tecla RETURN, el sistema conmuta entre los estados de ejecución y pausa. Durante la ejecución, es posible generar una interrupción mediante la pulsación de la tecla I. También es posible reiniciar la ejecución del programa pulsando la tecla R. Vamos a ver las distintas etapas llevadas a cabo por el programa: 1. El proceso se inicia mostrando en consola las opciones posibles, por medio de la función PrintCommandStep(). 2. El programa principal averigua si se ha pulsado alguna de las teclas anteriormente descritas. 3. Si se ha pulsado RETURN, se invoca a la función RunMode() que averigua el estado de ejecución del procesador, consultando internamente el valor de la variable running. En el caso de estar detenido, la función indica al procesador que se pase a modo RUN y en el caso contrario, que se pase al modo STEP. Esta situación va alternando entre RUN y STEP en cada pulsación de la tecla. 4. Si se ha pulsado la tecla I se invoca la función Interrupt(). 5. Si se ha pulsado la tecla R se invoca la función Reset(). Comentar en este punto, que es posible iniciar la ejecución de un programa, detenerlo y pasar al modo STEP para continuar su ejecución. 90 5.1.4. Desarrollo del software de soporte Modo STEP El cometido de esta parte de la aplicación, es controlar el modo de ejecución del programa existente en memoria. En este modo, la ejecución se realiza de manera interrumpida insertando una pausa entre la ejecución de cada instrucción. Una vez cargado el programa, e introducidos en este modo, la ejecución se inicia mediante la pulsación de la tecla RETURN. Cada vez que se pulsa la tecla RETURN, se ejecuta una instrucción y a continuación se muestra el estado de los registros internos del procesador ERIC. La visualización, diferencia mediante colores los cambios de estado de los registros entre lecturas consecutivas. El número de instrucciones ejecutadas en cada interacción es modificable, siendo el valor por defecto de 1. Al igual que pasaba en el modo RUN, es posible generar una interrupción pulsando la tecla I o bien reiniciar la ejecución pulsando R. Vamos a ver las distintas etapas llevadas a cabo por el programa: 1. El proceso se inicia mostrando en consola las opciones posibles, por medio de la función PrintCommandStep(). 2. A continuación, se programa el procesador en el modo STEP por medio de la función StepMode(). 3. El programa principal, averigua si se ha pulsado alguna de las teclas anteriormente descritas. 4. Si se ha pulsado RETURN, se genera un pulso en la señal STROBE del procesador, indicándole que ya puede ejecutar una instrucción. Esto se realiza mediante la función Strobe(). El programa queda a la espera de que ERIC le indique que a ejecutado la instrucción. 5. La señal utilizada para la sincronización de ambos procesos es la señal HALT. Cuando ERIC finaliza la ejecución de una instrucción activará esta señal indicando que se encuentra detenido. 6. En este punto, se procede a la lectura de los registros internos del ERIC con la ayuda de la función DumpStep(). La función generará un error de timeout EricMON 91 si la señal HALT no se activa en el espacio de tiempo de 2 sg. En este caso, la lectura se realiza igualmente pero los datos pueden no ser validos. 7. Se procede a la visualización mediante la función PrintDumpStep(). 8. Si la variable N, que indica el número de instrucciones a ejecutar por interacción, es mayor que 1 se repetirán los pasos 4, 5 6 y 7. 9. Si se ha pulsado la tecla I se invoca la función Interrupt(). 10. Si se ha pulsado la tecla R se invoca la función Reset(). Figura 43: Ejemplo de una sesión en modo STEP 92 Desarrollo del software de soporte 5.1.5. Implementación El punto de partida para la implementación del software, fue aprovechar la conexión con el puerto paralelo entre el PC y la tarjeta de desarrollo, como medio de intercambio de información. Dado que para la programación de la tarjeta, el puerto paralelo debe estar configurado como SPP (Standard Parallel Port) se eligió este modo como configuración de trabajo. Por otro lado, el SPP es el modo más sencillo de todos los posibles y además el más compatible. El siguiente punto a tratar fue el método a seguir para dialogar con el puerto paralelo. En los sistemas operativos Windows95 y 98 la programación del puerto paralelo se puede hacer de manera directa. No ocurre lo mismo, para los sistemas basados en el entorno NT ,es decir, Windows NT, 2000 y XP, donde la gestión del puerto paralelo es realizado en exclusiva por el sistema operativo, siendo necesario la instalación de un driver para posibilitar el acceso al mismo. Dado que el entorno de trabajo, para el diseño de la FPGA (WebPack) precisa de un sistema operativo NT y, que se buscaba una solución lo más abierta posible, se decidió acometer la programación del puerto paralelo vía driver. Para trabajar con las tarjetas de desarrollo de Xess, es obligatorio el instalar un conjunto de utilidades denominadas las XSTOOLS. Estas utilidades, realizan funciones de configuración de distintos aspectos de la tarjeta vía puerto paralelo, instalando para ello un driver conocido como UNIOO.DLL. Por otro lado, Xess suministra los ficheros fuente de sus utilidades por lo que a partir de esta información fue posible desarrollar el EricMON sin necesidad de empezar de cero y utilizando el mismo driver. Como ya se ha comentado, la instalación del driver UNIOO.DLL va implícita en la instalación de las XSTOOLS. En el caso de no trabajar con tarjetas Xess, es necesario instalar el driver de manera aislada, siendo esto posible con la ayuda del programa PORT95NT.EXE que se puede localizar en el CD de instalación de las utilidades de Xess, bien desde la web del fabricante, o bien en el CD que acompaña el proyecto. EricMON 5.1.5.1. 93 El puerto paralelo en modo SPP Aunque este puerto, fue diseñado originariamente para permitir la comunicación entre el ordenador y la impresora, a lo largo de la historia del PC han proliferado diseños ajenos a la impresión, que han aprovechado las capacidades de comunicación bidireccional de este puerto. El puerto paralelo del PC, dispone de 17 líneas de comunicación distribuidas en tres grupos: 8 líneas de datos, 4 de control y 5 de estado. Estas líneas han sido utilizadas en este proyecto para permitir la comunicación entre el ERIC y el programa EricMON. Veamos las características de cada una de estas líneas y su relación con el ERIC. PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 SEÑAL P. PARALELO CONTROL 0 DATA 0 DATA 1 DATA 2 DATA 3 DATA 4 DATA 5 DATA 6 DATA 7 STATUS 6 STATUS 7 STATUS 5 STATUS 4 CONTROL 1 STATUS 3 CONTROL 2 CONTROL 3 DIRECCION OUT OUT OUT OUT OUT OUT OUT OUT OUT IN IN IN IN OUT IN OUT OUT SEÑAL ERIC RST MODE 0 MODE 1 STROBE IRQ SNIF_CLK SNIF_DIN SNIF_DOUT - Tabla 17: Descripción de las señales del puerto paralelo y su relación con ERIC Para poder acceder a cada una de las señales, deberemos escribir o leer en la dirección del correspondiente registro de 8 bits: DATA Dirección base, normalmente la 0x378 (LPT1) STATUS Dirección base + 1. CONTROL Dirección base + 2. Como ya se comentó con anterioridad, la escritura y la lectura no puede realizarse directamente en entornos NT. 94 Desarrollo del software de soporte 5.1.5.2. Arquitectura software de las XSTOOLS El punto de partida del desarrollo, fue el estudio de la arquitectura de los distintos módulos de las XSTOOLS. En este punto, es necesario aclarar que las utilidades de XESS están disponibles en dos formatos: en modo gráfico y en modo línea de comando en formato texto. Por ejemplo, es posible descargar el fichero .bit en la FPGA utilizando bien la utilidad GXLOAD (para entorno Windows) o XSLOAD (entorno MS-DOS). Los ficheros fuentes, a los que nos referimos aquí, son los relativos a las utilidades en versión línea de comando. Las utilidades de las XSTOOLS 4.0 han sido desarrolladas con Microsoft Visual C++ 5.0, por lo que EricMON también está escrito en C++. Figura.44: Vista general del entorno de programación Visual C++ EricMON 95 Analizada la documentación, sobre la arquitectura del software de las XSTOOLS, nos encontramos con una descripción de objetos, métodos y clases que se resumen en la siguiente figura: Figura.45: Esquema jerárquico de los objetos de las utilidadaes XSTOOLS A pesar de lo amplio de la jerarquía de objetos de las XSTOOLS, EricMON sólo aprovecha las clases PPORT, XSError y Utils. De estas tres, sólo vamos a describir la PPORT por ser la que maneja el puerto paralelo, siendo las otras dos clases subsidiarias de PPORT y de escaso interés para el proyecto. Para más información, consultar en la sección de documentos del CD, XSTOOLS Source Documentation 4.0 96 Desarrollo del software de soporte 5.1.5.3. La clase PPORT PPORT es el objeto que maneja el puerto paralelo vía el driver UNIOO.DLL antes comentado. Dicha clase, ofrece una serie de métodos de los cuales sólo nos interesan tres: bool Setup(XSError* e, unsigned int n, unsigned int invMask); void Out(unsigned int v, unsigned int loPos, unsigned int hiPos); unsigned int In(unsigned int loPos, unsigned int hiPos) const; Setup(): Permite la inicialización del puerto paralelo, indicando el canal de errores a utilizar, el LPT del puerto paralelo, y una máscara de inversión. Out(): Permite la escritura en un registro del puerto paralelo. Existe un registro asignado a cada grupo de líneas del puerto paralelo, esto es: datos, control y status24. La función trata a los 3 registros de 8 bits como un único registro de 24 bits donde se reparte el primer byte (0 …7) para el registro de datos, segundo byte (8 … 15) para el registro de status y el último (16 … 23) para el de control. Dependiendo del valor asignado a loPOS y hiPOS tendremos acceso a todo el registro o sólo a una parte. Ej.- Si queremos escribir un dato en las líneas de C1 y C2 deberemos escribir OUT(dato,16,17). In(): Funciona de manera similar a OUT, salvo que realiza una operación de lectura y devuelve un dato entero. Ej. Para leer la línea S6 deberemos escribir dato=IN(8,8) Es importante mencionar que la tarjeta XSA-50 invierte las líneas D0 y D1 del bus de datos del puerto paralelo. El objeto PPORT realiza internamente este cambio, de tal modo que el dato no se ve afectado. No obstante, si vamos a utilizar otra tarjeta, es necesario proceder a la inversión de estas señales bien a nivel de hardware o a nivel de software. 24 Hay que tener en cuenta que PPORT puede trabajar también en modo EPP. EricMON 5.1.5.4. 97 La clase EricPORT La clase EricPORT, es una clase derivada de la PPORT y por lo tanto hereda los métodos antes comentados de configuración, lectura y escritura del puerto paralelo. Se han añadido nuevos métodos que dan respuesta a las necesidades funcionales de EricMON, y que a continuación se detallan: void Reset(void); void PrintVersion(void); void Interrupt(void); void PrintCommandEricmon(void); void Strobe(void); void PrintCommandStep(void); void RunMode(void); void PrintCommandRun(void); void StepMode(void); void PrintCommandLoad(void); void LoadMode(void); void PrintInterrupt(void); void Sniffer_clk(void); void PrintRun(void); int Sniffer_read(void); void PrintReset(void); void Sniffer_write(unsigned int a); void PrintPromptEricmon(void); int DumpStep(void); void PrintPromptStep(void); int DumpLoad(void); void PrintPromptRun(void); int ReadByteFile(void); void PrintPromptLoad(void); int Load(void); void PrintDumpStep(void); int hex2int(char *a); void PrintDumpLoad(void); Reset(): Genera un pulso en el terminal RST del procesador, consiguiendo de este modo la inicialización de la CPU. Interrupt(): Genera un pulso en el terminal IRQ del procesador, solicitando de este modo un servicio de atención a la interrupción generada. Strobe(): Genera un pulso en el terminal STROBE del procesador. Esta señal controla la evolución de la ejecución del proceso en el modo paso a paso. StepMode(): Asigna el valor 0 al bus MODE(1:0) del procesador. En este modo, el procesador ejecuta el programa en el modo paso a paso. Es el valor por defecto asignado al procesador al ser reiniciado. 98 Desarrollo del software de soporte RunMode(): Asigna el valor 1 al bus MODE(1:0) del procesador. En este modo, el procesador ejecuta el programa en el modo continuo. LoadMode(): Asigna el valor 2 al bus MODE(1:0) del procesador. En este modo, el procesador se dispone a recibir el programa para la ROM. Sniffer_clk(): Genera un pulso en el terminal SNIF_CLK. Esta señal controla la evolución del módulo SNIFFER, utilizado tanto para la lectura de los registros internos, como para la carga de datos en ROM en el modo LOAD. Sniffer_read(): Devuelve un byte, resultado de la lectura de la información disponible en el pin SNIF_DOUT del procesador. La lectura es serie. Sniffer_write(): Escribe un byte en el registro de desplazamiento del módulo SNIFFER del procesador. La escritura se hace vía el pin SNIF_DIN del procesador y por tanto es serie. DumpStep(): Realiza un lectura de la información disponible en los registros internos del procesador. La lectura se hace sincronizadamente con la señal HALT del procesador. Si transcurrido un tiempo (2 sg) el procesador no indica estar listo, se realiza igualmente la lectura generándose un error de timeout de lectura. La información obtenida queda almacena para su posterior visualización. DumpStep(): Igual que DumpStep(), salvo que se le ha retirado la parte de sincronización con el procesador y la gestión del timeout. ReadByteFile(): Solicita el nombre de un fichero ensamblado con extensión .BYTE. Si el fichero no se encuentra se genera un error de apertura. En caso afirmativo, interpreta el fichero según el formato BYTE, y genera internamente una imagen del contenido de la ROM. Load(): Carga la imagen generada por ReadByteFile() en el procesador ERIC vía bloque SNIFFER. La sincronización de los distintos pasos de la carga se realiza vía señal HALT del procesador. En el caso de no estar disponible se genera un error. Cada dato cargado es comprobado inmediatamente, procediendo a la lectura de lo grabado con la ayuda de la función DumpLoad(). En caso de que se detecte alguna incongruencia se genera un mensaje de error. EricMON 99 hex2int(): Interpreta una cadena ascii con caracteres hexadecimales y devuelve el valor entero correspondiente. PrintVersion(): Visualiza en consola el nombre del programa y su versión. PrintCommandEricmon(): Visualiza en consola la ayuda sobre los comandos disponibles en el menú principal de EricMON. PrintCommandStep(): Visualiza en consola la ayuda sobre los comandos disponibles en el submenú STEP. PrintCommandRun(): Visualiza en consola la ayuda sobre los comandos disponibles en el submenú RUN. PrintCommandLoad(): Visualiza en consola la ayuda sobre los comandos disponibles en el submenú LOAD. PrintInterrupt(): Visualiza el mensaje de solicitud de interrupción. PrintRun(): Visualiza en consola el mensaje de que el procesador está en ejecución si éste está detenido y viceversa. PrintReset(): Visualiza el mensaje de que el procesador ha sido reseteado. PrintPromptEricmon(): Visualiza en consola el prompt del menú principal. PrintPromptStep(), PrintPromptRun(), PrintPromptLoad(): Visualiza en consola el prompt de los submenús STEP, RUN y LOAD. PrintDumpStep(): Visualiza en consola el contenido de los registros internos del procesador, leídos previamente por la función DumpStep(). Se destacan aquellos valores que han variado desde la última llamada a la función. Los datos son mostrados en hexadecimal salvo el acumulador y el registro auxiliar que también se muestran en binario. Los banderas son visualizadas con su carácter representativo (C,Z y O). PrintDumpLoad(): Visualiza en consola el contenido de los registros PC y registro auxiliar B, leídos previamente por la función DumpLoad(). La razón de esta lectura, es que durante la carga de datos en ROM se realiza una comprobación del contenido en el registro B. 100 Desarrollo del software de soporte 5.1.5.5. La librería Console Aunque C++ dispone de clases que dan soporte a la visualización de aspectos gráficos en pantalla, lo cierto es que su definición resulta muy engorrosa y poco clara, por lo menos, para persona ajenas al mundo de la programación en C++. El hecho se agrava, cuando se trata de realizar aplicaciones en modo consola25. Con el fin de simplifica,r y a la vez hacer un código lo más claro posible, se decidió incluir dentro del proyecto la librería Console, de distribución gratuita y libre que incorpora al C++ las funciones habituales que se disponían en C de la librería CONIO.H (gotoxy, clrscr, textcolor, etc.). EricMON utiliza sólo alguna de las funciones disponibles que paso a comentar brevemente: textbackground (): Fija el color de la ventana, es decir del background. textcolor (): Modifica el color con que se va a visualizar el texto. clrscr (): Limpia la ventana y fija el cursor en la posición 1,1. delline(): Borra la línea donde está el cursor. El cursor se mueve hasta el primer carácter. gotoxy(): Mueve el cursor a las coordenadas fijadas por x e y. wherey(): Devuelve el valor de la coordenada y donde está el cursor. 5.1.6. Compatibilidad El uso de EricMON no está limitado a un entorno donde la protagonista sea una tarjeta de Xess. A pesar de utilizar funciones procedentes de las fuentes de las XSTOOLS, EricMON puede funcionar con variedad de hardware siempre que se tenga en cuenta algunas salvedades que garanticen su compatibilidad. 25 Aplicaciones que se ejecutan en ventanas tipo MS-DOS. EricMON 101 La tarjeta XSA-50, y en general todas las de la casa XESS, invierten los terminales D0 y D1 del puerto paralelo. Esta inversión ya es tenida en cuenta por la clase PPORT que de manera transparente al programador invierte el signo de estos 2 bits. Hay que tener la precaución, al trabajar con otras tarjetas, de invertir en el diseño estos dos bits o bien modificar el software para que no realice internamente esta inversión. Si no se instalan las XSTOOLS, deberemos instalar por separado el driver de gestión del puerto paralelo, que podemos encontrar en el CD adjunto. Recordemos también que esta versión de EricMON, sólo soporta 2048 bytes de RAM, por lo que si queremos trabajar tamaños de ROM superiores es necesario volver a compilar el programa con las modificaciones oportunas. 102 5.2. Desarrollo del software de soporte EricASM En el desarrollo del proyecto, surgió la necesidad de disponer de un ensamblador que facilitase la construcción de los programas que debería correr después en ERIC. La codificación manual de programas, aparte de ser engorrosa es susceptible de multitud de errores, por lo que el manejo de una herramienta de este tipo es siempre deseable. Por otro lado, tenemos que la construcción de un ensamblador con un mínimo de prestaciones como puede ser: un buen detector de sintaxis, flexibilidad a la hora de escribir el código fuente, soporte a etiquetas, etc., no es una tarea fácil y en cualquier caso laboriosa. Por este motivo, en lugar de desarrollar un ensamblador desde cero se optó por investigar si era posible disponer de algún programa de libre distribución que fuese susceptible de ser adaptado al procesador ERIC. Dado que ERIC está inspirado en el juego de instrucciones del 8051, se inicio la búsqueda en Internet de un ensamblador del 8051 que proporcionase su código fuente y que fuese de dominio público. Tras analizar múltiples programas, sopesando siempre la complejidad del software, la búsqueda concluyó con el AS31. Este software es fruto del trabajo de Ken Stauffer (Universidad de Calgary), aunque a lo largo de esta última década a sido mejorado con la contribución de otras personas. Por lo tanto, EricASM es una versión del AS31 al que se le ha modificado lo necesario para adaptarlo del 8051 al ERIC, heredando de este modo toda la funcionalidad del programa original. EricASM 5.2.1. 103 Descripción general del programa EricASM es una aplicación MS-DOS, que puede correr prácticamente en cualquier máquina del tipo PC. El único requisito del sistema operativo, es que permita ejecutar aplicaciones MS-DOS, por lo que funciona perfectamente en cualquier entorno Windows. El programa posee las prestaciones propias de un ensamblador comercial como son: Soporte de directivas (.equ, .org, .db, .byte …). Número en múltiples formatos (hex, bin, octal, decimal). Manejo de expresiones (+, -, *, / , mod, desplazamientos, etc.). Manejo de etiquetas. Cálculo automático de direcciones a etiquetas. Múltiples formatos de salida (byte, hex, srec, …) Es posible encontrar un manual de uso en el apéndice: Manual del ensamblador EricASM. 5.2.2. Implementación Cada vez que alguien diseña un ensamblador o un compilador, ha de acometer la programación de una serie de procedimientos comunes a todas estas aplicaciones. Estos procedimientos, podrían resumirse, en realizar análisis sintácticos en función de unas normas establecidas, convertir los códigos nemotécnicos en códigos binarios, detectar etiquetas y generar una base de datos de ellas para posteriormente referenciarlas, etc. Yacc y Bison son herramientas desarrolladas para la creación de compiladores26. A partir de la descripción de reglas sintácticas, nemotécnicos, etc., estos programas son capaces de generar ficheros fuentes, normalmente en lenguaje C, simplificando la labor de programación. El EricASM está escrito en Yacc. 26 Un ensamblador no deja de ser un tipo particular de compilador. 104 Desarrollo del software de soporte Veamos los ficheros implicados en el programa y la función de cada uno de ellos: PARSER.Y: Es el fichero en formato Yacc. En el se especifican los nemotécnicos de las distintas instrucciones, así como la reglas que rigen las sintaxis del ensamblador. El fichero es pasado al programa Yacc dando como resultado el fichero parser.c que se deberá compilar y linkar con el resto de los programas en C. EMITTER.C Dentro de este fichero, están definidos cada uno de los modos de salida soportados (Hex, Byte, Srec ….). LEXER.C Este fichero proporciona las reglas léxicas del ensamblador. SYMBOL.C Este fichero, contiene las equivalencias entre los símbolos y el código hexadecimal que debe aparecer en el fichero ensamblado. ERICASM.C Programa principal, desde donde se invocan los distintos programas según las opciones elegidas. Solo ha sido necesario modificar dos ficheros para adaptar el AS31 al EricASM. Estos ficheros son PARSER.Y y SYMBOL.C. El fichero ERICASM.C simplemente es el resultado de renombrar el nombre del compilador original AS31.C. La compilación de las distintas partes del programa, ha sido realizada con la ayuda del entorno de programación de libre distribución DJGPP (GNU C y C++). El DJGPP es un entorno muy completo y complejo, con múltiples utilidades y que se puede descargar de la pagina web http://www.delorie.com/dgjpp. El CD adjunto al proyecto, incluye una copia del DJGPP utilizada en este proyecto. La gestión de la compilación del proyecto se realiza con la ayuda de la utilidad MAKE y el fichero MAKEFILE. Una de las ventajas de compilar el proyecto con un compilador GNU, es que su portabilidad al entorno UNIX de LINUX es bastante sencilla. Veamos someramente los cambios realizados en los dos ficheros antes mencionados. EricASM 5.2.2.1. 105 PARSER.Y Como ya se ha comentado PARSER.Y es un fichero fuente para ser utilizado con los compiladores YACC o BISON27. El fichero está estructurado en 5 partes denominadas: GRAMMER: En esta parte se definen los símbolos (TOKENS) que va a manejar el ensamblador. Estos símbolos, incluyen todas las instrucciones y nombre de registros. Esta parte ha sido adaptada al ERIC. DIRECTIVIES: Define la sintaxis de las distintas directivas soportadas. No se ha modificado nada con respecto al AS31. EXPRESSIONS: Define la sintaxis de las distintas expresiones soportadas por el ensamblador (+, -, *, /, etc.). No se ha modificado nada. INSTRUCTIONS: Define la relación de las instrucciones, definidas en el apartado GRAMMAR, relacionándolo con los modos de direccionamiento que se comentan a continuación. Esta parte ha sido modificada. ADDRESSING MODES: Define la sintaxis de los distintos modos de direccionamiento soportados por cada instrucción. Esta parte ha sido modificada. 5.2.2.2. SYMBOL.C Este fichero, define que código numérico va a insertar el ensamblador, en función de la instrucción y del modo de direccionamiento. El trabajo de adaptación ha consistido en cambiar las tablas donde se relacionan instrucciones y códigos. 27 Hoy en día se usa más BISON que YACC Capítulo 6 Prueba final Una vez descritas, tantos la parte hardware como software del proyecto solo queda probar el conjunto. Para la prueba, se decidió conectar el ERIC a un visualizador LCD con el fin de escribir un programa que verificase el buen funcionamiento de gran parte de las instrucciones del repertorio, especialmente las de entrada/salida. 6.1. Instalación de la prueba Para el buen funcionamiento de la prueba, es importante realizar una serie de pasos previos que garanticen una correcta interacción entre las distintas aplicaciones. Los ficheros necesarios pueden encontrarse en el CD adjunto. Los pasos son los siguientes: Instalación del driver de gestión del puerto paralelo. Esto puede realizarse bien instalando las utilidades de XESS, recomendado si se está trabajando con tarjetas de desarrollo de este fabricante, o bien instalar el driver de manera aislada mediante la utilidad PORT95NT.EXE, disponible en el CD anexo. Crear un directorio y copiar en él los programas EricASM y EricMON. Para evitar problemas, es recomendable que todos los ficheros generados por el ensamblador estén en el mismo directorio. Copiar el fichero LCD.ASM en el directorio anteriormente creado. Copiar el fichero ERIC.BIT en el directorio anteriormente creado. 107 108 6.2. Prueba final Conexión del LCD al ERIC El LCD, dispone de 16 señales distribuidas a lo largo de un conector de 8x2 pines. La siguiente tabla recoge la descripción de cada una de estas señales, los terminales correspondientes al LCD y su conexión con las señales del ERIC. PIN NOMBRE VSS 1 VDD 2 VO 3 RS 4 R/W 5 E 6 DB0 7 DB1 8 DB2 9 DB3 10 DB4 11 DB5 12 DB6 13 DB7 14 A 15 K 16 ERIC GND A0 WR IO D0 D1 D2 D3 D4 D5 D6 D7 - XSA-50 GND +5 GND P66 P94 P93 P77 P79 P80 P83 P84 P85 P86 P87 - DESCRIPCION GND +5 Aunque variable, funciona conectada a GND Selección de los registros IR o DR Lectura/Escritura Habilitación del dispositivo D0 del bus de datos D1 del bus de datos D2 del bus de datos D3 del bus de datos D4 del bus de datos D5 del bus de datos D6 del bus de datos D7 del bus de datos Iluminación +. No es obligatorio. Iluminación -. No es obligatorio. Tabla 18: Conexiones entre el LCD y la XSA-50 Aunque V0 se puede conectar a un potenciómetro para ajustar su tensión, la realidad es que prácticamente está a un potencial muy próximo a GND, por lo que en esta prueba se ha decidido conectarlo directamente a masa. Los terminales 15 y 16 del LCD son utilizados para la iluminación general y su conexión es opcional. El LCD dispone de dos registros: el IR o registro de instrucciones y el DR o registro de datos. A través del IR, la CPU envía los comandos al LCD: limpiar el visualizador, posicionar el cursor en una posición, hacer parpadear un carácter, etc. A través del DR la CPU envía los datos que desea representar. Es posible encontrar más información sobre el LCD y sobre su programación en el apartado de documentación del CD adjunto. Ejecución de la prueba 6.3. 109 Ejecución de la prueba Los pasos a realizar para ejecutar la prueba son: Ensamblar el fichero fuente LCD.ASM, para obtener un fichero BYTE que pueda ser descargado en el ERIC, mediante la ejecución de la siguiente sentencia: ericasm -Fbyte –L lcd.asm Descargar el fichero ERIC.BIT en la FPGA. Para ello podemos utilizar la utilidad gráfica GXLOAD o bien el comando en línea XSLOAD. En este último caso, la sintaxis completa del comando es: xsload –P 1 –fpga eric.bit Arrancar el programa EricMON. Una vez dentro, cargar el fichero LCD y proceder a su ejecución en modo RUN. Aunque es posible la ejecución en el modo STEP, no es recomendable dado los numerosos bucles programados que haría muy tedioso el seguimiento del programa. Si el programa se ejecuta correctamente deberemos ver el siguiente mensaje: Procesador ERIC Si durante la visualización del mensaje, generamos una interrupción pulsando la tecla I, podemos ver el siguiente mensaje: INTERRUPCION Capítulo 7 Conclusiones y líneas futuras 7.1. Conclusiones Tal como se describía en los objetivos del proyecto, se ha realizado el diseño e implementación del diseño de un procesador didáctico, con el fin de valorar la viabilidad de su implantación en una asignatura de electrónica, dentro del plan de estudios de un Ingeniero de Telecomunicaciones. Adicionalmente, se han desarrollado dos programas, creo que muy útiles, como herramienta de apoyo que facilitará alcanzar este objetivo por parte del alumnado. Otro de los objetivos marcados por el autor, ha sido también exponer el trabajo del diseño de la manera más didáctica posible, para que ésta sirva de base para la acción formativa por parte del profesor, facilitando el desglose controlado de información a partir de sus numerosos apéndices. La conclusión de todo el proyecto es que, aunque sin ser el diseño de un procesador didáctico una tarea que represente un reto especialmente complicado, su ejecución implica un gran número de horas de trabajo que pueden superar ampliamente el tiempo disponible en un laboratorio estimadas alrededor de 60 horas. Otro inconveniente, es el gran número de aplicaciones y conceptos que ha de manejar el alumno para poder acometer el diseño, puesto que ha de tener una base relativamente buena en el conocimiento del VHDL, así como conocer las distintas herramientas del entorno de 111 112 Conclusiones y líneas futuras desarrollo: captura de esquemas, conocer las librerías de la Spartan-II, detectar los problemas de síntesis, saber entender los informes, etc. Todos estos inconvenientes, pueden reducirse con una adecuada introducción por parte del profesor sobre algunos puntos teóricos especialmente delicados. A continuación describo algunos, que a mi entender precisan de esta atención: Describir de manera esquemática, pero clara, los recursos disponibles en las FPGAs, en concreto la posibilidad del disponer de bloques BRAM, su correspondiente primitiva en los esquemáticos y sus posibilidad de configuración. Si el alumno desconoce este recurso y el modo de utilizarlo, puede hacerle perder mucho tiempo, puesto que, la síntesis VHDL no infiere bien las descripciones de memorias síncronas, o bien hace uso de las LUT haciendo inviable el proyecto por falta de recursos. Suministrar un juego de instrucciones ya definido tanto a nivel funcional como de codificación binaria. El desarrollar por uno mismo un juego de instrucciones es algo realmente didáctico, pero que requiere una gran cantidad de tiempo y modificaciones constantes en el diseño. Si adicionalmente, se quiere reducir más el tiempo de diseño, es posible reducir el juego de instrucciones, eligiendo unas cuantas de cada grupo, ya que, instrucciones similares incrementan la complejidad del diseño pero no aportan un valor especialmente didáctico. Hay que recordar, que se puede desarrollar un microprocesador funcional con sólo 2 instrucciones. Pasar de un conocimiento del VHDL, desde un marco teórico a otro enfocado a la síntesis, también acarrea ciertas dificultades. Es importante que el alumno sepa escribir código VHDL que el sintetizador sepa inferir fácilmente. Esto es especialmente importante a la hora de describir las máquinas de estados. Una introducción adecuada sobre estas limitaciones puede ahorrar mucho tiempo. En el CD adjunto se añaden dos guías orientadas en este sentido. Otro aspecto importante, que se puede tener en cuenta para reducir los tiempos de implantación, sería el establecer un orden en el diseño haciendo algunas recomendaciones sobre como acometer determinadas partes del diseño. Por ejemplo, la implementación de la ROM no debe acometerse desde un principio Conclusiones 113 como un bloque RAM de la Spartan-II, sino que, es más recomendable definirla de tal manera que se puedan escribir pequeños programas. Al margen de estos problemas a nivel formativo que puedan surgir, hay otros relativos al equipamiento que también deberían tenerse en cuenta: La placa XSA-50, dispone de una gran cantidad de periferia que, en el diseño tratado en este proyecto, lejos de ser una ventaja es más bien un inconveniente. Documentarse y entender las peculiaridades de la tarjeta, requiere una cantidad considerable de tiempo. Por otra parte la conexión de dispositivos externos es bastante engorrosa. Por estos motivos, es aconsejable el uso de tarjeta de desarrollo más simple, mejor conectorizada y que simplemente posea la FPGA requerida. Las placas probadas de Digilent, propuestas por el tutor de este proyecto, son una buena opción. El entorno de desarrollo WebPack de Xilinx, tiene a su favor el ser un programa gratuito y con funcionalidad más que suficiente para acometer diseños como el abordado en este proyecto. En su contra, la exigencia de que el equipamiento informático sea de última generación, ya que por defecto demanda una máquina equipada con Windows XP, cuyos requisitos mínimos puede que no se corresponda con las dotaciones actuales de los laboratorios de prácticas. Por otro lado, aunque se cumplan estos mínimos, es preciso disponer de un ordenador bien equipado para que las fases de ensayo, prueba y error sea lo más ágiles posibles, ya que al contrario dilataríamos aun más el tiempo de desarrollo. Otro posible inconveniente es el uso del simulador ModelSIM. La versión de evaluación utilizada en este proyecto, está limitada a 500 líneas de código. Para el autor, esto ha sido más que suficiente ya que se han hecho muy pocas simulaciones y se ha utilizado básicamente el EricMON para la depuración de la Unidad de Control, que es la parte más compleja del sistema. Si el alumno deseará hacer un uso más intensivo del simulador, es probable que la limitación de líneas acarrease un problema. En este sentido, tal vez fuese aconsejable estudiar la viabilidad de convertir este proyecto al entorno Linux por las siguiente razones: 114 Conclusiones y líneas futuras El sistema operativo es gratuito y menos exigente a nivel de máquina. Es posible disponer de gran cantidad de compiladores y material de libre distribución, entre ellos simuladores VHDL. Es posible reprogramar con relativa facilidad los programas del proyecto. La adaptación del EricASM es prácticamente trivial y el EricMON se podría realizar sin muchos problemas, puesto que también existen fuentes de las XSTOOLS en Linux que podría servir de base para la adaptación. El único problema a este posible cambio, es que no hay una versión de WebPACK para Linux, y que habría que utilizar alguna de las variantes no gratuitas como ISE Foundation. Para cerrar este apartado, la conclusión final es que sí es viable, la implantación de la tarea de desarrollo de un procesador didáctico, siempre que se haga una adecuada planificación de la asignatura. De hecho, si analizamos los planes de estudio de algunas ingenierías que podemos encontrar en la red, podemos observar que la idea de diseñar un microprocesador sobre una FPGA ya ha sido llevada a la práctica, por lo que hay que suponer su viabilidad. Líneas futuras 7.2. 115 Líneas futuras Aunque el proyecto, en sí, es de suficiente complejidad para el objetivo perseguido, es posible incluir nuevos diseños como complemento al ERIC con el fin de mejorarlo, y dedicarlo a otros fines que los inicialmente propuestos. En este sentido, se pueden apuntar líneas futuras como: Integrar en la misma FPGA bloques que mejoren las comunicaciones con el exterior, como pueden ser un controlador de VGA, un controlador de comunicaciones serie, decodificadores de teclado, etc. Aumentar las prestaciones del procesador, incorporando nuevas instrucciones, nuevos modos de direccionamiento y un mayor nivel de manejo de interrupciones. Hacer una versión de ERIC con capacidad de procesado en pipeline. A nivel software también es posible mejorar las prestaciones del diseño, incorporando mayores prestaciones al EricMON como pueden ser: Simular un teclado y un terminal de texto, que permita interaccionar con el ERIC como si tuviésemos conectado físicamente estos dispositivos. Esto facilitaría la entrada y salida de datos con los programas diseñados, aumentando su valor didáctico. Posibilitar el visionado de las zonas de memoria RAM y STACK sin necesidad de destruir los datos, y poder descargarlos a disco para su análisis en otras aplicaciones. Posibilitar la descargar los datos obtenidos en modo STEP y grabarlos en un fichero para su estudio posterior. Incluir algún sistema de puntos de ruptura en modo STEP, del mismo modo que existe en los depuradores, tomando como base los valores que van tomando los datos visualizados en pantalla. Capítulo 8 Presupuesto Material Hardware CANT 1 1 1 1 1 1 CONCEPTO Ordenador Pentium IV 2,4 Ghz, 256 Mb, 80 G, monitor 17" Tarjeta de desarrollo XSA-50 de XESS Fuente de alimentación de 2A, 12 V LCD Cables puerto paralelo, alimentación y del LCD Material fungible (papel, toner, CDs, conectores, ...) TOTAL MATERIAL HARDWARE PRECIO UNIDAD 1.200 150 30 40 60 120 PARCIAL 1.200 150 30 40 60 120 1.600 € Material Software CANT 1 1 1 1 1 CONCEPTO Sistema operativo Windows XP Microsoft Office XP Compilador Microsoft Visual C++ 6.0 Xilinx WebPACK 5.2. Compilador GNU de C TOTAL MATERIAL SOFTWARE 117 PRECIO UNIDAD 180 360 600 - PARCIAL 180 360 600 1.140 € 118 Presupuesto Mano de obra de ingeniería CANT 100 16 230 40 40 16 100 1 CONCEPTO Estudio, documentación y análisis del proyecto Estudio del WebPACK Diseño e implementación de ERIC Programación de EricMON Adaptación de AS31 a EricASM Estudio y programación del test del LCD Redacción de la memoria Conceptos varios (encuadernación, viajes, etc.) TOTAL MANO DE OBRA DE INGENIERÍA PRECIO €/HORA 30 30 30 30 30 30 30 150 PARCIAL 3.000 480 6.900 1.200 1.200 480 3.000 150 16.410 € Presupuesto final CONCEPTO Material Hardware Material Software Mano de obra de ingeniería. PARCIALES 1.600 1.140 16.410 19.150 € TOTALES TOTAL + IVA (16%) 22.214 € IVA 16% 256 182 2.626 3.064 € Referencias [1] L. Jacobo Álvarez Ruiz de Ojeda. Diseño de aplicaciones mediante PLDs y FPGAs. Tórculo Edicións, 2001. [2] Fernando Pardo Carpio, José A. Boluda Grau. VHDL : lenguaje para síntesis y modelado de circuitos. RAMA 1999. [3] E. Mandado. Procesadores programables. El microprocesador. Boixareu Editores. 1980. [4] Michel A. Lynch. Microprogrammed State Machine Design. CRC Press, cop. 1993. [5] David A. Patterson, John L. Hennessy. Estructura y diseño de computadores. Editorial Reverté, S.A. 2000. [6] J. Frutos Redondo, R. Rico López. Arquitectura de computadores. Servicio de publicaciones de la Universidad de Alcalá de Henares. 1995. [7] M. Morris Mano. Ingeniería computacional: Diseño del hardware. PrenticeHall International, 1983. [8] Antonio García Guerra. Sistemas Digitales: Ingeniería microprocesadores: Servicio de publicaciones de la ETSIT-UPM. En formato electrónico PDF y disponibles en el CD adjunto: 119 de los 120 Presupuesto [9] Xilinx, Inc. ISE 5 In-Depth Tutorial. [10] Xilinx, Inc. Libraries Guide. [11] Xilinx, Inc. Synthesis and Simulation Design Guide. [12] Xilinx, Inc. Spartan and SpartanXL Families FPGA. [13] Xilinx, Inc. Programmable Logic Design Quick Start Hand Book. [14] Actel, Corp. Actel HDL Coding: Style Guide. [15] Xess, Corp. Introduction to WebPACK 5.2 for FPGAs. [16] Xess, Corp. XSA Parallel Port Interface. [17] Xess, Corp. XSA Board 1.0 User Manual. [18] Xess, Corp. XSTOOLs V4.0 User Manual. [19] Peter J. Ashenden. The VHDL Cookbook. Dept. Computer Science University of Adelaide South Australia. [20] Silicore, Corp. SLC1657 8-Bit Risc µC Core: Technical Reference Manual. [21] PowerTIP. PC 1602 H [22] Cristalfontz America, Inc. LCD PC 1602 H Contenido del CD Esta memoria se completa con el CD adjunto. El contenido del CD-ROM esta estructurado en los siguientes directorios, dónde podemos encontrar: Proyecto ERIC. Ficheros correspondientes al diseño del ERIC realizado con el programa Webpack 5.2. EricASM. Ficheros correspondientes al diseño del ensamblador. Xess. Ficheros de Xess, librerías y utilidades para la compilación del programa EricMON, realizado con el programa Microsoft Visual C++. Prueba. Ficheros necesarios para la realización de la prueba final. Programas DJGPP. Compilador de C/C++ de libre distribución utilizado para la compilación del EricASM. XSTOOLS. Incluye la versión 4.0 de las utilidades XSTOOLS utilizadas en este proyecto. Se incluyen también los ficheros fuente para Windows, sobre las que se ha desarrollado EricMON, y los ficheros fuente para Linux por si fuesen necesarios en un futuro. En el caso de no instalar las XSTOOLS, se incluye la utilidad para la instalación del driver necesario para poder trabajar con el EricMON (PORT95NT.EXE) WebPACK 5.2. Entorno de desarrollo utilizado para el diseño del ERIC. ConTEXT. Editor de texto para Windows de libre distribución, sobre el que se puede implementar un IDE. Se incluye el fichero de 121 122 Presupuesto configuración, con las palabras reservadas de ERIC, para que el programa las resalte en color. Memoria. Incluye la presente memoria en formato PDF y Word XP. Presentación. Incluye la presentación del proyecto en formato PowerPoint XP. Documentación. Incluye la documentación utilizada para la realización de este proyecto, en formato PDF. Utilidades. Incluye una ayuda para VHDL y las hojas de cálculo utilizadas para describir el juego de instrucciones y las tablas necesarias para el cálculo de los vectores de señal, de cada una de las instrucciones del ERIC. Apéndice A Juego de instrucciones (ISA) del ERIC Antes de adentrarnos en la descripción del juego de instrucciones del ERIC, es preciso echar un vistazo a algunos aspectos sobre la arquitectura del procesador con el fin de poder hacer un uso adecuado de las instrucciones. A.1. Registros internos ERIC dispone de tres registros accesibles por el usuario que son: A El acumulador. B El registro auxiliar con el que se realizan operaciones lógicas/aritméticas. También se utiliza como registro índice en algunas instrucciones de transferencia. F Registro de banderas (flags). Este registro está compuesto por las banderas de acarreo (C), zero (Z) y overflow (O) IER A.2. Registro para el control de las interrupciones. Memoria ERIC dispone de los siguientes bancos de memoria: RAM 256 bytes (0x00 … 0xFF). PILA 64 bytes (0x00 … 0x3F). ROM 2048 o 4096 bytes dependiendo del tipo de FPGA utilizada (0x000 … 0x7FF para XC2S30 ó 0x000 … 0xFFF para XC2S100). 123 124 Juego de instrucciones (ISA) del ERIC A.3. Modos de direccionamiento El juego de instrucciones de ERIC, maneja varios modos de direccionamiento que son codificados del siguiente modo: addr4 Representados por los bits de menos peso de la propia instrucción. Ej.IN A, 0x3 se codifica como 0x23 donde 0x2 indica la instrucción IN y 0x3 indica la dirección addr4 (0 0 1 1). addr8 Se codifica con la ayuda de un segundo byte que acompaña a la instrucción. Ej.- MOV A, 0xAA se compone de un primer byte 0xD0 que representa la instrucción y un segundo byte, 0xAA que representa la dirección addr8. addr12 Es una combinación de los modos anteriores. Los 4 bits de mayor peso de addr12 van codificados en los bits de menor peso de la instrucción. El resto de addr12 va en el segundo byte. Ej.- AJMP 0x8FF se descompone en 0x28 (0x2 & 0x8) y 0xFF para el segundo byte. rel Representado por un segundo byte en complemento a 2. Se pueden representar saltos relativos de +128/-127 #dato A.4. Representado por un segundo byte. Reset Cuando ERIC recibe la señal de reset, se ponen a 0 todos los registros y memorias, salvo la memoria ROM, que sólo se pone a 0 durante la operación de encendido. Las interrupciones son deshabilitadas. El contador de programa apunta en este momento a la dirección 0x002. A.5. Interrupciones Para poder atender las interrupciones, es necesario por un lado poner a 1 el registro de interrupción (IER) y por otro incluir la instrucción de salto absoluto a la rutina de servicio, en la posición 0x000 de la memoria ROM. Cuando ERIC acepta una interrupción el PC irá buscar una instrucción a esa posición. Juego de instrucciones (ISA) del ERIC 125 Operaciones Aritméticas HEX 40 41 42 43 54 55 NEMOCTÉCNICO ADDC A,B SUBC A,B INC A DEC A INC B DEC B DESCRIPCIÓN C1 01 01 01 01 01 01 C2 00 00 00 00 01 01 C3 0000 0001 0010 0011 0100 0101 BYTES CICLOS C1 01 01 01 01 01 C2 00 00 00 00 00 C3 0110 0111 1000 1001 1010 BYTES CICLOS 4B RLC A (An + 1) <- (An) (A0) <- (C) (C) <- (A7) 01 00 4C RRC A (An) <- (An + 1) (A7) <- (C) (C) <- (A0) 01 (A) <- (A) + (B) + (C) (A) <- (A) - (B) - (C) (A) <- (A) + 1 (A) <- (A) - 1 (B) <- (B) + 1 (B) <- (B) - 1 1 1 1 1 1 1 3 3 3 3 3 3 C Z O x x x x x x x x x x MODO DIR. MODO DIR. REGISTRO REGISTRO REGISTRO REGISTRO REGISTRO REGISTRO Operaciones Lógicas HEX 46 47 48 49 4A NEMOCTÉCNICO AND A,B OR A,B XOR A,B CLR A CPL A DESCRIPCIÓN (A) <- (A) * (B) (A) <- (A) v (B) (A) <- (A) A (B) (A) <- 0 (A) <- /(A) 1 1 1 1 1 3 3 3 3 3 C Z O x x x 1 x 1011 1 3 x REGISTRO 00 1100 1 3 x REGISTRO C1 01 01 01 00 00 C2 11 11 11 00 00 C3 1101 1110 1111 0001 0010 BYTES CICLOS C1 00 00 C2 10 11 C3 xxxx xxxx BYTES CICLOS 00 00 00 REGISTRO REGISTRO REGISTRO REGISTRO REGISTRO Manipulación de Flags HEX 7D 7E 7F 01 02 NEMOCTÉCNICO CLR C SET C CPL C ION IOF DESCRIPCIÓN (C) <- 0 (C) <- 1 (C) <- /(C) (IEN) <- 1 (IEN) <- 0 1 1 1 1 1 3 3 3 2 2 C Z O 0 1 x MODO DIR. REGISTRO REGISTRO REGISTRO IMPLICITO IMPLICITO Transferencia de datos HEX NEMOCTÉCNICO 2# IN A,addr4 3# OUT addr4, A 13 POP A 04 PUSH B 14 POP B 05 PUSH F 15 POP F MOV A,#dato MOV B,#dato MOV A,addr8 MOV B,addr8 MOV addr8,A MOV addr8,B MOV A,@B MOVX A,@B MOVX A,addr12 C Z O MODO DIR. 1 1 3 4 INMEDIATO 0011 1 3 IMPLICITO 01 0011 1 3 IMPLICITO 00 00 0100 1 3 IMPLICITO 00 01 0100 1 3 IMPLICITO 00 00 0101 1 3 IMPLICITO 00 01 0101 1 3 IMPLICITO 00 00 01 01 01 01 10 10 11 0000 0001 0000 0001 0010 0011 0001 0010 xxxx 2 2 2 2 2 2 1 1 2 2 2 3 3 3 3 4 4 3 INMEDIATO (A) <- (addr12) 11 11 11 11 11 11 11 11 11 (addr4) <- (A) ((SP)) <- (A) (SP) <- (SP) + 1 (SP) <- (SP) - 1 ((SP)) <- (A) ((SP)) <- (B) (SP) <- (SP) + 1 (SP) <- (SP) - 1 ((SP)) <- (B) ((SP)) <- (Flags) (SP) <- (SP) + 1 (SP) <- (SP) - 1 ((SP)) <- (Flags) 03 PUSH A C0 C1 D0 D1 D2 D3 E1 E2 F# DESCRIPCIÓN (A) <- (addr4) (A) <- dato (B) <- dato (A) <- (addr8) (B) <- (addr8) (addr8) <- A (addr8) <- B (A) <- ((B)) (A) <- ((B)) INMEDIATO INMEDIATO DIRECTO DIRECTO DIRECTO DIRECTO INDIRECTO INDIRECTO DIRECTO Flujo de programa HEX NEMOCTÉCNICO DESCRIPCIÓN C1 C2 C3 80 JZ rel (PC) <- (PC) + 2 si (A) = 0 entonces (PC) + rel 10 00 0000 2 3 RELATIVO 81 JNZ rel (PC) <- (PC) + 2 si (A) != 0 entonces (PC) + rel 10 00 0001 2 3 RELATIVO 82 JC rel (PC) <- (PC) + 2 si (C) = 1 entonces (PC) + rel 10 00 0010 2 3 RELATIVO 83 JNC rel (PC) <- (PC) + 2 si (C) = 0 entonces (PC) + rel 10 00 0011 2 3 RELATIVO 84 JO rel (PC) <- (PC) + 2 si (OV) = 0 entonces (PC) + rel 10 00 0100 2 3 RELATIVO 85 JNO rel (PC) <- (PC) + 2 si (OV) != 0 entonces (PC) + rel 10 00 0101 2 3 RELATIVO 88 SJMP rel (PC) <- (PC) + rel 10 00 1000 2 3 RELATIVO 90 RET (SP) <- (SP)-1 (PCl) <- ((SP)) (SP) <- (SP)-1 (PCh) <- ((SP)) 10 01 0000 1 6 IMPLICITO BYTES CICLOS C Z O Tabla 19: Resumen del juego de instrucciones del ERIC MODO DIR. 126 Juego de instrucciones (ISA) del ERIC ACALL addr12 Función: Llamada absoluta Descripción: Llamada en modo de direccionamiento absoluto a una subrutina. La dirección de destino (addr12) se construye con los 4 bits menos significativos de la instrucción, unido al segundo byte que le acompaña. Bytes: 2 Ciclos de reloj: 6 Codificación: 10 10 addr(11:8) | addr(7:0) Operaciones: ((SP)) (SP) ((SP)) (SP) ADDC A, B Función: Suma con acarreo Descripción: ADDC suma simultáneamente el contenido de los registros A, B y el flag C. El resultado se deposita en A. Flags: C, OV y Z Bytes: 1 ← ← ← ← HEX [A#][##] (PCh) (SP) + 1 (PCl) (SP) + 1 Ciclos de reloj: 3 Codificación: 01 00 0000 Operaciones: (A) AJMP addr12 Función: Salto absoluto Descripción: AJMP transfiere la ejecución del programa a la dirección apuntada. La dirección de destino “addr12” se construye con los 4 bits menos significativos de la instrucción, unidos al segundo byte que acompaña. Por lo tanto, esta instrucción puede direccionar hasta 4096 bytes. Bytes: 2 ← HEX [40] (A) + (B) + (C) Ciclos de reloj: 3 Codificación: 10 11 addr(11:8) | addr(7:0) HEX [B#][##] Operaciones: (PC) ← AND A, B Función: Función lógica AND. Descripción: AND realiza la función lógica bit a bit entre los operados A y B. Flags: Z Bytes: 1 addr12 Ciclos de reloj: 3 Codificación: 01 00 0110 HEX [46] Juego de instrucciones (ISA) del ERIC Operaciones: (A) ← CLR A Función: Limpia el acumulador Descripción: CLR pone a 0 el registro del acumulador Flags: Z Bytes: 1 127 (A) ^ (B) Ciclos de reloj: 3 Codificación: 01 00 1001 Operaciones: (A) CLR C Función: Limpia el flag de C. Descripción: CLR pone a 0 el flag de C. Flags: C Bytes: 1 ← HEX [49] 0 Ciclos de reloj: 3 Codificación: 01 00 1001 Operaciones: (C) CPL A Función: Complementa el acumulador Descripción: CPL invierte el contenido del acumulador. Flags: C Bytes: 1 ← HEX [7D] 0 Ciclos de reloj: 3 Codificación: 01 00 1010 Operaciones: (A) CPL C Función: Complementa el flag de acarreo. Descripción: CPL invierte el contenido del flag de acarreo. Flags: C Bytes: 1 ← HEX [4A] /(A) Ciclos de reloj: 3 Codificación: 01 00 1111 Operaciones: (C) DEC A Función: Decrementa el acumulador. ← HEX [7F] /(C) 128 Juego de instrucciones (ISA) del ERIC Descripción: DEC disminuye en una unidad el contenido del registro acumulador. Cuanto el valor sea 0x00, esto dará lugar a un desbordamiento con el consiguiente resultado 0xFF. Flags: Z Bytes: 1 Ciclos de reloj: 3 Codificación: 01 00 0011 Operaciones: (A) DEC B Función: Los mismo que DEC A pero con el registro B. Codificación: 01 01 0101 Operaciones: (B) ← ← HEX [43] (A) - 1 HEX [55] (B) - 1 HALT Función: Detiene el procesador. Descripción: HALT detiene la ejecución del procesador. Solo es posible salir de este estado activando la señal reset del procesador. Bytes: 1 Ciclos de reloj: 2 Codificación: 00 00 1111 HEX [0F] IN A, addr4 Función: Lee de un puerto I/O. Descripción: Copia el contenido del puerto de entrada/salida apuntada por “addr4” en el acumulador. Bytes: 1 Ciclos de reloj: 3 Codificación: 00 10 addr(3:0) Operaciones: (A) INC A Función: Incrementa el acumulador. Descripción: INC aumenta en una unidad el contenido del acumulador. Cuanto el valor sea 0xFF, esto dará lugar a un desbordamiento con el consiguiente resultado 0x00. Flags: Z Bytes: 1 ← HEX [2#] (addr4) Ciclos de reloj: 3 Codificación: 01 00 0010 Operaciones: (A) INC B Función: Los mismo que INC A pero con el registro B. ← HEX [42] (A) + 1 Juego de instrucciones (ISA) del ERIC Codificación: 01 00 0100 Operaciones: (B) ← 129 HEX [54] (B) + 1 IOF Función: Desactiva las interrupciones. Descripción: IOF imposibilita que el procesador sea interrumpido por una IRQ. Bytes: 1 Ciclos de reloj: 2 Codificación: 00 00 0010 Operaciones: (IEN) ← HEX [02] 1 ION Función: Activa las interrupciones. Descripción: ION posibilita que el procesador sea interrumpido por una IRQ. Bytes: 1 Ciclos de reloj: 2 Codificación: 00 00 0001 Operaciones: (IEN) JC rel Función: Salto si C está a 1. Descripción: JZ salta a la dirección relativa apuntada por “rel” si el flag de carry está activado (1). En el caso contrario, continúa con la instrucción siguiente. La dirección “rel” viene en el segundo byte que acompaña a la instrucción. Bytes: 2 ← HEX [01] 1 Ciclos de reloj: 3 Codificación: 10 00 0010 | rel Operaciones: (PC) (PC) (PC) + rel (PC) + 2 JNC rel Función: Similar a JC salvo que salta si C está a 0. Codificación: 10 00 0011 | rel Operaciones: (PC) (PC) (PC) + rel (PC) + 2 JNO rel Función: Similar a JC salvo que salta si OV está a 0. Codificación: 10 00 0101 | rel Operaciones: (PC) (PC) (PC) + rel (PC) + 2 ← ← ← ← ← ← HEX [82][##] si C=1 si C=0 HEX [83][##] si Z=0 si Z=1 HEX [85][##] si OV=0 si OV=1 130 Juego de instrucciones (ISA) del ERIC JNZ rel Función: Similar a JC salvo que salta si Z está a 0. Codificación: 10 00 0001 | rel Operaciones: (PC) (PC) (PC) + rel (PC) + 2 JO rel Función: Similar a JC salvo que salta si OV está a 1. Codificación: 10 00 0100 | rel Operaciones: (PC) (PC) (PC) + rel (PC) + 2 JZ rel Función: Similar a JC salvo que salta si Z está a 1. Codificación: 10 00 0000 | rel Operaciones: (PC) (PC) (PC) + rel (PC) + 2 MOV A, #dato Función: Mueve byte de memoria RAM. Descripción: Copia en el acumulador, el valor de “dato”. Bytes: 2 ← ← ← ← ← ← HEX [81][##] si Z=0 si Z=1 HEX [84][##] si OV=1 si OV=0 HEX [80][##] si Z=1 si Z=0 Ciclos de reloj: 2 Codificación: 11 00 0000 | dato Operaciones: (A) MOV A, @B Función: Mueve byte de memoria RAM. Descripción: Copia en el acumulador, el dato de la posición de memoria apuntada en el contenido del registro B. Bytes: 1 ← HEX [C0][##] dato Ciclos de reloj: 4 Codificación: 11 10 0001 Operaciones: (A) MOV A, addr8 Función: Mueve byte de memoria RAM. Descripción: Copia en el acumulador, el contenido de la posición indicada en “addr8”. Dicha información se obtiene del segundo byte. Bytes: 2 ← HEX [E1][##] ((B)) Juego de instrucciones (ISA) del ERIC 131 Ciclos de reloj: 3 Codificación: 11 00 0000 Operaciones: (A) MOV addr8, A Función: Mueve byte de memoria RAM. Descripción: Copia el contenido del acumulador en la posición de memoria indicada en “addr8”. Dicha información se obtiene del segundo byte. Bytes: 2 ← HEX [C0][##] (addr8) Ciclos de reloj: 3 Codificación: 11 01 0010 HEX [D2][##] Operaciones: (addr8) ← MOV addr8, B Función: Similar a MOV addr8, A pero en este caso con el registro B. Codificación: 11 01 Operaciones: (addr8) ← MOV B, #dato Función: Similar a MOV A, #dato pero en este caso con el registro B. Codificación: 11 00 0001 Operaciones: (B) ← MOV B, addr8 Función: Similar a MOV A, addr8 pero en este caso con el registro B. Codificación: 11 01 0001 Operaciones: (B) ← MOVX A, @B Función: Similar a MOV A, @B. En este caso se accede a una posición de la ROM comprendida (A) 0011 HEX [D3][##] (B) HEX [C1][##] dato HEX [D1][##] (addr8) entre 0x00 y 0xFF. Codificación: 11 10 0010 Operaciones: (A) ← MOVX A, addr12 Función: Mueve byte de memoria ROM. Descripción: Copia en el acumulador, el contenido de la posición indicada en “addr12”. Dicha dirección se forma con el segundo byte. Bytes: 2 Ciclos de reloj: 3 HEX [E2][##] ((B)) 132 Juego de instrucciones (ISA) del ERIC Codificación: 11 11 add(11:8) | add(7:0) Operaciones: (A) ← HEX [F#][##] (addr12) NOP Función: No operación. Descripción: NOP consume el tiempo de 2 ciclos máquina sin hacer nada. Bytes: 1 Ciclos de reloj: 2 Codificación: 00 00 0000 Operaciones: (PC) OR A, B Función: Función lógica OR. Descripción: OR realiza la función lógica bit a bit entre los operados A y B. Flags: Z Bytes: 1 ← HEX [00] (PC) + 1 Ciclos de reloj: 3 Codificación: 01 00 0111 Operaciones: (A) OUT addr4, a Función: Escribe en un puerto I/O. Descripción: Copia el contenido del acumulador en el puerto de entrada/salida apuntada por “addr4”. Bytes: 2 ← HEX [47] (A) v (B) Ciclos de reloj: 4 Codificación: 00 11 addr(3:0) HEX [3#] Operaciones: (addr4) ← POP A Función: Extrae un dato de la pila y lo guarda en el acumulador. Descripción: POP extrae el dato, apuntado por SP, de la pila. Antes de la operación, el puntero SP se decrementa y posteriormente se obtiene un valor que se guarda en el acumulador. Bytes: 1 (A) Ciclos de reloj: 3 Codificación: 00 01 0011 HEX [13] Operaciones: (SP) ← ((SP)) ← POP B Función: Similar a POP A, pero en este caso con el registro B. (SP) - 1 (A) Juego de instrucciones (ISA) del ERIC 133 Codificación: 00 01 0100 HEX [14] Operaciones: (SP) ← ((SP)) ← POP F Función: Similar a POP A, pero en este caso con F. Codificación: 00 01 0101 Operaciones: (SP) ← ((SP)) ← PUSH A Función: Guarda el contenido del acumulador en la pila. Descripción: PUSH guarda el contenido del acumulador en la posición de la pila apuntado por SP. Posteriormente incrementa el valor del puntero SP. Bytes: 1 (SP) - 1 (B) HEX [15] (SP) - 1 (F) Ciclos de reloj: 3 Codificación: 00 00 0011 Operaciones: ((SP)) (SP) PUSH B Función: Similar a PUSH A, pero en este caso con el registro B. Codificación: 00 00 0100 Operaciones: ((SP)) (SP) PUSH F Función: Similar a PUSH A, pero en este caso con el registro F. Codificación: 00 00 0101 Operaciones: ((SP)) (SP) ← ← ← ← ← ← HEX [03] (A) (SP) + 1 HEX [04] (B) (SP) + 1 HEX [05] (F) (SP) + 1 RET Función: Retorna de una subrutina. Descripción: RET extrae de la pila la dirección de retorno. Al ser la dirección de 12 bits es necesario realizar dos lecturas. Bytes: 1 Ciclos de reloj: 6 Codificación: 10 01 0000 Operaciones: (SP) ← (PCl) ← (SP) ← (PCh) ← HEX [90] (SP) - 1 ((SP)) (SP) - 1 ((SP)) 134 Juego de instrucciones (ISA) del ERIC RETI Función: Retorna de una interrupción. Descripción: RETI extrae de la pila la dirección de retorno. Al ser la dirección de 12 bits es necesario realizar dos lecturas. Se habilita la posibilidad de nuevas interrupciones. Bytes: 1 Ciclos de reloj: 6 Codificación: 10 01 0001 Operaciones: (SP) ← (PCh) ← (SP) ← (PCl) ← (IEN) ← HEX [91] (SP) - 1 ((SP)) (SP) - 1 ((SP)) 1 RLC Función: Rotación a al izquierda a través del flag de C. Descripción: Los 8 bits del acumulador y el flag C son rotados 1 bit a la izquierda. El bit 7 se mueve a C, y C pasa al bit 0. Flags: C Bytes: 1 Ciclos de reloj: 3 Codificación: 01 00 1011 Operaciones: (An) (A0) (C) ← ← ← HEX [4B] (An + 1) (C) (A7) RRC Función: Rotación a la derecha a través del flag de C. Descripción: Los 8 bits del acumulador y el flag C son rotados 1 bit a la derecha. El bit 0 se mueve a C, y C pasa al bit 7. Flags: C Bytes: 1 Ciclos de reloj: 3 Codificación: 01 00 1100 Operaciones: (An) (A7) (C) SET C Función: Pone a 1 el flag C. Descripción: SET pone a 1 el flag C. Flags: C Bytes: 1 ← ← ← HEX [4C] (An + 1) (C) (A0) Juego de instrucciones (ISA) del ERIC 135 Ciclos de reloj: 3 Codificación: 01 11 1111 Operaciones: (C) SJMP rel Función: Salto relativo. Descripción: El control del programa salta incondicionalmente a la dirección relativa “rel”. La dirección de salto se calcula como la suma de la dirección actual más la dirección relativa. Por lo tanto, la cobertura de este salto es de +128/-127. Bytes: 2 ← HEX [7E] 1 Ciclos de reloj: 3 Codificación: 10 00 1000 | rel Operaciones: (PC) (PC) + rel SUBC A, B Función: Resta con acarreo Descripción: SUBC substrae el contenido de los registros B y el flag C al contenido del acumulador. El resultado es depositado en A. Flags: C, OV y Z Bytes: 1 ← HEX [88][##] Ciclos de reloj: 3 Codificación: 01 00 0001 Operaciones: (A) XOR A, B Función: Función lógica XOR. Descripción: XOR realiza la función lógica bit a bit entre los operados A y B. Flags: Z Bytes: 1 ← HEX [41] (A) - (B) - (C) Ciclos de reloj: 3 Codificación: 01 00 1000 Operaciones: (A) ← HEX [48] (A) ¥ (B) Apéndice B Microinstrucciones En este apéndice, se resumen los valores adoptados por la señal SV (Signal Vector) de la Unidad de Control. Dicho valor es una función de las instrucciones y del estado en que se encuentre en el proceso de ejecución de la misma. Han sido estructuradas en INSTRUCCIONES ESTADO MOV A,#dato MOV B,#dato MOV A,addr8 MOV B,addr8 MOV addr8,A MOV addr8,B MOV A,@B MOVX A,@B MOVX A,addr12 io ram_ ce rom_ ce we pc_u p pc_ld ir_ld a_ld b_ld f_ld s_m ux1 halt en_ie r dis_ ier mar_ ld8 mar_ ld12 s_m ux2 s_m ux3 e_m ux3 snif_ rst s_m ux4 s_m ux5 pc_r el stac k_ce sc_u p sc_d own e_bu f1 s_m ux6 e_m ux6 s_m ux7 mar_ ld4 pc_r st función del tipo de instrucción: MOV, MIX, ALU, JMP. FETCH DECODE 1 1 1 1 1 FETCH DECODE 1 1 1 1 1 FETCH DECODE EXECUTE 1 1 1 1 1 FETCH DECODE EXECUTE FETCH DECODE EXECUTE FETCH DECODE EXECUTE FETCH DECODE EXECUTE STORE 1 1 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 5 0 0 0 A 0 0 0 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 5 0 0 0 E 0 0 0 1 1 1 1 1 1 A 0 0 1 0 0 0 0 0 0 2 0 1 6 6 8 0 8 8 0 0 0 0 0 0 0 0 0 1 1 2 0 0 2 A 0 0 1 0 0 0 0 0 0 2 0 1 6 6 8 0 8 8 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 0 0 4 1 1 1 1 1 1 1 1 1 1 1 FETCH DECODE EXECUTE 1 1 1 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 4 0 8 0 8 0 0 0 1 1 1 FETCH DECODE EXECUTE STORE 1 1 1 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 4 1 0 0 8 0 0 0 1 1 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 2 8 8 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 2 9 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 Tabla 20: Microinstrucciones de las instrucciones del tipo MOV 137 VECTOR DE SEÑALES 2 A 0 0 1 0 0 0 2 8 0 1 0 0 0 0 2 1 0 0 8 0 0 0 Microinstrucciones INSTRUCCIONES ESTADO io ram_ ce rom_ ce we pc_u p pc_ld ir_ld a_ld b_ld f_ld s_m ux1 halt en_ie r dis_ ier mar_ ld8 mar_ ld12 s_m ux2 s_m ux3 e_m ux3 snif_ rst s_m ux4 s_m ux5 pc_r el stac k_ce sc_u p sc_d own e_bu f1 s_m ux6 e_m ux6 s_m ux7 mar_ ld4 pc_r st 138 VECTOR DE SEÑALES NOP FETCH DECODE 1 1 1 1 2 A 0 0 1 0 0 0 0 0 0 0 0 0 0 0 HALT FETCH DECODE 1 1 1 1 2 A 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ION FETCH DECODE 1 1 1 1 2 A 0 0 1 0 0 0 0 0 0 8 0 0 0 0 FETCH DECODE 1 1 2 A 0 0 1 0 0 0 0 0 0 4 0 0 0 0 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 1 FETCH DECODE EXECUTE 1 STORE 1 IOF PUSH A POP A PUSH B POP B PUSH F POP F IN A,addr4 OUT addr4, A 1 1 1 1 1 1 2 A 0 0 1 0 0 0 1 0 0 0 2 1 0 0 0 0 0 0 0 0 8 0 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 0 0 0 0 0 0 4 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 2 A 0 0 1 0 0 0 1 0 0 0 6 1 0 0 0 0 0 0 0 0 8 0 1 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 0 0 0 0 0 0 4 0 0 0 8 0 0 1 0 0 1 1 1 1 1 1 2 A 0 0 1 0 0 0 1 0 0 0 0 1 2 0 0 0 0 0 0 0 8 0 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 0 0 0 0 0 0 4 0 0 0 4 0 0 5 0 0 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 0 0 0 0 0 0 0 2 8 1 0 0 8 0 0 0 1 1 1 1 1 1 2 0 9 1 1 1 1 1 1 1 1 1 A 0 0 0 0 0 0 0 0 0 0 0 1 0 A A 0 0 0 0 0 0 0 0 0 2 0 0 INSTRUCCIONES ESTADO LOAD INTERRUPCION LOAD1 LOAD2 LOAD3 LOAD4 LOAD5 LOAD5 INT1 INT2 INT3 INT4 io ram_ ce rom_ ce we pc_u p pc_ld ir_ld a_ld b_ld f_ld s_m ux1 halt en_ie r dis_ ier mar_ ld8 mar_ ld12 s_m ux2 s_m ux3 e_m ux3 snif_ rst s_m ux4 s_m ux5 pc_r el stac k_ce sc_u p sc_d own e_bu f1 s_m ux6 e_m ux6 s_m ux7 mar_ ld4 pc_r st Tabla 21: Microinstrucciones de las instrucciones del tipo MIX 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Tabla 22: Microinstrucciones de las instrucciones de carga e interrupción VECTOR DE SEÑALES 0 0 0 3 2 0 0 0 1 0 8 0 0 1 1 0 8 0 0 0 0 0 0 0 1 0 0 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 1 0 1 0 1 8 0 8 8 0 8 1 INSTRUCCIONES ESTADO ADDC A,B SUBC A,B INC A DEC A INC B DEC B AND A,B OR A,B XOR A,B CLR A CPL A RLC A RRC A CLR C SET C CPL C 139 io ram_ ce rom_ ce we pc_u p pc_ld ir_ld a_ld b_ld f_ld s_m ux1 halt en_ie r dis_ ier mar_ ld8 mar_ ld12 s_m ux2 s_m ux3 e_m ux3 snif_ rst s_m ux4 s_m ux5 pc_r el stac k_ce sc_u p sc_d own e_bu f1 s_m ux6 e_m ux6 s_m ux7 mar_ ld4 pc_r st Microinstrucciones FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 FETCH DECODE EXECUTE 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 E 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 E 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 6 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 4 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 4 0 0 0 0 0 1 2 A 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 4 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 VECTOR DE SEÑALES 1 1 Tabla 23: Microinstrucciones de las instrucciones del tipo ALU Microinstrucciones INSTRUCCIONES ESTADO JZ rel io ram_ ce rom_ ce we pc_u p pc_ld ir_ld a_ld b_ld f_ld s_m ux1 halt en_ie r dis_ ier mar_ ld8 mar_ ld12 s_m ux2 s_m ux3 e_m ux3 snif_ rst s_m ux4 s_m ux5 pc_r el stac k_ce sc_u p sc_d own e_bu f1 s_m ux6 e_m ux6 s_m ux7 mar_ ld4 pc_r st 140 FETCH DECODE EXECUTE 1 1 1 1 si Z=0 FETCH DECODE EXECUTE 1 1 si C=1 FETCH DECODE EXECUTE 1 1 si C=0 FETCH DECODE EXECUTE 1 1 si OV=1 FETCH DECODE EXECUTE FETCH DECODE EXECUTE 1 1 FETCH DECODE EXECUTE 1 1 FETCH DECODE EXECUTE 1 1 FETCH DECODE EXECUTE SUBR1 SUBR2 SUBR3 1 1 FETCH DECODE EXECUTE SUBR1 SUBR2 SUBR3 1 FETCH DECODE EXECUTE SUBR1 SUBR2 SUBR3 1 si Z=1 JNZ rel JC rel JNC rel JO rel JNO rel si OV=0 SJMP rel AJMP addr12 ACALL addr12 RET RETI 1 1 1 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 0 4 0 0 0 2 0 0 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 0 4 0 0 0 2 0 0 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 0 4 0 0 0 2 0 0 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 0 4 0 0 0 2 0 0 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 0 4 0 0 0 2 0 0 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 0 4 0 0 0 2 0 0 1 2 A 0 0 1 0 0 0 2 8 0 2 0 0 0 0 0 4 0 0 0 2 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 A 0 0 1 0 0 0 2 8 0 1 0 0 0 0 0 4 0 0 0 0 0 0 1 2 2 1 0 1 0 A 8 0 0 0 4 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 1 8 0 8 0 0 8 0 8 0 2 0 0 0 0 0 A 0 0 0 0 4 0 0 0 0 0 0 0 0 2 0 3 0 1 0 0 0 0 0 0 0 1 0 1 0 0 4 0 4 0 0 0 0 2 0 4 0 2 0 0 0 0 0 A 0 0 0 0 4 0 0 0 0 0 0 0 0 2 0 3 8 1 0 0 0 0 0 0 0 1 0 1 0 0 4 0 4 0 0 0 0 2 0 4 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 VECTOR DE SEÑALES 1 1 1 Tabla 24: Microinstrucciones de las instrucciones del tipo JMP Todas estas tablas, han sido generadas con la ayuda de la hoja de cálculo Excel. Es posible encontrarlas en la sección de utilidades del CD que acompaña el proyecto. Es importante reseñar que para poder trabajar con ellas, es necesario tener instalada la función BIN.A.HEX(), no disponible en la instalación por defecto que hace el OFFICE28. 28 El autor disponía de la versión Excel 2002 disponible en el OFFICE XP PROFESIONAL Apéndice C Manual del monitor EricMON C.1. Requisitos previos EricMON es un programa monitor de apoyo al procesador ERIC. Por lo tanto, su uso debe realizarse conjuntamente con una placa de desarrollo, Xess, Digilent o cualquier otra provista de la FPGA adecuada, donde se haya implementado el procesador. EricMON, es una aplicación MS-DOS que funciona bajo cualquier sistema operativo Windows (9x, NT, 2000, XP). La comunicación con la tarjeta, se realiza por medio del puerto paralelo que deberá estar configurado como SPP (Standard Parallel Port) y con la dirección 0x378. La aplicación no se comunica directamente con el dispositivo, por lo que previamente deberemos tener instalado el driver de manejo del puerto paralelo (iniio.sys). El programa de instalación de dicho driver se llama PORT95NT.EXE y puede ser encontrado en el CD-ROM que acompaña a esta memoria, o bien, ser descargarda de la página web del fabricante (DriverLinx). Si se tienen instaladas la utilidades XSTOOLS de XESS, no es necesario realizar este paso ya que la instalación de las mismas incluye la instalación del driver. 141 142 Manual del monitor EricMON C.2. Instalación del software Crear un directorio y copiar el programa ERICMON.EXE. Para facilitar su integración con el ensamblador EricASM, se recomienda que ambos programas estén juntos en el mismo directorio. De este modo los programas ensamblados serán más fácil de localizar. Para este manual, se ha elegido como ejemplo el directorio c:\eric . C.3. Ejecución de la aplicación Una vez realizados los pasos previos, podemos pasar a ejecutar la aplicación. Para ello debemos abrir una ventana MS-DOS e invocar el programa tecleando: C:\eric\ericmon Figura 46: Ventana en MS-DOS para invocar el programa EricMON La aplicación nos mostrará el prompt EricMON> junto a una breve ayuda sobre las tres opciones disponibles tecleado la inicial de cada modo: L Modo LOAD o modo carga. S Modo STEP o modo ejecución paso a paso. R Modo RUN o modo ejecución en modo continuo. Manual del monitor EricMON 143 Veamos una descripción más detallada de cada uno de estos modos. Figura 47: Menú principal del programa EricMON C.3.1. Modo LOAD Esta opción permite cargar un programa ensamblado en la memoria ROM de ERIC. Figura 48: Submenú del modo LOAD del programa EricMON Pulsando la tecla F, EricMON nos solicitará el nombre del fichero ensamblado. 144 Manual del monitor EricMON Es importante destacar en este punto, que dicho fichero deberá haber sido ensamblado con el formato BYTE (EricASM –Fbyte). Al introducir el nombre del fichero, no es necesario introducir la extensión ya que internamente el programa busca el fichero con extensión .BYTE. En el caso de no encontrar el fichero indicado, o que existan problemas de comunicación con el procesador ERIC, el programa mostrará los mensajes pertinentes abortando la operación. Figura 49: EricMON mostrando un mensaje de error en modo LOAD Figura 50: Volcado de datos en memoria en el modo LOAD del programa EricMON Manual del monitor EricMON 145 Si todo funciona correctamente, EricMON nos mostrará la evolución de la descarga, representando la posición de memoria en curso junto al dato almacenado. Esto nos permite comprobar, en caso de problemas, que es lo que ha cargado realmente el programa. C.3.2. Modo RUN Una vez cargado el programa en memoria, ERIC esta preparado para ejecutarlo. En modo RUN, la ejecución se realiza en modo continuo, esto es, sin interrupciones. Figura 51: Submenú del modo RUN del programa EricMON Pulsando la tecla RETURN es posible iniciar/detener la ejecución del programa. En este modo también es posible reiniciar el procesador (pulsando R) o bien, solicitar una interrupción (pulsando I). Con el programa detenido, es posible continuar la ejecución en el modo paso a paso del programa, desde el punto en que se había detenido, sin necesidad de reiniciar el procesador. 146 C.3.3. Manual del monitor EricMON Modo STEP En este modo, es posible ejecutar el programa cargado en modo paso a paso. De esta manera, se puede obtener información sobre la evolución de los registros internos de ERIC al ir interpretando cada una de las instrucciones. También representa una buena herramienta a la hora de depurar variaciones del diseño, implementación de nuevas instrucciones, etc. Figura 52: Submenú del modo STEP del programa EricMON Cada vez que se pulsa la tecla RETURN se ejecuta una instrucción. Es posible variar el número de instrucciones a ejecutar por interacción, variando el valor de N. Al igual que en el modo RUN, es posible reiniciar el procesador (R) y solicitar una interrupción (I). EricMON, realiza la lectura de los registros de manera sincronizada con ERIC, esperando un máximo de 2 segundos por los datos. En el caso de no estar disponibles, el programa mostrará un mensaje de expiración del TIMEOUT de lectura, volcando finalmente los datos que deberán ser tomados con reservas. Apéndice D Manual del ensamblador EricASM Esta documentación es una adaptación del manual del AS31 de Ken Stauffer (Universidad de Calgary), a las características propias del ERIC. D.1. Comando EricASM [-Fformat] [-Aarg] [-l] infile.asm El ensamblador genera un fichero objeto de salida con el nombre infile, seguido de una extensión que depende de la opción de formato elegida. Si no se elige ninguna opción, se utilizará la forma HEX por defecto. Esta conversión se realiza en dos fases: una en la que se analiza la sintaxis y se crea una tabla de símbolos, y una segunda donde se hace la traslación a código objeto. El fichero infile.asm deberá ser un fichero de texto plano (sin formatear). D.2. Opciones del comando Las opciones del comando, deben aparecer antes del nombre del fichero fuente. Ambas opciones no son obligatorias. El texto de cada opción, debe aparecer unido al mismo argumento, es decir “-Fod” es un argumento valido y no lo es “-F od”. 147 148 Manual del ensamblador EricASM -Fformat: Esta opción especifica el formato de salida. Las opciones disponibles son: hex Este formato es un Intel HEX, usado comúnmente por los programadores de EPROM. tdr Este formato genera un fichero ASCII de dígitos hexadecimales formateados de tal forma que puede ser usado por un TDR’s Debbuger. Esta opción admite un argumento (Ver opción –A) donde se le puede definir una dirección base, a tener en cuenta por el contador de localización (Location Counter) del ensamblador. Esta dirección se define en decimal y por defecto toma el valor de 64*1024 (0x10000). Para especificar un offset de 100 deberá teclear “Ftdr –A100” a la hora de invocar el programa. byte Este formato es simplemente una dirección y un byte en cada línea en ASCII. od Este formato consiste en una dirección seguida de 16 bytes en hexadecimal. Al final de cada línea se incluye el equivalente ASCII de estos 16 bytes. srec2, srec3, srec4 Este formato genera una salida de tipo “srecord” con direcciones de 2, 3 o 4 bytes. La opción –A puede ser usada para definir una dirección base de offset que por defecto es la 0x0000. - Aarg: Esta opción permite definir una dirección base que será utilizada por el generador de direcciones interno del ensamblador. Esta opción es valida únicamente para los formatos HEX y TDR. -l: Esta opción le indica al ensamblador que genere, adicionalmente al fichero ensamblado, un fichero de texto que incluye el fichero fuente junto al código ensamblado en formato hexadecimal. El fichero generado tendrá de nombre el fichero fuente seguido de la extensión .LST. Manual del ensamblador EricASM D.3. 149 Instrucciones EricASM soporta todas las instrucciones del procesador ERIC recogidas en este documento en el apéndice A. D.4. Directivas EricASM soporta las siguientes directivas: .ORG expresión: Indica al ensamblador, la dirección de inicio del programa, desde donde debe empezar a ensamblar. Se genera un error, si el código generado excede la posición 0xFFF (4095), que es la dirección más alta que maneja el ERIC. .EQU símbolo, expresión: Asigna al símbolo el valor de la expresión que viene a continuación. .DB expresión, expresión … .BYTE expresión, expresión …: Ambas directivas originan que se inserte en formato byte el valor especificado por la expresiones. Esta opción, también puede ser usada para especificar una cadena de caracteres. .WORD expresión, expresión …: Similar a la opción .BYTE pero la codificación se hace en formato WORD. .END: Esta directiva es ignorada. .SKIP expresión: Añade el valor de la expresión, al contador de localidad del ensamblador. La expresión debe ser fijada en bytes. 150 D.5. Manual del ensamblador EricASM Sintaxis del lenguaje A la hora de redactar los ficheros fuente, es necesario tener en cuenta ciertas reglas sintácticas que aseguren un funcionamiento correcto del ensamblador. D.5.1. Generalidades Tanto los comandos, directivas, instrucciones, etc., pueden ser utilizados tanto en minúscula como en mayúscula. Se puede utilizar cualquier carácter (A..Z), número (0..9) y caracteres especiales (#,_,- ….). D.5.2. Comentarios Todos los caracteres precedidos del símbolo “;” son ignorados y considerados comentarios hasta que se encuentra un carácter newline. D.5.3. Números Por defecto los números son considerados en formato decimal, salvo que se precedan de las siguientes expresiones: 0X o 0x Indica un número en hexadecimal. Ej.- 0x00ff 0B o 0b Indica un número en binario. Ej.- 0b1100110010 O Indica un número en octal. Ej.- 0377 o bien que se terminen con los siguientes caracteres: Hoh Indica un número en hexadecimal. Sin embargo, si el primer carácter no es numérico, es necesario encabezar la cifra con un 0 o con 0x. Ej.- 20h, 0x20, 0ffh, 0xffh Bob Indica un número en binario, salvo vaya precedido por 0x. Ej.1100110010b Dod Indica un número en decimal, salvo vaya precedido por 0x. Ej.- 129d Ooo Indica un número en octal, salvo que vaya precedido por 0x. Ej.377o. Manual del ensamblador EricASM D.5.4. 151 Cadena de caracteres Cualquier secuencia de caracteres delimitadas por dobles comillas (“) es considerada como una cadena de caracteres (string). Se consideran caracteres válidos, todos los caracteres del código ASCII así como las secuencias de escape \b, \n, \r, \t quedando excluido \0. Las cadenas de caracteres han de ser definidas mediante el uso de la directiva .BYTE. D.5.5. Símbolos Un símbolo puede ser cualquier conjunto de caracteres alfanuméricos incluido el guión bajo (_). Para asegurar que el ensamblador pueda distinguir entre símbolos y números, los primeros deberán empezar siempre por un carácter alfabético. D.5.6. Expresiones En general, las expresiones pueden ser utilizadas en cualquier lugar donde sea necesario un valor o un símbolo. Las expresiones, pueden incluir los siguientes operadores que a continuación se detallan, ordenados por orden de precedencia: - Cambio de signo & AND lógica | OR lógica * Multiplicación de enteros \ División de enteros % Módulo de enteros + Suma de enteros - Resta de enteros << Desplazamiento a la izquierda >> Desplazamiento a la derecha Adicionalmente a estos operadores, existe un símbolo especial ‘*’ que puede ser utilizado para representar el valor actual del contador de localización (LC), utilizado por el ensamblador. 152 D.6. Manual del ensamblador EricASM Ejemplo de un fichero fuente Figura 53: Ejemplo de un fichero fuente para el ensamblador EricASM Apéndice E El entorno de desarrollo ISE WebPACK Figura 54: Ventana del Project Manager del entorno WebPACK WebPACK™ ISE™ es un conjunto de herramientas gratuitas, de la casa Xilinx, que conforman un entorno de desarrollo, cuya finalidad es la de poder realizar diseños basados en sus dispositivos programables de los tipo CPLD y FPGA. 153 154 El entorno de desarrollo ISE WebPACK La versión profesional de las herramientas del WebPACK se denomina Foundation ISE. El corazón central de las aplicaciones es el Project Navigator, que está estructurado siguiendo las distintas fases del desarrollo de un proyecto: captura, síntesis, implementación y generación del fichero de programación (bitstream). Figura 55: Esquema organizativo del entorno WebPACK El entorno de desarrollo ISE WebPACK 155 Desde el Project Navigator, es posible invocar las distintas herramientas de apoyo para la generación de los distintos ficheros: generador de diagramas de estado, generador de banco de pruebas (testbench), analizador de tiempos, simulador, etc. Debemos reseñar que en la versión de estudiante algunas de estas aplicaciones están disponibles en versión demo, por lo que, o bien no funcionan (caso del simulador) o bien tienen limitadas sus capacidades (caso del simulador). A pesar de todo, WebPACK es una herramienta suficientemente funcional. Puesto que, una descripción operativa del uso de la herramienta puede llegar a ocupar decenas de páginas (incluso una descripción somera), veamos brevemente las características generales de cada una de las fases de un desarrollo completo, recomendando la lectura de alguno de los tutoriales, incluidos en el CD de este proyecto, a aquellas personas que deseen saber más. E.1. Descripción HDL o esquemáticos ISE, permite la entrada de la descripción funcional del diseño, bien a través de esquemáticos, bien a través de lenguajes de descripción de hardware (HDL). Para el primer caso, el sistema incluye una herramienta CAD para la captura de esquemas con las características típicas de este tipo aplicaciones: biblioteca de símbolos, editor de símbolos, conexionado, etc. En el segundo caso, es posible elegir alguno de los HDL soportados: VHDL, VERILOG, ABEL dependiendo su disponibilidad para el tipo de dispositivo programable elegido. Para facilitar la descripción HDL de ciertos módulos (testbench, diagramas de estado, etc.), el sistema incluye herramientas de apoyo como son HDL Bencher, StateCAD, etc., aunque están limitadas en el número de líneas de código que pueden generar. 156 E.2. El entorno de desarrollo ISE WebPACK Síntesis Una vez concluida la descripción funcional del diseño, el sistema comprueba la consistencia de los distintos módulos y procede a su síntesis, infiriendo los distintos componentes del circuito. Durante el proceso, el sistema genera una serie de informes que nos informan sobre la evolución del proceso, recomendaciones de diseño, simplificaciones, etc. E.3. Posicionamiento y enrutado Tras la síntesis el sistema está preparado para ubicar nuestro diseño en el dispositivo programable elegido. En este punto del diseño, es necesario fijar físicamente las distintas señales de entrada/salida de nuestro circuito dentro del dispositivo programable elegido. Con esta finalidad, el sistema incluye un editor (Constraints Editor). Con esta información y la resultante de la síntesis, la aplicación procede a asignar, posicionar y enrutar (map, place & route) el diseño. Cada una de estas subfases, va acompañada de la generación de informes sobre la evolución de la actividad. Si deseamos analizar como ha quedado la implementación del diseño, es posible hacerlo con la ayuda de la utilidad FloorPlan. E.4. Simulación Cada uno de los circuitos diseñados, son susceptibles de ser simulados con el fin de verificar el correcto funcionamiento del diseño. WebPACK non incluye ningún simulador propio, aunque sí incluye la posibilidad de instalar uno de la casa Mentor Graphics™. Esta aplicación, se denomina ModelSIM, y existe una versión profesional y otra de evaluación limitada a 500 líneas de código VHDL (para la que es necesario registrarse vía Internet). El entorno de desarrollo ISE WebPACK 157 Figura 56: Ventanas del simulador ModelSIM de la casa Mentor E.5. Generación del bitstream y programación Una vez concluidos con éxito los pasos anteriores, ya se puede proceder a la generación del fichero de programación (bitstream) que va a definir el comportamiento del dispositivo programable elegido. El sistema incluye la aplicación iMPACT, que permite, tanto la generación de ficheros para su grabación vía una memoria serie del tipo (E)PROM, como la programación directa del dispositivo mediante un cable conectado a un ordenador personal, a través de, alguno de los medios que permite el dispositivo programable (Boundary-Scan, SelectMap, etc.) 158 E.6. El entorno de desarrollo ISE WebPACK Tabla de prestaciones Tabla 25: Prestaciones de los distintos productos software de Xilinx Apéndice F La tarjeta de desarrollo XSA-50. Figura 57: Tarjeta XSA-50 de Xess La XSA-50 es una tarjeta de desarrollo, de la casa Xess Corporation™, orientada al desarrollo de aplicaciones basadas en la FPGA de Xilinx Spartan-II XC2S50. A la FPGA le acompañan otros dispositivos como son una memoria dinámica de 8 Mbytes, otra de tipo Flash de 128 Kbytes y un CPLD XC9572XL así como varios componentes como un oscilador programable, un visualizador de 7 segmentos, un pulsador y distintos tipos de conectores. Se alimenta con 9 V en continua, y la programación se realiza por el puerto paralelo con la ayuda de utilidades que acompañan la tarjeta. 159 160 La tarjeta de desarrollo XSA-50. F.1. Descripción de la tarjeta La FPGA posee conexiones prácticamente con cualquiera de los dispositivos auxiliares que constituyen la placa, tal como podemos ver en el siguiente esquema de bloques: Figura 58: Esquema general de la tarjeta XSA-50 Veamos brevemente las particularidades de cada conexión, así como los aspectos más relevantes de cada dispositivo. F.1.1. Los dispositivos programables: La tarjeta dispone de dos dispositivos programables a saber: Una FPGA SPARTAN II XC2S50 de la casa Xilinx con una capacidad de 50.000 puertas lógicas equivalentes. Un CPLD XC9572XL, cuya finalidad es doble: por un lado es susceptible de ser programado al igual que la FPGA, en el desarrollo de una aplicación y por otro lado, realiza las funciones de interfaz entre el mundo exterior (puerto paralelo) y los distintos componentes (memorias, FPGA y oscilador) a la hora de ser programados. La tarjeta de desarrollo XSA-50. F.1.2. 161 El reloj programable Se trata del circuito integrado DS1075 de la casa Dallas que provee de señal de reloj tanto a la FPGA como al CPLD. La frecuencia máxima de trabajo es de 100 Mhz, que puede ser dividida por un número entero comprendido entre 1 y 2052. La programación del mismo se realiza vía software, con la ayuda de la utilidad XSTEST (ir al apartado de utilidades para más información). F.1.3. La RAM dinámica La placa incorpora una memoria síncrona dinámica SDRAM de la casa Hynix HY57V561620T-H, con una capacidad de 8 Mbytes (4M x 16). Como toda RAM dinámica, para poder utilizarla es necesario incorporar un controlador de refresco. En este sentido Xess proporciona una nota de aplicación que incluye un listado en VHDL para la implementación del mismo (XSA SDRAM.controller). Figura 59: Conexión de la FPGA y la DRAM enana XSA-50 Es posible cargar/descargar el contenido de la memoria por medio de la utilidad XSLOAD. 162 F.2. La tarjeta de desarrollo XSA-50. La RAM FLASH La placa, incorpora una memoria FLASH de la casa Atmel AT49F002, con una capacidad de 128 Kbytes. Tanto el CPLD como la FPGA, tienen acceso a la memoria FLASH, siendo el CPLD el encargado de cargar/descargar su contenido por medio de la utilidad XSLOAD. Dado que el modelo de FPGA, que incorpora la XSA-50, no permite guardar el diseño de manera permanente, es posible utilizar la memoria FLASH con este cometido. Destacar la necesidad de fijar el terminal /CE a 1 en el caso de no utilizar la memoria FLASH, con el fin de evitar conflictos de hardware. Figura 60: Conexión entre la FPGA, el CPLD y la FLASH en la XSA-50 F.2.1. El visualizador de 7 segmentos La tarjeta incorpora un visualizador de 7 segmentos, activos a nivel alto que pueden ser utilizados indistintamente por la FPGA o por el CPLD. La tarjeta de desarrollo XSA-50. F.3. 163 Puerto VGA y PS2 La tarjeta dispone, de dos conectores normalizados que permiten la conexión de un teclado y un monitor. Destacar que, a pesar de ser denominados PS2 y VGA, no existe en la tarjeta ningún hardware, que por defecto haga las funciones de interfaz con los dispositivos conectados a los mismos, es decir, no hay ningún controlador VGA ni controlador de teclado, siendo la conexión puramente física. Figura 61: Detalles de las conexiones VGA y PS2 de la XSA-50 F.3.1. Banco de interruptores DIP y pulsador La tarjeta, incorpora un banco de 4 interruptores DIP de 2 posiciones, conectados a VCC por medio de resistencias. En el caso de que no se utilicen, es recomendable dejarlos en posición de abiertos, para que los terminales de la FPGA puedan ser asignados para otros fines. Comparte terminales de la FPGA con los terminales A14 … A17 de la memoria Flash. La tarjeta también incluye un pulsador conectado a VCC por medio de una resistencia. El pulsador aplica un valor bajo (0 lógico) al ser pulsado y alto cuando esta sin pulsar. Comparte terminal de la FPGA con el terminal de datos del puerto PS2 164 F.3.2. La tarjeta de desarrollo XSA-50. El puerto paralelo El puerto paralelo es la interfaz principal de la tarjeta con el mundo exterior. A través de él, es posible la programación de los dispositivos, la carga/descarga de datos, así como el uso que posteriormente podamos hacer de él en nuestros diseños. Para la programación de los distintos dispositivos, el puerto paralelo ha de configurarse en modo SPP (Modo estandar o compatible), no siendo recomendable el uso de otros modos (EPP, ECP …). En este modo, el puerto paralelo dispone de 12 líneas de salida repartidas en 4 líneas de control (PPC0…PPC3) y 8 de datos (PPD0 …PPD7), y de 5 líneas de entrada conocidas como status (PPS3 … PPS7). Las líneas de control (PPC1 …PPC3) se conectan directamente a los terminales JTAG del CPLD, obteniendo la realimentación vía PPS7. PPC0, es utilizada para la programación del oscilador. Estas líneas, son de uso exclusivo de la tarjeta y por lo tanto no pueden ser utilizadas por el diseñador. El resto PPD0 … PPD7 y PPS3 … PPS6 pueden ser utilizadas como líneas de propósito general. Hay que destacar que las líneas PPD0 y PPD1 están conectadas a la FPGA por medio de unos inversores SchmittTrigger. El resto de los dispositivos (SDRAM, FLASH y FPGA) son programados a través del CPLD e incluso a través de la FPGA (en el caso de la SDRAM). En función del dispositivo a programar y de lo que queremos hacer con él (ej.- cargar o descargar el contenido de la SDRAM) se modifica el contenido del CPLD/FPGA. De este modo, existe una secuencia a la hora de programar los dispositivos: SDRAM, FPGA, FLASH y CPLD. Todas estas reprogramaciones, se realizan de manera automática por medio de las utilidades XSTOOLS por lo que el diseñador sólo debe preocuparse de sus diseños. Si el diseñador no utiliza el CPLD, éste quedará configurado con el fichero dwnldpar.swf (utilizado para la programación de la FPGA), permitiendo de este modo una conexión directa entre el puerto paralelo y la FPGA. La tarjeta de desarrollo XSA-50. Figura 62: Detalles de la conexión del la XSA-50 con el puerto paralelo. Figura 63: Conexionado entre el puerto paralelo y distintas partes de la XSA-50 165 166 F.4. La tarjeta de desarrollo XSA-50. Las utilidades XSTOOLS La tarjeta viene acompañada de unas herramientas software, conocidas como las XSTOOLS, cuya finalidad son la programación, comprobación y manejo del puerto paralelo. Todas estas utilidades son gráficas para el entorno Windows (9x, 2000, etc.) y poseen su equivalente a nivel de comando MS-DOS (entre paréntesis). Veamos brevemente cuáles son estas utilidades y cuáles son sus funciones. F.4.1. GXSTEST (XSTEST) La finalidad del mismo es comprobar que existe buena comunicación entre el ordenador y la tarjeta. Para ello, el puerto paralelo deberá estar configurado como SPP y la frecuencia del oscilador de la tarjeta deberá ponerse en 50 Mhz. Figura 64: Ventana de dialogo de GXSTEST F.4.2. GXSSETCLK (XSSETCLK) La finalidad del mismo, es la de fijar la frecuencia del oscilador programable, introduciendo para ello el valor de división del reloj. Antes de la programación, y con la XSA-50 apagada, es necesario cambiar la posición del puente J6 a SET devolviéndolo a su posición original una vez realizada la programación. Figura 65: Ventana de diálogo de GXSSETCLK La tarjeta de desarrollo XSA-50. F.4.3. 167 GXLOAD(XSLOAD) Con la ayuda de esta utilidad es posible programar tanto el CPLD como de la FPGA, así como cargar/descargar el contenido de las memorias FLASH y SDRAM. Para la programación de los dispositivos programables, se deberá seleccionar el fichero .BIT o .SVF, arrastrarlo y dejarlo caer sobre la casilla FPGA/CPLD. En el caso de programar las memorias, habrá que arrastrar un fichero con el formato elegido en la opción UPLOAD FORMAT, dentro de la casilla correspondiente. En el caso de querer descargar el contenido de las mismas, será preciso fijar las direcciones bajas y altas que se quieren volcar así como el tipo de formato del fichero. Figura 66: Ventana de diálogo de GXLOAD F.4.4. GXPORT(XSPORT) Permite programar el contenido del registro de las líneas de datos del puerto paralelo. Figura 67: Ventana de diálogo de GXPORT 168 F.5. La tarjeta de desarrollo XSA-50. Listado de conexiones La tarjeta de desarrollo XSA-50. Tabla 26: Listado de las conexiones de la tarjeta XSA-50 169 Apéndice G FPGAs de la familia SPARTAN II DE XILINX. La Spartan-II™, es una familia de la FPGAs (Field Programmable Gate Array) de la casa Xilinx. Se denomina II por pertenecer a la tecnología de ASICs programables de segunda generación. Disponible en 6 formatos, con una densidad de puertas comprendida entre las 15.000 a las 200.000 puertas, la frecuencia máxima de trabajo puede llegar a 200 Mhz. Tabla 27: Tipos de dispositivos de la familia Spartan-II El uso de esta familia de FPGAs está orientado al desarrollo de aplicaciones con un alto consumo de recursos, donde la versatilidad y la reprogramación sean aspectos a tener en cuenta. 171 172 G.1. FPGAs de la familia SPARTAN II DE XILINX. Arquitectura Como todas las FPGAs, la familia Spartan-II, posee una configuración básica en cuadrícula (array) compuesta por CLBs (Configurable Logic Blocks) e IOBs (Input/Output Blocks), al que se le han añadido algunos elementos, como son 4 DLLs (Delay-Locked Loops) y varios bloques de memoria SRAM (de 4096 bits cada uno) en, cantidad variable según el dispositivo concreto, con el fin de aportarle una mayor funcionalidad. Todos estos elementos, están interconectados por una potente jerarquía de líneas de interconexión versátiles. Figura 68: Esquema interno de una FPGA de la familia Spartan-II La configuración de la Spartan-II, se realiza por medio de la programación de las celdas internas de la memoria SRAM de configuración, que pueden ser programadas un número ilimitado de veces. La configuración, puede ser leída a partir de memorias serie externas de tipo (E)PROM (Master Serial Mode) o bien escribiendo directamente en el dispositivo por medio algunos de los siguientes modos disponibles (Slave Serial, Slave Parallel o Boundary Scan). FPGAs de la familia SPARTAN II DE XILINX. G.2. 173 Bloques de entrada/salida (IOBs) Los IOBs de la Spartan-II soportan hasta 16 tipos diferentes de niveles lógicos estándar, siendo su estructura básica la mostrada a continuación: Figura 69: Diagrama de bloques de los IOBs de una FPGA Spartan-II Según el tipo de dispositivo, es posible disponer entre 86 a 284 I/Os. Las entradas, pueden ser memorizadas mediante biestables o bien conectadas directamente a la lógica interna. Las salidas, tienen capacidad tres estados (3-state) y es posible su realimentación de nuevo al interior del circuito. También es posible, definir características como la pendiente de cambio (slew-rate), resistencias de puesta a uno (pull-up) o puesta a cero (pull-down), keeper y retardos programables. G.3. Bloques lógicos configurables (CLBs) La unidad básica a partir de la que está construido un CLB es la celda lógica LC (Logic Cell). Una LC, incluye una memoria de acceso aleatorio estática (SRAM) con 4 variables de dirección (tabla de consulta), que permite generar una función lógica de 4 174 FPGAs de la familia SPARTAN II DE XILINX. entradas, una lógica de acarreo (Carry Logic) y un biestable de almacenamiento. Cada CLB incluye 4 de estas LCs, por lo que uniendo todos los recursos disponibles es posible realizar una función lógica de 5 o 6 entradas. Figura 70: Diagrama de bloques de un SLICE de una Spartan-II G.3.1. Tablas de consulta LUT (Look-Up Table) Cada LUT permite la definición de una función lógica de 4 entradas. También es posible definir en su lugar una SRAM síncrona de 16x1 bits, o bien, combinar las 2 LUTs para definir una SRAM de 16x2 ó 32x1 bits. Cada LUT está provista de un registro de desplazamiento de 16-bits, ideal para ser usado en captura de datos a alta velocidad o en modo ráfaga (burst-mode) como en el caso de los DSPs. FPGAs de la familia SPARTAN II DE XILINX. G.3.2. 175 Lógica de acarreo (Carry Logic) Este bloque permite la realización de funciones aritméticas y lógicas a alta velocidad. Cada CLB dispone de 2 cadenas independientes de arrastre acarreo (carry). G.3.3. Amplificadores (BUFTs) Cada CLB dispone de 2 amplificadores (buffers) de tres estados (3-state) que pueden conectarse a los buses internos. G.3.4. Lógica adicional Los multiplexores denominados F5 (no aparecen en la figura) permiten la implementación de una función lógica de 5 entradas, ser usados como multiplexor 4:1 o bien realizar funciones lógicas de hasta 9 entradas, combinando varias tablas de consulta. Los multiplexores F6 permiten la implementación bien de una función lógica de 6 entradas, bien de un multiplexor de 8:1 o bien, la realización de funciones de hasta 19 entradas Cada CLB posee además 4 caminos de retorno, uno por cada LC, que permite líneas de entrada adicionales o ser usadas como líneas de conexionado local sin consumir para ello recursos de interconexión generales. G.4. Bloques de memoria (BRAM) La familia SPARTAN-II incorpora varios bloques de memoria estática SRAM, en número variable según el tipo de dispositivo, tal como se puede observar en la siguiente tabla: Figura 71: Tamaño de los bloques RAM según el modelo de Spartan-II 176 FPGAs de la familia SPARTAN II DE XILINX. Cada uno de estos bloques es de 4096-bits. Esta memoria, puede ser utilizada de varias formas: RAM de simple o doble puerto de tamaño variable tanto en el bus de datos como el de direcciones. Esta SRAM es siempre síncrona (SSRAM) y se incluyen líneas dedicadas para facilitar la interconexión entre los bloques RAM y el resto de los CLBs. Tabla 28: Configuraciones posibles de los bloques RAM G.5. Matriz de interconexión programable Spartan, dispone de distintos recursos a nivel de conexionado mejorados con respecto a otras familias, con el fin de alcanzar mayores frecuencias de trabajo. A continuación se describen los distintos tipos. G.6. Caminos de interconexión local Los caminos de interconexión local, mostrados en la figura, permiten: Figura 72: Enrutado local de una Spartan-II FPGAs de la familia SPARTAN II DE XILINX. 177 Interconexión entre LUTs, biestables y la matriz de conexión general (GRM). Realimentación interna en los CLBs, proporcionando de este modo alta velocidad de conexionado entre LUTs dentro del mismo CLB o, encadenamiento de los mismos con un mínimo retardo. Conexión directa de alta velocidad entre CLBs que ocupen posiciones adyacentes en línea horizontal. G.6.1. Caminos de interconexión de propósito general Los caminos de interconexión de propósito general, que son los utilizadas más habitualmente y los que soportan la mayoría de la carga de conexión, están constituidos por canales horizontales y verticales que discurren entre las filas y las columnas de los CLBs. Los recursos disponibles para esta tarea son los siguientes: Una GRM adyacente a cada CLB. La GRM es una matriz que permite el conexionado entre líneas horizontales y verticales, así como el conexionado entre el CLB y las líneas de propósito general. 24 líneas de conexión entre GRM adyacentes en cualquiera de las cuatro direcciones. 96 buses de 16 líneas con amplificadores (buffer), que permiten la conexión entre los GRM adyacentes en cualquiera de las cuatro direcciones. 12 líneas con amplificador (buffer) de largo recorrido (long lines), bidirecionales para la distribución de señales a lo largo de la FPGA de manera rápida y eficiente. Figura 73: Líneas de interconexión de propósito general en una Spartan-II 178 FPGAs de la familia SPARTAN II DE XILINX. G.6.2. Caminos de interconexión globales Estos recursos de conexionado son utilizados para la distribución de relojes y señales que precisan de una elevada cargabilidad (fan-out) de salida. Spartan-II establece dos niveles: Caminos primarios, consistentes en 4 líneas globales con terminales de entrada dedicados, que permiten la distribución de señales con alta cargabilidad (fanout) y con un mínimo desfase (skew). Caminos secundarios, consistentes en 24 líneas distribuidas a partes iguales entre la parte superior e inferior del dispositivo. Son más flexibles, al no estar restringidas únicamente a la distribución a señales de reloj, a cambio de introducir mayores retardos. G.7. DLL (Delay-Locked Loop) Cada una de las 4 líneas globales, dedicadas a la distribución de relojes, lleva asociado un DLL cuya finalidad es la de reducir los desfases (skew), en las señales de reloj, mejorando de este modo la sincronización entre las señales de reloj externas e internas. El modo de funcionamiento de cada DLL consiste en monitorizar la señal de reloj procedente del exterior, y la distribuida en el dispositivo, y ajustar de manera dinámica un valor de retardo, de tal modo que sea la señal interna sea una versión retardada en un ciclo exacto de la señal externa. Adicionalmente a esta función, los DLLs permiten disponer de la señal de reloj desfasada en cuadratura, lo que permite doblar internamente las frecuencias de las señales de reloj externas, o bien, disponer de la señal dividida por un factor de 1.5, 2, 2.5, 3, 4, 5 ,8 ó 18. Dispone de 6 salidas. G.8. Exploración periférica (boundary scan) La familia Spartan-II presenta los elementos necesarios para la utilización del método boundary scan conforme al estandar IEEE 1149.1. Apéndice H LCD PowerTIP 1602-H. Figura 74: Vistas anterior y posterior del LCD PowerTIP 1602 El LCD 1602-H es una visualizador de cristal líquido de 2 líneas de 16 caracteres. A continuación se detalla una información elemental del dispositivo. Para una información más detallada consultar la hoja de características disponible en el CD. 179 180 LCD PowerTIP 1602-H. Figura 75: Características mecánicas y diagrama de bloques del LCD-1602H Apéndice I Intregración del proyecto en un IDE. Figura 76: Vista general del editor ConTEXT utilizado como IDE Aunque, es posible trabajar con todas la aplicaciones del proyecto de manera aislada, abriendo en cada caso la ventana pertinente de MS-DOS e invocando manualmente 181 182 Intregración del proyecto en un IDE. cada uno de los programas, también es posible integrar el conjunto alrededor de un IDE29 mejorando de esta manera la interfaz de trabajo. El corazón del IDE puede ser cualquier editor de texto en Windows que disponga de ciertas funcionalidades como son la posibilidad de ejecutar programas externos, la captura de la salida de ventanas tipo consola. Existen multitud de programas con estas características en la red. Figura 77: Ejemplo de configuración de F9 para que ejecute EricASM 29 Integrated Development Enviroment. Intregración del proyecto en un IDE. 183 Para este proyecto, se ha elegido el editor de texto ConTEXT de distribución gratuita y que posee las siguientes características: simple, orientado a programadores, resalta visualmente las palabras reservadas de los lenguajes, soporta la ejecución de aplicaciones externas, etc. Las figuras de este apéndice, recogen los parámetros a configurar en el menú de opciones de entorno, para que las teclas programables puedan ejecutar cada una de las aplicaciones del proyecto, o bien por medio de iconos relacionados con estas teclas. Figura 78: Ejemplo de configuración de F10 para que ejecute EricMON Estas configuraciones están asociadas a la extensión del fichero que estemos manejando, en este caso partimos de que estamos editando un fichero en ensamblador 184 Intregración del proyecto en un IDE. con extensión ASM. Como para el seguimiento de los programas, es importante estar visualizando la versión ensamblada, con extensión LST, es importante también configurarla del mismo modo. Figura 79: Ejemplo de configuración de F11 para que ejecute el XSLOAD El editor tiene capacidad de colorear las palabras reservadas de un lenguaje. Estos lenguajes, pueden también ser configurados junto a la definición de estas palabras. En el CD anexo se incluye el fichero de configuración para que soporte los nemotécnicos propios del juego de instrucciones del ERIC. Para más información sobre el programa consultar la página del autor de ConTEXT http://fixedsys.com/context/ Apéndice J Listados y esquemas 185