coprocesador fpu (floating-point unit)deeea.urv.cat/public/propostes/pub/pdf/1464pub.pdf · 3.2.1...

143
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

Upload: votu

Post on 04-Feb-2018

222 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 2: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Í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

Page 3: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 4: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 5: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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).

Page 6: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 7: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 8: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 9: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 10: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 11: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 12: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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,

Page 13: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 14: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 15: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 16: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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 PowerPCTM

y procesadores Xilinx

MicroBlazeTM

.

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

Page 17: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

común como C/C++ ampliamente utilizado en sistemas embebidos. SDK usa la

estructura opensource EclipseTM

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

Page 18: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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 PowerPCTM

o Xilinx MicroBlazeTM

.)

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

Page 19: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 20: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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).

Page 21: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Figura 13: Detalle de la pestaña IP Catalog

b) System Assembly View

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

Page 22: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

o deshabilitar una conexión solo hay que darle con el puntero del ratón al

símbolo de conector.

Figura 14

Page 23: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 24: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Figura 16: Detalle de la pestañas de la consola

1.3.5 ModelSim SE Plus 6.2c

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 post-

layout entre otras.

Figura 17: Ventana principal del ModelSim

Page 25: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 26: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 27: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 28: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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:

Page 29: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 30: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 31: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

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

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]; }

Page 32: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 33: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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).

Page 34: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Caso 1: rango de 0x01AAAFFF a 0x01AAAFF0

Número entero 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

Page 35: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Caso 2: rango de 0x02AAAFFF a 0x02AAAFF0

Número entero 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

Caso 3: rango de 0x04AAAFFF a 0x04AAAFF0

Número entero 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

Page 36: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Caso 4: rango de 0x08AAAFFF a 0x08AAAFE0

Número entero 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

Page 37: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Caso 5: rango de 0x1AAAAFFF a 0x1AAAAFCC

Número entero Bits

pedidos

Bit

m(0),R,

G,SB

Bit

redond

eo

Número flotante

Copro

Número flotante

Microblaze

Diferencia

Page 38: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 39: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Caso 6: rango de 0x2AAAAFFC a 0x2AAAAF9A

Número entero 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

Page 40: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

0x2AAAAF99 001 0 011 0 0x4E2AAABE 0x4E2AAABE No hay

0x2AAAAF98 000 0 011 0 0x4E2AAABE 0x4E2AAABE No hay

Caso 7: rango de 0x4AAAAFF8 a 0x4AAAAF30

Número entero 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

Page 41: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 42: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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:

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)

El código utilizado es:

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.

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]; }

Page 43: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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)

Page 44: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 45: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 46: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 47: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 48: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 49: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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:

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).

2.4 Operación Mul

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.

Page 50: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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:

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)

El código utilizado es:

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

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]; }

Page 51: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 52: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

0 1000 0010 1010 0000 0000 0000 0000 0001 0x41200001

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

bits)

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.

Page 53: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 54: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 55: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 56: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 57: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 58: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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).

Page 59: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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)

Page 60: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

El código utilizado es:

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

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]; }

Page 61: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 62: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 63: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 64: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 65: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Page 66: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

1,1' q ; q’ formada por -1 y 1

1,0'' q ; q’’ cambiando -1 por 0

1*2 '' qq

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)

Page 67: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 68: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 69: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 70: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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

Page 71: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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).

Page 72: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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) Mult DCM

Fil Col Total CLBs

XC3S1500 1.5M 29,952 64 52 3,328 32 32 4

XC3S2000 2M 46,080 80 64 5,120 40 40 4

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

Page 73: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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:

Frecuencia #pin FPGA Observaciones

66MHz AD13

100MHz A13

40MHz typ. AE14 Socket

- AE13 SMA

- AF14 Header

125MHz typ. C14, B14 No instalado por defecto

2.6.3 Memoria SRAM

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

Page 74: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

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.

Figura 39: Pantalla principal de la herramienta de desarrollo XPS

2.6.5 Comunicación R232

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.

Page 75: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Figura 40: Conector serie DB9

2.7 Resultados experimentales

A diferencia de los apartados donde se averigua el comportamiento de Microblaze

con la ayuda del entorno de simulación ModelSim, los resultados experimentales se

obtienen mediante la ejecución de varios programas en la placa de desarrollo AVnet

Spartan-3.

2.7.1 Comprobación funcional

Para la comprobación funcional se ha utilizado el programa del anexo 3.1.1. Este

programa tiene dos entradas que son los operandos A y B y consiste en la ejecución de

las intrucciones suma, resta, multiplicacion, división y entero a flotante analizadas en

este proyecto. Estas ejecuciones se hacen con los dos procesadores y los resultados de

las mismas operaciones realizadas con cada procesador se comparan entre ellos. Con la

ayuda de un bucle y variando los operandos, estas ejecuciones y comparaciones de

resultados se prolongarán hasta que se decida parar o hasta que se llegue a un límite de

ejecuciones predefinido. Cuando se encuentra una diferencia se guarda el valor de los

operandos y el resultado de la operación en un fichero de texto via puerto serie.

Ejecutando el programa con los dos procesadores se han encontrado diferencias

entre los resultados de las operaciones suma, resta, multiplicación y división cuando los

dos operandos tienen un valor muy pequeño. Si el operando a y b tienen el valor

0x00002030 el resultado que obtiene Microblaze al hacer la operación suma es un

NAN(0xFFC00000) y el caso de Copro el resultado es 0x00802030. A continuación se

va hacer el análisis númerico para aseguarar que el valor dado por Copro es correcto.

En este caso particular donde el operando A= 0x00002030 (0000 0000 0000 0000

0010 0000 0011 0000b) y el operando B= 0x00002030 (0000 0000 0000 0000 0010

0000 0011 0000b) se puede ver que |a|>=|b| con lo cual se obtienen los siguientes

valores:

Signo Exponente Mantisa Numero representado en

hexadecimal

0 0000 0000 1000 0000 0010 0000 0011 0000 0x00002030

0 0000 0000 1000 0000 0010 0000 0011 0000 0x00002030

Exp_absdif= exp_a = 0x00h=0d como que 0 no es > 25 Exp_absdif=0d

Sig_res= sig_a = 0

Exp_res = exp_a = 0x0h

Man_high= ‘0’& Man_high & ”000”= 0x4010180

Man_low= 0x802030

Page 76: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

En esta caso, como que Exp_absdif=0 no se hace ningún desplazamiento de la

man_low, por lo tanto, sticky bit=0.

Man_low_desplazada = Man_low &”000”

Man_low =’0’& 26 bits de más peso de la mantisa desplazada & sticky bit

Man_low = 0100 0000 0001 0000 0001 1000 0000 = 0x4010180

Man=Man_high + Man_low = 0x4010180+ 0x4010180= 0x8020300

Finalmente el número desnormalizado es: ‘0’&0x00&0x8020300.

Ahora, se tiene que normalizar el número pero esta vez se va a utilizar el método

de redondeo de Microblaze.

Mantisa desnormaliza=1000 0000 0010 0000 0011 0000 0000

Mantisa normalizada=1000 0000 0010 0000 0011 0000 0000no desplazamiento

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) del mismo modo que lo hace

Microblaze, es decir, no habra redondeo porque el conjunto de los bits R, G y SB es

inferior a 100.

Por tanto, la mantisa normalizada es 1000 0000 0010 0000 0011 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-0=0x1.

Una vez la mantisa y el exponente están normalizados se genera el resultado

normalizado de la operación 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 00000001 1000 0000 0010 0000 0011 0000 0x00802030

Para asegurar que el resultado de la suma realizada por Copro es correcto, se

recurrirá a una página web en la cual se pueden convertir de un modo muy sencillo un

número de representación decimal a otro de representación en coma flotante definido por

el estandar IEEE-754( http://www.h-schmidt.net/FloatApplet/IEEE754.html).

Utilizando el conversor de este sitio web se obtiene que el valor del operando A,

que es el mismo que el de B, es igual a 1.1547E-41 si se representa en decimal.

Seguidamente, si se hace la misma operación suma realizada por Copro con los

operandos A y B pero en formato decimal y utilizando un calculadora convencional, el

resultado es 2.3148E-41. Finalmente, si se vuelve a convertir el resultado decimal de la

suma a representación en coma flotante se obtiene el valor 0x00004087. Ahora,

comparando los dos resultados se ve a simple vista que el resultado de la suma realizada

por Copro es completamente diferente del resultado de la suma realizada con una

calculadora convencional y convirtiendo el resultado utilizando el sitio web mencionado

anteriormente, por lo tanto, se puede asegurar que para números cerecanos a cero Copro

no funciona correctamente y Microblaze devuelve un NAN. Volviendo al estándar IEEE

Page 77: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

754, el conjunto de valores posibles a representar el cual llamaremos clases se dividen

en:

ceros

números normalizados

números desnormalizados

infinitos

NaN (not a number)

Las clases se distinguen principalmente por el valor del campo Exp, siendo

modificada ésta por el campo mantisa. Se considera Exp y Mantisa como campos de

números binarios sin signo (Exp se encuentra en el rango 0–255):

Clase Exp Mantisa

Ceros 0 0

Números desnormalizados 0 distinto de 0

Números normalizados 1-254 cualquiera

Infinitos 255 0

NaN (Not a Number) 255 distinto de 0

Se puede ver que los operandos A y B pertenecen a la clase de números

desnormalizados ya que todos los bits del campo exponente valen 0 y la mantisa es

diferente de 0. Esto hace pensar que Microblaze no trabaja con valores tan pequeños, por

lo tanto, se deduce que si alguno de los operandos tiene el campo exponente a 0 y el

campo mantisa diferente de 0, Microblaze devuelve una NAN como resultado de la

operación. Esta hipótesis se va comprobar y demostras seguidamente con 3 graficas,

realizas con el simulador ModelSim, las cuales van a mostrar la operación suma

realizada por Microblaze cuando cualquiera de los operandos esta formado por un

número desnomalizado. En caso de que la hipótesis sea cierta, Copro se va a modicar

para que su comportamiento sea el mismo que el de Microblaze ya que se ha

comprobado que de momento no es asi y además, la operación relalizada por Copro es

incorrecta.

Figura 41: Señales de Microblaze cuando realiza la suma de 0x00002030 y 0x00002030.

Page 78: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Figura 42: Señales de Microblaze cuando realiza la suma de 0x00002030 y 0x40000000.

Figura 43: Señales de Microblaze cuando realiza la suma de 0x40000000 y 0x00002030.

Las figuras 41, 42 y 43 confirman la hipótesis propuesta anteriormente. Se puede

ver que si el operando A y/o el B contienen un valor desnormalizado definido por el

estándar IEEE 754, el resultado de la operación es un NAN. También se ha comprobado

del mismo modo que este comportamiento es igual si se realiza cualquier operación la

cual precise dos operandos. En cuanto a la operación entero-flotante, este problema no

existe porque el valor a convertir es un decimal y no un flotante. Esto significa no nunca

se podrá guardar un número de dimensiones tant pequeñas en un operando del tipo

entero, por lo tanto, no será necesaria tal comprobación en el caso de la operación

entero-flotante.

2.7.2 Comprobación de la acceleración

Para la comprobación de la acceleración se ha utilizado el programa del anexo

3.1.2. Este programa tiene dos entradas que son los operandos A y B y consiste en la

ejecución de las intrucciones suma, resta, multiplicacion, división y entero a flotante

analizadas en este proyecto y también la raiz cuadrada la cual no se ha visto en este

proyecto porque la FPU de Microblaze no la tiene implementada si no que se emula por

software. Estas ejecuciones se hacen con los dos procesadores y con la ayuda de un

bucle se ejecuta desde 1 operación hasta un total de 1000 operaciones por cada una de la

intrucciones ya que, con este número, es suficiente para ver el valor asintótico al que

tiende la aceleración en cada caso. El tiempo que tarda en hacer las ejecuciones se

guarda en un fichero de texto via puerto serie. Este tiempo esta representado en ciclos de

reloj que, en caso de la placa de desarrollo Avnet spartan-3 la cual trabaja a una

frecuencia de 50MHz, es de ns 2050

16 por ciclo. Los resultados obtenidos son los

siguientes:

Page 79: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Entero a flontante, Suma, Resta y Multiplicación

Int2f, Suma, Resta y Multiplicación

0

5000

10000

15000

20000

25000

30000

35000

40000

1

48

95

14

2

18

9

23

6

28

3

33

0

37

7

42

4

47

1

51

8

56

5

61

2

65

9

70

6

75

3

80

0

84

7

89

4

94

1

98

8

Operaciones

Tie

mp

o

Microblaze

Copro

Figura 44: Operaciones vs tiempo de ejecución de 1 hasta 1000

Int2f, Suma, Resta y Multiplicación

0

50

100

150

200

250

300

350

400

450

1 2 3 4 5 6 7 8 9

Operaciones

Tie

mp

o

Microblaze

Copro

Figura 45: Operaciones vs tiempo de ejecución de 1 hasta 10

Acceleración Int2f, Suma, Resta y Multiplicación

0

1

2

3

4

5

6

7

8

9

10

1 48 95 142 189 236 283 330 377 424 471 518 565 612 659 706 753 800 847 894 941 988

Operaciones

Acele

ració

n

Acceleración

Figura 46: Aceleración de Copro respecto Microblaze

Page 80: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

En las figuras 44 y 45 se puede ver que ejecutando una única operación

Microblaze es algo más rápido pero a medida que se incrementa el número de

operaciones ejecutadas, Copro se hace vuelve mucho más rápido. Básicamente, esto se

debe a que por cada operación el microprocesador softcore Microblaze tiene que leer los

operandos desde memoria, lanzar los comandos a la FPU, y escribir el resultado a

memoria decodificando en cada caso intrucciones de lenguaje máquina. Sin embargo, en

el caso de Copro esto no es asi ya que la circuiteria que tiene permite hacer operaciones

con los datos que hay en la memoria y escribir el resultado alli mismo sin la ayuda del

microprocesador, es decir, no es necesario decodificar intrucciones de lenguaje máquina

en cada operación realizada.

En la figura 46 se puede ver que la aceleración de Copro en caso de operaciones

entero a flotante, suma, resta y multiplicación es exponecial tendiendo a 9 a partir de

1000 operaciones, es decir, Copro es 9 veces más rápido que Microblaze a partir de 1000

operaciones.

División

División

0

10000

20000

30000

40000

50000

60000

70000

80000

90000

1

46

91

136

181

226

271

316

361

406

451

496

541

586

631

676

721

766

811

856

901

946

991

Operaciones

Tie

mp

o

Microblaze

Copro

Figura 47: Operaciones vs tiempo de ejecución de 1 hasta 1000

Page 81: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

División

0

100

200

300

400

500

600

700

800

900

1 2 3 4 5 6 7 8 9

Operaciones

Tie

mp

o

Microblaze

Copro

Figura 48: Operaciones vs tiempo de ejecución de 1 hasta 10

Acceleración División

0

0,5

1

1,5

2

2,5

3

1 48 95 142 189 236 283 330 377 424 471 518 565 612 659 706 753 800 847 894 941 988

Operaciones

Accele

ració

n

Acceleración

Figura 49: Aceleración de Copro respecto Microblaze

En las figuras 47 y 48 se puede ver en primer lugar que Copro es igual de rápido

que Microblaze al ejecutar una única operación, y en segundo lugar, que Copro no es tan

rápido como lo es en el caso de las operaciones conversión entero a flotatante, suma,

resta y multiplicación. Esto se debe a que las dos FPUs necesitan muchos ciclos de reloj

para realizar la división haciendo que el tiempo que necesita la FPU de Microblaze para

obtener los datos, lanzar comandos y escribir resultados en memoria no sea tan grande

respecto al tiempo de ejecución de la división

En la figura 49 se puede ver que la aceleración es de 2.7 aproximadamente en caso

de ejecutar 1000 o más operaciones.

Page 82: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Raiz cuadrada

Raiz

0

500000

1000000

1500000

2000000

2500000

1

47

93

139

185

231

277

323

369

415

461

507

553

599

645

691

737

783

829

875

921

967

Operaciones

Tie

mp

o

Microblaze

Copro

Figura 50: Operaciones vs tiempo de ejecución de 1 hasta 1000

Raiz

0

2000

4000

6000

8000

10000

12000

14000

16000

18000

20000

1 2 3 4 5 6 7 8 9

Operaciones

Tie

mp

o

Microblaze

Copro

Figura 51: Operaciones vs tiempo de ejecución de 1 hasta 10

Page 83: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

Acceleración Raiz

0

10

20

30

40

50

60

70

80

1 48 95 142 189 236 283 330 377 424 471 518 565 612 659 706 753 800 847 894 941 988

Operaciones

Accele

ració

n

Acceleración

Figura 52: Aceleración de Copro respecto Microblaze

En las figuras 50, 51, y 52 se puede ver claramente que Copro es muchísimo más

rápido que Microblaze y la aceleración esta por encima de 70 al ejecutar 1000

operaciones o más. Esto se debe a que Microblaze emula la operación raiz cuadrada en

todo momento.

2.8 Conclusiones

En los sistemas digitales con microprocesador un factor muy importante, y muchas

veces determinante, es la velocidad del sistema. En este trabajo se ha comprobado que la

VFPU llamada Copro es mucho más rápida la FPU de Microblaze. Esto básicamente se

debe a que las FPUs necesitan del microprocesador para leer y ejecutar las instrucciones

que permiten leer los operandos desde memoria, lanzar los comandos a la FPU, y

escribir el resultado a memoria. En cambio, las VFPUs son más autonomas ya que, una

vez el microprocesador configura el tipo de operación, las direcciones de los vectores y

su tamaño, estas acceden directamente a memoria leyendo los operandos y escribiendo

los resultados. Tambien se ha comprobado que cuando una operación se emula por

software en el microprocesador, como es el caso de la raiz cuadrada, el rendimiento de

este cae considerablemente.

2.9 Propuestas

Una mejora para un coprocesador matemático es ampliar el abanico de

operaciones que se pueden realizar. En este proyecto se han visto las operaciones de

conversión entero-flotante de un número, suma, resta, multiplicación y división pero no

se ha visto otras operaciones que Copro es capaz de realizar como son las operaciones de

comparación mayor que, menor que o igual que, valor absoluto y negación porque es

estos casos no es necesario redondear el número resultante ni hacer el cálculo del sticky

bit. Otra operación compleja que se puede realizar con Copro es la raíz cuadrada de un

número pero no se ha estudiado en detalle como las otras porque Microblaze no puede

realizar dicha operación con la FPU sino que lo hace por emulación de software. Las

operaciones con las cuales se podría ampliar el abanico de instrucciones de Copro son

operaciones exponenciales y también de senos y cosenos.

Otra mejora sería poder configurar la unidad de división y raiz cuadrada para

disminuir el número de ciclos de reloj requeridos. En la actual implementación se usa un

circuito de radix-2, al calcular un bit del resultado por ciclo de reloj. Se podría modificar

Page 84: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

para calcular dos o más bits por ciclo de reloj (radix-4, radix-8, etc.), acelerando el

cómputo. Sin embargo sería necesario estudiar con mayor detalle el incremento de área

requerida, y que el retardo del critical-path no supere el periodo del reloj del sistema (20

ns para 50 MHz).

Otra mejora es mejorar el throughput de los cálculos vectoriales con flotantes,

mediante una arquitectura de pipeline. La FPU que se encuentra insertada en la VFPU

está segmentada en 4 etapas para las operaciones de suma, resta, multiplicación y

conversión de entero a flotante, lo que permite ejecutar 4 cálculos diferentes

concurrentente por ciclo de reloj, y obtener obtener un nuevo resultado por cada ciclo de

reloj. Sin embargo, el circuito de control de la VFPU para el acceso a memoria y control

de la FPU, no permite en la actualidad aprovechar esta posibilidad que permitiría

multiplicar por 4 el throughput para las operaciones descritas anteriormente.

3 Anexos

3.1 Anexos de Software

3.1.1 Programa C utilizado en la comprobación funcional.

void test_5()

{

float *operando_A=(float*)0x2E0000;

float *operando_B=(float*)0x2D0000;

float *resultado_Copro=(float*)0x2C0000;

float *resultado_Microblaze;

int Operando_A_int,Operando_B_int;

operando_A[0]=tofloat(0x02000001);//valor inicial OpA en flotante

operando_B[0]=tofloat(0x01200001); //valor inicial OpB en flotante

xil_printf("Start\n\r");

xil_printf("\n\r");

do{

CoproFPU_VectorAddr((float*)p1,p3,p4);

CoproFPU_VectorOP(CoproFPU_INT2F,2,true);

xil_printf("OpeA: %x,OpeB: %x\n\r",(int&)a,(int&)b);

CoproFPU_VectorAddr(operando_A,operando_B,resultado_Copro);

//Operación SUMA Microblaze

*resultado_Microblaze=(*operando_A)+(*operando_B);

//Operación SUMA Copro

CoproFPU_VectorOP(CoproFPU_ADD,1,true);

Page 85: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

if ((*resultado_Microblaze)!=(*resultado_Copro))

{

xil_printf("Diferencias entre Copro y Microblaze

al realizar la operación SUMA\n\r");

xil_printf("OperandoA: %x, ",*(int*)operando_A);

xil_printf("OperandoB: %x\n\r",*(int*)operando_B);

xil_printf("Result Micro: %x\n\r",*(int*) resultado_Microblaze);

xil_printf("Result Copro: %x\n\r",*(int*) resultado_Copro);

xil_printf("\n\r");

}

//Operación RESTA Microblaze

*resultado_Microblaze=(*operando_A)-(*operando_B);

//Operación RESTA Copro

CoproFPU_VectorOP(CoproFPU_SUB,1,true);

if ((*resultado_Microblaze)!=(*resultado_Copro))

{

xil_printf("Diferencias entre Copro y Microblaze

al realizar la operación RESTA\n\r");

xil_printf("OperandoA: %x, ",*(int*)operando_A);

xil_printf("OperandoB: %x\n\r",*(int*)operando_B);

xil_printf("Result Micro: %x\n\r",*(int*) resultado_Microblaze);

xil_printf("Result Copro: %x\n\r",*(int*) resultado_Copro);

xil_printf("\n\r");

}

//Operación MULTIPLICACION Microblaze

*resultado_Microblaze=(*operando_A)*(*operando_B);

//Operación MULTIPLICACION Copro

CoproFPU_VectorOP(CoproFPU_MUL,1,true);

if ((*resultado_Microblaze)!=(*resultado_Copro))

{

xil_printf("Diferencias entre Copro y Microblaze

al realizar la operación MULTIPLICACIÓN\n\r");

Page 86: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

xil_printf("OperandoA: %x, ",*(int*)operando_A);

xil_printf("OperandoB: %x\n\r",*(int*)operando_B);

xil_printf("Result Micro: %x\n\r",*(int*) resultado_Microblaze);

xil_printf("Result Copro: %x\n\r",*(int*) resultado_Copro);

xil_printf("\n\r");

}

//Operacion DIVISION Microblaze

*resultado_Microblaze=(*operando_A)/(*operando_B);

//Operación DIVISION Copro

CoproFPU_VectorOP(CoproFPU_DIV,1,true);

if ((*resultado_Microblaze)!=(*resultado_Copro))

{

xil_printf("Diferencias entre Copro y Microblaze

al realizar la operación DIVISION\n\r");

xil_printf("OperandoA: %x, ",*(int*)operando_A);

xil_printf("OperandoB: %x\n\r",*(int*)operando_B);

xil_printf("Result Micro: %x\n\r",*(int*) resultado_Microblaze);

xil_printf("Result Copro: %x\n\r",*(int*) resultado_Copro);

xil_printf("\n\r");

}

//Incremento de los operandos

Operando_A_int=(*(int*)operando_A)+1;

Operando_B_int=(*(int*)operando_B)+1;

operando_A[0]=tofloat(Operando_A_int);

operando_B[0]=tofloat(Operando_A_int);

}while (1);//Bucle infinito

xil_printf("End\n\r");

xil_printf("\n\r");

}

3.1.2 Programa C utilizado en la comprobación de la aceleración.

void test_6()

{

int timer,repetitions;

int *p1=(int*)0x2F0000;

float *p2=(float*)0x2E0000;

Page 87: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

float *p3=(float*)0x2D0000;

float *p4=(float*)0x2C0000;

CoproFPU_VectorAddr(p2,p3,p4);

//llenar espacio reservado con los mimos valores

for (int j=0; j<1000; j++)

{

p2[j]=2.0;

p3[j]=1.3;

}

xil_printf("Start\n\r");

xil_printf("\n\r");

for (repetitions=1; repetitions<1000; repetitions++)

{

xil_printf("Nº Operations: %d",repetitions);

xil_printf("\n\r");

//Addition Microblaze

timer=0;

timer_clear_run(0);

timer_run(0);

for(int j=0; j<repetitions; j++)

{

p4[9]=p2[9]+p3[9];

}

timer=timer_stop_read(0);

xil_printf("Time for Microblaze Add operations: %d",timer);

xil_printf("\n\r");

//Addition Copro

timer=0;

timer_clear_run(0);

timer_run(0);

CoproFPU_VectorOP(CoproFPU_ADD,repetitions,true);

timer=timer_stop_read(0);

xil_printf("Time for Copro Add operations: %d",timer);

Page 88: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

xil_printf("\n\r");

//Substraccion Microblaze

timer=0;

timer_clear_run(0);

timer_run(0);

for(int j=0; j<repetitions; j++)

{

p4[9]=p2[9]-p3[9];

}

timer=timer_stop_read(0);

xil_printf("Time for Microblaze Sub operations: %d",timer);

xil_printf("\n\r");

//Substraccion Copro

timer=0;

timer_clear_run(0);

timer_run(0);

CoproFPU_VectorOP(CoproFPU_SUB,repetitions,true);

timer=timer_stop_read(0);

xil_printf("Time for Copro Sub operations: %d",timer);

xil_printf("\n\r");

//Multiplication Microblaze

timer=0;

timer_clear_run(0);

timer_run(0);

for(int j=0; j<repetitions; j++)

{

p4[9]=p2[9]*p3[9];

}

timer=timer_stop_read(0);

xil_printf("Time for Microblaze Mul operations: %d",timer);

xil_printf("\n\r");

Page 89: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

//Multiplication Copro

timer=0;

timer_clear_run(0);

timer_run(0);

CoproFPU_VectorOP(CoproFPU_MUL,repetitions,true);

timer=timer_stop_read(0);

xil_printf("Time for Copro Mul operations: %d",timer);

xil_printf("\n\r");

//Division Microblaze

timer=0;

timer_clear_run(0);

timer_run(0);

for(int j=0; j<repetitions; j++)

{

p4[j]=p2[j]/p3[j];

}

timer=timer_stop_read(0);

xil_printf("Time for Microblaze Div operations: %d",timer);

xil_printf("\n\r");

//Division Copro

timer=0;

timer_clear_run(0);

timer_run(0);

CoproFPU_VectorOP(CoproFPU_DIV,repetitions,true);

timer=timer_stop_read(0);

xil_printf("Time for Copro Div operations: %d",timer);

xil_printf("\n\r");

//Root Square Microblaze

timer=0;

timer_clear_run(0);

timer_run(0);

for(int j=0; j<repetitions; j++)

Page 90: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

{

p4[j]=sqrt(p2[j]);

}

timer=timer_stop_read(0);

xil_printf("Time for Microblaze Sqrt operations: %d",timer);

xil_printf("\n\r");

//Root Square Copro

timer=0;

timer_clear_run(0);

timer_run(0);

CoproFPU_VectorOP(CoproFPU_SQRT,repetitions,true);

timer=timer_stop_read(0);

xil_printf("Time for Copro Sqrt operations: %d",timer);

xil_printf("\n\r");

}

xil_printf("Stop\n\r");

xil_printf("\n\r");

}

3.1.3 Programa C utilizado en el desarrollo de las operaciones de int2f, suma, resta,

multiplicación y división. .

void test_7()

{

//Operando A para la conversion entero-flontate en Copro

const int a[2]={0x1AAAAFEF,0x01AAAFEF};

//Operandos A y B para las otras operaciones expresados en real

const float ax[10]={3,2,1000000.0625,-

3,7563.576,1177.356,16.8567,1027.3367,135.2587,0.7};

const float b[10]={2,3,10.0625,2,7.456,3.376,4.356,3.356,2.356,7.2156};

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];}

Page 91: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

for(int j=0; j<10; j++)

{p2[j]=ax[j];

p3[j]=b[j];}

//Operandos A y B para las otras operaciones expresados en flotante

/*p2[0]=tofloat(0x42F80000);

p3[0]=tofloat(0x40000000);

p2[1]=tofloat(0x4FFFFFF0);

p3[1]=tofloat(0x3F900002);

p2[2]=tofloat(0x42EEE000);

p3[2]=tofloat(0x40000003);

p2[3]=tofloat(0x42DDD000);

p3[3]=tofloat(0x40000004);

p2[4]=tofloat(0x42CCC000);

p3[4]=tofloat(0x40000002);

p2[5]=tofloat(0x42BBB000);

p3[5]=tofloat(0x40000004);

p2[6]=tofloat(0x42AAA000);

p3[6]=tofloat(0x40000002);

p2[7]=tofloat(0x42999000);

p3[7]=tofloat(0x4F800654);

p2[8]=tofloat(0x42888000);

p3[8]=tofloat(0x40800652);

p2[9]=tofloat(0x42777000);

p3[9]=tofloat(0x40800654);

Page 92: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

for(int j=0; j<10; j++)

{p4[j]=p2[j]+p3[j];

}

/*for(int j=0; j<10; j++)

{p4[j]=p2[j]-p3[j];

}

for(int j=0; j<10; j++)

{p4[j]=p2[j]*p3[j];

}

for(int j=0; j<10; j++)

{p4[j]=p2[j]/p3[j];

}*/

CoproFPU_VectorAddr((float*)p1,p3,p4);

//CoproFPU_VectorOP(CoproFPU_INT2F,2,true);

CoproFPU_VectorAddr(p2,p3,p4);

CoproFPU_VectorOP(CoproFPU_ADD,10,true);

//CoproFPU_VectorOP(CoproFPU_SUB,10,true);

//CoproFPU_VectorOP(CoproFPU_MUL,10,true);

//CoproFPU_VectorOP(CoproFPU_DIV,10,true);

}

3.2 Anexos de Hardware

3.2.1 Adaptación del código VHDL

Este anexo no contendrá el código VHDL completo sino el código que se ha

modificado de los ficheros hardware del siguiente modo. Si hay algún cambio en una

línea de código existente se podrá justo debajo la misma línea de código con el cambio

aplicado. Esta línea de código nueva será resaltada en rojo y entre paréntesis. Si lo que

se ha hecho es introducir alguna línea de código nueva, esta se resaltará en azul. En

cualquier caso anterior se añadirá el número de línea. Finalmente, si hay alguna línea de

código que ha sido eliminada completamente sin ser reemplazada, esta se resaltará en

púrpura.

3.2.1.1 Modificaciones en el fichero FPU_int2f.vhd

use IEEE.STD_LOGIC_UNSIGNED.ALL;

use IEEE.STD_LOGIC_ARITH.conv_std_logic_vector;

use IEEE.STD_LOGIC_MISC.ALL;línea 5

architecture beh2b of FPU_int2f is

subtype T_INDEX is integer range 0 to 3;

Page 93: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

(subtype T_INDEX is integer range 0 to 4;línea 34)

constant NBITS_INDEX: integer:=2;

(constant NBITS_INDEX: integer:=3;línea 35)

signal strt_s1,fin_s1: std_logic;

variable man: std_logic_vector(27 downto 0);

variable int,shfint: std_logic_vector(31 downto 0);

variable bitsperdidos: std_logic_vector(3 downto 0);línea 58

variable rshift: T_INDEX;

begin

man:=shfint(man'range);

De la línea 75 hasta la línea 84

if rshift>0 then --Si rshift>0 hacer el calculo del Sticky bit

bitsperdidos:=int(int'right+3 downto int'right);

case rshift is

when 1 => bitsperdidos:=bitsperdidos and "0001";

when 2 => bitsperdidos:=bitsperdidos and "0011";

when 3 => bitsperdidos:=bitsperdidos and "0111";

when others => null; --NO tocamos nada

end case;

man(0):=or_reduce(man(0)&bitsperdidos);

end if;

3.2.1.2 Modificaciones en el fichero FPU_addsubcmp.vhd

if not (rshift<3 or rshift>31) then

(if not (rshift<3) thenLínea 72)

for i in 0 to mant'left loop

if i+3<=rshift and mant(i)='1' then

(if i+3<rshift and mant(i)='1' then Línea 74)

if exp_absdif>=32 then

(if exp_absdif>=24 thenLínea 192)

exp_absdif:=conv_std_logic_vector(32,exp_absdif'length);

(exp_absdif:=conv_std_logic_vector(24,exp_absdif'length); Línea 193)

end if;

Page 94: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

De la línea 308 hasta la línea 310

if man (man’left=’1’) then

man(1):=man(1) or man(0);

end if;

3.2.1.3 Modificaciones en el fichero FPU_mul.vhd

variable r: std_logic_vector(47 downto 0);

variable man: std_logic_vector(27 downto 0);

variable sticky_bit_vector: std_logic_vector(20 downto 0); línea 140

begin

fin_s2<=strt_s2;--fin_s2<=fin_s12;

r3:=r2(13 downto 12)+ab11_s12(23 downto 12);

r:=r3 & r2(11 downto 0) & r1(11 downto 0) & r0;

man:=r(47 downto 20);

De la línea 156 hasta la línea 162

sticky_bit_vector:=r(20 downto 0);

if man(man'left)='1' then

man(1):=or_reduce(sticky_bit_vector);

else

sticky_bit_vector(20):='0';

man(0):=or_reduce(sticky_bit_vector);

end if;

3.2.1.4 Modificaciones en el fichero FPU_mul.vhd

signal stickybit_divsqrt: std_logic;

signal dec_exp: std_logic_vector(0 downto 0);Línea 49

begin

ST1B: process(op_a,op_b,mode,mode_divsqrt)

begin

stickybit_divsqrt<='0';

De la línea 124 hasta la línea 126

if mode_divsqrt='1' then

stickybit_divsqrt<='1';

end if;

end process;

Page 95: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

ST1C:

variable exp: std_logic_vector(7 downto 0);

variable exp_aux: std_logic_vector(7 downto 0);Línea 132

begin

strt_divsqrt<=strt_s1 and not fin_excep;

rst_divsqrt<=rst;

fin_s1<=qrdy_divsqrt;

exp:=exp_aux-dec_exp; Línea 137

res_s1<=sig & exp & ('0'&q_divsqrt);

tag_s1<=strt_tag;

if rising_edge(clk) and strt_divsqrt='1' then

sig:=sig_s1;

exp_aux:=exp_s1; Línea 146

end if;

end process;

ST2_0: if FPU_DIVISION_ZEROSHIFT=0 generate ST2: process

variable cmp: std_logic_vector(r'left+1 downto r'right);

variable r_first_24_bits: std_logic_vector(26 downto 3); Línea 159

variable rdy,busy,qready,mode,stickybit: std_logic;

begin

case estado is

when ESPERA =>

if strt_divsqrt='1' and busy='0' then

stickybit:=stickybit_divsqrt;

estado:=COMPARA;

if mode='0' then -- division

one:=(one'left=>'1', others=>'0');

b:="00" & b_divsqrt;

dec_exp<=(others=>'0'); Línea 179

end if;

end if;

when COMPARA =>

cmp:=('0'&r)-('0'&b);

if mode='0' then -- division

Page 96: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

if cmp(cmp'left)='1' then

--q:=q;

else

q:=q or one;

r:=cmp(r'range);

end if;

De la línea 199 hasta la línea 210

r_first_24_bits:=r(r_first_24_bits'range);

if r_first_24_bits=X"000000" then

stickybit:='0';

else

stickybit:='1';

end if;

if index=T_INDEX'high and cmp(cmp'left)='1' then

--NO shr one

else

one:=shr(one,"1");

end if;

r:=shl(r,"1");

end if;

if index=T_INDEX'low or cmp=0 then

busy:='1'; qready:='1'; estado:=ESPERA;

else

De la línea 229 hasta la línea 233

if index=T_INDEX'high and cmp(cmp'left)='1' then

dec_exp<=(others=>'1');

else

index:=index-1;

end if;

end if;

end case;

3.2.1.5 Modificaciones en el fichero FPU_norm.vhd

function RoundBit(a: std_logic_vector; constant n: integer) return std_logic is

variable slc,cmp: std_logic_vector(n-1 downto 0);

Page 97: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

variable round: std_logic:='0';

begin

if ROUND_METHOD=1 then

cmp(cmp'left):='1'; cmp(cmp'left-1 downto cmp'right):=(others=>'0');

slc:=a(a'right+n-1 downto a'right);

slc:=a(a'right+n downto a'right+1);Línea 90

if slc>cmp then

round:='1';

end if;

De la línea 94 hasta la línea 96

if slc=cmp and a(4)='1' then

round:='1';

end if;

end if;

return round;

end function;

begin

ST2: process(strt_s2,exp_res_s12,man_val_s12,index_s12,sig_s12,tag_s12)

variable round_bit,sig: std_logic;

begin

man_ext:=BarrelLShift(man_val_s12,index_s12);

round_bit:=RoundBit(man_ext,4);

round_bit:=RoundBit(man_ext,3); Línea 183

man:=man_ext(man'range)+round_bit;

end process;

3.2.1.6 Modificaciones en el fichero FPU_alu.vhd

scan_a: process(op_a)

begin

op_a_status<=FOK;

if op_a(30 downto 0)=0 then

op_a_status<=FZERO;

end if;

if op_a(30 downto 23)=255 then

if op_a(22 downto 0)=0 then

op_a_status<=FINF;

Page 98: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

else

op_a_status<=FNAN;

end if;

end if;

De la línea 269 hasta la línea 273

if op_a(30 downto 23)=0 and op_a(22 downto 0)>0 then

op_a_status<=FNAN;

end if;

end process;

scan_b: process(op_b)

begin

op_b_status<=FOK;

if op_b(30 downto 0)=0 then

op_b_status<=FZERO;

end if;

if op_b(30 downto 23)=255 then

if op_b(22 downto 0)=0 then

op_b_status<=FINF;

else

op_b_status<=FNAN;

end if;

end if;

De la línea 288 hasta la línea 290

if op_b(30 downto 23)=0 and op_b(22 downto 0)>0 then

op_b_status<=FNAN;

end if;

end process;

3.2.2 Código VHDL completo

Este anexo contendrá el código VHDL completo de los ficheros hardware.

3.2.2.1 Fichero FPU_int2f.vhd

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

use IEEE.STD_LOGIC_ARITH.conv_std_logic_vector;

Page 99: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

use IEEE.STD_LOGIC_MISC.ALL;

library copro_fpu_v2_00_b;

use copro_fpu_v2_00_b.FPU_pack_configuration.all;

use copro_fpu_v2_00_b.FPU_pack_defines.all;

entity FPU_int2f is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req : in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a: in std_logic_vector(31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

res: out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end entity;

architecture beh2b of FPU_int2f is

subtype T_INDEX is integer range 0 to 4;

constant NBITS_INDEX: integer:=3;

signal strt_s1,fin_s1: std_logic;

signal res_s1: std_logic_vector(res'range);

signal res_status_s1: T_FLOAT;

Page 100: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

function RSHIFT_IDX(a: std_logic_vector(31 downto 0)) return T_INDEX is

variable idx: T_INDEX:=0;

begin

for i in 1 to T_INDEX'high loop

if a(a'left-1-T_INDEX'high+i)='1' then

idx:=i;

end if;

end loop;

return idx;

end function;

begin

ST1: process(strt_s1,op_a,fin_s1)

variable sig: std_logic;

variable exp: std_logic_vector(7 downto 0);

variable man: std_logic_vector(27 downto 0);

variable int,shfint: std_logic_vector(31 downto 0);

variable bitsperdidos: std_logic_vector(3 downto 0);

variable rshift: T_INDEX;

begin

fin_s1<=strt_s1;

if fin_s1='1' then

sig:=op_a(31);

if sig='1' then

int:=0-op_a;

else

int:=op_a;

end if;

rshift:=RSHIFT_IDX(int);

exp:=conv_std_logic_vector(127+26+rshift,exp'length);

shfint:=shr(int,conv_std_logic_vector(rshift,NBITS_INDEX));

man:=shfint(man'range);

Page 101: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

if rshift>0 then --Si rshift>0 hacer el calculo del Sticky bit

bitsperdidos:=int(int'right+3 downto int'right);

case rshift is

when 1 => bitsperdidos:=bitsperdidos and "0001";

when 2 => bitsperdidos:=bitsperdidos and "0011";

when 3 => bitsperdidos:=bitsperdidos and "0111";

when others => null; --NO tocamos nada

end case;

man(0):=or_reduce(man(0)&bitsperdidos);

end if;

else

sig:='X';

exp:=(others=>'X');

man:=(others=>'X');

end if;

res_status_s1<=FOK;

res_s1<=sig & exp & man;

if fin_s1='1' and Is_X(op_a)=false then assert int(31)='0'

report "Error in int2f" severity failure; end if;

end process;

handshake: block

begin

res<=res_s1;

res_status<=res_status_s1;

strt_s1<=strt_req and op_a_rdy;

strt_ack<=res_ack;

op_a_ack<=res_ack;

res_tag<=strt_tag;

res_rdy<=fin_s1;

end block;

Page 102: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

end architecture;

3.2.2.2 Fichero FPU_addsubcmp.vhd

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

use IEEE.STD_LOGIC_ARITH.conv_std_logic_vector;

library copro_fpu_v2_00_b;

use copro_fpu_v2_00_b.FPU_pack_configuration.all;

use copro_fpu_v2_00_b.FPU_pack_defines.all;

entity FPU_addsubcmp is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

mode: T_MODE_ADDSUBCMP;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req : in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a_status : in T_FLOAT;

op_a : in std_logic_vector(31 downto 0);

op_b_rdy: in std_logic;

op_b_ack: out std_logic;

op_b_status : in T_FLOAT;

op_b : in std_logic_vector(31 downto 0);

cmp_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

cmp: out std_logic_vector(31 downto 0);

cmp_rdy: out std_logic;

cmp_ack: in std_logic;

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

Page 103: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

res : out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end entity;

architecture beh2b of FPU_addsubcmp is

constant STAGES: integer:=FPU_ADDSUB_STAGES;

signal res_addsub_s2,res_addsub_excep: std_logic_vector(36 downto 0);

signal res_cmp: std_logic_vector(31 downto 0);

signal man_high_s1,man_high_s12: std_logic_vector(22+1 downto 0);

signal man_low_s1,man_low_s12: std_logic_vector(22+1 downto 0);

signal sig_res_s1,sig_res_s12: std_logic;

signal exp_res_s1,exp_res_s12: std_logic_vector(7 downto 0);

signal exp_dif_s1,exp_dif_s12: std_logic_vector(5 downto 0);

signal mode_subNadd,mode_cmp,mode_subNadd_s1,mode_subNadd_s12: std_logic;

signal cmp_agtb_excep,cmp_aeqb_excep,cmp_agtb_s1,cmp_aeqb_s1: std_logic;

signal fin_addsub_s1,fin_addsub_s12,fin_addsub_s2: std_logic;

signal fin_cmp_s1,fin_excep: std_logic;

signal status_addsub_excep,status_addsub_s2: T_FLOAT;

signal strt_s1,strt_s2: std_logic;

signal tag_cmp,tag_addsub_excep,tag_s2,tag_s1,tag_s12:

std_logic_vector(res_tag'range);

function STICKYBIT(mant,rshift: std_logic_vector) return std_logic is

variable sticky: std_logic:='0';

begin

if FPU_ADDSUB_ENABLE_STICKYBIT=1 then

if not (rshift<3) then

for i in 0 to mant'left loop

if i+3<rshift and mant(i)='1' then

sticky:='1';

end if;

end loop;

end if;

end if;

return sticky;

Page 104: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

end function;

begin

ST1D: process(mode)

begin

case mode is

when FADD=> mode_subNadd<='0'; mode_cmp<='0';

when FSUB=> mode_subNadd<='1'; mode_cmp<='0';

when others=> mode_subNadd<='X'; mode_cmp<='1';

end case;

end process;

ST1A: process(op_a_status,op_b_status,op_a,op_b,strt_s1,tag_s1)

variable man_excep: std_logic_vector(27 downto 0);

variable exp_excep: std_logic_vector(7 downto 0);

variable sig_a,sig_b,sig_excep: std_logic;

begin

sig_a:=op_a(31);

sig_b:=op_b(31);

status_addsub_excep<=FOK;

cmp_agtb_excep<='X'; cmp_aeqb_excep<='X';

sig_excep:='X';

exp_excep:=(others=>'X');

man_excep:=(others=>'X');

fin_excep<='0';

if op_a_status=FINF then

status_addsub_excep<=FINF; --si alguno es INF resultado=INF

cmp_agtb_excep<=not sig_a; cmp_aeqb_excep<='0';

sig_excep:=sig_a;

fin_excep<=strt_s1;

end if;

if op_b_status=FINF then

status_addsub_excep<=FINF; --si alguno es INF resultado=INF

cmp_agtb_excep<=sig_b; cmp_aeqb_excep<='0';

sig_excep:=sig_b;

fin_excep<=strt_s1;

Page 105: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

end if;

if op_a_status=FINF and op_b_status=FINF then

if sig_a=sig_b then

status_addsub_excep<=FINF;--si ambos son INF con mismo signo

cmp_agtb_excep<='0'; cmp_aeqb_excep<='1';

sig_excep:=sig_a;

fin_excep<=strt_s1;

else

status_addsub_excep<=FNAN;--si ambos son INF con diferente signo

cmp_agtb_excep<=sig_b; cmp_aeqb_excep<='0';

sig_excep:='0';

fin_excep<=strt_s1;

end if;

end if;

if op_a_status=FNAN or op_b_status=FNAN then

status_addsub_excep<=FNAN;--si alguno es NaN el resultado es NaN

cmp_agtb_excep<='0'; cmp_aeqb_excep<='0';

sig_excep:='0';

fin_excep<=strt_s1;

end if;

tag_addsub_excep<=tag_s1;

res_addsub_excep<=sig_excep & exp_excep & man_excep;

end process;

ST1B:

process(mode_cmp,strt_tag,strt_s1,fin_excep,op_a,op_b,mode_subNadd,op_a_status,op

_b_status)

variable sig_a,sig_b,sig_dif,sig_res,agtb,aeqb: std_logic;

variable exp_a,exp_b,exp_high: std_logic_vector(7 downto 0);

variable exp_dif,exp_absdif,testa,testb: std_logic_vector(7+1 downto 0);

variable man_a,man_b: std_logic_vector(22+1 downto 0);

variable man_high,man_low: std_logic_vector(22+1 downto 0);

variable man_dif: std_logic_vector(22+2 downto 0);

variable hidebit_a,hidebit_b: std_logic;

begin

fin_addsub_s1<=not mode_cmp and strt_s1 and not fin_excep;

Page 106: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

fin_cmp_s1<=mode_cmp and strt_s1;-- and not fin_excep;

if op_a_status=FZERO then hidebit_a:='0'; else hidebit_a:='1'; end if;

if op_b_status=FZERO then hidebit_b:='0'; else hidebit_b:='1'; end if;

sig_a:=op_a(31);

sig_b:=op_b(31);

sig_dif:=sig_a xor sig_b;

exp_a:=op_a(30 downto 23);

exp_b:=op_b(30 downto 23);

testa:='0'&exp_a;

testb:='0'&exp_b;

exp_dif:=('0'&exp_a)-('0'&exp_b);

man_a:=hidebit_a&op_a(22 downto 0);

man_b:=hidebit_b&op_b(22 downto 0);

man_dif:=('0'&man_a)-('0'&man_b);

if exp_dif(exp_dif'left)='1' or (exp_dif=0 and man_dif(man_dif'left)='1') then

exp_absdif:=0-exp_dif;

man_high:=man_b;

--status_high:=status_b;

man_low:=man_a;

--status_low:=status_a;

--man_low_notzero:=hide_bit_b;

exp_high:=exp_b;

sig_res:=(not mode_subNadd and sig_b) or (mode_subNadd and not

sig_b);

else

exp_absdif:=exp_dif;

man_high:=man_a;

--status_high:=status_a;

man_low:=man_b;

--status_low:=status_b;

--man_low_notzero:=hide_bit_a;

exp_high:=exp_a;

sig_res:=sig_a;

end if;

if exp_absdif>=24 then

Page 107: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

exp_absdif:=conv_std_logic_vector(24,exp_absdif'length);

end if;

cmp_aeqb_s1<='0';

cmp_agtb_s1<='0';

if sig_dif='1' then

cmp_agtb_s1<=sig_b;

elsif exp_dif(exp_dif'left)='1' then

cmp_agtb_s1<=sig_b;

elsif exp_dif/=0 then

cmp_agtb_s1<=not sig_b;

elsif man_dif(man_dif'left)='1' then

cmp_agtb_s1<=sig_b;

elsif man_dif/=0 then

cmp_agtb_s1<=not sig_b;

else

cmp_agtb_s1<='0';

cmp_aeqb_s1<='1';

end if;

man_high_s1<=man_high;

man_low_s1<=man_low;

exp_dif_s1<=exp_absdif(exp_dif_s1'range);

exp_res_s1<=exp_high;

sig_res_s1<=sig_res;

mode_subNadd_s1<=(not mode_subNadd and sig_dif) or (mode_subNadd and

not sig_dif);

tag_s1<=strt_tag;

end process;

ST1C:

process(cmp_agtb_s1,cmp_aeqb_s1,cmp_agtb_excep,cmp_aeqb_excep,fin_excep,mode,

op_a,op_b,tag_s1)

variable agtb,aeqb: std_logic;

variable bitres: std_logic;

begin

agtb:=cmp_agtb_s1; aeqb:=cmp_aeqb_s1;

Page 108: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

if fin_excep='1' then

agtb:=cmp_agtb_excep; aeqb:=cmp_aeqb_excep;

end if;

case mode is

when FEQU=> bitres:=aeqb;

when FHIG=> bitres:=agtb;

when FHEQ=> bitres:=aeqb or agtb;

when FNEQ=> bitres:=not aeqb;

when FLWR=> bitres:=not(aeqb or agtb);

when FLEQ=> bitres:=not agtb;

when others=> bitres:='X';

end case;

case mode is

when FMAX|FMIN=>

res_cmp<=op_a;

if (mode=FMAX and agtb='0')or(mode=FMIN and agtb='1') then

res_cmp<=op_b;

end if;

when others=>

res_cmp<=(24=>bitres, 16=>bitres, 8=>bitres, 0=>bitres, others=>'0');

end case;

tag_cmp<=tag_s1;

end process;

ST1toST2_1: if STAGES=1 generate

process(man_high_s1,man_low_s1,exp_dif_s1,exp_res_s1,sig_res_s1,mode_subNadd_s

1,tag_s1)

begin

man_high_s12<=man_high_s1;

man_low_s12<=man_low_s1;

exp_dif_s12<=exp_dif_s1;--man_low_stickybit_s12<=man_low_stickybit_s1;

exp_res_s12<=exp_res_s1;

sig_res_s12<=sig_res_s1;

mode_subNadd_s12<=mode_subNadd_s1;

tag_s12<=tag_s1;

end process; end generate;

Page 109: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

ST1toST2_2: if STAGES=2 generate process

begin

wait until rising_edge(clk);

if fin_addsub_s1='1' then

man_high_s12<=man_high_s1;

man_low_s12<=man_low_s1;

exp_dif_s12<=exp_dif_s1;--man_low_stickybit_s12<=man_low_stickybit_s1;

exp_res_s12<=exp_res_s1;

sig_res_s12<=sig_res_s1;

mode_subNadd_s12<=mode_subNadd_s1;

tag_s12<=tag_s1;

end if;

end process; end generate;

ST2:

process(strt_s2,exp_res_s12,exp_dif_s12,man_high_s12,man_low_s12,sig_res_s12,mod

e_subNadd_s12,tag_s12)

variable man_low_ext: std_logic_vector(26 downto 0);

variable man,man_high,man_low: std_logic_vector(27 downto 0);

variable man_low_stickybit: std_logic;

begin

fin_addsub_s2<=strt_s2;--fin_addsub_s12;

man_high:=("0"&man_high_s12&"000");

man_low_stickybit:=STICKYBIT(man_low_s12,exp_dif_s12);

man_low_ext:=shr(man_low_s12&"000",exp_dif_s12

man_low:=('0'&man_low_ext(26 downto 1)&man_low_stickybit);

if mode_subNadd_s12='0' then

man:=man_high+man_low;

else

man:=man_high-man_low;

end if;

if man (man’left=’1’) then

man(1):=man(1) or man(0);

end if;

res_addsub_s2<=sig_res_s12 & exp_res_s12 & man;

Page 110: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

status_addsub_s2<=FOK;

tag_s2<=tag_s12;

end process;

handshake: block

signal state_busy_s1,strt_req_s1,strt_ack_s1,res_rdy_s1,res_ack_s1: std_logic;

signal state_busy_s2,strt_req_s2,strt_ack_s2,res_rdy_s2,res_ack_s2: std_logic;

begin

strt_ack<=res_ack when fin_excep='1' else strt_ack_s1;

op_a_ack<=res_ack when fin_excep='1' else strt_ack_s1;

op_b_ack<=res_ack when fin_excep='1' else strt_ack_s1;

res_tag<=tag_addsub_excep when fin_excep='1' else tag_s2;

res_rdy<=fin_excep when fin_excep='1' else res_rdy_s2;

res_status<=status_addsub_excep when fin_excep='1' else status_addsub_s2;

res<=res_addsub_excep when fin_excep='1' else res_addsub_s2;

cmp_tag<=tag_cmp;

cmp_rdy<=fin_cmp_s1;

cmp<=res_cmp;

strt_req_s1<=strt_req;

strt_s1<=strt_req_s1 and op_a_rdy and op_b_rdy and not state_busy_s1;

strt_ack_s1<=strt_s1;

res_rdy_s1<=fin_addsub_s1 or fin_cmp_s1 or fin_excep;

res_ack_s1<=(res_ack_s2 and not mode_cmp) or (cmp_ack and mode_cmp

strt_req_s2<=state_busy_s1;

strt_s2<=strt_req_s2 and not state_busy_s2;

strt_ack_s2<=strt_s2 ;

res_rdy_s2<=fin_addsub_s2;

res_ack_s2<=res_ack;

state_busy_s2<='0';

handshake_1: if STAGES=1 generate

state_busy_s1<='0';

end generate;

handshake_2: if STAGES=2 generate process

begin

wait until rising_edge(clk);

Page 111: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

if rst='1' then

state_busy_s1<='0';

elsif fin_addsub_s1='1' then

state_busy_s1<='1';

elsif res_ack_s1='1' then

state_busy_s1<='0';

end if;

end process; end generate;

end block;

end architecture;

3.2.2.3 Fichero FPU_mul.vhd

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

library copro_fpu_v2_00_b;

use copro_fpu_v2_00_b.FPU_pack_configuration.all;

use copro_fpu_v2_00_b.FPU_pack_defines.all;

use IEEE.STD_LOGIC_MISC.ALL;

entity FPU_mul is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req: in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a_status: in T_FLOAT;

op_a: in std_logic_vector(31 downto 0);

op_b_rdy: in std_logic;

op_b_ack: out std_logic;

op_b_status : in T_FLOAT;

Page 112: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

op_b: in std_logic_vector(31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

res: out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end entity;

architecture beh2b of FPU_mul is

constant STAGES: integer:=FPU_MULTIPLIER_STAGES;

signal fin_s1,fin_s12,fin_s2,fin_s,fin_excep: std_logic;

signal signo_s1,signo_s12: std_logic;

signal ab00_s1,ab01_s1,ab10_s1,ab11_s1,ab00_s12,ab01_s12,ab10_s12,ab11_s12:

std_logic_vector(23 downto 0);

signal exp_s1,exp_s12: std_logic_vector(7 downto 0);

signal res_s2,res_excep: std_logic_vector(36 downto 0);

signal status_s2,status_excep: T_FLOAT;

signal strt_s1,strt_s2: std_logic;

signal tag_s1,tag_s12,tag_s2,tag_excep: std_logic_vector(res_tag'range);

begin

ST1A: process(op_a_status,op_b_status,signo_s1,strt_s1,tag_s1)

variable man_excep: std_logic_vector(27 downto 0);

variable exp_excep: std_logic_vector(7 downto 0);

variable sig_excep: std_logic;

begin

status_excep<=FOK;

sig_excep:=signo_s1;

exp_excep:=(others=>'X');

man_excep:=(others=>'X');

fin_excep<='0';

if op_a_status=FINF or op_b_status=FINF then

status_excep<=FINF; --si uno o los dos son INF hay que mirar los signos

fin_excep<=strt_s1;

Page 113: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

end if;

if op_a_status=FZERO or op_b_status=FZERO then

status_excep<=FZERO;-- si alguno es cero el resultado es cero

fin_excep<=strt_s1;

end if;

if (op_a_status=FINF and op_b_status=FZERO) or (op_a_status=FZERO and

op_b_status=FINF) then

status_excep<=FNAN;--si uno es cero y el otro INF el resultado es NaN

fin_excep<=strt_s1;

end if;

if op_a_status=FNAN or op_b_status=FNAN then

status_excep<=FNAN; --si uno es NaN el resultado es NaN

fin_excep<=strt_s1;

end if;

res_excep<=sig_excep & exp_excep & man_excep;

tag_excep<=tag_s1;

end process;

ST1B: process(op_a,op_b,strt_s1,fin_excep,strt_tag)

variable a,b: std_logic_vector(11 downto 0);

variable exp_a,exp_b: std_logic_vector(7 downto 0);

begin

fin_s1<=strt_s1 and not fin_excep;

a:=op_a(11 downto 0);

b:=op_b(11 downto 0);

ab00_s1<=a*b;

a:='1'&op_a(22 downto 12);

b:=op_b(11 downto 0);

ab10_s1<=a*b;

a:=op_a(11 downto 0);

b:='1'&op_b(22 downto 12);

ab01_s1<=a*b;

a:='1'&op_a(22 downto 12);

b:='1'&op_b(22 downto 12);

ab11_s1<=a*b;

Page 114: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

exp_a:=op_a(30 downto 23);

exp_b:=op_b(30 downto 23);

exp_s1<=exp_a+exp_b-127;--ojo puede dar overflow

signo_s1<=op_a(31) xor op_b(31);

tag_s1<=strt_tag;

end process;

ST1toST2_1: if STAGES=1 generate

process(ab00_s1,ab10_s1,ab01_s1,ab11_s1,exp_s1,signo_s1,tag_s1)

begin

ab00_s12<=ab00_s1;

ab10_s12<=ab10_s1;

ab01_s12<=ab01_s1;

ab11_s12<=ab11_s1;

exp_s12<=exp_s1;

signo_s12<=signo_s1;

tag_s12<=tag_s1;

end process; end generate;

ST1toST2_2: if STAGES=2 generate process

begin

wait until rising_edge(clk);

if fin_s1='1' then

ab00_s12<=ab00_s1;

ab10_s12<=ab10_s1;

ab01_s12<=ab01_s1;

ab11_s12<=ab11_s1;

exp_s12<=exp_s1;

signo_s12<=signo_s1;

tag_s12<=tag_s1;

end if;

end process; end generate;

ST2:

process(strt_s2,ab00_s12,ab01_s12,ab10_s12,ab11_s12,exp_s12,signo_s12,tag_s12)

variable r0,r3: std_logic_vector(11 downto 0);

Page 115: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

variable r1,r2: std_logic_vector(13 downto 0);

variable r: std_logic_vector(47 downto 0);

variable man: std_logic_vector(27 downto 0);

variable sticky_bit_vector: std_logic_vector(20 downto 0);

begin

fin_s2<=strt_s2;--fin_s2<=fin_s12;

r0:=ab00_s12(11 downto 0);

r1:=("00"&ab00_s12(23 downto 12))+("00"&ab01_s12(11 downto

0))+("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;

man:=r(47 downto 20);

sticky_bit_vector:=r(20 downto 0);

if man(man'left)='1' then

man(1):=or_reduce(sticky_bit_vector);

else

sticky_bit_vector(20):='0';

man(0):=or_reduce(sticky_bit_vector);

end if;

res_s2<=signo_s12 & exp_s12 & man;

status_s2<=FOK;

tag_s2<=tag_s12;

end process;

handshake: block

signal state_busy_s1,strt_req_s1,strt_ack_s1,res_rdy_s1,res_ack_s1: std_logic;

signal state_busy_s2,strt_req_s2,strt_ack_s2,res_rdy_s2,res_ack_s2: std_logic;

begin

strt_ack<=strt_ack_s1;

op_a_ack<=strt_ack_s1;

op_b_ack<=strt_ack_s1;

res_tag<=tag_excep when fin_excep='1' else tag_s2;

res_status<=status_excep when fin_excep='1' else status_s2;

res_rdy<=fin_excep when fin_excep='1' else res_rdy_s2;

Page 116: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

res<=res_excep when fin_excep='1' else res_s2;

strt_req_s1<=strt_req;

strt_s1<=strt_req_s1 and op_a_rdy and op_b_rdy and not state_busy_s1;

strt_ack_s1<=strt_s1;

res_rdy_s1<=fin_s1 or fin_excep;

res_ack_s1<=res_ack_s2;

strt_req_s2<=state_busy_s1;

strt_s2<=strt_req_s2 and not state_busy_s2;

strt_ack_s2<=strt_s2 ;

res_rdy_s2<=fin_s2;

res_ack_s2<=res_ack;

state_busy_s2<='0';

handshake_1: if STAGES=1 generate

state_busy_s1<='0';

end generate;

handshake_2: if STAGES=2 generate process

begin

wait until rising_edge(clk);

if rst='1' then

state_busy_s1<='0';

elsif fin_s1='1' then

state_busy_s1<='1';

elsif res_ack_s1='1' then

state_busy_s1<='0';

end if;

end process; end generate;

end block;

end architecture;

3.2.2.4 Fichero FPU_divsqrt.vhd

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

library copro_fpu_v2_00_b;

use copro_fpu_v2_00_b.FPU_pack_configuration.all;

use copro_fpu_v2_00_b.FPU_pack_defines.all;

Page 117: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

entity FPU_divsqrt is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

mode: in T_MODE_DIVSQRT;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req: in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a_status: in T_FLOAT;

op_a: in std_logic_vector(31 downto 0);

op_b_rdy: in std_logic;

op_b_ack: out std_logic;

op_b_status : in T_FLOAT;

op_b: in std_logic_vector(31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

res: out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end entity;

architecture beh2b of FPU_divsqrt is

signal status_excep,status_s1: T_FLOAT;

signal exp_s1: STD_LOGIC_VECTOR (7 downto 0);

signal res_excep,res_s1: std_logic_vector(36 downto 0);

signal strt_s1,fin_excep,fin_s1,sig_s1,res_ack_s1,busy_s1: std_logic;

signal rst_divsqrt, strt_divsqrt, rdy_divsqrt, qrdy_divsqrt, qack_divsqrt, mode_divsqrt,

a_oddexp_divsqrt: std_logic;

signal a_divsqrt,b_divsqrt: std_logic_vector(23 downto 0);

Page 118: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

signal q_divsqrt: std_logic_vector(23+3 downto 0);--2 bits adicionales + sticky_bit

signal stickybit_divsqrt: std_logic;

signal dec_exp: std_logic_vector(0 downto 0);--Decrementar exponente si la primera

resta de r-b da negativa.

signal tag_s1,tag_excep: std_logic_vector(res_tag'range);

begin

ST1A: process(op_a_status,op_b_status,strt_s1,mode,op_a(31),op_b(31),tag_s1)

variable man_excep: std_logic_vector(27 downto 0);

variable exp_excep: std_logic_vector(7 downto 0);

variable sig_excep: std_logic;

begin

status_excep<=FOK;

exp_excep:=(others=>'X');

man_excep:=(others=>'X');

fin_excep<='0';

if mode=FDIV then

sig_excep:=op_a(31) xor op_b(31);

if op_a_status=FZERO or op_b_status=FINF then

status_excep<=FZERO;

fin_excep<=strt_s1;

end if;

if op_a_status=FINF or op_b_status=FZERO then

status_excep<=FINF;

fin_excep<=strt_s1;

end if;

if op_a_status=FZERO and op_b_status=FZERO then

status_excep<=FNAN;

fin_excep<=strt_s1;

end if;

if op_a_status=FINF and op_b_status=FINF then

status_excep<=FNAN;

fin_excep<=strt_s1;

end if;

if op_a_status=FNAN or op_b_status=FNAN then

Page 119: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

status_excep<=FNAN;

fin_excep<=strt_s1;

end if;

end if;

if mode=FSQRT then

sig_excep:='0';

if op_a_status=FZERO then

status_excep<=FZERO;

fin_excep<=strt_s1;

end if;

if op_a_status=FINF then

status_excep<=FINF;

fin_excep<=strt_s1;

end if;

if op_a_status=FNAN or op_a(31)='1' then

status_excep<=FNAN;

fin_excep<=strt_s1;

end if;

end if;

res_excep<=sig_excep & exp_excep & man_excep;

tag_excep<=tag_s1;

end process;

ST1B: process(op_a,op_b,mode,mode_divsqrt)

variable div_exp,sqrt_exp: std_logic_vector(7 downto 0);

begin

if mode=FSQRT then mode_divsqrt<='1'; else mode_divsqrt<='0'; end if;

div_exp:=op_a(30 downto 23)-op_b(30 downto 23);

sqrt_exp:=shr(op_a(30 downto 23)+1,"1");

a_divsqrt<='1'&op_a(22 downto 0);

b_divsqrt<='1'&op_b(22 downto 0);

a_oddexp_divsqrt<=not op_a(23);

if mode_divsqrt='0' then

sig_s1<=op_a(31) xor op_b(31);

exp_s1<=div_exp+127;--ojo que puede dar overflow

Page 120: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

else

sig_s1<='0';

exp_s1<=sqrt_exp+63;

end if;

stickybit_divsqrt<='0';

if mode_divsqrt='1' then

stickybit_divsqrt<='1';

end if;

end process;

ST1C:

process(clk,rst,strt_s1,fin_excep,qrdy_divsqrt,sig_s1,exp_s1,q_divsqrt,strt_divsqrt,rdy_d

ivsqrt,res_ack_s1,strt_tag,dec_exp)

variable sig: std_logic;

variable exp: std_logic_vector(7 downto 0);

variable exp_aux: std_logic_vector(7 downto 0);

begin

strt_divsqrt<=strt_s1 and not fin_excep;

rst_divsqrt<=rst;

fin_s1<=qrdy_divsqrt;

exp:=exp_aux-dec_exp;

res_s1<=sig & exp & ('0'&q_divsqrt);

status_s1<=FOK;

qack_divsqrt<=res_ack_s1;

busy_s1<=not rdy_divsqrt;

tag_s1<=strt_tag;

if rising_edge(clk) and strt_divsqrt='1' then

sig:=sig_s1;

exp_aux:=exp_s1;

end if;

end process;

ST2_0: if FPU_DIVISION_ZEROSHIFT=0 generate ST2: process

type T_ESTADO is (ESPERA,COMPARA);

variable estado: T_ESTADO;

subtype T_INDEX is integer range q_divsqrt'left downto q_divsqrt'right+1;

Page 121: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

variable index: T_INDEX;

variable q,one: std_logic_vector(T_INDEX'left downto T_INDEX'right);

variable r: std_logic_vector(a_divsqrt'left+5 downto a_divsqrt'right+3);

variable b: std_logic_vector(a_divsqrt'left+5 downto a_divsqrt'right+3);

variable cmp: std_logic_vector(r'left+1 downto r'right);

variable r_first_24_bits: std_logic_vector(26 downto 3);

variable rdy,busy,qready,mode,stickybit: std_logic;

begin

wait until rising_edge(clk);

case estado is

when ESPERA =>

if strt_divsqrt='1' and busy='0' then

mode:=mode_divsqrt;

busy:='1'; qready:='0';

index:=T_INDEX'high;

r:="00" & a_divsqrt;

q:=(others=>'0');

stickybit:=stickybit_divsqrt;

estado:=COMPARA;

if mode='0' then -- division

one:=(one'left=>'1', others=>'0');

b:="00" & b_divsqrt;

dec_exp<=(others=>'0');

else -- sqrt

one:=(one'left=>'1', others=>'0');

b:="00" & one(b'left-2 downto b'right);

if a_oddexp_divsqrt='1' then

r:=shl(r,"1");

end if;

end if;

end if;

when COMPARA =>

cmp:=('0'&r)-('0'&b);

if mode='0' then -- division

Page 122: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

if cmp(cmp'left)='1' then

--q:=q;

else

q:=q or one;

r:=cmp(r'range);

end if;

r_first_24_bits:=r(r_first_24_bits'range);

if r_first_24_bits=X"000000" then

stickybit:='0';

else

stickybit:='1';

end if;

if index=T_INDEX'high and cmp(cmp'left)='1' then

--NO shr one

else

one:=shr(one,"1");

end if;

r:=shl(r,"1");

else -- sqrt

if cmp(cmp'left)='1' then

--q:=q;

else

q:=q or one;

r:=cmp(r'range);

end if;

one:=shr(one,"1");

r:=shl(r,"1");

b:=('0'&q(b'left-2 downto b'right)&'0') or ("00"&one(b'left-

2 downto b'right));

end if;

if index=T_INDEX'low or cmp=0 then

busy:='1'; qready:='1'; estado:=ESPERA;

else

if index=T_INDEX'high and cmp(cmp'left)='1' then

dec_exp<=(others=>'1');

Page 123: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

else

index:=index-1;

end if;

end if;

end case;

if qack_divsqrt='1' or rst_divsqrt='1' then

busy:='0'; qready:='0';

q:=(others=>'X');

estado:=ESPERA;

end if;

rdy_divsqrt<=not busy;

qrdy_divsqrt<=qready;

q_divsqrt<=q&stickybit;

end process;

end generate;

handshake: block

signal state_busy_s1: std_logic;

begin

strt_ack<=res_ack when fin_excep='1' else strt_s1;

op_a_ack<=res_ack when fin_excep='1' else strt_s1;

op_b_ack<=(res_ack and mode_divsqrt) when fin_excep='1' else (strt_s1 and

mode_divsqrt);

strt_s1<=strt_req and op_a_rdy and (op_b_rdy or mode_divsqrt) and not

state_busy_s1;

res_tag<=tag_excep when fin_excep='1' else tag_s1;

res_rdy<=fin_excep when fin_excep='1' else fin_s1;

res<=res_excep when fin_excep='1' else res_s1;

res_status<=status_excep when fin_excep='1' else status_s1;

res_ack_s1<=res_ack;

state_busy_s1<=busy_s1;

end block;

end architecture;

Page 124: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

3.2.2.5 Fichero FPU_norm.vhd

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

use IEEE.STD_LOGIC_ARITH.conv_std_logic_vector;

use IEEE.STD_LOGIC_MISC.ALL;

library copro_fpu_v2_00_b;

use copro_fpu_v2_00_b.FPU_pack_configuration.all;

use copro_fpu_v2_00_b.FPU_pack_defines.all;

entity FPU_norm is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req: in std_logic;

strt_ack: out std_logic;

op_a_status: in T_FLOAT;

op_a: in std_logic_vector(36 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res: out std_logic_vector(31 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end entity;

architecture beh2b of FPU_norm is

constant STAGES: integer:=FPU_NORMALIZER_STAGES;

constant ROUND_METHOD: integer:=FPU_NORMALIZER_ROUND;

subtype T_INDEX is integer range 0 to 28;

constant T_INDEX_NBITS: integer:=5;

signal index_s1,index_s12: T_INDEX; --integer range 30 downto 0;

signal exp_res_s1,exp_res_s12: STD_LOGIC_VECTOR (7 downto 0);

signal man_val_s1,man_val_s12: STD_LOGIC_VECTOR (27 downto 0);

signal res_excep,res_s2: STD_LOGIC_VECTOR (31 downto 0);

Page 125: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

signal fin_excep,fin_s1,fin_s2: std_logic;--signal fin_excep,fin_s1,fin_s12,fin_s2:

std_logic;

signal sig_s1,sig_s12: STD_LOGIC;

signal strt_s1,strt_s2: std_logic;

signal tag_s1,tag_s12,tag_s2,tag_excep: std_logic_vector(res_tag'range);

function Index1(a: std_logic_vector(27 downto 0)) return T_INDEX is

variable o: T_INDEX:=T_INDEX'high;

variable f: std_logic:='0';

begin

for idx in a'high downto a'low loop

if f='0' and a(idx)='1' then

f:='1';

o:=a'high-idx;

end if;

end loop;

return o;

end function;

function BarrelLShift(a: std_logic_vector; idx: T_INDEX) return std_logic_vector is

begin

return shl(a,conv_std_logic_vector(idx,T_INDEX_NBITS));

end function;

function RoundBit(a: std_logic_vector; constant n: integer) return std_logic is

variable slc,cmp: std_logic_vector(n-1 downto 0);

variable round: std_logic:='0';

begin

if ROUND_METHOD=1 then

cmp(cmp'left):='1'; cmp(cmp'left-1 downto cmp'right):=(others=>'0');

slc:=a(a'right+n downto a'right+1);

if slc>cmp then

round:='1';

end if;

if slc=cmp and a(4)='1' then

Page 126: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

round:='1';

end if;

end if;

return round;

end function;

begin

ST1A: process(op_a_status,sig_s1,strt_s1,tag_s1)

variable man_excep: std_logic_vector(22 downto 0):=conv_std_logic_vector(0,23);

variable exp_excep: std_logic_vector(7 downto 0):=conv_std_logic_vector(0,8);

variable sig_excep: std_logic;

begin

sig_excep:='X';

exp_excep:=(others=>'X');

man_excep:=(others=>'X');

fin_excep<='0';

if op_a_status=FZERO then

sig_excep:=sig_s1;

exp_excep:=(others=>'0');

man_excep:=(others=>'0');

fin_excep<=strt_s1;

end if;

if op_a_status=FINF then

sig_excep:=sig_s1;

exp_excep:=(others=>'1');

man_excep:=(others=>'0');

fin_excep<=strt_s1;

end if;

if op_a_status=FNAN then

sig_excep:='1';

exp_excep:=(others=>'1');

man_excep:=(22=>'1', others=>'0');

fin_excep<=strt_s1;

end if;

res_excep<=sig_excep & exp_excep & man_excep;

Page 127: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

tag_excep<=tag_s1;

end process;

ST1B: process(strt_s1,fin_excep,op_a,strt_tag)

variable idx: T_INDEX;

begin

fin_s1<=strt_s1 and not fin_excep;

exp_res_s1<=op_a(35 downto 28);

idx:=Index1(op_a(27 downto 0));

man_val_s1<=op_a(27 downto 0);--BarrelLShift(op_a(27 downto 0),idx);

index_s1<=idx;

sig_s1<=op_a(36);

tag_s1<=strt_tag;

end process;

ST1toST2_1: if STAGES=1 generate

process(exp_res_s1,man_val_s1,index_s1,sig_s1,tag_s1)

begin

--fin_s12<=fin_s1 and not rst;

exp_res_s12<=exp_res_s1;

man_val_s12<=man_val_s1;

index_s12<=index_s1;

sig_s12<=sig_s1;

tag_s12<=tag_s1;

end process; end generate;

ST1toST2_2: if STAGES=2 generate process

begin

wait until rising_edge(clk);

if fin_s1='1' then

--fin_s12<=fin_s1 and not rst;

exp_res_s12<=exp_res_s1;

man_val_s12<=man_val_s1;

index_s12<=index_s1;

Page 128: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

sig_s12<=sig_s1;

tag_s12<=tag_s1;

end if;

end process; end generate;

ST2: process(strt_s2,exp_res_s12,man_val_s12,index_s12,sig_s12,tag_s12)

variable man_ext: std_logic_vector(27 downto 0);

variable man: std_logic_vector(27 downto 4);--:=conv_std_logic_vector(0,23);

variable exp: std_logic_vector(7 downto 0);--:=conv_std_logic_vector(0,8);

variable round_bit,sig: std_logic;

begin

fin_s2<=strt_s2;--fin_s12;

exp:=exp_res_s12+(1-index_s12);--exp_res_s1<=redondeo_v2(30 downto 23);

man_ext:=BarrelLShift(man_val_s12,index_s12);

round_bit:=RoundBit(man_ext,3);

man:=man_ext(man'range)+round_bit;

sig:=sig_s12;

if exp_res_s12=254 and index_s12=0 then

exp:=(others=>'1');--miramos overflow, si el exponente es 255 implica

infinito pero manteniento el signo

man:=(others=>'0');

sig:=sig_s12;

end if;

if index_s12=T_INDEX'high then--index_s12=28 then

exp:=(others=>'0');--miramos underflow si la mantisa es cero el resultado

es cero

man:=(others=>'0');

sig:=sig_s12;

end if;

res_s2<=sig & exp & man(26 downto 4);

tag_s2<=tag_s12;

end process;

handshake: block

signal state_busy_s1,strt_req_s1,strt_ack_s1,res_rdy_s1,res_ack_s1: std_logic;

Page 129: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

signal state_busy_s2,strt_req_s2,strt_ack_s2,res_rdy_s2,res_ack_s2: std_logic;

begin

strt_ack<=res_ack when fin_excep='1' else strt_ack_s1;

res_tag<=tag_excep when fin_excep='1' else tag_s2;

res_rdy<=fin_excep when fin_excep='1' else res_rdy_s2;

res<=res_excep when fin_excep='1' else res_s2;

strt_req_s1<=strt_req;

strt_s1<=strt_req_s1 and not state_busy_s1;

strt_ack_s1<=strt_s1;

res_rdy_s1<=fin_s1 or fin_excep;

res_ack_s1<=res_ack_s2;

strt_req_s2<=state_busy_s1;

strt_s2<=strt_req_s2 and not state_busy_s2;

strt_ack_s2<=strt_s2 ;

res_rdy_s2<=fin_s2;

res_ack_s2<=res_ack;

state_busy_s2<='0';

handshake_1: if STAGES=1 generate

state_busy_s1<='0';

end generate;

handshake_2: if STAGES=2 generate process

begin

wait until rising_edge(clk);

if rst='1' then

state_busy_s1<='0';

elsif fin_s1='1' then

state_busy_s1<='1';

elsif res_ack_s1='1' then

state_busy_s1<='0';

end if;

end process; end generate;

end block;

end architecture;

3.2.2.6 Fichero FPU_alu.vhd

library IEEE;

Page 130: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

library copro_fpu_v2_00_b;

use copro_fpu_v2_00_b.FPU_pack_configuration.all;

use copro_fpu_v2_00_b.FPU_pack_defines.all;

entity FPU_alu is

generic(

NBITS_TAG: integer:=0);

port (

clk: in std_logic;

rst: in std_logic;

mode : in T_MODE_ALU;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0):=(others=>'X');

strt_req : in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a : in STD_LOGIC_VECTOR (31 downto 0);

op_b_rdy: in std_logic;

op_b_ack: out std_logic;

op_b : in STD_LOGIC_VECTOR (31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res : out STD_LOGIC_VECTOR (31 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end entity;

architecture beh2b of FPU_alu is

component FPU_sign is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

Page 131: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

rst : in std_logic;

mode: in T_MODE_SIGN;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req : in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a_status: in T_FLOAT;

op_a: in std_logic_vector(31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res: out std_logic_vector(31 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end component;

component FPU_int2f is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req : in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a: in std_logic_vector(31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

res: out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end component;

Page 132: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

component FPU_addsubcmp is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

mode: T_MODE_ADDSUBCMP;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req : in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a_status : in T_FLOAT;

op_a : in std_logic_vector(31 downto 0);

op_b_rdy: in std_logic;

op_b_ack: out std_logic;

op_b_status : in T_FLOAT;

op_b : in std_logic_vector(31 downto 0);

cmp_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

cmp: out std_logic_vector(31 downto 0);

cmp_rdy: out std_logic;

cmp_ack: in std_logic;

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

res : out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end component;

component FPU_mul is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

Page 133: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req: in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a_status: in T_FLOAT;

op_a: in std_logic_vector(31 downto 0);

op_b_rdy: in std_logic;

op_b_ack: out std_logic;

op_b_status : in T_FLOAT;

op_b: in std_logic_vector(31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

res: out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end component;

component FPU_divsqrt is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

mode: in T_MODE_DIVSQRT;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req: in std_logic;

strt_ack: out std_logic;

op_a_rdy: in std_logic;

op_a_ack: out std_logic;

op_a_status: in T_FLOAT;

op_a: in std_logic_vector(31 downto 0);

op_b_rdy: in std_logic;

op_b_ack: out std_logic;

Page 134: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

op_b_status : in T_FLOAT;

op_b: in std_logic_vector(31 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res_status: out T_FLOAT;

res: out std_logic_vector(36 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end component;

component FPU_norm is

generic(

NBITS_TAG: integer:=0);

port(

clk : in std_logic;

rst : in std_logic;

strt_tag: in std_logic_vector(NBITS_TAG-1 downto 0);

strt_req: in std_logic;

strt_ack: out std_logic;

op_a_status: in T_FLOAT;

op_a: in std_logic_vector(36 downto 0);

res_tag: out std_logic_vector(NBITS_TAG-1 downto 0);

res: out std_logic_vector(31 downto 0);

res_rdy: out std_logic;

res_ack: in std_logic);

end component;

signal op_a_status,op_b_status: T_FLOAT;

signal mode_addsubcmp: T_MODE_ADDSUBCMP;

signal strt_req_addsubcmp,strt_ack_addsubcmp,cres_rdy_addsub,cres_ack_addsub:

std_logic;

signal op_a_ack_addsubcmp,op_b_ack_addsubcmp: std_logic;

signal cres_rdy_cmp,cres_ack_cmp: std_logic;

signal cres_cmp: std_logic_vector(31 downto 0);

signal cres_addsub: std_logic_vector(36 downto 0);

signal cres_status_addsub: T_FLOAT;

Page 135: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

signal cres_tag_addsub,cres_tag_cmp: std_logic_vector(NBITS_TAG-1 downto 0);

signal strt_req_mul,strt_ack_mul,cres_rdy_mul,cres_ack_mul: std_logic;

signal op_a_ack_mul,op_b_ack_mul: std_logic;

signal cres_mul: std_logic_vector(36 downto 0);

signal cres_status_mul: T_FLOAT;

signal cres_tag_mul: std_logic_vector(NBITS_TAG-1 downto 0);

signal mode_divsqrt: T_MODE_DIVSQRT;

signal strt_req_divsqrt,strt_ack_divsqrt,cres_rdy_divsqrt,cres_ack_divsqrt: std_logic;

signal op_a_ack_divsqrt,op_b_ack_divsqrt: std_logic;

signal cres_divsqrt: std_logic_vector(36 downto 0);

signal cres_status_divsqrt: T_FLOAT;

signal cres_tag_divsqrt: std_logic_vector(NBITS_TAG-1 downto 0);

signal strt_req_int2f,strt_ack_int2f,cres_rdy_int2f,cres_ack_int2f: std_logic;

signal op_a_ack_int2f: std_logic;

signal cres_int2f: std_logic_vector(36 downto 0);

signal cres_status_int2f: T_FLOAT;

signal cres_tag_int2f: std_logic_vector(NBITS_TAG-1 downto 0);

signal strt_req_norm,strt_ack_norm,cres_rdy_norm,cres_ack_norm: std_logic;

signal op_a_status_norm: T_FLOAT;

signal op_a_norm: std_logic_vector(36 downto 0);

signal cres_norm: std_logic_vector(31 downto 0);

signal strt_tag_norm,cres_tag_norm: std_logic_vector(NBITS_TAG-1 downto 0);

signal mode_sign: T_MODE_SIGN;

signal strt_req_sign,strt_ack_sign,cres_rdy_sign,cres_ack_sign: std_logic;

signal op_a_ack_sign: std_logic;

signal cres_sign: std_logic_vector(31 downto 0);

signal cres_tag_sign: std_logic_vector(NBITS_TAG-1 downto 0);

signal cres_mux_addsub, cres_mux_mul, cres_mux_divsqrt, cres_mux_int2f,

op_mux_norm: std_logic_vector(NBITS_TAG+op_a_norm'length-1 downto 0);

signal cres_mux_norm, cres_mux_cmp, cres_mux_sign, res_mux:

std_logic_vector(NBITS_TAG+res'length-1 downto 0);

begin

------------------------------------------------------

-- ports to/from Stage#1

------------------------------------------------------

Page 136: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

scan_cmd:

process(mode,strt_req,strt_ack_addsubcmp,strt_ack_mul,strt_ack_divsqrt,strt_ack_int2f,

strt_ack_sign,op_a_ack_addsubcmp,op_b_ack_addsubcmp,op_a_ack_mul,op_b_ack_m

ul,op_a_ack_divsqrt,op_b_ack_divsqrt,op_a_ack_int2f,op_a_ack_sign)

begin

strt_req_sign<='0'; strt_req_addsubcmp<='0'; strt_req_mul<='0';

strt_req_divsqrt<='0'; strt_req_int2f<='0'; --evita inferencia latches

strt_ack<='0';

op_a_ack<='0'; op_b_ack<='0';

mode_sign<=FPOS; mode_addsubcmp<=FADD; mode_divsqrt<=FDIV; --evita

inferencia latches

case mode is

when FADD to FLWR =>

strt_ack<=strt_ack_addsubcmp;

strt_req_addsubcmp<=strt_req;

op_a_ack<=op_a_ack_addsubcmp;

op_b_ack<=op_b_ack_addsubcmp;

mode_addsubcmp<=mode;

when FMUL=>

strt_ack<=strt_ack_mul;

strt_req_mul<=strt_req;

op_a_ack<=op_a_ack_mul;

op_b_ack<=op_b_ack_mul;

when FDIV|FSQRT=>

strt_ack<=strt_ack_divsqrt;

strt_req_divsqrt<=strt_req;

op_a_ack<=op_a_ack_divsqrt;

op_b_ack<=op_b_ack_divsqrt;

mode_divsqrt<=mode;

when FINT2F=>

strt_ack<=strt_ack_int2f;

strt_req_int2f<=strt_req;

op_a_ack<=op_a_ack_int2f;

when FPOS to FABS=>

strt_ack<=strt_ack_sign;

strt_req_sign<=strt_req;

op_a_ack<=op_a_ack_sign;

Page 137: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

mode_sign<=mode;

end case;

end process;

scan_a: process(op_a)

begin

op_a_status<=FOK;

if op_a(30 downto 0)=0 then

op_a_status<=FZERO;

end if;

if op_a(30 downto 23)=255 then

if op_a(22 downto 0)=0 then

op_a_status<=FINF;

else

op_a_status<=FNAN;

end if;

end if;

if op_a(30 downto 23)=0 and op_a(22 downto 0)>0 then

op_a_status<=FNAN;

end if;

end process;

scan_b: process(op_b)

begin

op_b_status<=FOK;

if op_b(30 downto 0)=0 then

op_b_status<=FZERO;

end if;

if op_b(30 downto 23)=255 then

if op_b(22 downto 0)=0 then

op_b_status<=FINF;

else

op_b_status<=FNAN;

end if;

end if;

if op_b(30 downto 23)=0 and op_b(22 downto 0)>0 then

op_b_status<=FNAN;

Page 138: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

end if;

end process;

------------------------------------------------------

-- Stage#1

------------------------------------------------------

int2f: FPU_int2f generic map(NBITS_TAG) port map(

clk=> clk,

rst=> rst,

strt_tag=> strt_tag,

strt_req=> strt_req_int2f,

strt_ack=> strt_ack_int2f,

op_a_rdy=> op_a_rdy,

op_a_ack=> op_a_ack_int2f,

op_a=> op_a,

res_tag=> cres_tag_int2f,

res_status=> cres_status_int2f,

res=> cres_int2f,

res_rdy=> cres_rdy_int2f,

res_ack=> cres_ack_int2f);

addsubcmp: FPU_addsubcmp generic map(NBITS_TAG) port map(

clk=> clk,

rst=> rst,

mode=> mode_addsubcmp,

strt_tag=> strt_tag,

strt_req=> strt_req_addsubcmp,

strt_ack=> strt_ack_addsubcmp,

op_a_rdy=> op_a_rdy,

op_a_ack=> op_a_ack_addsubcmp,

op_a_status=> op_a_status,

op_a=> op_a,

op_b_rdy=> op_b_rdy,

op_b_ack=> op_b_ack_addsubcmp,

op_b_status=> op_b_status,

op_b=> op_b,

cmp_tag=> cres_tag_cmp,

Page 139: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

cmp=> cres_cmp,

cmp_rdy=> cres_rdy_cmp,

cmp_ack=> cres_ack_cmp,

res_tag=> cres_tag_addsub,

res_status=> cres_status_addsub,

res=> cres_addsub,

res_rdy=> cres_rdy_addsub,

res_ack=> cres_ack_addsub);

mul: FPU_mul generic map(NBITS_TAG) port map(

clk=> clk,

rst=> rst,

strt_tag=> strt_tag,

strt_req=> strt_req_mul,

strt_ack=> strt_ack_mul,

op_a_rdy=> op_a_rdy,

op_a_ack=> op_a_ack_mul,

op_a_status=> op_a_status,

op_a=> op_a,

op_b_rdy=> op_b_rdy,

op_b_ack=> op_b_ack_mul,

op_b_status=> op_b_status,

op_b=> op_b,

res_tag=> cres_tag_mul,

res_status=> cres_status_mul,

res=> cres_mul,

res_rdy=> cres_rdy_mul,

res_ack=> cres_ack_mul);

divsqrt: FPU_divsqrt generic map(NBITS_TAG) port map(

clk=> clk,

rst=> rst,

mode=> mode_divsqrt,

strt_tag=> strt_tag,

strt_req=> strt_req_divsqrt,

strt_ack=> strt_ack_divsqrt,

op_a_rdy=> op_a_rdy,

Page 140: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

op_a_ack=> op_a_ack_divsqrt,

op_a_status=> op_a_status,

op_a=> op_a,

op_b_rdy=> op_b_rdy,

op_b_ack=> op_b_ack_divsqrt,

op_b_status=> op_b_status,

op_b=> op_b,

res_tag=> cres_tag_divsqrt,

res_status=> cres_status_divsqrt,

res=> cres_divsqrt,

res_rdy=> cres_rdy_divsqrt,

res_ack=> cres_ack_divsqrt);

------------------------------------------------------

-- Stage#1 to Stage#2

------------------------------------------------------

cres_mux_addsub<=cres_tag_addsub & cres_addsub;

cres_mux_mul<=cres_tag_mul & cres_mul;

cres_mux_divsqrt<=cres_tag_divsqrt & cres_divsqrt;

cres_mux_int2f<=cres_tag_int2f & cres_int2f;

muxreg: FPU_muxreg generic map(VOLATILE=>1,

REG_BEFORE_MUX=>FPU_MUXREG_REG_BEFORE_MUX,

NBITS=>op_mux_norm'length) port map(

clk=> clk,

rst=> rst,

a_strt_req=> cres_rdy_addsub,

a_strt_ack=> cres_ack_addsub,

a_status=> cres_status_addsub,

a=> cres_mux_addsub,

b_strt_req=> cres_rdy_mul,

b_strt_ack=> cres_ack_mul,

b_status=> cres_status_mul,

b=> cres_mux_mul,

c_strt_req=> cres_rdy_divsqrt,

c_strt_ack=> cres_ack_divsqrt,

c_status=> cres_status_divsqrt,

c=> cres_mux_divsqrt,

Page 141: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

d_strt_req=> cres_rdy_int2f,

d_strt_ack=> cres_ack_int2f,

d_status=> cres_status_int2f,

d=> cres_mux_int2f,

o_status=> op_a_status_norm,

o=> op_mux_norm,

o_rdy=> strt_req_norm,

o_ack=> strt_ack_norm);

strt_tag_norm<=op_mux_norm(op_mux_norm'left downto op_mux_norm'left-

(NBITS_TAG-1));

op_a_norm<=op_mux_norm(op_a_norm'range);

------------------------------------------------------

-- Stage#2

------------------------------------------------------

norm: FPU_norm generic map(NBITS_TAG) port map(

clk=> clk,

rst=> rst,

strt_tag=> strt_tag_norm,

strt_req=> strt_req_norm,

strt_ack=> strt_ack_norm,

op_a_status=> op_a_status_norm,

op_a=> op_a_norm,

res_tag=> cres_tag_norm,

res=> cres_norm,

res_rdy=> cres_rdy_norm,

res_ack=> cres_ack_norm);

------------------------------------------------------

-- Stage#2 to/from ports

------------------------------------------------------

sign: FPU_sign generic map(NBITS_TAG) port map(

clk=> clk,

rst=> rst,

mode=> mode_sign,

strt_tag=> strt_tag,

strt_req=> strt_req_sign,

Page 142: Coprocesador FPU (Floating-Point Unit)deeea.urv.cat/public/PROPOSTES/pub/pdf/1464pub.pdf · 3.2.1 Adaptación del ... diferentes figuras de un diagrama de bloques de la arquitectura

strt_ack=> strt_ack_sign,

op_a_rdy=> op_a_rdy,

op_a_ack=> op_a_ack_sign,

op_a_status => op_a_status,

op_a => op_a,

res_tag=> cres_tag_sign,

res=> cres_sign,

res_rdy=> cres_rdy_sign,

res_ack=> cres_ack_sign);

cres_mux_norm<=cres_tag_norm & cres_norm;

cres_mux_cmp<=cres_tag_cmp & cres_cmp;

cres_mux_sign<=cres_tag_sign & cres_sign;

muxo: FPU_mux generic map(NBITS=>res_mux'length) port map(

a_strt_req=> cres_rdy_norm,

a_strt_ack=> cres_ack_norm,

a=> cres_mux_norm,--cres_norm,

b_strt_req=> cres_rdy_cmp,

b_strt_ack=> cres_ack_cmp,

b=> cres_mux_cmp,--cres_cmp,

c_strt_req=> cres_rdy_sign,

c_strt_ack=> cres_ack_sign,

c=> cres_mux_sign,--cres_sign,

o=> res_mux,--res,

o_rdy=> res_rdy,

o_ack=> res_ack);

res_tag<=res_mux(res_mux'left downto res_mux'left-(NBITS_TAG-1));

res<=res_mux(res'range);

end architecture;

4 Bibliografia

http://www.h-schmidt.net/FloatApplet/IEEE754.html

http://babbage.cs.qc.edu/IEEE-754/

http://www.eetimes.com/design/programmable-logic/4014815/All-

about-FPGAs