Coprocesador FPU (Floating-Point Unit) Titulación: Ingeniería en Automática y Electrónica Industrial



Documentos relacionados
Metodologías de diseño de hardware

Dispositivos Lógicos Programables (FPGAs) Guillermo Güichal Emtech

5. Metodologías de diseño de un ASIC

by Tim Tran:

picojava TM Características

Encuesta sobre utilización de la microelectrónica en la Argentina

Laboratorio de Diseño de Sistemas Digitales

Memoria La memoria es la parte del ordenador en la que se guardan o almacenan los programas (las instrucciones y los datos).

CAPITULO 5. DISPOSITIVOS DE LOGICA RECONFIGURABLE

ACTIVIDADES TEMA 1. EL LENGUAJE DE LOS ORDENADORES. 4º E.S.O- SOLUCIONES.

Una computadora de cualquier forma que se vea tiene dos tipos de componentes: El Hardware y el Software.

Guía de uso del Cloud Datacenter de acens

Uso del simulador Modelsim

WINDOWS. Iniciando Windows. El mouse

UNIDADES DE ALMACENAMIENTO DE DATOS

Creado dentro de la línea de sistemas operativos producida por Microsoft Corporation.

INSTITUTO TECNOLÓGICO DE COLIMA LIC. EN INFORMÁTICA

MANUAL COPIAS DE SEGURIDAD

Edición de Ofertas Excel Manual de Usuario

Actividad 4: Comunicación entre PLC s vía Ethernet

Servicio de Informática Vicerrectorado de Tecnologías de la Información y la Comunicación

Intérprete entre el Operador y el Ordenador.

Curso Completo de Electrónica Digital

TEMA 20 EXP. WINDOWS PROC. DE TEXTOS (1ª PARTE)

Operación de Microsoft Excel

Introducción a FPGAs. Contenido

Configuracion Escritorio Remoto Windows 2003

AGREGAR UN EQUIPO A UNA RED Y COMPARTIR ARCHIVOS CON WINDOWS 7

Placa de control MCC03


UNIDADES FUNCIONALES DEL ORDENADOR TEMA 3

UNIVERSIDAD TECNOLOGICA ECOTEC DIEGO BARRAGAN MATERIA: Sistemas Operativos 1 ENSAYO: Servidores BLADE

Escritorio remoto y VPN. Cómo conectarse desde Windows 7

Internet Information Server

TEMA 5. ELECTRÓNICA DIGITAL

Módulo 1 El lenguaje Java

Informática 4º ESO Tema 1: Sistemas Informáticos. Sistemas Operativos (Parte 2)

TEMA 3. EL PROCESO DE COMPILACIÓN, DEL CÓDIGO FUENTE AL CÓDIGO MÁQUINA

Elementos requeridos para crearlos (ejemplo: el compilador)

Plataforma e-ducativa Aragonesa. Manual de Administración. Bitácora

Guía de selección de hardware Windows MultiPoint Server 2010

UNIVERSIDAD DE ANTIOQUIA DISEÑO DE SISTEMAS DIGITALES COMPLEJOS LABORATORIO 1 INTRODUCCIÓN AL MICROBLAZE Y AL ENTORNO EDK

WINDOWS : TERMINAL SERVER

Operación Microsoft Access 97

Tarjeta Principal. Disco Duro. Memoria RAM. Procesador. Fuente de Poder. Tarjetas de Expansión. Jair Acosta Núñez

Sistemas de Computadoras Índice

PROYECTOS, FORMULACIÓN Y CRITERIOS DE EVALUACIÓN

La informática es el conjunto de técnicas y conocimientos necesarios para el tratamiento automático de la información mediante el ordenador.

Tema 16 ELECTRÓNICA DIGITAL LENGUAJES DE DESCRIPCIÓN DE LOS SISTEMAS DIGITALES (PARTE 1)

1.- MENU DE CONTROL O MENU VENTANA: permite cerrar la ventana cambiarla de tamaño y pasar a otra ventana

Tema: INSTALACIÓN Y PARTICIONAMIENTO DE DISCOS DUROS.

Capítulo 9. Archivos de sintaxis

Conexión de GPS a Open CPN.

UF0513 Gestión auxiliar de archivo en soporte convencional o informático

El programa Minitab: breve introducción a su funcionamiento. Para mostrar la facilidad con la que se pueden realizar los gráficos y cálculos

Aritmética finita y análisis de error

Manual de uso de la plataforma para monitores. CENTRO DE APOYO TECNOLÓGICO A EMPRENDEDORES -bilib

COMO CONFIGURAR UNA MAQUINA VIRTUAL EN VIRTUALBOX PARA ELASTIX

Tema2 Windows XP Lección 1 MENÚ INICIO y BARRA DE TAREAS

18. Camino de datos y unidad de control

SCT Software para la calibración de transductores de fuerza. Versión 3.5. Microtest S.A.

CAPÍTULO 4 ANÁLISIS DE IMPLEMENTACIONES

1.- DESCRIPCIÓN Y UTILIDAD DEL SOFTWARE DAEMON TOOLS.

CONCEPTOS BASICOS. Febrero 2003 Página - 1/10

PRUEBAS DE ACCESO A CICLOS FORMATIVOS DE GRADO SUPERIOR Convocatoria de 23 de junio de 2005 (Orden de 18 de febrero de 2005, BOA de 05/03/2005)

Windows Server 2012: Infraestructura de Escritorio Virtual

LÓGICA PROGRAMABLE. Introducción Simple PLDs Complex PLDs FPGAs. Dpto. Ingeniería Electrónica y Comunicaciones

DISCOS RAID. Se considera que todos los discos físicos tienen la misma capacidad, y de no ser así, en el que sea mayor se desperdicia la diferencia.

Representación de números en binario

LABORATORIO DE COMPUTADORAS

Toda base de datos relacional se basa en dos objetos

Unidad I. 1.1 Sistemas numéricos (Binario, Octal, Decimal, Hexadecimal)

Utilidades de la base de datos

PROGRAMACIÓN ORIENTADA A OBJETOS Master de Computación. II MODELOS y HERRAMIENTAS UML. II.2 UML: Modelado de casos de uso

MACROS. Automatizar tareas a través del uso de las macros.

Sistema de Gestión Portuaria Sistema de Gestión Portuaria Uso General del Sistema

Técnicas de Programación Hardware: CAD para FPGAs y CPLDs

Bajo coste, alta densidad, alta velocidad, bajo consumo de energía y alta fiabilidad.

Arquitectura Von Neumann

Tema 11: Instrumentación virtual

Operación Microsoft Windows

CAPÍTULO 1 Instrumentación Virtual

Ayuda para la instalación Componente Firma Digital INDICE. 1 Configuración previa Configuración Internet Explorer para ActiveX...

Transformación de binario a decimal. Transformación de decimal a binario. ELECTRÓNICA DIGITAL

CAPÍTULO 4. EL EXPLORADOR DE WINDOWS XP

GESTIÓN DOCUMENTAL PARA EL SISTEMA DE CALIDAD

Apéndice 5 Manual de usuario de ColeXión. ColeXión 1.0. Manual de usuario

Desde el punto de vista físico en un ordenador se pueden distinguir los siguientes elementos:

Manual de software. Dynamic Cloud. 10/2014 MS-Dynamic_Cloud v1.2

Notas para la instalación de un lector de tarjetas inteligentes.

Windows Server 2012: Infraestructura de Escritorio Virtual

Trabajo TICO Unidad 2: Sistemas Operativos. Guillermo Jarne Bueno.

Bienvenida. Índice. Prefacio

WINDOWS : COPIAS DE SEGURIDAD

No se requiere que los discos sean del mismo tamaño ya que el objetivo es solamente adjuntar discos.

Apuntes de ACCESS. Apuntes de Access. Campos de Búsqueda:

Tipos de Dispositivos Controladores

Introducción a las redes de computadores

TEMA VII: DISEÑO SECUENCIAL PROGRAMABLE

PROCESAMIENTO DIGITAL DE IMÁGENES MEDIANTE EL USO DE UN FPGA Y LENGUAJE VHDL

Transcripción:

Coprocesador FPU (Floating-Point Unit) Titulación: Ingeniería en Automática y Electrónica Industrial AUTOR: Pere Blanch Aubia DIRECTOR: Enric Cantó Navarro DATA: Junio 2012

Índice 1 Introducción... 4 1.1 Objetivos... 4 1.2 Definiciones... 7 1.2.1 Ordenadores personales Vs sistemas embedidos... 7 1.2.2 Unidad de Proceso Central (CPU)... 7 1.2.3 Circuito Integrado para Aplicaciones especificas (ASIC)... 8 1.2.4 Field Programmable Gate Array (FPGA)... 9 1.2.5 Hardware Description Language (HDL)... 14 1.2.6 IP Cores... 15 1.3 Software Principal... 16 1.3.1 Xilinx Platform Studio (XPS)... 16 1.3.2 Embedded Development Kit (EDK)... 16 1.3.3 Integrated software environment (ISE)... 16 1.3.4 Software Development Kit (SDK)... 16 1.3.5 ModelSim SE Plus 6.2c... 24 1.4 Avnet Spartan-3 Development Board... 25 2 Memoria Descriptiva... 28 2.1 IEEE 754... 28 2.2 Operación Intf... 31 2.2.1 Comportamiento Copro VS Microblaze... 31 2.2.2 Adaptación en Copro... 41 2.3 Operación Add/Sub... 41 2.3.1 Comportamiento Copro VS Microblaze... 42 2.3.2 Adaptación en Copro... 49 2.4 Operación Mul... 49 2.4.1 Comportamiento Copro VS Microblaze... 49 2.4.2 Adaptación en Copro... 58 2.5 Operación Div... 59 2.5.1 Comportamiento Copro VS Microblaze... 59 2.5.2 Adaptación en Copro... 71 2.6 Ensayo con Avnet Spartan-3 Development Board... 72 2.6.1 Configuración... 72

2.6.2 Señal de reloj... 73 2.6.3 Memoria SRAM... 73 2.6.4 Conexión y grabación... 73 2.6.5 Comunicación R232... 74 2.7 Resultados experimentales... 75 2.7.1 Comprobación funcional... 75 2.7.2 Comprobación de la acceleración... 78 2.8 Conclusiones... 83 2.9 Propuestas... 83 3 Anexos... 84 3.1 Anexos de Software... 84 3.1.1 Programa C utilizado en la comprobación funcional.... 84 3.1.2 Programa C utilizado en la comprobación de la aceleración... 86 3.1.3 Programa C utilizado en el desarrollo de las operaciones de int2f, suma, resta, multiplicación y división..... 90 3.2 Anexos de Hardware... 92 3.2.1 Adaptación del código VHDL... 92 3.2.2 Código VHDL completo... 98 4 Bibliografia... 142

1 Introducción 1.1 Objetivos El objetivo final es diseñar una unidad de operaciones en coma flotante vectorial, en inglés Vector Floating Point Unit (VFPU), de tal modo que produzca el mismo resultado que la unidad de operaciones en coma flotante del microprocesador softcore de 32 bits Microblaze de Xilinx. La VFPU tiene asociada una circuiteria para acceder a memoria autónomamente con la finalidad de acelerar el procesado de vectores con flotantes. La FPU de Microblaze necesita que el microprocesador lea y escriba datos a memoria mientras que la VFPU accede a memoria por si sola, lo que permite acelerar el cálculo con vectores. Finalmente, decir que la VFPU, la cual llamaremos Copro en todo este trabajo, está en fase de desarrollo y experimenta problemas en el cálculo del sticky bit y el redondeo cuando se realizan operaciones y se comparan los resultados con los de la FPU de Microblaze. Esto básicamente es debido a que el cálculo del sticky bit no esta estandarizado y por esta razón es difícil analizar el cálculo que realizan otras FPUs. Por tanto, el principal objetivo de este trabajo esta formado de dos partes: Investigar como la unidad de operaciones en coma flotante del microprocesador softcore de 32 bits Microblaze calcula el sticky bit y hace el redondeo cuando realiza operaciones en coma flotante. Modificar la unidad de operaciones en coma flotante vectorial implementada en una FPGA y diseñada por Enrique Cantó, de tal modo que su comportamiento tanto en el cálculo del sticky bit como en el redondeo sea el mismo que el del microprocesador softcore de 32 bits Microblaze de Xilinx. Con este fin, se definen los siguientes objetivos secundarios: Estudio de FPGAs (Field Programmable Gate Array) Estudio de las herramientas de simulación VHDL (ModelSim) y de síntesis e implementación (ISE). Estudio de la placa de desarrollo Avnet Spartan-3A Evaluation Kit. Estudio del estándar de la IEEE para aritmética en coma flotante (IEEE 754) Simulación funcional, síntesis, implementación y verificación del diseño sobre un dispositivo FPGA. Ejecución y comprobación del funcionamiento del coprocesador utilizando la placa de desarrollo Avnet Spartan-3A Evaluation Kit. Para una mejor comprensión del trabajo realizado a continuación se mostrarán diferentes figuras de un diagrama de bloques de la arquitectura de un sistema digital con microprocesador. Estas contendran el sistema original, el sistema modificado, en el cual se podrá ver la VFPU y otros componentes necesarios para su funcionamiento, y finalmente un pequeño zoom de la VFPU para ver las partes que integra.

Figura 1: Sistema digital con el microprocesdor Microblaze de 32bits En la figura 1 se puede ver el diagrama original de un sistema digital con microprocesador montado en una FPGA de Xilinx. Este está formado por controladores de bus DLMB e ILMB, un controlador de interrupciones designado para un puerto de comunicación serie, una memoria interna, un MDM, en inglés Machine Debug Module, el cual permite debugar aplicaciones ejecutadas por el microprocesador, un timer, un generador de señal de reloj conectado a un oscilador de 50MHz externo a la FPGA, un switch de reset, un controlador de un display de led de 7 segmentos y un microprocesador de 32bits llamado Microblaze el cual tiene una unidad de operaciones con flotantes (FPU).

Figura 2: Sistema digital modificado con el microprocesdor Microblaze de 32bits Utilizando como base el sistema de la figura 1, la figura 2 muestra como el sistema original se ha modificado creando una VFPU, la cual está conectada a un controlador EMC permitiendo que la unidad VFPU pueda acceder a una memoria externa SRAM de manera autónoma. El sistema se ha modificado de tal modo que el microprocesador pueda también acceder a la memoria externa SRAM. Figura 3: Vista de la unidad de operaciones en coma flotante vectorial y las partes que la integran La figura 3 muestra la VFPU formada por un circuiteria, la cual hace posible que esta acceda a la memoria SRAM externa de manera autónoma, y una FPU. También se puede ver las partes que integra la FPU. Estas son un bloque divisor, un multiplicador, un sumardor/restador, un convertidor entero a flotante, un bloque que hace el valor absoluto, un bloque que hace la negación y un bloque comparador. Esta VFPU es la que se ha utilizado para desarrollar este trabajo.

1.2 Definiciones 1.2.1 Ordenadores personales Vs sistemas embedidos Los ordenadores personales, personal computers en inglés, se han creado para ejecutar un amplio número de aplicaciones diferentes las cuales, algunas de ellas, requieren la utilización de muchos recursos de dicho ordenador. Por esta razón, los PCs se han fabricado con procesadores de alto rendimiento, memorias de gran capacidad y otro tipo de periféricos como puertos USB, tarjetas de video, tarjetas de sonido, discos duros Estas aplicaciones dependen del sistema operativo el cual se encarga de manejar la memoria, controlar periféricos, manejar archivos de sistema e interrupciones y administrar tareas. En cambio, un sistema embebido es todo lo contrario a un ordenador personal, es decir, es un sistema digital con procesador diseñado y programado para reunir los requisitos de una aplicación específica como en el caso de reproductores de música, impresoras, escaners Estas aplicaciones pueden no requerir un sistema operativo o un sistema operativo simple y personalizado. Algunos aspectos importantes sobre los sistemas embebidos respecto a los ordenaros personales son la reducción del tamaño, del coste y del consumo de energía. Un sistema embebido normalmente esta compuesto de un microprocesador de bajo coste, algo de memoria y algunos periféricos. A veces, un sistema embebido puede incluir periféricos personalizados o coprocesadores de operaciones en coma flotante, en inglés Floating Point Unit (FPU), para acelerar la ejecución de la aplicación. Los microprocesadores son el celebro de los sistemas digitales con procesador sobre los cuales se ejecutan las instrucciones que forman el sistema operativo y otras tareas más específicas. Los microprocesadores embebidos no tienen las mismas prestaciones que los microprocesadores utilizados en los ordenadores personales pero son suficientemente potentes para ejecutar la aplicación específica de un sistema embebido. Hoy en día existen en el mercado una gran variedad de procesadores embebidos los cuales tienen diferentes prestaciones. Entonces, antes de diseñar un sistema embebido hay que hacer una buena elección del microprocesador para obtener un mejor rendimiento del sistema. 1.2.2 Unidad de Proceso Central (CPU) La CPU, también conocida como procesador o microprocesador, es el componente principal de un sistema computador. Su misión es ejecutar las instrucciones que forman los programas y gestionar los datos. Habitualmente, la CPU la cual está fabricada en un chip es un único trozo de silicio que contiene millones de componentes electrónicos. Las partes típicas de una CPU son: La unidad aritmético lógica (ALU): ejecuta operaciones aritméticas y lógicas. La unidad de control (CU): responsable de extraer las instrucciones de la memoria, decodificarlas y ejecutarlas, haciendo uso de la ALU cuando sea necesario. Registros los cuales proporcionan almacenamiento interno a la CPU. Interconexiones CPU que son mecanismos que proporcionan comunicación entre la unidad de control, la ALU y los registros.

Tipos de CPUs: Básicamente nos encontramos con dos tipos de diseño de las CPUs: RISC (Reduced-Instruction-Set Computing) y CISC (complex-instruction-set computing). Las CPUs RISC se basan en la idea de que la mayoría de las instrucciones para realizar procesos en el computador son relativamente simples por lo que se minimiza el número de instrucciones y su complejidad a la hora de diseñar la CPU. Algunos ejemplos de arquitectura RISC son el SPARC de Sun Microsystem's, el microprocesador Alpha diseñado por la antigua Digital, hoy absorbida por Compaq y los Motorola 88000 y PowerPC. Estas CPUs se suelen emplear en aplicaciones industriales y profesionales por su gran rendimiento y fiabilidad. Al contrario, las CPUs CISC tienen una gran cantidad de instrucciones y por tanto son muy rápidos procesando código complejo. Fue la primera tecnología de CPUs con la que la máquina PC se dio a conocer mundialmente. Su sistema de trabajo se basa en la microprogramación. Dicha técnica consiste en hacer que cada instrucción sea interpretada por un microprograma localizado en una sección de memoria de la CPU. A su vez las instrucciones compuestas se decodifican para ser ejecutadas por el procesador. Las instrucciones estan almacenadas en una ROM interna y las operaciones se realizan a ritmo de los ciclos de un reloj. Considerando la extraordinaria cantidad de instrucciones que la CPU puede manejar, la construcción de una CPU con arquitectura CISC es realmente compleja. A este grupo pertenecen los procesadores populares utilizados en ordenadores personales de escritorio y ordenadores portátiles. El origen de la arquitectura CISC se remonta a los inicios de la programación ubicada en los años 60 y 70. Para contrarrestar la crisis del software de ese entonces, empresas electrónicas fabricantes de hardware pensaron que una buena solución seria crear una CPU con un amplio y detallado manejo de instrucciones, a fin de que los programas fueran más sencillos. Los programadores en consecuencia crearon multitud de programas para esa arquitectura. La posterior masificación de los ordenadores personales, permitió que el mercado fuera luego repleto de software creado para procesadores CISC. Las principales ventajas de la tecnología CISC destacan las siguientes: 1. Reduce la dificultad de crear compiladores. 2. Permite reducir el coste total del sistema. 3. Reduce los costes de creación de Software. 4. Mejora la compactación de código. 5. Facilita la depuración de errores (debugging). 1.2.3 Circuito Integrado para Aplicaciones especificas (ASIC) Un ASIC es circuito integrado personalizado creado para una aplicación particular. Debido a la reducción del tamaño de los elementos y a la mejora en las herramientas de diseño a lo largo de los años, la complejidad máxima (y, por lo tanto, la funcionalidad) ha crecido desde 5000 puertas lógicas hasta por encima de los 100 millones. Los ASIC modernos a menudo incluyen procesadores de 32 bits, bloques de memoria ROM, EEPROM, Flash y otros bloques. Los diseñadores de ASIC digital utilizan lenguajes HDL, como Verilog o VHDL, para describir la funcionalidad de los ASIC. Las FPGA son la alternativa moderna al prototipado de sistemas ASIC ya que, debido a su característica de fácil reprogramación, permiten la utilización del mismo dispositivo para muchas aplicaciones diferentes. Para diseños y/o volúmenes de producción menores, las FPGA pueden ser menos costosas que un diseño ASIC. El coste

de preparación de una fábrica para producir un ASIC particular puede oscilar entre los cientos de miles de euros. El término general application specific integrated circuit incluye las FPGA, pero la mayoría de diseñadores utilizan ASIC solamente para dispositivos no programables. 1.2.4 Field Programmable Gate Array (FPGA) Se trata de un dispositivo semiconductor que contiene bloques lógicos programables (CLB en inglés), interconexiones programables y bloques de entrada/ salida configurables. Cada fabricante tiene su propia arquitectura de FPGA pero en rasgos generales, todas las FPGAs, con sus variaciones, tienen una arquitectura similar al de la figura siguiente. Figura 4: Matriz de bloques lógicos programables Los bloques lógicos pueden ser programados para imitar la funcionalidad de puertas lógicas básicas como and, or, xor, not o funciones combinacionales más complejas como decodificadores, funciones matemáticas simples o multiplexores para enrutar la lógica de dentro el bloque hacia o desde fuentes externas. En la mayoría de FPGAs, estos bloques lógicos incluyen a su vez elementos de memoria como simples flip-flop o bloques de memoria más completos. Un ejemplo seria el circuito de la siguiente figura.

Figura 5: Bloque programable La red de conexiones internas programables permite al diseñador del sistema conectar los bloques lógicos de la FPGA según sus necesidades. Tras el proceso de fabricación, estos bloques y conexiones lógicas pueden ser programadas por el cliente/ diseñador para que la FPGA pueda ejecutar cualquier función lógica que se precise. La figura 6 muestra un ejemplo de la red usada para conectar los diferentes bloques lógicos. Las líneas más largas se usan para conectar aquellos bloques que están físicamente situados lejos dentro de la FPGA, mientras que las líneas cortas se utilizan para conectar bloques lógicos que están situados más cerca dentro de la FPGA. Muy a menudo también hay una matriz de interruptores, switch matrix en inglés, para conectar las líneas largas con las líneas cortas de manera específica. Para conectar múltiples bloques lógicos a una línea larga se utiliza un buffer tri-estado creando así un bus de comunicaciones. Las líneas largas están especialmente diseñadas para tener una impedancia muy baja lo que significa que el tiempo de propagación es muy rápido. Estas están también conectadas a un buffer de reloj y a los elementos que funcionan con reloj, como los flip-flops de cada uno de los bloques lógicos. Así es como la señal de reloj se distribuye por toda la FPGA. En los ASICs, la mayoría de retardos vienen dados por la lógica del diseño porque la lógica esta conectada con líneas de metal que provocan retardos. Sin embargo, en las FPGAs, lo que provoca el retardo son las interconexiones. Para conectar diferentes bloques lógicos distribuidos dentro de la FPGA requiere conexiones a través de muchos transistores y matrices de interruptores los cuales introducen un retardo extra.

Figura 6: Red de conexiones internas programables Las celdas de entrada y salida configurables, como el que se puede ver es la figura 7, sirven para llevar señales dentro y fuera de la FPGA. Estas celdas están formadas de un buffer de entrada y otro de salida con control de salida triestado y colector abierto. Normalmente hay resistores pull up y a veces pull down los cuales se pueden utilizar para terminar señales y buses sin que se tengan de utilizar resistores externos a la FPGA. Normalmente, la polaridad de la salida puede ser programada para que sea activa a nivel alto o activa a nivel bajo y también, en muchas ocasiones, el slew rate de las salidas se puede programar para obtener tiempos de subida o bajada más rápidos o más lentos. En el circuito se puede ver que hay flip-flops tanto para señales configuradas como salidas como para señales configuradas como estradas. En el caso de las salidas, estos flip-flops transmiten las señales controladas por reloj hacia la salida de manera muy rápida sin que se ocasionen demasiados retardos proporcionando una mejor comunicación con dispositivos externos. En el caso de las entradas, estos flip-flops reducen el tiempo de la señal cuando entra en un flip-flop aumentando el tiempo de espera requerido en las FPGAs. Figura 7: Celdas de entrada y salida configurables

Programacion FPGAs (SRAM vs Antifuse vs Flash) Hay 3 tecnologías para programar una FPGA. Programación SRAM la cual usa un bit de RAM estática para cada uno de los elementos de programación. Para escribir un cero se abre el interruptor y para escribir un uno se cierra el interruptor. Otro método es el antifusible el cual consiste en un estructura microscópica que, a diferencia de los fusible convencionales, normalmente esta abierto (no hace conexión). Una cantidad considerable de corriente durante la programación del dispositivo provoca que el antifusible se cierre. Un tercer método y relativamente nuevo es el de utilizar bits EPROM para cada uno de los elementos de programación. Las ventajas de las FPGAs que se basan en programación SRAM, la cual es la más extendida hasta el momento, es que se utiliza un proceso de fabricación estándar el cual proporciona un rendimiento mejor. Como que las SRAM son programables, las FPGAs se pueden reprogramar infinitas veces, incluso si están en el sistema, es decir, sin tener que desconectar el dispositivo, igual que si se escribiese en una SRAM normal. Los dispositivos que utilizan este método pueden utilizar en el diseño la SRAM interna como pequeñas memorias. Las desventajas de las FPGAs que se basan en programación SRAM es que son volátiles lo que significa que una caída de tensión, por muy pequeña que sea, puede corromper el contenido del dispositivo. Las FPGAs que utilizan esta tecnología tienen unos retardos debido al largo enrutamiento aunque este es más pequeño que el retardo producido por otra tecnología. Una buena noticia es que la continua mejora de la tecnología SRAM ha hecho este retardo sea casi insignificante. Las FPGAs SRAM pueden consumir bastante potencia y son menos seguras que otras FPGAs que utilizan otras tecnologías ya que tienen que ser reprogramadas cada vez que el sistema es alimentado. Esto hace que el flujo de bits de programación (bitstream en inglés) esté al alcance de cualquiera durante la programación, sin embargo, se puede encontrar en el mercado FPGAs SRAM personalizadas con llaves de encriptación para la programación. Otra desventaja es que los errores de bits son más comunes en FPGAs SRAM que en otros dispositivos de tecnologías diferentes. La conclusión final de la esta tecnología de programación es que las ventajas de las FPGAs SRAM sobrepasan sus desventajas haciendo que esta tecnología sea la predominante en el mercado. Las ventajas de las FPGAs que se basan en programación antifusible son que no son volátiles y que los retardos de enrutamiento son muy pequeños, por tanto, se puede decir que son bastante rápidas. Las FPGAs antifusible tienden a consumir poco y son buenas para guardar los diseños en el interior del mismo dispositivo ya que no se tienen que reprogramar cada vez que el dispositivo se alimente. La principal desventaja de las FPGAs que se basan en programación antifusible es el proceso de fabricación complejo. Otras desventajas es que se necesita un programador externo para programarlas y, una vez han sido programadas, estas ya no se pueden borrar para ser reprogramadas. Pero como se ha dicho de buen principio el proceso de fabricación complejo y no estándar ha sido la razón por la cual esta tecnología haya mejorado más lentamente que las de SRAM. Finalmente tenemos las FPGAs que combinan los dos métodos anteriores. La FPGAs que se basan en programación Flash. Son no volátiles como la antifusible pero se pueden programar tantas veces como se quiere como las FPGAs SRAM. También utilizan un proceso de fabricación estándar como la SRAM. Son relativamente rápidas,

sin embargo, no están tan extendidas como las SRAM. En cualquier caso esto podría cambiar en cualquier momento. Ejemplos de familias de FPGA. Fabricantes de familias de FPGAs SRAM: Altera Stratix II and Cyclone II families Atmel AT6000 and AT40K families Lattice LatticeEC and LatticeECP families Xilinx Spartan-3 and Virtex-4 families Fabricantes de familias de FPGAs antifusible: Actel SX and Axcelerator families Quicklogic Eclipse II family Fabricantes de familias de FPGAs Flash: Actel ProASIC family Fabricantes de familias de FPGAs hibridas Flash/SRAM: Lattice LatticeXP family Uno de los principales fabricantes de FPGAs es la empresa Xilinx la cual fue fundada por Ross Freeman (el inventor de las FPGA), Bernie Vonderscmitt (pionero del concepto de compañía fabless) y Jim Barnett en 1984 y con base en Silicon Valley, California. Al año siguiente desarrollaron su primera FPGA, el modelo XC2064. Hoy en día, los headquaters están en San José, California, mientras que la sucursal Europea se halla en Dublín, Irlanda y la asiática en Singapur. Algunas de la FPGAs Virtex-4/5 de Xilinx ofrecen un microprocesador hardcore de 32 bits denominado PowerPC del cual existen dos versiones, el 405 y el 440. El PowerPC-405 es procesador little-endian el cual se caracteriza por utilizar la técnica pipeline de 5 etapas, cache y una unidad de manejo de memoria, en inglés Memory Manegement Unit (MMU). El PowerPC-440 es una versión mejorada del 405 el cual esta diseñado siguiendo la arquitectura superescalar y utiliza la técnica pipeline de 7 etapas. La arquitectura de los procesadores PowerPC 405 y 440 soportan FPU auxiliares u otro tipo de coprocesadores. La más nueva versión de FPGAs de Xilinx Zynq-7000 integran un procesador dual core ARM Cortex-A9. De hecho, los procesadores ARM se han convertido el estándar de los microprocesadores de 32 bits montados en ASICs. Xilinx también proporciona Microblaze, un microprocesador softcore de 32 bits pensado para sistemas embebidos implementados en cualquiera de sus FPGAs. Este microprocesador se puede configurar para utilizar técnica pipeline de 3 a 5 etapas, se puede activar una cache lógica, una MMU, una FPU de precisión simple Diseño de FPGA Para definir el comportamiento de una FPGA el usuario proporciona un diseño hardware. Esto se consigue con un lenguaje de programación llamado HDL (hardware description language en inglés) el cual ayuda al diseñador a hacer una descripción del

circuito hardware mediante programación software. Los lenguajes más comunes son VHDL y Verilog. Una vez completados los procesos de diseño y validación, se genera el fichero binario usado para reconfigurar el dispositivo FPGA. Para simplificar el diseño de sistemas complejos en FPGAs, existen librerías de funciones complejas predefinidas y circuitos que han sido testeados y optimizados para agilizar el proceso de diseño. Estos circuitos predefinidos se llaman IP Cores y se pueden conseguir gratuitamente o comprándolos a fabricantes de FPGA o a proveedores de IP Cores pero lo más normal es que no sean gratuitos, y típicamente protegidos bajo licencias de propiedad. Otros circuitos predefinidos están disponibles en comunidades de desarrolladores como OpenCores (típicamente gratuitos).una sitio web muy conocido donde los usuarios registrados comparten sus IP Cores es http://opencores.org 1.2.5 Hardware Description Language (HDL) Se trata de un lenguaje para la descripción formal de circuitos electrónicos. Puede describir tanto la operación del circuito, su diseño y testeo para verificar su funcionamiento mediante simulación. Un HDL es una expresión estándar basada en texto del comportamiento temporal y/o la estructura circuital de un sistema electrónico. En contraste con un lenguaje de programación software, la sintaxis y la semántica de un HDL incluyen notaciones explícitas para expresar tiempo y concurrencia, que son atributos principales del hardware. Aquellos lenguajes cuya única característica es la de expresar la conectividad del circuito entre una serie de bloques se clasifican como lenguajes netlist. Los HDL son utilizados para escribir especificaciones ejecutables de algunos circuitos hardware. Un programa de simulación, diseñado para implementar la semántica de las declaraciones del lenguaje, combinado con la simulación del progreso del tiempo, proporciona al diseñador de hardware la habilidad de modelar un dispositivo hardware antes de ser creado físicamente. Un programa software llamado sintetizador puede deducir operaciones lógicas hardware de las declaraciones del lenguaje HDL y producir una netlist equivalente de primitivas hardware genéricas para implementar el comportamiento especificado. Esto suele requerir que el sintetizador ignore la expresión de cualquier construcción temporal en el texto. Diseño con HDL Los lenguajes HDL se utilizan para diseñar dos tipos de sistemas. Primero, son utilizados para diseñar un circuito integrado personalizado (ASIC), como un procesador u otro tipo de chip de lógica digital. En este caso, un HDL especifica un modelo del comportamiento de un circuito antes que el circuito sea diseñado y fabricado. El resultado final es un chip de silicio que será producido en una fábrica. En segundo lugar, son utilizados para la programación de dispositivos lógicos programables (PLD), como las FPGA. El código HDL es introducido en un compilador lógico, y la salida se carga en el dispositivo programable. La característica especial de este proceso y de la lógica programable en general es la posibilidad de alterar el código, compilarlo y cargarlo en el mismo dispositivo programable varias veces para que este pueda ser testeado.

1.2.6 IP Cores En un diseño electrónico una IP Core (intellectual property core) es una unidad lógica, celda o diseño reutilizable que tiene la finalizar de realizar una tarea especifica. Una IP core puede ser propiedad de un grupo o de una única persona física y se utilizan como bloques dentro de diseños para chips ASIC o para diseños lógicos con FPGAs. Las IP cores se venden en el mercado a través de empresas especializas en diseñar estas unidades. Recientemente, empresas que fabrican y venden FPGA han empezado a ofrecer sus propias IP cores. Las IP cores reducen el tiempo de diseño así como la necesidad de mano de obra a los diseñadores que trabajan con FPGAs. Una de las principales ventajas de estas unidades es que han sido previamente diseñadas y verificadas. También, pueden ser modificadas lo que significa que se puede añadir así como eliminar parte de la funcionalidad inicial con el fin de que se adapte a las necesidades del sistema que se este creando. Otra ventaja es que son portables entre diferentes fabricantes. Un problema de las IP cores es que a veces pueden ser caras. Otro aspecto a tener en cuenta son las características eléctricas, como puede ser tiempo o consumo, ya que estas pueden ser optimizadas hasta cierto punto pero las características actuales dependen del uso en un dispositivo en particular y también dependen de la lógica a la cual están conectadas. La compra de IP cores a terceros puede causar resultados no esperados especialmente cuando ha sido integrada en un diseño propio. Estos resultados adversos pueden ser causados por falta de velocidad y/o exceso de consumo. En cuanto a los tipos que existen, se puede decir que existen dos grupos. Las unidades soft cores y las hard cores. Soft cores Las IP cores se ofrecen sintetizables RTL. RTL, en inglés register transfer language, es un término utilizado para describir representaciones intermedias muy cercanas al lenguaje ensamblador. Las IP cores sintetizables se distribuyen en un lenguaje de descripción de hardware como Verilog o VHDL. Estos son análogos a otros lenguajes de nivel alto como C en el campo de programación de computadores. Las IP cores se distribuyen a los fabricantes de chips en formato RTL permitiendo al diseñador de chips hacer modificaciones a nivel funcional, aunque la mayoría de distribuidores de estas unidades no aseguran un buen funcionamiento de las IP cores que han sido modificadas ni tampoco soporte a los diseñadores que han modificado estas unidades. A veces las IP cores se ofrecen como netlists a nivel de puertas genéricas (en ingles generic gate-level netlists). Un netlist es una representación algebraica booleana de la función lógica de las IP cores implementadas en puertas genéricas o celdas estándar para procesos específicos. Una IP core implementada en puertas genéricas es portable a cualquier tecnología de procesos, mientras que, los netlist son análogos al código ensamblador utilizado para programación de computadores, es decir, un netlist proporciona al distribuidor de IP cores una protección razonable contra ingeniería inversa. Hard cores Estas IP cores ofrecen una predicción mayor del rendimiento del chip en cuanto a área y rendimiento de la respuesta. Esto es gracias a la naturaleza de su representación a bajo nivel. La lógica analógica y mixta (digital-analógica) son generalmente definidas mediante descripciones físicas y a bajo nivel. Por esta razón, las IP cores analógicas (SerDes, PLLs, DAC, ADC, etc.) se distribuyen a los fabricantes de chip en formato de

trazado de transistores como GDSII. El formato GDSII, en inglés Graphic Data System, es un formato de fichero de datos que desde hace años ha sido en la industria de los circuitos integrados el estándar para el intercambio de datos entre herramientas de diseño físico de chips. A veces, las IP cores digitales también se ofrecen en este formato. Estas IP cores, ya sean analógicas o digitales, se llaman hard IP cores porque su función no puede ser modificada por los diseñadores de chips. 1.3 Software Principal 1.3.1 Xilinx Platform Studio (XPS) El Xilinx Platform Studio es una interfaz gráfica que conjuntamente con otras herramientas software hace posible desarrollar sistemas embebidos personalizados. Xilinx Platform Studio integra todos los procesos necesarios para un diseño completo. Estos procesos constan de las siguientes etapas: diseño, depuración y verificación. El diseñador utiliza XPS para configurar y crear las especificaciones de su sistema embebido (procesador, controlador de memoria, periféricos de entrada/salida ). Luego XPS convierte las especificaciones del diseñador en una descripción sintetizable RTL (Verilog or VHDL) y escribe un conjunto de scripts para automatizar la implementación del sistema embebido (de RTL a un archivo bitstream). Para crear un sistema embebido con procesador hay que seguir los pasos siguientes: 1.- Diseñar la plataforma hardware que puede estar formada de uno o más procesadores, buses y periféricos. 2.- Crear un software el cual correrá dentro de sistema. 3.- Simular el sistema completo. 4.- Depurar y verificar que el resultado sea el esperado. 1.3.2 Embedded Development Kit (EDK) EDK, conocido también como Embedded Development Kit, esta formado por una serie de herramientas software e IP Cores para el diseño de sistemas embebidos con procesador y soporta procesadores IBM PowerPC TM y procesadores Xilinx MicroBlaze TM. 1.3.3 Integrated software environment (ISE) ISE es el pilar del diseño lógico para FPGAs de Xilinx que permite la síntesis y el análisis de diseños HDL (Hardware Description Language). Como que el diseño lógico de una FPGA es complejo y además hay que tener muchos aspectos en cuenta, ISE proporcionar una serie de herramientas las cuales permiten al desarrollador del sistema sintetizar ( compilar ) sus diseños, realizar análisis de tiempos, examinar diagramas RTL, simular la reacción del diseño a diferentes estímulos, comprobar enrutamiento y emplazamiento lógico, programación y configuración del dispositivo con la ayuda de un programa especialmente creado para este propósito. 1.3.4 Software Development Kit (SDK) SDK es un entorno de desarrollo integrado, complementario a XPS, el cual se utiliza para escribir, compilar y también depurar aplicaciones en un lenguaje bastante

común como C/C++ ampliamente utilizado en sistemas embebidos. SDK usa la estructura opensource Eclipse TM lo que hace que esta herramienta resulte familiar a muchos de los miembros del equipo de diseño de un sistema embebido con procesador. El diagrama siguiente muestra la relación que hay entre los entornos de desarrollo XPS, EDK, ISE y SDK. Figura 8 Creación de un sistema embebido con XPS XPS proporciona 3 opciones para abrir un proyecto. La primera opción es un asistente llamado Base System Builder wizard el cual facilita la tarea de crear la base del sistema embebido que se quiere diseñar, pero esto no es posible para cualquier tipo de placa sino que solo con algunos modelos de placas de determinados fabricantes, o para un modelo genérico de placa. La segunda opción que proporciona el XPS es la posibilidad de crear un proyecto en blanco para que el diseñador pueda crear la base del sistema manualmente y de la manera que más le convenga. Obviamente, esta opción es para usuarios avanzados los cuales tienen un buen conocimiento de la herramienta. Finalmente, la última opción es la de abrir un proyecto ya existente ya sea para terminar el diseño el cual no fue finalizado con anterioridad o para hacer cualquier tipo de modificaciones. La figura 6 muestra la ventana emergente cada vez que se arranca el XPS. Figura 9

Los pasos los cuales el asistente ira preguntando si se selecciona la primera opción son: El nombre del proyecto y directorio en el cual se almacenaran todos los archivos necesarios. El tipo de placa que vamos a utilizar para hacer las pruebas. En este proyecto se utiliza una AVnet Spartan-3 Development Board. El tipo de procesador (IBM PowerPC TM o Xilinx MicroBlaze TM.) Configuración del procesador (frecuencia de reloj ) Configuración de la interfaz entrada-salida. En este caso se pueden utilizar IP cores ya existentes que pueden ser proporcionados por la misma empresa que nos proporciona la placa o comprándolos a terceros. Periféricos internos. Finalmente, especificando como se pretende utilizar el sistema, BSB crea un software de prueba para probar la memoria, los periféricos A finalizar estos pasos se obtiene una pantalla similar a la que se puede ver en la figura siguiente. Figura 10: Ventana principal de XPS. A continuación se describirá la distribución de la información del sistema

a) Project Información Esta sección esta formada por tres pestañas las cuales contienen toda información sobre nuestro sistema y control sobre el mismo. Estas pestañas son Project, Applications y IP Catalog. Pestaña Project: Aquí podemos encontrar la lista de referencias de todos los archivos que contiene nuestro proyecto. Esta lista esta formada de tres sublistas. Archivos de proyecto (Project Files): contiene todos los archivos que hacen referencia al proyecto, por ejemplo, archivos de especificación Hardware del microprocesador, en inglés Microprocessor Hardware Specification (MHS) files, archivos de especificación Software del microprocesador, en inglés Microprocessor Software Specification (MSS) files, Archivos de limitaciones impuestas por el usuario, en inglés User Contraints File( UCF) files, archivos de comandos impact, archivos de opciones de implementación Opciones de proyecto (Project Options): contiene todo las opciones configurables del proyecto, por ejemplo, Dispositivo, netlist, implementación, archivos de configuración. Archivos de referencia (Referente Files): contiene todo los archivos log y de salida generados por proceso de implementación del XPS. A continuación se muestra un listado de todos los archivos de configuración, de especificación, de salida de nuestro proyecto. Figura 11: Detalle de la pestaña Project

Pestaña Applications: Esta pestaña muestra una lista de las aplicaciones de software y sus configuraciones, los archivos.h y los códigos fuente asociados a cada proyecto de aplicación. En esta pestaña se puede. Crear y añadir un proyecto de aplicación de software, compilarlo y cargarlo al bloque de memoria RAM. Configurar las opciones de compilador. Añadir códigos fuentes así como archivos.h al proyecto. La pestaña Applications sirve de mucha ayuda cuando se quiere generar un software de prueba para testear nuestro sistema. Mediante un lenguaje conocido como es C o C++ se pueden crear las instrucciones las cuales queremos que se ejecuten en el sistema embebido. Un ejemplo claro para este proyecto seria crear instrucciones las cuales estén formadas por operaciones en como flotante. De esto modo se ve de una manera muy sencilla si el diseño del coprocesador matemático de operaciones en como flotante funciona correctamente. Figura 12: Detalle de la pestaña Applications Pestaña IP Catalog: Esta pestaña muestra un catálogo de todos los periféricos (IP cores) utilizados en el diseño. Estos pueden se creados por otros diseñadores o creados por el mismos diseñador del sistema. En caso de que se hayan obtenido de otros diseñadores, los periféricos pueden ser libres o pueden tener licencia lo que significa que hay que comprar la licencia para utilizarlos. Cuando se abre un proyecto solo se muestran todos aquellos periféricos que son compatibles con los dispositivos de arquitectura Xilinx. De todos los periféricos disponibles en la lista se puede ver la versión, el estado (activo ), bloqueo (sin licencia, bloqueado, no bloqueado), soporte para procesador y finalmente un corta descripción. También dándole al botón derecho de ratón aparece un menú el cual proporciona datos adicionales como cambios de versiones, hoja de datos y archivo de descripción de periféricos del microprocesador (MPD).

b) System Assembly View Figura 13: Detalle de la pestaña IP Catalog Esta sección llamada vista del montaje del sistema, en inglés System Assembly View, es donde se puede configurar los elementos de los bloques del sistema. Aquí se puede ver una lista de todos los elementos que forma el diseño (Bus interfaces, Puertos, Direcciones) la cual muestra información sobre el mismo y además permite editar la parte hardware de una manera muy sencilla. La información en esta vista puede representarse en modo jerárquico o modo plano. El modo jerárquico es el modo por defecto de esta vista y muestra una lista de las instancias de las IP cores. Además proporciona menús desplegables para acceder a diferentes zonas configurables del sistema hardware. En cambio, el modo plano permite ordenar cualquier información mediante cualquier columna. Seleccionando esta vista, a la izquierda hay una subsección llamada panel de conexiones, en inglés connectivity panel, la cual muestra una representación grafica de las conexiones hardware del diseño. Un línea vertical representa un bus, y una de horizontal representa un bus interface a un IP core. Solo se muestran todas aquellas conexiones las cuales son compatibles, es decir que si entre buses la conexión es compatible, esta se va a mostrar, en caso contrario no será así. Las líneas y los conectores siguen un código de colores para indicar su compatibilidad. Los símbolos de las conexiones indican si un bloque IP core es bus master o esclavo. Un conector hueco representa una conexión la cual esta desactivada y un conector lleno representa una conexión la cual esta activada. Para habilitar

o deshabilitar una conexión solo hay que darle con el puntero del ratón al símbolo de conector. Figura 14

c) Block Diagram Esta sección llamada diagrama de bloques, en inglés block diagram, muestra de manera gráfica la distribución de los elementos utilizados en el diseño. Los elementos pueden ser procesador, memorias, controladores, buses internos los cuales se representan en diferentes colores dependiendo del tipo. Figura 15

d) Platform studio La sección platform studio proporciona un diagrama de flujo del diseño del sistema embebido con enlaces a una ayuda. Si en cualquier momento no se tiene claro como continuar o se necesita más información sobre como realizar un proceso, esta sección puede servir de mucha ayuda. e) Console window La sección console window proporciona información de todas las herramientas llamadas durante la ejecución de las mismas. En la siguiente figura se puede ver que esta console window esta formada de tres pestañas (Output, Warning, Error) las cuales mostraran información de salida, avisos y errores respectivamente durante la compilación del programa, sintentización del diseño y grabación del dispositivo. 1.3.5 ModelSim SE Plus 6.2c Figura 16: Detalle de la pestañas de la consola ModelSim SE (Special Edition) es un entorno de simulación y depurado desarrollado por Mentor Graphics Corporation. Trabaja en entornos basados en Unix, Linux y Windows, y combina un elevado rendimiento con un poderoso e intuitivo GUI (interfaz gráfica de usuario). Permite simular diseños escritos en verilog, vhdl y SystemC (o incluso netlist). Los límites entre lenguajes están impuestos al nivel de cada unidad de diseño. Por lo tanto, cualquier instancia en la jerarquía del diseño puede corresponder a una unidad de diseño escrita en otro lenguaje sin ninguna restricción. A partir de los ficheros fuente de los IP cores o de los diferentes modelos de simulación obtenidos durante el proceso de síntesis e implementación con el entorno ISE, la herramienta ModelSim permite depurar el diseño mediante simulación funcional y simulación postlayout entre otras. Figura 17: Ventana principal del ModelSim

A continuación se describirá las secciones de este entorno de simulación. a) Workspace Esta sección esta formada de 4 pestañas. Las pestañas Library, Objects and Locals, Wave and Visualizador de código La pestaña Library contiene una lista con todas las librarías que describen el comportamiento del sistema. La descripción esta hecha mediante lenguajes como verilog, vhdl o SystemC. Algunas de estas librerías son accesibles, es decir, que el código es abierto y además pueden ser modificadas bajo responsabilidad del diseñador. En cambio, hay otro tipo de librerías las cuales no son accesibles ya que protegidas bajo diferentes licencias sobre la patente y derechos de copyright por propiedad intelectual pero, esto no significa que no se puedan utilizar ya que si se adquiere las licencias correspondientes, estas se pueden utilizar el cualquier diseño. Finalmente, las librerías creadas por el diseñador también aparecen en esta sección. Una característica importante de este visualizador de librerías es que desglosa una librería en unidades de diseño siendo más fácil simular y depurar diferentes partes del diseño. La pestaña Sim aparece cuando se carga una unidad de diseño y contiene todas las librerías además de los archivos de descripción de aquella unidad de diseño. La pestaña files aparece cuando se carga una unidad de diseño y contiene todos los archivos además de los path de la unidad de diseño cargada. b) Objects and locals Muestra todas las señales y variables que se usan dentro de un proceso, entidad o incluso, dentro de una librería. Están aparecen al seleccionar un archivo o librería en la pestaña Sim. c) Wave Esta sección se muestra un gráfico con las formas de onda de todas las señales y variables que se quieren visualizar, además de su valor. Estas solo se muestran dentro de un rango de tiempo que es definido por el usuario y son cargadas directamente desde la ventana Object and locals. El usuario puede aumentar o disminuir el enfoque para ver con más detalle el cambio de valor de estas. d) Visualizor de código Esta sección muestra el código de todos aquellos archivos que se quieren visualizar y que sean accesibles. Sin embargo, también es posible utilizar otros visualizadores conocidos como UltraEDIT32 o el Notepad de Windows. 1.4 Avnet Spartan-3 Development Board La placa de desarrollo Spartan-3, en inglés Spartan3 development Board, la cual ha sido diseñada y fabricada por Avnet, proporciona una plataforma hardware estable para desarrollar y testear diseños con FPGAs de Xilinx que son consideradas las que tiene un coste por puerta lógica y coste por pin de entrada/ salida más barato. El dispositivo FPGA XC3S1500/2000 montado en el módulo electrónico ofrece un entorno de prototipado para implementar periféricos que proporcionen audio y video, comunicaciones, entrada/salida y capacidad de almacenamiento. El módulo esta provisto de conectores de expansión los cuales proporcionan conectividad a módulos de expansión Avnet personalizados y existentes en el mercado. Además, este también tiene dos conectores de expansión Avbus con pines de entrada/salida dedicados

proporcionando así un máximo rendimiento cuando son utilizados con módulos Avnet. El tipo de aplicaciones que se pueden implementar con este módulo va desde aplicaciones del sector de la automoción, industria, medicina y científica, testeo, video digital y redes de comunicación. Las Característica básicas de esta placa de desarrollo son: FPGA Xilinx XC3S1500/2000-FG676 Spartan-3 FPGA I/O Peripherals 2x16 character LCD 128x64 OSRAM OLED graphical display DB15 & video DAC Audio Codec PS2 keyboard and mouse ports 8-position DIP switch 2 push-buttons 8 discrete LEDs Piezo buzzer 3, 140-pin general purpose I/O expansion connectors (AvBus) Up to 30 LVDS pairs 1, 50-pin 0.1" header for easy I/O access Memory Micron DDR SDRAM (32 MB) 16 MB FLASH 2 MB SRAM Communication RS-232 serial port 10/100 Ethernet USB 2.0 Configuration Xilinx platform FLASH configuration PROM(s) Parallel IV cable support for JTAG Fly-wire support for Parallel III and MultiLINXTM Figura 18: Diagrama de bloques de la placa de desarrollo Spartan-3

Figura 19: Vista principal de la placa de desarrollo Spartan-3

2 Memoria Descriptiva 2.1 IEEE 754 La codificación de números reales utilizando lógica binaria es significativamente más compleja que el caso de los naturales o enteros. Parte de esta complejidad deriva del hecho de que si bien al utilizar un número finito de bits es posible representar un intervalo concreto de números enteros o naturales, en el caso de los números reales esta técnica no es posible. Dado que entre dos números reales existe un número infinito de números, no es posible representar todos los números en un intervalo concreto sino que se representan únicamente un subconjunto de los números contenidos en dicho intervalo. Esta propiedad plantea un inconveniente que se debe tener en cuenta no sólo en el diseño de los circuitos digitales capaces de procesar números reales, sino incluso en los programas que utilizan este tipo de números. Supongamos que se operan dos números reales representados en forma binaria y que el resultado no corresponde con uno de los números que pueden ser representados. Esta situación es perfectamente posible dado que entre dos números hay infinitos números reales. La única solución posible en lógica digital consiste en representar este resultado por el número real más próximo en la codificación. La consecuencia inmediata es que se ha introducido un error en la representación de este resultado. En general, cualquier número real fruto de una operación tiene potencialmente el mismo problema. En algunos casos este error no existe porque el número sí puede ser representado de forma digital, pero en general, la manipulación de números reales puede introducir un error. Este posible error introducido por la representación adquiere especial relevancia en aquellos programas que realizan cálculos masivos con números reales. Existen técnicas de programación orientadas a minimizar el error producido cuando se manipulan números reales. El estándar IEEE 754 ha sido definido por el Instituto de Ingenieros Eléctricos y Electrónicos (Institute of Electrical and Electronics Engineers, IEEE) y establece el formato básico para representar números en coma flotante, también llamados números reales, en computadoras digitales incluyendo números normalizados, no normalizados, el cero y valores especiales como infinito y NaN. Además, especifica cuatro modos de redondeo y cinco excepciones (incluyendo cuándo ocurren dichas excepciones y qué sucede en esos momentos). IEEE 754 también especifica cuatro formatos para la representación de valores en coma flotante: precisión simple (32 bits), precisión doble (64 bits), precisión simple extendida ( 43 bits, no usada normalmente) y precisión doble extendida ( 79 bits, usualmente implementada con 80 bits). Tanto Copro como Microblaze soft processor core trabajan con 32 bits, es decir, que utilizan precisión simple para representar los números en coma flotante. Precisión simple Como se ha mencionado anteriormente, en precisión simple se usan 32 bits (4 bytes) para representar un número real: 1 bit para el signo (s) del número, 23 bits para la mantisa (m) y 8 bits para el exponente (exp), los cuales se distribuyen de la siguiente forma:

Figura 20: Representación de un número real con precisión simple en el estándar 754. El bit de signo (S) es 0 para números positivos y 1 para números negativos. La mantisa (m) esta formada de 23 bits que se obtienen transformando el número decimal a binario y cogiendo los 23 bits de la derecha de la coma si esta es colocada a la parte derecha de primer 1 de más hacia la izquierda del número representado en binario. Si no hay suficiente bits a la parte derecha de la coma, los que faltan hasta 23 se rellenan con 0. Ejemplo 1: 8d=1000bmoviendo la coma detrás del 1 de mas a la izquierda (1.000)m=000 0000 0000 0000 0000 0000 Ejemplo 2: 0.1d=0.0001100110011 moviendo la coma detrás del 1 de la izquierda (1.100 1100 1100 1100 1100 1100)m=100 1100 1100 1100 1100 1100 Ejemplo 3: 8.5d=1000.1moviendo la como detrás del 1 de la izquierda (1.000 1)m=000 1000 0000 0000 0000 0000 El exponente se representa como 127 número de desplazamientos de la coma en la mantisa. + si el desplazamiento se hace hacia la izquierda y - en caso contrario. Si nos fijamos en los ejemplos del punto anterior tenemos: Ejemplo 1: 8d=1000b3 desplazamientos hacia la izquierda, por lo tanto exp=127+3=130d= 10000010b Ejemplo 2: 0.1d=0.0001100110011 4 desplazamientos hacia la derecha, por lo tanto exp=127-4=123d= 01111011 b Ejemplo 3: 8.5d=1000.13 desplazamientos hacia la izquierda, por lo tanto exp=127+3=130d= 10000010b Otro aspecto que el estándar IEEE 754 especifica es el método de redondeo los cuales están englobados en dos grupos. Redondeo lo más cerca posible Redondeo al valor más cercano: Este método de redondeo utilizado por Microblaze soft processor core y consiste en redondear el número a su valor más próximo dejando el ultimo digito a cero. A continuación se puede ver un claro ejemplo utilizando números reales

Ejemplo 1: 8,87 se redondea a 8,90 Ejemplo 2: 8,83 se redondea a 8,80 Redondeo al valor más cercano lejos de cero: Este método de redondeo consiste en redondear el número a su valor más próximo pero con la particularidad de estar lo más lejos de cero posible. A continuación se puede ver un claro ejemplo utilizando números reales Ejemplo 1: 8,87 se redondea a 8,90 y 8,83 se redondea a 8,90 Ejemplo 2: -8,87 se redondea a -8,90 y -8,83 se redondea a -8,90 Redondeo directo Redondeo hacia 0 redondeo al valor entero más cercano cero sin tener en cuenta la parte decimal. Redondeo hacia + redondeo al valor más cercano al entero superior. Redondeo hacia redondeo al valor más cercano al entero inferior.

2.2 Operación Intf Generalmente, las variables y constantes que intervienen en una expresión de un programa informático suelen ser del mismo tipo. Sin embargo, el lenguaje C permite utilizar variables y constantes de distinto tipo en una misma expresión. Obviamente, en el lenguaje C se hacen una serie de conversiones de tipos al calcular el resultado de una expresión si los tipos de las variables son diferentes. Por tanto, una de las operaciones que se ha implementado en Copro es la de convertir un número entero a un número en coma flotante representado del mismo modo que describe el estándar IEEE 754. Esta misma operación también puede ser realizada por Microblaze. El rango del números enteros con signo que se puede representar en binario natural de 32 bits es de [(2 31)- 1] hasta (2 31)-1, es decir, de -2147483647 hasta 2147483647. Este rango convertido en numeración en como flotante es de 0xCF000000 hasta 0x4F000000. 2.2.1 Comportamiento Copro VS Microblaze En el apartado 2.2 de este proyecto se dice de que el código fuente de Microblaze no es Open source pero en ningún momento se menciona que Microblaze pone a disposición del usuario señales de entrada, de salida e intermedias utilizadas en su código. Desafortunadamente, en el caso de la conversión entero flotante no se tiene acceso a ninguna señal intermedia del código fuente que Microblaze utiliza para realizar dicha conversión, pero si que se tiene acceso a señales de entrada, salida e intermedias de otras operaciones como por ejemplo la operación multiplicación. Entonces, para poder ver el resultado final de una conversión entero flotante realizada por Microblaze se va a utilizar el siguiente código en C el cual será ejecutado por Microblaze. const int a[2]={0x1aaaafff,0x01aaafff}; const float b[2]={0x1aaaafff,0x01aaafff }; const float ax[2]={0x2,0x3}; int *p1=(int*)0x2f0000; float *p2=(float*)0x2e0000; float *p3=(float*)0x2d0000; float *p4=(float*)0x2c0000; for(int j=0; j<2; j++) {p1[j]=a[j];} for(int j=0; j<2; j++) {p2[j]=ax[j]; p3[j]=b[j];} for(int j=0; j<2; j++) {p4[j]=p2[j]*p3[j]; } En el código anterior se puede ver que primero se declaran 3 vectores de dos elementos cado uno. Uno de ellos, llamémoslo vector a, que contenga enteros los cuales serán los datos de entrada de Copro. Los otros dos vestores, llamémoslos vectores ax y b, que contengan flotantes los cuales serán los datos de entrada de Microblaze. Los números de estos dos vectores ( ax y b ) están representados en entero pero mediante un cast se indica que estos sean transformados y almacenados en coma flotante de tal modo que, Microblaze tendrá que hacer la conversión entero a flotante antes de almacenar los datos en memoria. Finalmente, realizando multiplicaciones uno a uno entre los elementos de los vectores que almacenan flotantes y visualizando las señales de

entrada de dicha operación, se puede ver como Microblaze ha convertido los enteros de los vectores ax y b a flotante. El resultado de la ejecución del código anterior tras la compilación del proyecto y visualización de la señales tanto de Copro como Microblaze es el mostrado en las dos figuras siguientes. Figura 21: Datos de entrada (vector a) y salida de Copro cuando realiza un conversión entero flotante Figura 22: Datos de entrada de Microblaze (Vectores ax y b) En la figura 21 se puede ver como los datos de entrada de Copro están en el mismo formato que en el código, es decir, en entero porque nos que interesa ver como Copro hace la conversión entero flotante. Además, también se puede ver los datos de salida cuando dicha conversión ya ha sido realizada. Entonces, estos serán los datos que se utilizarán para compararlos con los datos de las conversiones hechas por Microblaze. Por otro lado, en la figura 22 se puede ver como los datos de los vectores ax y b han sido convertidos a flotante por Microblaze. El valor 2 en decimal (0x2 en hexa) corresponde a 40000000 en flotante, el valor 3 en decimal (0x3 en hexa) corresponde a 40400000 en flotante, el valor 447393791 (0x1AAAAFFF en hexa) corresponde a 4DD55580 en flotante y el valor 27963391 (0x01AAAFFF en hexa) corresponde a 4BD55800 en flotante. Es necesario mencionar que estos cuatro números de los vectores ax y b están representados siguiendo el estándar IEEE 754 una vez convertidos por Microblaze. Llegado a este punto, se supondrá que Microblaze utiliza el mismo método que Copro al realizar una conversión de entero a flotante. Obviamente, se verificará si esta hipótesis es cierta y en caso de que no lo sea se ajustará Copro para que sea así. El método general el cual sigue Copro para realizar la operación entero a flotante es el de transformar el operando en un número basado en exponente, mantisa y signo. Seguidamente se muestra un ejemplo basado en números enteros representados en base dos. Operando A=2; Operando B=8; Operando C=100; En el caso del operando A la mantisa y el exponente valen 1. Operando A=1* 2^1 En el caso del operando B la mantisa vale 1 y el exponente vale 3. Operando B= 1*2^3

En el caso del operando C la mantisa vale 1,5625 y el exponente vale 6. Operando B= 1,5625 *2^6 El método inicial utilizado por Copro es el siguiente. Sea el número N=0x4AAAAFFF (0100 1010 1010 1010 1010 1111 1111 1111b) siendo el bit de más peso (MSB) el de más a la izquierda, primero se obtiene el signo el cual viene dado por el bit 31 que es el MSB. Si este es 0 el bit de signo vale 0 que significa número positivo. En caso contrario, el bit de signo vale 1 y significa número negativo y además se cambia el signo de N del siguiente modo int=0-n. Luego se mira si el bit 30 o 29 o 28 o 27 de int es uno. Con esto se obtendrá un índice que podrá tomar cualquier valor entre 0 y 4. 0 si ni el bit 30 ni el 29 ni el 28 ni el 27 valen 1 1 si ni el bit 30 ni el 29 ni el 28 valen 1 y el 27 vale 1 2 si ni el bit 30 ni el 29 valen 1 y el 28 vale 1 3 si el bit 30 no vale 1 y el 29 vale 1 4 si el bit 30 vale 1 En esto caso particular el índice (idx) toma el valor 4. Después, se calcula el exponente desnormalizado del número flotante del siguiente modo: ExpD=127+26+idx=0x9D y finalmente se desplazan todos los bits de N hacia la derecha tanta veces como indique el índice idx para obtener la mantisa desnormalizada. Introducimos 4 ceros 0100 1010 1010 1010 1010 1111 1111 1111 Ceros introducidos 0000 0100 1010 1010 1010 1010 1111 1111 1111 Una vez llegado a este punto hay que formar el número desnomalizado el cual está formado por el bit de signo, 8 bits para representar el exponente desnormalizado y 28 bits para representar la mantisa desnormalizada. En este caso particular, el signo es 0, el exponente es 0x9D y la mantisa esta formada por los 28 bits de más peso de N después del desplazamiento. Se puede ver a simple vista que al hacer el desplazamiento hay algunos bits que van a desaparecer, en este caso particular son los bits coloreados en rosa, y esto solo ocurre cuando el número a convertir es muy grande. En el caso de Copro estos bits se van a despreciar pero más adelante en este apartado se comprobará si Microblaze ignora estos bits también. El número desnormalizado es: 0 &0x9D&0x4AAAAFF. El paso siguiente es el de normalizar el número cogiendo la mantisa desnomalizada e introduciendo tantos ceros por la derecha como sea necesario hasta que el 1 de más hacia la izquierda se coloque al bit de más peso. Mantisa desnormaliza=0100 1010 1010 1010 1010 1111 1111 Introducir 1 cero Mantisa normaliza =1001 0101 0101 0101 0101 1111 1110Cero introducido El siguiente paso es coger los 24 bits de mayor peso de la mantisa y redondear con los bits n+3, n+2 y n+1 (bits coloreados en magenta). El método de redondeo utilizado es el siguiente. Se suma uno a la mantisa si el número binario representado por los bits n+3, n+2 y n+1 es mayor o igual a 100b(4d).

La mantisa se deja igual si el número binario representado por los bits n+3, n+2 y n+1 es menor o igual a 011b(3d). Por tanto, la mantisa normalizada es 1001 0101 0101 0101 0110 0000 y el exponente normalizado es el exponente desnormalizado + 1 el numero de ceros introducciones por la derecha de la mantisa desnormalizada ExpN=ExpD+1-1=0x9D. Una vez la mantisa y el exponente están normalizados se genera el número flotante normalizado concatenando el bit de signo, exponente normalizado y los 23 bits de menos peso de la mantisa normalizada ya que el bit de mayor peso es el llamado bit oculto (bit coloreado en rojo), el cual siempre vale 1 a excepción del numero 0 donde vale 0, y nunca se utiliza en la representación. Signo Exponente Mantisa Número representado en hexadecimal 0 10011101 1001 0101 0101 0101 0110 0000 0x4E955560 A continuación se simulará la conversión entero a flotante tanto en Copro como en Microblaze de algunos números comprendidos entre 0x01AAAFFF y 0x4AAAAF30 ya que en este rango de números es donde primero, se pueden perder bits los cuales se utilizan para calcular el sticky bit y segundo, los bits los cuales se utilizan para calcular el bit de redondeo pueden ser diferentes de 0. Antes de empezar utilizaremos las abreviaciones m(0) para definir el bit menos significativo (LSB) de la mantisa normalizada y R,G,SB para definir los bits de redondeo, en inglés Round Bit, el bit de guarda, en inglés, Guard Bit y Sticky Bit respectivamente. Número entero Caso 1: rango de 0x01AAAFFF a 0x01AAAFF0 Bits pedidos Bit m(0),r, G,SB Bit redond eo Copro Número flotante Copro Número flotante Microblaze Diferencia 0x01AAAFFF No hay 1 100 1 0x4BD557800 0x4BD55800 No hay 0x01AAAFFE No hay 1 000 0 0x4BD557FF 0x4BD557FF No hay 0x01AAAFFD No hay 0 100 1 0x4BD557FF 0x4BD557FE Si hay 0x01AAAFFC No hay 0 000 0 0x4BD557FE 0x4BD557FE No hay 0x01AAAFFB No hay 1 100 1 0x4BD557FE 0x4BD557FE No hay 0x01AAAFFA No hay 1 000 0 0x4BD557FD 0x4BD557FD No hay 0x01AAAFF9 No hay 0 100 1 0x4BD557FD 0x4BD557FC Si hay 0x01AAAFF8 No hay 0 000 0 0x4BD557FC 0x4BD557FC No hay 0x01AAAFF7 No hay 1 100 1 0x4BD557FC 0x4BD557FC No hay 0x01AAAFF6 No hay 1 000 0 0x4BD557FB 0x4BD557FB No hay 0x01AAAFF5 No hay 0 100 1 0x4BD557FB 0x4BD557FA Si hay 0x01AAAFF4 No hay 0 000 0 0x4BD557FA 0x4BD557FA No hay

0x01AAAFF3 No hay 1 100 1 0x4BD557FA 0x4BD557FA No hay 0x01AAAFF2 No hay 1 000 0 0x4BD557F9 0x4BD557F9 No hay 0x01AAAFF1 No hay 0 100 1 0x4BD557F9 0x4BD557F8 Si hay 0x01AAAFF0 No hay 0 000 0 0x4BD557F8 0x4BD557F8 No hay Número entero Caso 2: rango de 0x02AAAFFF a 0x02AAAFF0 Bits pedidos Bit m(0),r, G,SB Bit redond eo Copro Número flotante Copro Número flotante Microblaze Diferencia 0x02AAAFFF No hay 1 110 1 0x4C2AAC00 0x4C2AAC00 No hay 0x02AAAFFE No hay 1 100 1 0x4C2AAC00 0x4C2AAC00 No hay 0x02AAAFFD No hay 1 010 0 0x4C2AABFF 0x4C2AABFF No hay 0x02AAAFFC No hay 1 000 0 0x4C2AABFF 0x4C2AABFF No hay 0x02AAAFFB No hay 0 110 1 0x4C2AABFF 0x4C2AABFF No hay 0x02AAAFFA No hay 0 100 1 0x4C2AABFF 0x4C2AABFE Si hay 0x02AAAFF9 No hay 0 010 0 0x4C2AABFE 0x4C2AABFE No hay 0x02AAAFF8 No hay 0 000 0 0x4C2AABFE 0x4C2AABFE No hay 0x02AAAFF7 No hay 1 110 1 0x4C2AABFE 0x4C2AABFE No hay 0x02AAAFF6 No hay 1 100 1 0x4C2AABFE 0x4C2AABFE No hay 0x02AAAFF5 No hay 1 010 0 0x4C2AABFD 0x4C2AABFD No hay 0x02AAAFF4 No hay 1 000 0 0x4C2AABFD 0x4C2AABFD No hay 0x02AAAFF3 No hay 0 110 1 0x4C2AABFD 0x4C2AABFD No hay 0x02AAAFF2 No hay 0 100 1 0x4C2AABFD 0x4C2AABFC Si hay 0x02AAAFF1 No hay 0 010 0 0x4C2AABFC 0x4C2AABFC No hay 0x02AAAFF0 No hay 0 000 0 0x4C2AABFC 0x4C2AABFC No hay Número entero Caso 3: rango de 0x04AAAFFF a 0x04AAAFF0 Bits pedidos Bit m(0),r, G,SB Bit redond eo Copro Número flotante Copro Número flotante Microblaze Diferencia 0x04AAAFFF No hay 1 111 1 0x4C955600 0x4C955600 No hay 0x04AAAFFE No hay 1 110 1 0x4C955600 0x4C955600 No hay 0x04AAAFFD No hay 1 101 1 0x4C955600 0x4C955600 No hay 0x04AAAFFC No hay 1 100 1 0x4C955600 0x4C955600 No hay

0x04AAAFFB No hay 1 011 0 0x4C9555FF 0x4C9555FF No hay 0x04AAAFFA No hay 1 010 0 0x4C9555FF 0x4C9555FF No hay 0x04AAAFF9 No hay 1 001 0 0x4C9555FF 0x4C9555FF No hay 0x04AAAFF8 No hay 1 000 0 0x4C9555FF 0x4C9555FF No hay 0x04AAAFF7 No hay 0 111 1 0x4C9555FF 0x4C9555FF No hay 0x04AAAFF6 No hay 0 110 1 0x4C9555FF 0x4C9555FF No hay 0x04AAAFF5 No hay 0 101 1 0x4C9555FF 0x4C9555FF No hay 0x04AAAFF4 No hay 0 100 1 0x4C9555FF 0x4C9555FE Si hay 0x04AAAFF3 No hay 0 011 0 0x4C9555FE 0x4C9555FE No hay 0x04AAAFF2 No hay 0 010 0 0x4C9555FE 0x4C9555FE No hay 0x04AAAFF1 No hay 0 001 0 0x4C9555FE 0x4C9555FE No hay 0x04AAAFF0 No hay 0 000 0 0x4C9555FE 0x4C9555FE No hay En los 3 casos anteriores se puede ver que hay algunas diferencias entre la conversión hecha por Copro y Microblaze. Esta diferencia esta en el cálculo del bit de redondeo ya que de momento no se pierden bits los cuales se utilizan para calcular el sticky bit. Si se analizan las tablas anteriores se puede deducir que Microblaze utiliza el siguiente método para el cálculo del bit de redondeo. Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es mayor a 100b(4d). Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 1. La mantisa se deja igual si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la matisa normalizada (m(0)) es igual a 0 La mantisa se deja igual si el número binario representado por los bits R, G y SB es menor o igual a 011b(3d). A continuación, los números enteros a convertir serán suficientemente mayores para que se pierdan bits durante la conversión. Esto permitirá ver el comportamiento de Microblaze cuando esto sucede y también se podrá comparar con el comportamiento de Copro. Número entero Caso 4: rango de 0x08AAAFFF a 0x08AAAFE0 Bits pedidos Bit m(0),r, G,SB Bit redond eo Copro Número flotante Copro Número flotante Microblaze Diferencia 0x08AAAFFF 1 1 111 1 0x4D0AAB00 0x4D0AAB00 No hay 0x08AAAFFE 0 1 111 1 0x4D0AAB00 0x4D0AAB00 No hay

0x08AAAFFD 1 1 110 1 0x4D0AAB00 0x4D0AAB00 No hay 0x08AAAFFC 0 1 110 1 0x4D0AAB00 0x4D0AAB00 No hay 0x08AAAFFB 1 1 101 1 0x4D0AAB00 0x4D0AAB00 No hay 0x08AAAFFA 0 1 101 1 0x4D0AAB00 0x4D0AAB00 No hay 0x08AAAFF9 1 1 100 1 0x4D0AAB00 0x4D0AAB00 No hay 0x08AAAFF8 0 1 100 1 0x4D0AAB00 0x4D0AAB00 No hay 0x08AAAFF7 1 1 011 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFF6 0 1 011 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFF5 1 1 010 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFF4 0 1 010 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFF3 1 1 001 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFF2 0 1 001 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFF1 1 1 000 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFF0 0 1 000 0 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFEF 1 0 111 1 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFEE 0 0 111 1 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFED 1 0 110 1 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFEC 0 0 110 1 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFEB 1 0 101 1 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFEA 0 0 101 1 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFE9 1 0 100 1 0x4D0AAAFF 0x4D0AAAFF No hay 0x08AAAFE8 0 0 100 1 0x4D0AAAFF 0x4D0AAAFE Si hay 0x08AAAFE7 1 0 011 0 0x4D0AAAFE 0x4D0AAAFE No hay 0x08AAAFE6 0 0 011 0 0x4D0AAAFE 0x4D0AAAFE No hay 0x08AAAFE5 1 0 010 0 0x4D0AAAFE 0x4D0AAAFE No hay 0x08AAAFE4 0 0 010 0 0x4D0AAAFE 0x4D0AAAFE No hay 0x08AAAFE3 1 0 001 0 0x4D0AAAFE 0x4D0AAAFE No hay 0x08AAAFE2 0 0 001 0 0x4D0AAAFE 0x4D0AAAFE No hay 0x08AAAFE1 1 0 000 0 0x4D0AAAFE 0x4D0AAAFE No hay 0x08AAAFE0 0 0 000 0 0x4D0AAAFE 0x4D0AAAFE No hay Número entero Caso 5: rango de 0x1AAAAFFF a 0x1AAAAFCC Bits pedidos Bit m(0),r, G,SB Bit redond eo Número flotante Copro Número flotante Microblaze Diferencia

Copro 0x1AAAAFFF 11 1 111 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFFE 10 1 111 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFFD 01 1 111 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFFC 00 1 111 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFFB 11 1 110 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFFA 10 1 110 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFF9 01 1 110 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFF8 00 1 110 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFF3 11 1 100 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFF2 10 1 100 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFF1 01 1 100 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFF0 00 1 100 1 0x4DD55580 0x4DD55580 No hay 0x1AAAAFEF 11 1 011 0 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFEE 10 1 011 0 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFED 01 1 011 0 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFEC 00 1 011 0 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFDF 11 0 111 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFDE 10 0 111 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFDD 01 0 111 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFDC 00 0 111 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFDB 11 0 110 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFDA 10 0 110 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFD9 01 0 110 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFD8 00 0 110 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFD3 11 0 100 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFD2 10 0 100 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFD1 01 0 100 1 0x4DD5557F 0x4DD5557F No hay 0x1AAAAFD0 00 0 100 1 0x4DD5557F 0x4DD5557E Si hay 0x1AAAAFCF 11 0 011 0 0x4DD5557E 0x4DD5557E No hay 0x1AAAAFCE 10 0 011 0 0x4DD5557E 0x4DD5557E No hay 0x1AAAAFCD 01 0 011 0 0x4DD5557E 0x4DD5557E No hay 0x1AAAAFCC 00 0 011 0 0x4DD5557E 0x4DD5557E No hay

Número entero Caso 6: rango de 0x2AAAAFFC a 0x2AAAAF9A Bits pedidos Bit m(0),r, G,SB Bit redond eo Copro Número flotante Copro Número flotante Microblaze Diferencia 0x2AAAAFFC 100 1 111 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFFA 010 1 111 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFF9 001 1 111 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFF8 000 1 111 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE7 111 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE6 110 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE5 101 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE4 100 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE3 011 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE2 010 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE1 001 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFE0 000 1 100 1 0x4E2AAAC0 0x4E2AAAC0 No hay 0x2AAAAFDC 100 1 011 0 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFDA 010 1 011 0 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFD9 001 1 011 0 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFD8 000 1 011 0 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFBC 100 0 111 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFBA 010 0 111 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFB9 001 0 111 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFB8 000 0 111 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA7 111 0 100 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA6 110 0 100 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA5 101 0 100 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA4 100 0 100 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA3 011 0 100 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA2 010 0 100 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA1 001 0 100 1 0x4E2AAABF 0x4E2AAABF No hay 0x2AAAAFA0 000 0 100 1 0x4E2AAABF 0x4E2AAABE Si hay 0x2AAAAF9C 100 0 011 0 0x4E2AAABE 0x4E2AAABE No hay 0x2AAAAF9A 010 0 011 0 0x4E2AAABE 0x4E2AAABE No hay

0x2AAAAF99 001 0 011 0 0x4E2AAABE 0x4E2AAABE No hay 0x2AAAAF98 000 0 011 0 0x4E2AAABE 0x4E2AAABE No hay Número entero Caso 7: rango de 0x4AAAAFF8 a 0x4AAAAF30 Bits pedidos Bit m(0),r, G,SB Bit redond eo Copro Número flotante Copro Número flotante Microblaze Diferencia 0x4AAAAFF8 1000 1 111 1 0x4E955560 0x4E955560 No hay 0x4AAAAFF4 0100 1 111 1 0x4E955560 0x4E955560 No hay 0x4AAAAFF2 0010 1 111 1 0x4E955560 0x4E955560 No hay 0x4AAAAFF1 0001 1 111 1 0x4E955560 0x4E955560 No hay 0x4AAAAFF0 0000 1 111 1 0x4E955560 0x4E955560 No hay 0x4AAAAFC8 1000 1 100 1 0x4E955560 0x4E955560 No hay 0x4AAAAFC4 0100 1 100 1 0x4E955560 0x4E955560 No hay 0x4AAAAFC2 0010 1 100 1 0x4E955560 0x4E955560 No hay 0x4AAAAFC1 0001 1 100 1 0x4E955560 0x4E955560 No hay 0x4AAAAFC0 0000 1 100 1 0x4E955560 0x4E955560 No hay 0x4AAAAFB8 1000 1 011 0 0x4E95555F 0x4E95555F No hay 0x4AAAAFB4 0100 1 011 0 0x4E95555F 0x4E95555F No hay 0x4AAAAFB2 0010 1 011 0 0x4E95555F 0x4E95555F No hay 0x4AAAAFB1 0001 1 011 0 0x4E95555F 0x4E95555F No hay 0x4AAAAFB0 0000 1 011 0 0x4E95555F 0x4E95555F No hay 0x4AAAAF78 1000 0 111 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF74 0100 0 111 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF72 0010 0 111 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF71 0001 0 111 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF70 0000 0 111 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF48 1000 0 100 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF44 0100 0 100 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF42 0010 0 100 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF41 0001 0 100 1 0x4E95555F 0x4E95555F No hay 0x4AAAAF40 0000 0 100 1 0x4E95555F 0x4E95555E Si hay 0x4AAAAF38 1000 0 011 0 0x4E95555E 0x4E95555E No hay 0x4AAAAF34 0100 0 011 0 0x4E95555E 0x4E95555E No hay

0x4AAAAF32 0010 0 011 0 0x4E95555E 0x4E95555E No hay 0x4AAAAF31 0001 0 011 0 0x4E95555E 0x4E95555E No hay 0x4AAAAF30 0000 0 011 0 0x4E95555E 0x4E95555E No hay En los casos 1, 2 y 3 ya se ha visto que el punto crítico es cuando los bits R, G y SB valen 100, entonces el redondeo depende del bit de menos peso de la mantisa, es decir, solo hay redondeo si m(0) es 1. En los casos 4, 5, 6 y 7 se puede ver que cuando los bits R, G y SB valen 100 y cualquiera de los bits perdidos vale 1, entonces hay redondeo contradiciendo la observación de los casos 1, 2 y 3. Con estas dos observaciones se deduce que Microblaze calcula el sticky bit haciendo la OR entre los bits perdidos y el bit de menos peso de la mantisa desnormalizada. Por lo tanto, si los bits R, G y SB valen 100 y cualquiera de los bits perdidos vale 1, SB pasa a valer 1 convirtiendo R, G y SB en 101 y por ser mayor que 100 se hace redondeo. 2.2.2 Adaptación en Copro Una vez se ha completado el análisis de la operación conversión entero a flotante realizada con los dos procesadores se va a hacer una lista de las diferencias que hay. La primera diferencia entre Microblaze y Copro que se ha encontrado esta en el método del cálculo del redondeo. La segunda diferencia esta en el cálculo del sticky bit. Se ha comprobado que Microblaze pone el sticky bit a 1 si alguno de los bits perdidos vale 1, en caso contrario este vale 0. En cuanto a la primera diferencia se refiere, Copro se ha modificado para que su comportamiento sea el siguiente: Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es mayor a 100b(4d). Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 1. La mantisa se deja igual si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 0 La mantisa se deja igual si el número binario representado por los bits R, G y SB es menor o igual a 011b(3d). En cuanto a la segunda diferencia se refiere, Copro se ha modificado de tal modo que si alguno de los bits perdidos vale 1 se hará la OR exclusiva de los bits perdidos y el bit de menos peso de la mantisa desnomalizada. 2.3 Operación Add/Sub Otras operaciones que se puede realizar tanto con Copro como con Microblaze son las operaciones suma y resta de números representados en coma flotante. Estas dos operaciones utilizan un algoritmo de cálculo muy parecido y por esa razón se verán juntas en este apartado. El rango de números en coma flotante que se puede representar en 32 bits para estas operaciones es de 0xFF800000 hasta 0x7F800000.

2.3.1 Comportamiento Copro VS Microblaze El planteamiento en este apartado va a ser diferente que en el apartado 3.2.1 ya que en esta caso Microblaze pone a disposición del usuario señales de entrada, de salida e intermedias utilizadas en su código fuente cuando realiza cualquier de estas dos operaciones. Entonces, primero se mostraran la señales más significativas de Microblaze así como el código en C ejecutado por el mismo para poder ver los valores que toman dichas señales, luego, se explicará como Copro hace la operación suma y resta y finalmente, se observarán algunos casos claves y algunas de las señales más significativas utilizadas por Microblaze cuando realiza dichas operaciones y se compararán con las de Copro. Las señales más significativas de Microblaze son: El código utilizado es: ex_start_fpu: início operación (1 bit) fpu_op: identificador operación (3 bits) ex_op1: operando 1 (32 bits) ex_op2: operando 2 (32 bits) mem_manta_2: mantisa operando 2 (24 bits) mem_mantb_2: mantisa operando 1 (24 bits) mem_manta_3: mantisa adaptada operando 2 (27 bits) mem_mantb_3: mantisa adaptada operando 1 (27 bits) mem_manta_sticky_3_cmb: sticky bit (1 bit) mem_mant_addsub_res_4: mantisa resultado (27 bits) fpu_result: resultado final (32 bits) const float b[2]={0x4b800000, 0x4B800000}; const float ax[2]={0x3fc00001, 0x3FC00000}; float *p2=(float*)0x2e0000; float *p3=(float*)0x2d0000; float *p4=(float*)0x2c0000; for(int j=0; j<2; j++) {p2[j]=ax[j]; p3[j]=b[j];} for(int j=0; j<2; j++) {p4[j]=p2[j]+p3[j]; } El método general el cual se basa Copro para realizar la operación suma y resta es el de transformar los operandos en números basados en exponente y mantisa, igualar exponentes y finalmente hacer la suma o la resta de mantisas. Seguidamente se muestra un ejemplo basado en números enteros. Operando A=2000; Operando B=200; Resultado = Operando A + Operando B Se identifica el Operando mayor y se transforma en un número formado por un exponente y una mantisa.

Operando A=1,953125 * 2^10 Se transforma el Operando B en un número formado por un exponente y una mantisa pero el exponente tiene que ser del mismo orden que el del operando mayor. En este caso es el Operando A. Operando B=0,1953125 * 2^10 Se deja el exponente el cual es común para los dos operandos y se suman o restan las mantisas. En esta caso particular Exponente=2^10 Mantisa=1,953125 + 0,1953125 =2,1484375 Resultado=2,1484375 * 2^10 Una vez visto el método general pasaremos a ver el método inicial para hacer sumas y restas en Copro. Hace falta remarcar que si no se encuentra ninguna diferencia entre los métodos de Copro y Microblaze, el método inicial de Copro pasará a ser el método final. El primer paso consiste en hacer una comprobación de posibles excepciones en el siguiente orden. Si cualquier de los operandos A y/o B son un NAN (not a number) entonces, el resultado de la operación es NAN. Si no, si el operando A y B son infinitos del mismo signo el resultado final es infinito. En caso de que sean de signo diferente el resultado final es un NAN. Finalmente, si no se cumple ninguna excepción anterior se comprueba si el operando A o el operando B es infinito y ninguno de ellos es NAN, el resultado final es infinito. Seguidamente, si no se da ninguna de las excepciones previas se procede del siguiente modo. Sea el operando A= 0x4B800000 (0100 1011 1000 0000 0000 0000 0000 0000b) y B= 0x3FC00001 (0011 1111 1100 0000 0000 0000 0000 0001b) siendo el bit de más peso (MSB) el de más a la izquierda, primero se obtiene el signo de los dos operandos el cual viene dado por el bit 31 que es el MSB y se hace la XOR entre ellos para saber si los operandos tienen el mismo signo o signo diferente (sig_dif=sig_a XOR sig_b). A continuación se restan los exponentes y las mantisas de los dos operandos. En este caso particular los valores que se obtienen son: Signo Exponente Mantisa Numero representado en hexadecimal 0 1001 0111 1000 0000 0000 0000 0000 0000 0x4B800000 0 0111 1111 1100 0000 0000 0000 0000 0001 0x3FC00001 Sig_dif = sig_a XOR sig_b = 0 xor 0 = 0 (1 bit) Exp_dif = exp_a exp_b = 0x97-0x7F =0x18 (9 bits) man_dif = man_a man_b =0x800000 0xC00001 =0x1BFFFFF (25 bits)

Una vez calculada la diferencia entre los signos, mantisas y exponentes de los dos operandos, se averigua que operando, en valor absoluto, es más grande. Esto se decide comprobando si el bit de más peso de la señal Exp_dif es igual a 1 o, si este es 0, se comprueba si el bit de más peso de la señal man_dif es igual a 1. En cualquier de estos dos casos se puede afirmar que b > a, en caso contrario a > b. En el caso de que a > b, el signo y el exponente del resultado de la operación son directamente el signo y el exponente del operando A. El valor absoluto de la diferencia de exponentes es directamente la diferencia de exponentes. Finalmente, antes de sumar o restar las mantisas hay que tener en cuenta el sticky bit el cual se obtendrá de la mantisa del operando mas pequeño, por lo tanto, la mantisa más grande (man_high) será la mantisa del operando A y la más pequeña (man_low) será la mantisa del operando B. Sin embargo, si b > a, el signo de la operación se calcula del siguiente modo sig_res=(not mode and sig_b) or (mode and not sig_b). Si la operación es suma, la señal mode es igual a 0 pero si es una resta, mode es igual a 1. El exponente del resultado de la operación viene dado por el exponente del operando B. El valor absoluto de la diferencia de exponentes se calcula cambiando de signo el resultado de dicha diferencia. Finalmente, antes de sumar o restar las mantisas hay que tener en cuenta el sticky bit el cual se obtendrá de la mantisa del operando mas pequeño, por lo tanto, en esta caso la mantisa más grande (man_high) será la mantisa del operando B y la más pequeña (man_low) será la mantisa del operando A. Otro aspecto a tener en cuenta en cualquier de los dos casos anteriores es que si el valor absoluto de la diferencia de exponentes es mayor que 25 se deja en 25, es decir, que Exp_absdif nunca debería tomar un valor mayor a 25 ya que así se agiliza el cálculo del sticky bit como se va a ver a continuación. Antes de hacer la suma o resta de las mantisas, hay que adaptarlas. Por un lado, la mantisa man_high se adapta añadiendo un cero a la parte izquierda el cual será el bit de carry y luego se añaden 3 ceros más a la parte derecha, es decir, que la mantisa man_high pasa a tener un total de 28 bits. Por el otro lado, la mantisa man_low se utiliza para calcular el sticky bit porque es la mantisa la cual puede sufrir un desplazamiento de bits debido a la introducción de ceros por izquierda si el valor absoluto de la diferencia de exponentes es diferente de cero. Entonces, si el valor absoluto de la diferencia de exponentes es inferior a 3 el sticky bit es cero, si es mayor o igual a 3 se comprueba tantos bits de la man_low como indique dicha deferencia empezando por el bit 3 y si alguno de ellos es 1 el sticky bit vale 1. Luego, se añaden 3 ceros a la parte derecha de man_low y se introducen tantos ceros por la izquierda como indique el valor absoluto de la diferencia de exponentes. Seguidamente, se forma la mantisa man_low con la concatenación de un bit de carry a cero, los 26 bits de más peso de la mantisa man_low después del desplazamiento si lo hay y el sticky bit. Finalmente se suma o resta las mantisas dependiendo del modo de operación y con el resultado se mira si el bit de carry es 1. Si es así, se hace mantisa(1)=mantisa(1) or mantisa(0). Esto se hace para no perder el valor de sticky bit cuando se normaliza el número. Luego, este resultado conjuntamente con el signo y el exponente se forma el número desnormalizado. En este caso particular se puede ver que a > b con lo cual se obtienen los siguientes valores: Exp_absdif= exp_a = 0x18h=24d como que 24 no es > 25 Exp_absdif=24d Sig_res= sig_a = 0 Exp_res = exp_a = 0x97h

Man_high= 0 & Man_high & 000 = 0x4000000 Man_low= 0xC00001 Siendo Exp_absdif=24 se mira si algún bit de Man_low, empezando por el bit 3, es igual a 1. En este caso esto es cierto, por lo tanto, sticky bit=1. Man_low_desplazada = shift to right(man_low & 000, Exp_absdif) Introducimos 24 ceros 1100 0000 0000 0000 0000 0001 000 Ceros introducidos000 0000 0000 0000 0000 0000 0110 Man_low_desplazada = 0x0000006 Bits perdidos0 0000 0000 0000 0000 0001 000 Sticky bit = OR (Bits perdidos) = 1 Man_low = 0 & 26 bits de más peso de desplazada & sticky bit Man_low = 0000 0000 0000 0000 0000 0000 0111 = 0x0000007 Man=Man_high + Man_low = 0x4000000 + 0x0000007 = 0x4000007 Finalmente el número desnormalizado es: 0 &0x97&0x4000007. Ahora, se tiene que normalizar el número tal y como se ha hecho en el apartado de la operación de conversión entero a flotante. Esto se hace separando la mantisa e introduciendo tantos ceros por la derecha como sea necesario para dejar a uno al bit de más peso. Mantisa desnormaliza=0100 0000 0000 0000 0000 0000 0111 Introducir 1 cero Mantisa normalizada=1000 0000 0000 0000 0000 0000 1110Cero introducido El siguiente paso es coger los 24 bits de mayor peso de la mantisa y redondear con los bits n+3, n+2 y n+1 (bits coloreados en magenta). El método de redondeo utilizado es el siguiente. Se suma uno a la mantisa si el número binario representado por los bits n+3, n+2 y n+1 es mayor o igual a 100b(4d). La mantisa se deja igual si el número binario representado por los bits n+3, n+2 y n+1 es menor o igual a 011b(3d). Por tanto, la mantisa normalizada es 1000 0000 0000 0000 0000 0001 y el exponente normalizado es el exponente desnormalizado + 1 el numero de ceros introducciones por la derecha de la mantisa desnormalizada ExpN=ExpD+1-1=0x97. Una vez la mantisa y el exponente están normalizados se genera el número flotante normalizado concatenando el bit de signo, exponente normalizados y los 23 bits de menos peso de la mantisa normalizada ya que el bit de mayor peso llamado bit oculto (bit coloreado en rojo) nunca se utiliza en la representación. Este bit se sabe que siempre vale 1 a excepción del número 0. Signo Exponente Mantisa Numero representado en hexadecimal 0 10010111 1000 0000 0000 0000 0000 0001 0x4B800001

A continuación se verán algunas operaciones realizadas por Microblaze de las cuales se podrá deducir su comportamiento y compararlo con el de Copro. Caso A: Operando 1 =0x4B800000 Operando 2 =0x3FC00000 Figura 23: Señales de Microblaze cuando realiza la suma de 0x4B800000 y 0x3FC00000. En la figura 23 se puede ver que la diferencia de exponentes representada por la señal men_exp_absubb es calculada del mismo modo que se calcula en Copro. men_exp_absubb = exp_1 exp_2 = 0x97-0x7F =0x18 También se ve claramente que las mantisas 1 y 2 vienen representadas por mem_mantb_2 =0x800000 y mem_manta_2=0xc00000 respectivamente. Entonces, se puede deducir que la mantisa adaptada B se forma del siguiente modo. mem_manta_3 = 0 & mem_mantb_2 & 000 = 0x4000000 Por otro lado, la mantisa adaptada A es un poco más compleja de calcular ya que esta sufre un dezplazamiento y, con los bits desplazados, se calcula el sticky bit. Entonces, se supondrá que se calcula del mismo modo que en Copro pero, en este caso, en vez de utilizar las señales de en Copro se utilizaran las señales de Microblaze. mem_manta_2 = shift to right(mem_manta_2 & 000, men_exp_absubb) Introducimos 24 ceros 1100 0000 0000 0000 0000 0000 000 Ceros introducidos 000 0000 0000 0000 0000 0000 0110 mem_manta_2 = 0x0000006 Bits perdidos0 0000 0000 0000 0000 0000 000 Sticky bit = OR (Bits perdidos) = 0 el sticky bit se puede ver claramente en la figura anterior que también vale 0 mem_mantb_3 = 0 & 26 bits de más peso de mem_manta_2 & sticky bit mem_mantb_3=0x0000006 Seguidamente, se suman las mantisas adaptadas y se pone el resultado en men_mant_addsu_res_4=0x4000006. Se puede ver que el resultado de la suma de mantisas adaptadas es el mismo que el obtenido por Microblaze, por tanto, se da por válido el procedimiento seguido hasta

ahora por Copro. El número desnormalizado obtenido hasta ahora es: 0 &0x97&0x4000006. Finalmente, este número tiene que ser normalizado y como que la etapa de normalización en Copro siempre es la misma, no importa el tipo de operación que sea, en el caso Mircroblaze se hará la misma hipótesis. Entonces, es resultado final obtenido es mismo que el obtenido en Copro Signo Exponente Mantisa Numero representado en hexadecimal 0 10010111 1000 0000 0000 0000 0000 0001 0x4B800001 Caso B: Operando 1 =0x4B800000 Operando 2 =0x3FC00001 Figura 24: Señales de Microblaze cuando realiza la suma de 0x4B800000 y 0x3FC00001. En la figura 24 se puede observar que el cálculo es prácticamente el mismo que en el caso anterior con la única variación de que el sticky bit toma el valor 1. Entonces, siguiendo los mismos pasos que en Copro pero utilizando las señales de Microblaze se puede ver que el resultado final es el mismo. mem_manta_2 = shift to right(mem_manta_2 & 000, men_exp_absubb) Introducimos 24 ceros 1100 0000 0000 0000 0000 0001 000 Ceros introducidos 000 0000 0000 0000 0000 0000 0110 mem_manta_2 = 0x0000006 Bits perdidos0 0000 0000 0000 0000 0001 000 Sticky bit= OR(Bits perdidos)=1 mem_mantb_3 = 0 & 26 bits de más peso de mem_manta_2 & sticky bit mem_mantb_3=0x0000007 Por tanto, se puede afirmar que sticky bit vale 1 si algún de los bits perdidos es uno, en caso contrario este toma el valor 0. Caso C: Operando 1 =0x4B800000

Operando 2 =0x3F800000 Figura 25: Señales de Microblaze cuando realiza la suma de 0x4B800000 y 0x3FC00000. Caso D: Operando 1 =0x4B800000 Operando 2 =0x3F800001 Figura 26: Señales de Microblaze cuando realiza la suma de 0x4B800000 y 0x3FC00000. Caso E: Operando 1 =0x4B800001 Operando 2 =0x3F800000 Figura 27: Señales de Microblaze cuando realiza la suma de 0x4B800000 y 0x3FC00000.

En las figuras 25, 26 y 27 se vuelve a confirmar la hipótesis que ya se había confirmado en el apartado 3.2.1 donde se deduce claramente como Microblaze hace el cálculo del bit de redondeo. En el caso C los bits m(0) R,G,SB valen 0100 respectivamente por lo tanto, a m(0) no se le va a sumar 1 por que este vale 0 y el conjunto de bit R,G,SB es igual a 100, es decir, no va haber redondeo. Al concatenar el bit de signo, el exponente y la mantisa normalizada el resultado final de la suma es 0x4B800000. En el caso D se puede ver el contrario del caso C ya que los bits m(0) R,G,SB valen 1100 respectivamente por lo tanto, a m(0) se le va a sumar 1 por que este vale 1 y el conjunto de bit R,G,SB es igual a 100, es decir, si va haber redondeo. Al concatenar el bit de signo, el exponente y la mantisa normalizada la cual se la ha sumado el resultado final de la suma es 0x4B800001. Finalmente, en el caso E se puede ver que si R,G,SB son igual o mayor que 101 se suma 1 a m(0) independientemente del valor que tenga m(0), es decir, también va haber redondeo. En esta caso m(0) es 1 y al concatenar el bit de signo, el exponente y la mantisa normalizada la cual se le ha sumado 1 el resultado final de la suma es 0x4B800002. 2.3.2 Adaptación en Copro Como ya se ha visto en el caso de la conversión entero a flotante una de las diferencias que hay esta en el modo en que Microblaze hace el cálculo del bit de redondeo, por lo tanto, Copro se ha modificado para que su comportamiento en dicho cálculo sea el siguiente: 2.4 Operación Mul Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es mayor a 100b(4d). Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 1. La mantisa se deja igual si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la matisa normalizada (m(0)) es igual a 0 La mantisa se deja igual si el número binario representado por los bits R, G y SB es menor o igual a 011b(3d). La operación multiplicación es un poco más compleja de realizar en comparación con las operaciones de conversión entero flotante, suma y resta. Por esa razón tarda algunos ciclos de reloj más en ejecutarse. Al igual que las operaciones vistas hasta ahora esta se puede realizar tanto con Copro como con Microblaze utilizando números representados en coma flotante. El rango de números en coma flotante que se puede representar en 32 bits para esta operación es de 0xFF800000 hasta 0x7F800000. 2.4.1 Comportamiento Copro VS Microblaze El planteamiento en este apartado va a ser el mismo que en el apartado 3.3.1 ya que en este caso Microblaze también pone a disposición del usuario señales de entrada, de salida e intermedias utilizadas en su código fuente cuando realiza dicha operación.

Entonces, primero se mostraran las señales más significativas de Microblaze así como el código en C ejecutado por el mismo para poder visualizar dichas señales, luego, se explicará como Copro hace la operación multiplicación y finalmente, se observarán algunos casos claves y algunas de las señales más significativas utilizadas por Microblaze cuando realiza dicha operación y se compararán con las de Copro. Las señales más significativas de Microblaze son: El código utilizado es: ex_start_fpu: início operación (1 bit) ex_fpu_op: identificador operación (3 bits) ex_op1: operando 1 (32 bits) ex_op2: operando 2 (32 bits) ex_manta_1: mantisa operando 2 (24 bits) ex_mantb_1: mantisa operando 1 (24 bits) ex_a_oper: parte alta mantisa 1(18bits) ex_b_oper: parte baja mantisa 1(18bits) ex_c_oper: parte alta mantisa 2(18bits) ex_d_oper: parte baja mantisa 2(18bits) mem_prod_bd_3: multiplica entre ex_b_oper y ex_d_oper (32 bits) mem_prod_ad_3: multiplica entre ex_a_oper y ex_d_oper (24 bits) mem_prod_bc_3: multiplica entre ex_b_oper y ex_c_oper (24 bits) mem_prod_ac_3: multiplica entre ex_a_oper y ex_c_oper (16 bits) mem_mul_sticky_bit_vec_5_cmb: vector sticky bit (21 bits) mem_mul_sticky_bit_5_cmb: sticky bit (1 bit) mem_mul_res_4: mantisa desnormalizada (27 bits) fpu_result: resultado final (32 bits) const float b[2]={0x41200001, 0x4B800000}; const float ax[2]={0x41200001, 0x3FC00000}; float *p2=(float*)0x2e0000; float *p3=(float*)0x2d0000; float *p4=(float*)0x2c0000; for(int j=0; j<2; j++) {p2[j]=ax[j]; p3[j]=b[j];} for(int j=0; j<2; j++) {p4[j]=p2[j]*p3[j]; } El método general el cual se basa Copro para realizar la operación mulplicación es el de transformar los operandos en números basados en exponente y mantisa, multiplicar

las mantisas y finalmente sumar los exponentes. Seguidamente se muestra un ejemplo basado en números enteros. Operando A=2; Operando B=200; Resultado = Operando A * Operando B Se transforman los operandos A y B en números formados por un exponente y una mantisa. Operando A=1 * 2^1 Operando B=1,5625 * 2^7 Se suman los exponentes y si multiplican las mantisas. Exponente=(2^1) + (2^7)= 2^8 Mantisa=1 * 1,5625 = 1,5625 Resultado=1,5625 * 2^8 Una vez visto el método general pasaremos a ver el método inicial para hacer multiplicaciones en Copro. El primer paso consiste en hacer multiplicaciones parciales de las mantisas. Estas se separan en dos partes y se multiplican entre ellas como si de una multiplicación numérica se tratará pero, antes de empezar con el cálculo se hacen una serie de comprobaciones de los contenidos de los operandos para detectar posibles excepciones. Inicialmente se hace la comprobación de excepciones en el siguiente orden. Si cualquier de los operandos A y/o B son un NAN (not a number) entonces, el resultado de la operación es NAN. Si no, si el operando A es infinito y el operando B es cero o viceversa, el resultado final es un NAN. Si no, si entre el operando A y el operando B uno toma cualquier valor diferente de infinito o NAN y el otro 0, el resultado final es cero. Finalmente, si no se cumple ninguna excepción anterior se comprueba si el operando A y/o el operando B es infinito, el resultado final es infinito. En caso de que no se de ninguna de estas excepciones se procede del siguiente modo. Sea el operando A= 0x41200001 (0100 0001 0010 0000 0000 0000 0000 0001b) y B= 0x41200001 (0100 0001 0010 0000 0000 0000 0000 0001b) siendo el bit de más peso (MSB) el de más a la izquierda, primero se obtiene el signo de los dos operandos el cual viene dado por el bit 31 que es el MSB y se hace la XOR entre ellos para saber el signo del resultado de la operación (signo_s12=sig_a XOR sig_b). A continuación se calcula el exponente de la operación del siguiente modo exp_s12=exp_a + exp_b 127. Seguidamente, se hace la multiplicación parcial de las mantisas multiplicando la parte baja de los dos operandos, la parte alta del operando 1 con la parte baja del operando 2, la parte alta del operando 2 con la parte baja del operando 1 y finalmente la parte alta de los dos operandos. En este caso particular los valores que se obtienen son: Signo Exponente Mantisa Numero representado en hexadecimal 0 1000 0010 1010 0000 0000 0000 0000 0001 0x41200001

0 1000 0010 1010 0000 0000 0000 0000 0001 0x41200001 bits) signo_s12 = sig_a XOR sig_b = 0 xor 0 = 0 (1 bit) exp_s12 = exp_a + exp_b -127 = 0x82+0x82-127 =0x85 (8 bits) ab00_s12 = op_a (11downto0) * op_b (11downto0) = 0x000001 (24 bits) ab01_s12 = 1 &op_a (22downto12) * op_b (11downto) = 0x000A00 (24 bits) ab10_s12 =op_a (11downto) * 1 &op_b (22downto12) = 0x000A00 (24 bits) ab11_s12 = 1 &op_a (22downto12) * 1 &op_b (22downto12) = 0x640000 (24 Una vez obtenidos los valores de las multiplicaciones parciales, se calcula la mantisa sumando dichos valores del siguiente modo. r0 = ab00_s12(11 downto 0) r1=("00"&ab00_s12(23downto12))+("00"&ab01_s12(11downto0))+("00"&ab10_ s12(11 downto 0)) r2=r1(13 downto 12)+("00"&ab01_s12(23 downto 12))+("00"&ab10_s12(23 downto 12)) + ("00"&ab11_s12(11 downto 0)) r3 = r2(13 downto 12) + ab11_s12(23 downto 12) r = r3 & r2 (11 downto 0) & r1(11 downto 0) & r0=0x640001400001 Finalmente, se obtiene una mantisa de 48 bits la cual se tiene de truncar ya que Copro trabaja con mantisas desnormalizadas de 28 bits. Entonces, los 28 bits de más peso son los que forman la mantisa desnormalizada y los 20 bits de menos peso se desprecian sin tener en cuenta el sticky bit. Man = r(47 downto 20) = 0x6400014 (28 bits) Una vez llegado ha este punto se forma el número desnormalizado concatenando el signo, exponente y mantisa obtenido. Esto es: 0 &0x85&0x6400014. Ahora, se tiene que normalizar el número tal y como se ha hecho en los apartados 3.2.1 y 3.3.1. Esto se hace separando la mantisa e introduciendo tantos ceros por la derecha como sea necesario para dejar un uno al bit de más peso. Mantisa desnormaliza=0110 0100 0000 0000 0000 0001 0100 Introducir 1 cero Mantisa normalizada=1100 1000 0000 0000 0000 0010 1000Cero introducido El siguiente paso es coger los 24 bits de mayor peso de la mantisa y redondear con los bits n+3, n+2 y n+1 (bits coloreados en magenta). El método de redondeo utilizado es el siguiente. Se suma uno a la mantisa si el número binario representado por los bits n+3, n+2 y n+1 es mayor o igual a 100b(4d). La mantisa se deja igual si el número binario representado por los bits n+3, n+2 y n+1 es menor o igual a 011b(3d). Por tanto, la mantisa normalizada es 1100 1000 0000 0000 0000 0010 y el exponente normalizado es el exponente desnormalizado + 1 el numero de ceros introducciones por la derecha de la mantisa desnormalizada ExpN=ExpD+1-1=0x85.

Una vez la mantisa y el exponente están normalizados se genera el número flotante normalizado concatenando el bit de signo, exponente normalizado y los 23 bits de menos peso de la mantisa normalizada ya que el bit de mayor peso llamado bit oculto (bit coloreado en rojo) nunca se utiliza en la representación. Este bit se sabe que siempre vale 1 a excepción del número 0. Signo Exponente Mantisa Numero representado en hexadecimal 0 10000101 1100 1000 0000 0000 0000 0010 0x42C80002 A continuación se verán algunas operaciones realizadas por Microblaze de las cuales se podrá deducir su comportamiento y compararlo con el de Copro. Caso A: Operando 1 =0x41200001 Operando 2 =0x41200001 Figura 28: Señales de Microblaze cuando realiza la multiplicación de 0x41200001 y 0x41200001. La figura 28 muestra el cálculo realizado por Microblaze con los mismos operandos utilizados en la descripción del comportamiento de Copro cuando realiza la operación multiplicación. Para empezar, se puede ver que las multiplicaciones parciales en Microblaze tienen una pequeña diferencia respecto a las multiplicaciones parciales en Copro. En Copro la parte alta y la parte baja de la mantisa de los operandos están formadan por un vector de 12 bits cada uno mientras que en Microblaze, la parte alta está formada por un vector de 8 bits y la parte baja por uno de 16 bits pero esto no tiene ninguna implicación significativa si la suma de la multiplicaciones parciales se realiza de forma correcta. El resultado de dichas multiplicaciones en Microblaze es: mem_prod_ad_2 = 1 &ex_op1 (22downto16) * ex_op2 (15downto0) = 0x0000A0 mem_prod_bd_2 = ex_op1 (15downto0) * ex_op2 (15downto0) = 0x00000001

mem_prod_ac_2= ex_op1 (15downto0) * 1 &ex_op2 (22downto15) = 0x0000A0 mem_prod_bc_2= 1 &ex_op1 (22downto16) * 1 &ex_op2 (22downto16) = 0x6400 Un aspecto importante a tener en cuenta es valor que toma la mantisa desnomalizada en Microblaze. Esta es de 0x6400015 mientras que en Copro es 0x6400014. Esto hace pensar que Microblaze hace de algun modo el cálculo del sticky bit y por esa razón, la mantisa de este ejemplo calculada por Microblaze difiere un poco respecto a la calculada por Copro. Por lo tanto, se va hacer la hipótesis de que dicho cálculo se hace con los bits que no van a forma parte de la mantisa desnormalizada. A continuación se muestra el vector de bits utilizado para el cálculo del sticky bit ya que así lo indica el nombe utilizado por Microblaze. también se muestra la mantisa desnomalizada con el sticky bit ya aplicado. mem_mul_sticky_bit_5_cmb=0x00001 mem_mul_res_2= r(47 downto 20) = 0x6400015 (28 bits) Al no tener ninguna señal que represente el exponente, se supondrá que Microblaze calcula el exponente del mismo modo que Copro. Entonces, el número desnormalizado obtenido hasta ahora es: 0 &0x85&0x6400015. Finalmente, este número tiene que ser normalizado y como que la etapa de normalización en Copro siempre es la misma, no importa el tipo de operación que sea, aquí se hará la misma hypótesis para Microblaze. Entonces, se puede ver que el conjunto de bit R, G y SB es mayor que 100 por lo tanto se suma 1 a m(0). El resultado final obtenido es siguiente Signo Exponente Mantisa Número representado en hexadecimal 0 10000101 1100 1000 0000 0000 0000 0011 0x42C80003 Ahora si se comparan los resultados de las operaciones realizadas con los dos procesadores, se puede ver que son diferentes. 0x42C80003 en Microblaze frente a 0x42C80002 en Copro. Para confimar la hipótesis se planteará un caso nuevo en el cual se va a modificar los operandos de tal modo que los 20 bits de menos pesos de la mantisa de 48 bits van a ser 0. Entonces si el sticky bit toma el valor 0 se podrá dar por buena la hipótesis hecha en este caso. El operando 1 tendra el valor 0x4FFFFFF0 y el operando 2 el valor 0x3F900000.

Caso B: Operando 1 =0x4FFFFFF0 Operando 2 =0x3F900000 Figura 29: Señales de Microblaze cuando realiza la multiplicación de 0x4FFFFFF0 y 0x3F900000. La figura 29 es perfecta para confirmar que el cálculo del sticky bit se hace con los bits que no se van a tener en cuenta al formar la mantisa desnormalizada. Además, conjuntamente con la figura 28, se deduce que el sticky bit toma el valor 1 si alguno de los bits mencionados anteriormente vale 1, en caso contrario el sticky bit toma el valor 0. Seguidamente, se mostraran algunos casos más para ver como Microblaze hace el cálculo del redondeo. Caso C: Operando 1 =0x4FFFFFE8 Operando 2 =0x3F900000 Figura 30: Señales de Microblaze cuando realiza la multiplicación de 0x4FFFFFE8 y 0x3F900000.

Caso D: Operando 1 =0x4FFFFFF8 Operando 2 =0x3F900000 Figura 31: Señales de Microblaze cuando realiza la multiplicación de 0x4FFFFFF8 y 0x3F900000. Caso E: Operando 1 =0x4FFFFFFA Operando 2 =0x3F900000 Figura 32: Señales de Microblaze cuando realiza la multiplicación de 0x4FFFFFFA y 0x3F900000.

En las figuras 30,31 y 32, se confirma una vez más la hipótesis que ya se había confirmado en el apartado 3.2.1 y 3.3.1 donde se deduce claramente como Microblaze hace el cálculo del bit de redondeo. Se puede ver que en la figura 30 los bits m(0), R, G y SB valen 0100 respectivamente por lo tanto, a m(0) no se le va a sumar 1 por que este vale 0 y el conjunto de bit R, G y SB es igual a 100, es decir, no va haber redondeo. Mantisa desnormaliza=100 0111 1111 1111 1111 1001 0100 Introducir 0 cero Mantisa desnormaliza=100 0111 1111 1111 1111 1001 0100 Mantisa normalizada=1000 1111 1111 1111 1111 0010 Al no tener ninguna señal que represente el exponente, se supondrá que Microblaze calcula el exponente del mismo modo que Copro. Entonces, el exponente desnormalizado es exp_op1+exp_op2 127ExpD=0x9F+0x7F-0x7F=0x9F. Ahora hay que normalizar el exponente del siguiente modo: exponente desnormalizado + 1 el número de ceros introducciones por la derecha de la mantisa desnormalizada hasta que el bit de más peso sea 1. Se puede ver claramente que en este caso el bit de más peso de mantisa desnomalizada es 1, por lo tanto, no será necesario introducir ceros por la derecha de la mantisa desnomalizada ExpN=ExpD+1-0=0xA0. Al concatenar el bit de signo, el exponente normalizado y la mantisa normalizada se obtiene el número 0 &0xA0&0x8FFFF2 el cual se tiene de agrupar de tal modo que represente un número definido por la norma IEEE 754. Signo Exponente Mantisa Numero representado en hexadecimal 0 10100000 1000 1111 1111 1111 1111 0010 0x500FFFF2 El bit coloreado en rojo es el bit oculto el cual no se utiliza en las representaciones, por lo tanto el resultado final de la multiplicación es 0x500FFFF2. En la figura 31 se puede ver el contrario de la figura 27 ya que los bits m(0), R, G y SB valen 1100 respectivamente por lo tanto, a m(0) se le va a sumar 1 por que este vale 1 y el conjunto de bit R, G y SB es igual a 100, es decir, si va haber redondeo. Mantisa desnormaliza=100 0111 1111 1111 1111 1101 1100 Introducir 0 cero Mantisa desnormaliza=100 0111 1111 1111 1111 1101 1100 Mantisa normalizada=1000 1111 1111 1111 1111 1100 Al no tener ninguna señal que represente el exponente, se supondrá que Microblaze calcula el exponente del mismo modo que Copro. Entonces, siguiendo los pasos seguidos en el caso C se obtiene que el exponente desnormalizado es exp_op1+exp_op2 127ExpD=0x9F+0x7F-0x7F=0x9F y que exponente normalizado es ExpN=ExpD+1-0=0xA0. Al concatenar el bit de signo, el exponente normalizado y la mantisa normalizada se obtiene el número 0 &0xA0&0x8FFFFC el cual se tiene de agrupar de tal modo que forme un número definido por la norma IEEE 754.

Signo Exponente Mantisa Número representado en hexadecimal 0 10100000 1000 1111 1111 1111 1111 1100 0x500FFFFC El bit coloreado en rojo es el bit oculto el cual no se utiliza en las representaciones, por lo tanto el resultado final de la multiplicación es 0x500FFFFC. Finalmente, en el caso E se puede ver que si R, G y SB son igual o mayor que 101 se suma 1 a m(0) independientemente del valor que tenga m(0), es decir, también va haber redondeo. Mantisa desnormaliza=100 0111 1111 1111 1111 1110 0101 Introducir 0 cero Mantisa desnormaliza=100 0111 1111 1111 1111 1110 0101 Mantisa normalizada=1000 1111 1111 1111 1111 1101 Al no tener ninguna señal que represente el exponente, se supondrá que Microblaze calcula el exponente del mismo modo que Copro. Entonces, siguiendo los pasos seguidos en el caso C y D se obtiene que el exponente desnormalizado es exp_op1+exp_op2 127ExpD=0x9F+0x7F-0x7F=0x9F y que exponente normalizado es ExpN=ExpD+1-0=0xA0. Al concatenar el bit de signo, el exponente normalizado y la mantisa normalizada se obtiene el número 0 &0xA0&0x8FFFFD el cual se tiene de agrupar de tal modo que quede un numero definido por la norma IEEE 754. Signo Exponente Mantisa Número representado en hexadecimal 0 10100000 1000 1111 1111 1111 1111 1101 0x500FFFFD El bit coloreado en rojo es el bit oculto el cual no se utiliza en las representaciones, por lo tanto el resultado final de la multiplicación es 0x500FFFFD. 2.4.2 Adaptación en Copro En este caso se harán dos adaptaciones. La primera adaptación es la de tener en cuenta el sticky bit tal y como hace Microblaze, es decir, que una vez hecha la multiplicación parcial con la cual se obtendrá una mantisa de 48 bits, se cogerán los 28 bits de más peso para formar la mantisa desnomalizada y los 20 bits restantes serán lo que se utilizarán para el cálculo del sticky bit. Este tomará el valor 1 si alguno de estos 20 bits es 1, en caso contrario, tomará el valor 0. La segunda adaptación será totalmente igual que la vista en los casos de las operaciones entero a flotante, suma y resta. La modificación es la siguiente: Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es mayor a 100b(4d).

Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 1. La mantisa se deja igual si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 0 La mantisa se deja igual si el número binario representado por los bits R, G y SB es menor o igual a 011b(3d). 2.5 Operación Div La operación división es la más compleja que se verá en este trabajo. Esta puede tarda 2, 3 o 10 veces más en ejecutarse que cualquiera de las operaciones vistas anteriormente. Al igual que las operaciones conversión entero a flotante, suma, resta y multiplicación, esta también se puede realizar tanto con Copro como con Microblaze utilizando números representados en coma flotante. El rango de números en coma flotante que se puede representar en 32 bits para esta operación es de 0xFF800000 hasta 0x7F800000. 2.5.1 Comportamiento Copro VS Microblaze El planteamiento en este apartado va a ser igual que en los apartados de la suma y resta y multiplicación ya que en este caso Microblaze también pone a disposición del usuario señales de entrada, de salida e intermedias utilizadas en su código cuando realiza dicha operación. Entonces, primero se mostraran la señales más significativas de Microblaze así como el código en C ejecutado por Microblaze para poder visualizar dichas señales, luego, se explicará como Copro hace la operación división y finalmente se observarán algunos casos claves y algunas de las señales más significativas utilizadas por Microblaze cuando realiza dichas operaciones y se compararán con las de Copro. Las señales más significativas de Microblaze son: Mem_start_div: inicio operación (1 bit) ex_fpu_op: identificador operación (3 bits) ex_op1: operando 1 (32 bits) ex_op2: operando 2 (32 bits) ex_manta_1: mantisa operando 2 (24 bits) ex_mantb_1: mantisa operando 1 (24 bits) mem_q: cociente (25bits) mem_r: dividendo (25bits) mem_b: divisor (25bits) mem_diff_cmb: resta (25bits) mem_div_sticky_bit_cmb: sticky bit (21 bits) mem_div_res_4: mantisa resultado (27 bits) fpu_result: resultado final (32 bits)

El código utilizado es: const float b[2]={0x42f80000, 0x4B800000}; const float ax[2]={0x40000000, 0x3FC00000}; float *p2=(float*)0x2e0000; float *p3=(float*)0x2d0000; float *p4=(float*)0x2c0000; for(int j=0; j<2; j++) {p2[j]=ax[j]; p3[j]=b[j];} for(int j=0; j<2; j++) {p4[j]=p2[j]/p3[j]; } El método general el cual se basa Copro para realizar la operación division es bastente similar al de la multiplicación con la diferencia que las mantisas se dividen y los exponentes se restan. Seguidamente se muestra un ejemplo basado en números enteros. Operando A=2; Operando B=200; Resultado = Operando A / Operando B Se transforman los operandos A y B en números formados por un exponente y una mantisa. Operando A=1 * 2^1 Operando B=1,5625 * 2^7 Se suman los exponentes y si multiplican las mantisas. Exponente=(2^1) - (2^7)= 2^-6 Mantisa=1 /1,5625 = 0,64 Resultado=0,64* 2^-6 El método inicial a seguir para realizar divisiones en Copro es: Inicialmente se hace la comprobación de posibles excepciones en el siguiente orden. Si cualquier de los operandos A y/o B son un NAN (not a number) entonces, el resultado de la operación es NAN. Si no, si los dos operandos A y B son infinitos o cero el resultado final es un NAN. Si no, si el operando A es infinito y el operando B es cero el resultado final es infinito con el mismo signo que el operando a. Finalmente, si no se cumple ninguna excepción anterior se comprueba si el operando A es 0 o si el operando B es infinito. En cualquier caso el resultado final es 0. En caso de que no se de ninguna de estas excepciones se procede del siguiente modo. Sea el operando A= 0x42F80000 (0100 0010 1111 1000 0000 0000 0000 0000b) y B= 0x40000000 (0100 0000 0000 0000 0000 0000 0000 0000b) siendo el bit de más

peso (MSB) el de más a la izquierda, primero se obtiene el signo de los dos operandos el cual viene dado por el bit 31 que es el MSB y se hace la XOR entre ellos para saber el signo del resultado de la operación (sig_s12=sig_a XOR sig_b). A continuación se calcula el exponente de la operación del siguiente modo exp_s12=exp_a - exp_b +127. Luego, se separan las mantisas de los dos operando tal y como se indica a continuación. a_divsqrt= 1 & op_a (22downto0) y b_divsqrt= 1 & op_b (22downto0) y seguidamente, se pone la señal del sticky bit a 1 si el exponente de la operación calculado es inferior a 31, en caso contrario, esta toma el valor 0. Una vez llegado a este punto, es momento de empezar la división. Para realizar divisiones en diseños digitales existen diferentes algoritmos los cuales se pueden clasificar en dos categorías. Algoritmos lentos y algoritmos rápidos. En la categoría de lentos podemos encontrar el algoritmo Restoring Division, Non Restoring Division y SRT, por otro lado, en la categoría de rápidos podemos encontrar el algoritmo de Newto- Raphson y Goldschmidt. El algoritmo Restoring Division consiste en restar el dividendo con el divisor. Si el resultado de esta resta es negativo se pone un 0 al bit de más peso de la señal q llamada cociente y se deshace el cambio de la resta sumando el resultado de la resta con el divisor. En caso contrario, se pone un 1 al bit de más peso de q y no se deshace el cambio de la resta. Finalmente, sea cual sea el caso, se multiplica por dos el contenido de la resta, es decir, desplazamos un bits hacia la izquierda la variable P que contiene el resultado de la resta entre dividendo y divisor. Esta interación se repite n veces hasta que se hayan recorrido todos los bits del cociente. Algoritmo Restoring Division P: dividendo; D: divisor for i = n-1..0 // n: número de bit a recorrer P:= P D // Restar dividendo con divisor if P >= 0 then q(i) := 1 // Almacenar 1 a q else q(i) := 0 // Almacenar 0 a q P := P + D // Deshacer cambio end if P=2P // Desplazar dividendo nuevo un bit a la izquierda end do En el caso de Copro se utiliza un algoritmo basado en el Restoring Division algorithm pero con algunas modificaciones para que sea más eficiente y rápido. La primera modificación consiste en añadir una condición de finalización de la división si el resto es 0 ya que si esto sucede las iteraciones siguentes serian completamente iguales. Consecuentemente, el cociente se inicializa a 0 porque si la división es interrumpida por obtener un resto a cero, los bits restantes hasta el bit de menos peso van a ser cero. La segunda modificación es utilizar una variable intermedia la cual tomará el valor de la resta y se copiará al dividiendo si, y solo si, el signo de dicha resta es positiva. Con esta modificación se optimizará el diseño ahorrando lógica digital para deshacer el resultado de la resta de P y D en caso de que este sea negativo. Algoritmo Restoring Division modificado Cmp:resta; P: dividendo; D: divisor

i=n-1 // n el número de bits de q q=0 // Inicialización de q do Cmp:= P D // Restar dividendo con divisor if Cmp >= 0 then q(i) := 1 // Almacenar 1 a q P=Cmp // Nuevo dividendo else do nothing end if P=2P // Desplazar dividendo nuevo un bit a la izquierda i=i-- While (cmp!=0 and i >=0) En este caso particular los valores que se obtienen son: Signo Exponente Mantisa Número representado en hexadecimal 0 1000 0101 1111 1000 0000 0000 0000 0000 0x42F80000 0 1000 0000 1000 0000 0000 0000 0000 0000 0x40000000 signo_s12 = sig_a XOR sig_b = 0 xor 0 = 0 (1 bit) exp_s12 = exp_a + exp_b -127 = 0x85-0x80-127 =0x84 (8 bits) a_divsqrt= 1 & op_a (22downto0)= 0xF80000 (24 bits) b_divsqrt= 1 & op_b (22downto0)= 0x800000 (24 bits) r= 00 & a_divsqrt =0x0F80000 (26 bits) b= 00 & b_divsqrt =0x0800000 (26 bits) Como se puede apreciar el dividendo (r) y el divisor (b) se les ha añadido dos ceros a la izquierda para detectar los resultados negativos al restar. q=0x0000000 (26 bits) q es el cociente y se inicializa a cero. Iteración número 1 index=26 bit de q a rellenar Cmp=(r-b)= 0x0780000 Como que cmp left=0 se pone el bit de más peso de Q a 1 q=0x2000000 Cogemos los 26 bits de menos peso de la resta en r y b (Cmp) y los pones a r r= 0x0780000 Se desplaza r en un bit hacia la izquierda r=0x0f00000

Iteración número 2 index=25 bit de q a rellenar Cmp=(r-b)= 0x0700000 Como que cmp left=0 se pone el bit 25 de Q a 1 q=0x3000000 Cogemos los 26 bits de menos peso de la resta en r y b (Cmp) y los pones a r r= 0x0700000 Se desplaza r en un bit hacia la izquierda r=0x0e00000 Iteración número 3 index=24 bit de q a rellenar Cmp=(r-b)= 0x0600000 Como que cmp left=0 se pone el bit 24 de Q a 1 q=0x3800000 Cogemos los 26 bits de menos peso de la resta en r y b (Cmp) y los pones a r r= 0x0600000 Se desplaza r en un bit hacia la izquierda r=0x0c00000 Iteración número 4 index=23 bit de q a rellenar Cmp=(r-b)= 0x0400000 Como que cmp left=0 se pone el bit 23 de Q a 1 q=0x3c00000 Cogemos los 26 bits de menos peso de la resta en r y b (Cmp) y los pones a r r= 0x0400000 Se desplaza r en un bit hacia la izquierda r=0x0800000 Iteración número 5 index=22 bit de q a rellenar Cmp=(r-b)= 0x0000000 Como que cmp left=0 se pone el bit 22 de Q a 1 q=0x3e00000 Cogemos los 26 bits de menos peso de la resta en r y b (Cmp) y los pones a r r= 0x0000000 Se desplaza r en un bit hacia la izquierda

r=0x0000000 Y esta es la ultima iteración ya que el resultado de la resta entre dividendo y divisor es cero. A continuación se genera la mantisa desnormalizada concatenando q y el sticky bit tal y como se muestra a continuación. Q_divsqrt=q&SB=0x3E00000& 1 =0x7C00001 Luego se forma el número desnormalizado. Se puede ver que se ha añadido un zero a la izquierda de la mantisa desnomalizada para que esta esté formada de 28 bits. Res=sig & exp & 0 & Q_divsqrt= 0 1000 0100 0111 1100 0000 0000 0000 0000 0001= 0 &0x84&0x7C00001 Ahora, se tiene que normalizar el número tal y como se ha hecho en los apartados 3.2.1, 3.3.1 y 3.4.1. Esto se hace separando la mantisa e introduciendo tantos ceros por la derecha como sea necesario para dejar un uno al bit de más peso. Mantisa desnormaliza=0111 1100 0000 0000 0000 0000 0001 Introducir 1 cero Mantisa normalizada=1111 1000 0000 0000 0000 0000 0010Cero introducido El siguiente paso es coger los 24 bits de mayor peso de la mantisa y redondear con los bits n+3, n+2 y n+1 (bits coloreados en magenta). El método de redondeo utilizado es el siguiente. Se suma uno a la mantisa si el número binario representado por los bits n+3, n+2 y n+1 es mayor o igual a 100b(4d). La mantisa se deja igual si el número binario representado por los bits n+3, n+2 y n+1 es menor o igual a 011b(3d). Por tanto, la mantisa normalizada es 1111 1000 0000 0000 0000 0000 y el exponente normalizado es el exponente desnormalizado + 1 el numero de ceros introducciones por la derecha de la mantisa desnormalizada ExpN=ExpD+1-1=0x84. Una vez la mantisa y el exponente están normalizados se genera el número flotante normalizado concatenando el bit de signo, exponente normalizado y los 23 bits de menos peso de la mantisa normalizada ya que el bit de mayor peso llamado bit oculto (bit coloreado en rojo) nunca se utiliza en la representación. Este bit se sabe que siempre vale 1 a excepción del número 0. Signo Exponente Mantisa Número representado en hexadecimal 0 10000100 1111 1000 0000 0000 0000 0000 0x42780000 A continuación se verán algunas operaciones realizadas por Microblaze de las cuales se podrá deducir su comportamiento y compararlo con el de Copro. También es importante mencionar que no se va a mostrar todas las iteraciones que se realicen en las operaciones si no que en algunos casos se mostraran la primeras y las últimas y, en otros casos solo se mostraran la últimas iteraciones.

Caso A: Operando 1 =0x42F80000 Operando 2 =0x40000000 Figura 33: Señales de Microblaze cuando realiza la división de 0x42F80000 y 0x40000000. Figura 34: Señales de Microblaze cuando realiza la división de 0x42F80000 y 0x40000000. Comparando los resultados de las dos figuras anteriores y el análisis de la división realizada por Copro en este mismo apartado, se puede apreciar muy bien que los comportamientos de los dos procesadores son bastante diferentes. Por un lado, Copro necesita 5 iteraciones para completar la división de las mantisas ya que cuando el resto es 0, este finaliza dicha división, mientras que Microblaze hace tantas iteraciones como bits tenga la señal men_q la cual es el cociente. Entonces, una primera conclusión que se puede extraer es que el método que utiliza Copro es más rápido si la división es exacta. Otra diferencia que se puede ver es el valor que toma la mantisa resultante después de hacer la división y concaternarla con el sticky bit. En el caso de Microblaze la mantisa resultante toma el valor 0x7C00002 y en el caso de Copro la mantisa toma el valor 0x7C00001. Mirando la figura 30, se puede ver que el sticky bit vale 0 si 24 bits de menos peso de r son cero, en caso contrario, este toma el valor 1 mientras que, en el caso de Copro, el sticky bit toma el valor 0 o 1 dependiendo del exponente resultante. Entonces, este será el primer cambio que se va a aplicar a Copro para el cálculo del sticky bit sea igual que el de Microblaze. Pero, aunque se aplicase este cambio los resultados de las mantisas resultantes de los dos procesadores serian todavía diferente. Entonces esto hace pensar en que los dos procesadores podrían utilizar diferentes algoritmos de cálculo para la división, por lo tanto se propondrá la hipótesis de que Microblaze utiliza el algoritmo Non Restoring Division.

El paso siguiente es hacer un análisis como el que se ha hecho para Copro en este mismos apartado pero siguiendo el algoritmo Non Restoring Division. La particularidad que tiene el algoritmo Non Restoring Division es que cada bit del cociente se rellena con 1 o 1 dependiendo de si la resta entre dividendo y divisor es positiva o negativa. Luego el cociente se normaliza dejándolo con 0 y 1. Algoritmo Non Restoring Division r: dividendo; b: divisor i=n //n el número de bits de q i=i-- do if r >= 0 then q (i) := 1 //Almacenar 1 a q else q (i) := -1 //Almacenar -1 a q end if r:=r b //Restar dividendo con divisor r=2*r i=i-- While ( i >=0) Finalmente se normaliza el cociente q formado por -1 y 1 al cociente normalizado q formado por 0 y 1. Para normalizar, Se cambian los -1 por 0, se desplaza un bit hacia la izquierda de la nueva q y se le suma 1. ' q 1,1 ; q formada por -1 y 1 '' q 0,1 ; q cambiando -1 por 0 q 2 * q '' 1 Volviendo al ejemplo numérico pero aplicado al algoritmo Non Restoring Division tenemos: Sea el operando A= 0x42F80000 (0100 0010 1111 1000 0000 0000 0000 0000b) y B= 0x40000000 (0100 0000 0000 0000 0000 0000 0000 0000b) siendo el bit de más peso (MSB) el de más a la izquierda, primero se obtiene el signo de los dos operandos el cual viene dado por el bit 31 que es el MSB y se hace la XOR entre ellos para saber el signo del resultado de la operación (sig_s12=sig_a XOR sig_b). A continuación se calcula el exponente de la operación del siguiente modo exp_s12=exp_a - exp_b +127. Luego, se separan las mantisas de los dos operando tal y como se indica a continuación. a_divsqrt= 1 & op_a (22downto0) y b_divsqrt= 1 & op_b (22downto0). En este caso particular los valores que se obtienen son: Signo Exponente Mantisa Número representado en hexadecimal 0 1000 0101 1111 1000 0000 0000 0000 0000 0x42F80000 0 1000 0000 1000 0000 0000 0000 0000 0000 0x40000000 signo_s12 = sig_a XOR sig_b = 0 xor 0 = 0 (1 bit)

exp_s12 = exp_a + exp_b -127 = 0x85-0x80-127 =0x84 (8 bits) a_divsqrt= 1 & op_a (22downto0)= 0xF80000 (24 bits) b_divsqrt= 1 & op_b (22downto0)= 0x800000 (24 bits) r= 0 & a_divsqrt =0x0F80000 (25 bits) b= 0 & b_divsqrt =0x0800000 (25 bits) Una vez llegado a este punto, es momento de empezar la división. Como se puede apreciar el dividendo (r) y el divisor (b) se les ha añadido 1 cero a la izquierda tal y como lo hace Microblaze para detectar los resultados negativos al hacer la resta entre r y b. En cuanto al cociente q, este también tiene 25 bits y no se inicializa a cero ya que se van hacer tantas iteraciones como bits existan en q. i=25 Se decrementa i b=0x0800000 r=0x0f80000 Iteración número 1 i=24 bit de q a rellenar Como que r>=0 se pone el bit 24 de q (i) a 1 y r=r-b= 0x0780000 Luego se desplaza un bit de r hacia la izquierda r=2*r=0x0f00000 q =1 Se decrementa i Iteración número 2 i=23 bit de q a rellenar Como que r>=0 se pone el bit 23 de q (i) a 1 y r=r-b= 0x0700000 Luego se desplaza un bit de r hacia la izquierda r=2*r=0x0e00000 q =11 Se decrementa i Iteración número 3 i=22 bit de q a rellenar Como que r>=0 se pone el bit 22 de q (i) a 1 y r=r-b= 0x0600000 Luego se desplaza un bit de r hacia la izquierda r=2*r=0x0c00000 q =111 Se decrementa i Iteración número 4

i=21 bit de q a rellenar Como que r>=0 se pone el bit 21 de q (i) a 1 y r=r-b= 0x0400000 Luego se desplaza un bit de r hacia la izquierda r=2*r=0x0800000 q =1111 Se decrementa i Iteración número 5 i=20 bit de q a rellenar Como que r>=0 se pone el bit 20 de q (i) a 1 y r=r-b= 0x0000000 Luego se desplaza un bit de r hacia la izquierda r=2*r=0x0000000 q =1 1111 Se decrementa i Iteración número 6 i=19 bit de q a rellenar Como que r>=0 se pone el bit 19 de q (i) a 1 y r=r-b= 0x1000000 Luego se desplaza un bit de r hacia la izquierda r=2*r=0x0000000 q =1 1111 1 Se decrementa i Iteración número 7 i=18 bit de q a rellenar Aunque r sea igual que cero se sabe que en la iteración anterior era inferior a 0 Entonces, como que r<0 se pone el bit 18 de q (i) a -1 y r=r-b= 0x1000000 Luego se desplaza un bit de r hacia la izquierda r=2*r=0x0000000 q =1 1111 1-1 Se decrementa i De aquí hacia delante, todas las iteraciones son iguales, es decir, con el resultado de la resta negativa, por lo tanto, todos los siguientes bits de q serán puestos a 1. q = 1 1111 1-1-1-1 -1-1-1-1 -1-1-1-1 -1-1-1-1 -1-1-1-1 Ahora hay que normaliza q siguiendo los pasos descritos anteriormente, es decir, cambiando los -1 de q por 0, con este paso se obtine q. Luego se introduce un 0 por la derecha de q y finalmente se le suma 1. En este caso particular, los valores que se obtiene son los siguientes. q {-1,1} = 11 1111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1

q {0,1} = 11 1111 0000 0000 0000 0000 0000 q{0,1} = 11 1110 0000 0000 0000 0000 0001 q{0,1} = 0x3E0001 A continuación se genera la mantisa desnormalizada concatenando q y el sticky bit tal y como se muestra a continuación. Q_divsqrt=q&SB=0x3E00001& 0 =0x7C00002 Una vez obtenida la mantisa desnomalizada se puede comprobar que es igual a la obtenida por Microblaze en la figura 34, por lo tanto podemos afirma que Microblaze utiliza el algoritmo Non Restoring Division. Siguiendo en este ejemplo y en cuanto a la etapa normalizadora se refiere, se puede ver que el resultado final de la división realizada por los dos procesadores es el mismo, hecho que hace pensar que dicha etapa sea la misma que la que se ha utilizado en las operaciones anteriores. Aunque esto no se puede afirmar ahora mismo, se trabajara con esta hipótesis la cual se confirmará a continuación con más ejemplos. Caso B: Operando 1 =0x4FFFFFF0 Operando 2 =0x3F9000002 Figura 35: Señales de Microblaze cuando realiza la división de 0x4FFFFFF0 y 0x3F9000002. Partiendo del punto donde la única operación que queda es normalizar el siguiente número: Res=sig & exp & 0 & Q_divsqrt= 0 1001 1111 0111 0001 1100 0111 0001 0011 1101= 0 &0x9F&0x71C713D Se puede ver que los bits m(0), R, G y SB valen 1101 respectivamente por lo tanto, a m(0) se le va a sumar 1 por que el conjunto de bit R, G y SB es superior a 100, es decir, va haber redondeo. Mantisa desnormaliza=0111 0001 1100 0111 0001 0011 1101 Introducir 1 cero Mantisa desnormaliza=1110 0011 1000 1110 0010 0111 1010 Mantisa normalizada=1110 0011 1000 1110 0010 1000 Al no tener ninguna señal que represente el exponente, se supondrá que Microblaze calcula el exponente del mismo modo que Copro. Entonces, el exponente

desnormalizado es exp_op1-exp_op2+127expd=0x9f-0x7f+0x7f=0x9f. Ahora hay que normalizar el exponente del siguiente modo: exponente desnormalizado + 1 el número de ceros introducciones por la derecha de la mantisa desnormalizada hasta que el bit de más peso sea 1. Se puede ver claramente que en este caso el bit de más peso de mantisa desnomalizada es 0, por lo tanto, será necesario introducir 1 cero por la derecha de la mantisa desnomalizada ExpN=ExpD+1-1=0x9F. Al concatenar el bit de signo, el exponente normalizado y la mantisa normalizada se obtiene el número 0 &0x9F &0xE38E28 el cual se tiene de agrupar de tal modo que represente un número definido por la norma IEEE 754. Signo Exponente Mantisa Número representado en hexadecimal 0 10011111 1110 0011 1000 1110 0010 1000 0x4FE38E28 El bit coloreado en rojo es el bit oculto el cual no se utiliza en las representaciones, por lo tanto el resultado final de la multiplicación es 0x4FE38E28. Caso C: Operando 1 =0x42EEE000 Operando 2 =0x40000003 Figura 36: Señales de Microblaze cuando realiza la división de 0x42EEE000 y 0x40000003. En este caso se va a proceder del mismo modo que el caso anterior, es decir, teniendo en cuenta que la única operación que queda es normalizar el siguiente número: Res=sig & exp & 0 & Q_divsqrt= 0 1001 1111 0111 0111 0110 1111 1111 1101 0011= 0 &0x84&0x776FFD3 se puede ver que los bits m(0), R, G y SB valen 0011 respectivamente por lo tanto, a m(0) no se le va a sumar 1 por que el conjunto de bit R, G y SB es inferior a 100, es decir, no va haber redondeo. Mantisa desnormaliza=0111 0111 0110 1111 1111 1101 0011 Introducir 1 cero Mantisa desnormaliza=1110 1110 1101 1111 1111 1010 0110 Mantisa normalizada=1110 1110 1101 1111 1111 1010

Al no tener ninguna señal que represente el exponente, se supondrá que Microblaze calcula el exponente del mismo modo que Copro. Entonces, el exponente desnormalizado es exp_op1-exp_op2+127expd=0x85-0x80+0x7f=0x84. Ahora hay que normalizar el exponente del siguiente modo: exponente desnormalizado + 1 el número de ceros introducciones por la derecha de la mantisa desnormalizada hasta que el bit de más peso sea 1. Se puede ver claramente que en este caso el bit de más peso de mantisa desnomalizada es 0, por lo tanto, será necesario introducir 1 cero por la derecha de la mantisa desnomalizada ExpN=ExpD+1-1=0x84. Al concatenar el bit de signo, el exponente normalizado y la mantisa normalizada se obtiene el número 0 &0x84 &0xEEDFFA el cual se tiene de agrupar de tal modo que represente un número definido por la norma IEEE 754. Signo Exponente Mantisa Número representado en hexadecimal 0 10000100 1110 1110 1101 1111 1111 1010 0x426EDFFA El bit coloreado en rojo es el bit oculto el cual no se utiliza en las representaciones, por lo tanto el resultado final de la multiplicación es 0x426EDFFA. 2.5.2 Adaptación en Copro Una vez se ha completado el análisis de la operación división realizada con los dos procesadores se va a hacer una lista de las diferencias que hay y cuales de ellas se van a aplicar. La primera diferencia esta en el cálculo del sticky bit. Se ha comprobado que Microblaze pone el sticky bit a 0 si los 24 bits de menos peso de la variable que representa la resta entre dividendo y divisor son 0, en caso contrario, el sticky bit vale 1. La segunda diferencia la cual se ha demostrado es que los dos procesadores utilizan un algoritmo diferente para realizar la operación división. Finalmente, la última diferencia entre Microblaze y Copro esta en el un método de redondeo como ya se había demostrado en los otros apartados, De las 3 diferencias encontradas, solamente se van aplicar dos de ellas, el sticky bit y el redondeo. En cuanto al algoritmo utilizado por los procesadores, no se va a adaptara Copro al algoritmo Non Restoring Division porque el Restoring Division modificado utilizado en Copro tiene unas mejores prestaciones que el Non Restoring Division y además es bastante más rápido en caso de la división sea exacta. Entonces, como se ha mencionado anteriormente, la primera adaptación es la de tener en cuenta el sticky bit tal y como hace Microblaze, es decir, poner el sticky bit a 0 si los 24 bits de menos peso de la variable que representa la resta entre dividendo y divisor son 0, en caso contrario, el sticky bit vale 1. La segunda adaptación será totalmente igual que la vista en los casos de la operación entero a flotante, suma y resta y multiplicación. La modificación es la siguiente: Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es mayor a 100b(4d).

Se suma uno a la mantisa si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 1. La mantisa se deja igual si el número binario representado por los bits R, G y SB es igual a 100b(4d) y el bit de menos peso de la mantisa normalizada (m(0)) es igual a 0 La mantisa se deja igual si el número binario representado por los bits R, G y SB es menor o igual a 011b(3d). 2.6 Ensayo con Avnet Spartan-3 Development Board Hasta ahora se ha trabajado con el entorno de simulación y depurado ModelSim SE 6.2 plus para ver los resultados de las operaciones realizadas tanto por Microblaze como Copro. De este modo es muy sencillo ver como trabajan los dos procesadores en cada ciclo de reloj facilitando el estudio del comportamiento de Microblaze y el ajuste del diseño de Copro con la finalidad de que los dos procesadores se comporten del mismo modo. La placa de dessarrollo Avnet Spartan-3, la cual se usa en este proyecto, utiliza la un dispositivo FPGA XC3S 2000 formado por 2 millones de puertas lógicas programables. Esta misma placa de desarrollo esta en el mercado pero con una FPGA XC3S 1500 la cual esta formada por 1,5 millones de puertas lógicas programables. Las características principales de los dispositivos disponibles son: FPGA Logic Gates Logic Cells Array CLB (4 celdas lógicas) BRAM (2KB) Fil Col Total CLBs Mult XC3S1500 1.5M 29,952 64 52 3,328 32 32 4 XC3S2000 2M 46,080 80 64 5,120 40 40 4 DCM Entonces, para probar un diseño en un entorno real con la placa de desarrollo Avnet Spartan-3 hay que seguir una serie de pasos. El primer paso es sintetizar el diseño de Copro con el entorno XPS (Xilinx Platform Studio). La sintetización de un diseño basado en FPGA es el proceso de generar un fichero de formato bitstream el cual contiene la implementación del diseño a grabar en la FPGA. En este proyecto, se ha visto como se ejecuta un programa en C en los procesadores Microblaze y Copro con la ayuda del simulador. El siguiente paso es compilar el programa en C a ejecutar y añadirlo al fichero resultante de la sintetización del diseño de tal modo que al cargar el fichero resultante en la FPGA, esta ya contenga el diseño más el programa a ejecutar. Finalmente, antes de verificar el sistema hay que descargar el diseño además del programa a ejecutar en la FPGA de placa de desarrollo. Esto se hace mediante un programador USB-JTAG el cual permite grabar FPGAs placa de desarrollo desde el mismo entorno XPS (Xilinx Platform Studio). 2.6.1 Configuración La placa de desarrollo soporta tanto el modo Boundary-Scan como Master/Slave serie o paralelo usando las memorias PROM de la placa. Programar el dispositivo FPGA mediante Boundary-Scan requiere el uso de un cable JTAG. La placa contiene los

conectores J1 y J5 para la conexión de los cables Parallel III y Parallel IV respectivamente. El conector J5 está destinado a la conexión de un cable plano de 14 pines suministrado con el cable Xilinx Parallel IV. Se debe conectar un jumper en las posiciones 2-3 del JP6 para configurar la cadena de JTAG en modo standalone. Figura 37: Conexión del cable Xilinx Parallel IV Figura 38: Cadena JTAG en modo standalone 2.6.2 Señal de reloj La placa de desarrollo tiene diferentes fuentes de reloj disponibles. En la tabla siguiente se muestran las entradas de reloj recomendadas para la señal de reloj del sistema: 2.6.3 Memoria SRAM Frecuencia #pin FPGA Observaciones 66MHz AD13 100MHz A13 40MHz typ. AE14 Socket - AE13 SMA - AF14 Header 125MHz typ. C14, B14 No instalado por defecto La memoria SRAM es uno de los tipos de memoria disponibles en la placa de desarrollo (además de memoria Flash y DDR SDRAM). Se trata de un dispositivo de SRAM asíncrona conectado al bus compartido de datos con anchura de 32 bits. Proporciona 2MB de memoria SRAM en un IC único organizada como 512KB x 32. 2.6.4 Conexión y grabación El establecimiento de la conexión del equipo de desarrollo (ordenador personal) con el dispositivo destino se realiza mediante la herramienta Impact del entorno de desarrollo ISE de Xilinx pero esta herramienta no se ejecutar directamente sino que se hace desde XPS (Xilinx Platform Studio), es decir, que Impact queda en segundo plano. En cuanto a la conexión física, esta se consigue mediante la conexión física desde un extremo del programador al puerto USB del ordenador y desde el otro hasta al conector J5 de la placa de desarrollo. La cadena detectada automáticamente por el Boundary Scan está compuesta por dos puertos JTAG diferentes. El primero corresponde con la memoria PROM de la placa de desarrollo utilizada para almacenar de forma permanente la configuración del dispositivo FPGA, normalmente utilizada para diseños definitivos. El segundo puerto es utilizado para la configuración del dispositivo programable desde el equipo de desarrollo. Se especifica el fichero bitstream para el puerto. La generación del fichero bitstream se lleva a cabo pulsando el botón Generate bitstream del menú principal de XPS (Xilinx Platform Studio). Este proceso puede

llegar a tardar algunos minutos dependiendo de la envergadura del diseño. Una vez generado el fichero bitstream, este se actualiza con el programa que se ejecutará en la FPGA pulsando el botón Update bitstream with software program information. Finalmente, el fichero resultante se descarga en la FPGA directamente utilizando el puerto indicado en el fichero. En este proyecto la descarga será directa a la FPGA. En la figura 39 se puede ver el menú principal de XPS (Xilinx Platform Studio) con los botones principales utilizados para la sinterización del diseño y descarga a la FPGA. Un aspecto a tener en cuenta es los pasos que se tienen que repetir si se modifica algún fichero ya sea del diseño, del programa o los dos. En caso de que se modifique el programa a ejecutar solo es necesario compilar dicho programa y añadirlo al fichero bitstream y luego descargar el fichero resultante a la FPGA, mientras que, si se modifica algún fichero del diseño, se tienen que repetir todos los tres pasos anteriores. 2.6.5 Comunicación R232 Figura 39: Pantalla principal de la herramienta de desarrollo XPS En este proyecto se utiliza el puerto de comunicación serie que proporciona la placa de desarrollo el cual se utiliza para enviar los resultados de algunas operaciones realizadas por los dos procesadores además de todas aquellas en que los resultados de las operaciones sean diferentes. Las señales de transmisión/recepción están conectadas a un banco de entrada/salida de la FPGA (banco 6). Los puertos de entrada/salida utilizados para las líneas RX y TX son los pines P4 y P5 respectivamente.