1. ÍNDICE GENERAL
Diseño sobre FPGA de una Unidad Aritmética Decimal Índice general
2. INTRODUCCIÓN
3. MEMORIA DESCRIPTIVA
-3-
Diseño sobre FPGA de una Unidad Aritmética Decimal Índice general
4. MEMORIA EXPERIMENTAL
5. ANEXOS
6. BIBLIOGRAFÍA........................................................................................................................ 99
-4-
Diseño sobre FPGA de una Unidad Aritmética Decimal
2. INTRODUCCIÓN
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
-6-
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
El objetivo de este proyecto es el diseño del modelo VHDL de una Unidad Aritmética
Decimal, que pueda funcionar como coprocesador/acelerador dentro de otro sistema más
complejo. Por tanto, se trata de un componente virtual utilizable en cualquier tipo de
sistemas que requieran operar en decimal.
Dicha unidad permitirá realizar las operaciones aritméticas básicas – siempre operando en
decimal – como son la suma, resta, multiplicación y división de dos valores decimales.
Los sistemas que operan en decimal son preferibles a los que lo hacen en binario en un
gran número de aplicaciones aritméticas informáticas. El motivo principal no es la
complejidad de las interfaces de codificación y decodificación (que también influye), sino
principalmente la falta de precisión y claridad de los resultados.
-7-
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
El código decimal codificado en binario (BCD, Binary Coded Decimal, también conocido
como código 8421) codifica los dígitos decimales del 0 al 9 mediante sus representaciones
binarias sin signo de 4 bits, desde 0000 a 1001. Las palabras de código restantes, de 1010 a
1111, no se utilizan. Las conversiones entre las representaciones BCD y decimal son
triviales e implican la sustitución directa de cuatro bits por cada dígito decimal.
El decimal codificado en binario es un código ponderado, puesto que cada dígito decimal
puede obtenerse a partir de su palabra de código asignando un peso fijo a cada bit de
palabra de código. Los pesos para los bits BCD son 8, 4, 2, 1, y por esta razón el código se
denomina en ocasiones código 8421.
Decimal BCD
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
Tabla 2.1. Correspondencia entre los dígitos decimales y código BCD
Hoy en día, las FPGA (Field Programmable Gate Arrays, de las que se hablará más
adelante) son una de las tecnologías disponibles para el desarrollo de sistemas electrónicos.
Representan una atractiva opción para la producción de pequeñas cantidades ya que sus
costes fijos (coste del prototipo, de la primera unidad) son bastante más bajos que los
correspondientes en ASIC (Application-Specific Integrated Circuit, circuitos integrados de
aplicación específica). Además, en pos de reducir el tamaño y por tanto el coste unitario,
una posibilidad interesante es reconfigurarlas mientras operan de modo que el mismo
dispositivo pueda ejecutar diferentes funciones predefinidas.
-8-
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
Actualmente, los lenguajes HDL más utilizados son VHDL y Verilog, ya que están
estandarizados por el IEEE (Institute of Electrical and Electronic Engineers). Nosotros nos
centraremos en el primero de ellos.
-9-
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
VHDL proviene de VHSIC (Very High Speed Integrated Circuit) Hardware Description
Language. VHDL es un lenguaje de descripción del hardware que puede utilizarse para
modelar, documentar, simular, verificar y sintetizar un sistema digital. Por tanto, abarca el
ciclo completo de diseño (salvo el trazado físico o layout) desde las especificaciones
iniciales hasta la construcción del prototipo hardware. Proporciona el soporte necesario
para especificar su comportamiento o estructura, incluyendo jerarquías. Asimismo, es útil
para metodologías de diseño ascendentes (bottom-up) como, sobre todo, descendentes (top-
down).
La semántica y construcciones del lenguaje permiten también diseñar con facilidad bancos
de prueba (test-benches), mediante los que se lleva a cabo la simulación de los sistemas
modelados.
2.3.2.2.2 Características
Admite casi todos los niveles de descripción, desde el algorítmico (nivel más alto) hasta el
lógico (nivel más bajo). Para ello proporciona herramientas semánticas y sintácticas que se
pueden agrupar así:
- 10 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
El lenguaje VHDL presenta tres métodos básicos para describir un circuito digital por
software:
Toda descripción en VHDL está constituida al menos por tres tipos de elementos:
bibliotecas (libraries), entidades (entities) y arquitecturas (architectures).
- 11 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
Una vez finalizada la prueba del concepto, se pasa al diseño detallado. Dependiendo de la
herramienta de síntesis que se utilice y de las especificaciones del circuito, la descripción
VHDL estará desarrollada en un nivel de abstracción mayor o menor (desde un nivel
algorítmico a uno lógico).
Por último se aborda la síntesis del circuito, es decir, el paso de una descripción en VHDL
a un circuito real. El proceso de diseño puede terminar antes si el objetivo final no es la
fabricación sino, por ejemplo, la creación de componentes de biblioteca para uso posterior.
- 12 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
Los PLDs están basados en una matriz AND + OR. Dentro de los PLDs encontramos las
PROM (Programmable Read Only Memory), las PAL (Programmable Logic Array) y las
PAL (Programmable Array Logic).
Dentro de las PAL se encuentran los CPLDs (Complex PLD), compuestos por la
integración de PLDs (PAL/GAL o PLA). Están formados por bloques lógicos y matrices
de interruptores, donde cada bloque lógico corresponde a un PLD.
Figura 2.4. Ejemplo de arquitectura de CPLD (con 4 elementos lógicos o bloques programables)
- 13 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
Las FPGA están compuestas por una matriz de elementos lógicos cuya interconexión y
funcionalidad se puede programar. En comparación con los dispositivos CPLD, difieren en
la arquitectura, no utilizan matrices de tipo PAL/PLA y tienen unas densidades mucho
mayores que los anteriores. Una FPGA típica tiene un número de puertas equivalentes
mucho mayor que un dispositivo CPLD típico. Los elementos que implementan las
funciones lógicas en las FPGA son, generalmente, mucho más pequeños que en los CPLD,
por lo que hay muchos más de esos elementos. Asimismo, en las FPGA, las
interconexiones programables están organizadas según una disposición de filas y
columnas.
Los tres elementos básicos en una FPGA son el bloque configurable (CLB, Configurable
Logic Block), las interconexiones y los bloques de entrada/salida (E/S). Los bloques CLB
de una FPGA son menos complejos que sus homónimos en un CPLD, pero suele haber
muchos más de ellos. La matriz distribuida de interconexiones programables permite
interconectar los bloques CLB entre sí y conectarlos a las entradas y a las salidas. Los
bloques de E/S situados alrededor del perímetro de las estructura proporcionan un acceso
de entrada/salida o bidireccional, individualmente seleccionable, hacia el mundo exterior.
Cada bloque lógico de la FPGA está formado por múltiples módulos lógicos más pequeños
(que son los componentes básicos) y por una serie de interconexiones programables locales
que se emplean para conectar entre sí los módulos lógicos que componen el CLB.
CLB
Módulo lógico
Módulo lógico
Interconexión
local
Módulo lógico
- 14 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
Salida suma de
productos
A0
A1
Lógica E/S
LUT
asociada
…
An-1
Módulo lógico
Los dispositivos FPGA son reprogramables, y los de gran tamaño pueden tener decenas de
miles de bloques CLB, además de memoria y otros recursos. Por todo ello y la gran
flexibilidad que presentan, son ideales para realizar prototipos de manera rápida, en
pequeñas cantidades.
Dentro de una FPGA se puede incluir la funcionalidad de varios circuitos integrados. Esta
funcionalidad puede ser desarrollada uno mismo o adquirida a través de terceros. Debido a
que estas funcionalidades son como componentes electrónicos, pero sin su parte física, se
les suele llamar componentes virtuales. En la industria se les conoce como bloques de
propiedad intelectual o IP cores (Intellectual Property).
- 15 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
Dichas tarjetas incluyen los componentes necesarios para esta misión: dispositivos
programables (CPLD, FPGA), memoria de datos y de programa, componentes de entrada-
salida y conectores (displays, puertos Ethernet, USB, RS-232, conversores analógico-
digital y viceversa, interruptores, LEDs…), osciladores internos (reloj del sistema)…
La unidad Spartan-3E Starter Kit Board nos proporciona las herramientas necesarias para
testear nuestro sistema. Incluye la placa de pruebas con una FPGA Spartan-3E modelo
XC3S500E, fuente de alimentación, cable USB para programar el dispositivo, software
para sintetizar e implementar nuestro modelo y manuales de referencia.
- 16 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Introducción
• Interfaces y conectores:
- 17 -
Diseño sobre FPGA de una Unidad Aritmética Decimal
3. MEMORIA DESCRIPTIVA
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
- 19 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Nuestro objetivo es la creación del modelo VHDL de una Unidad Aritmética Decimal, es
decir, una unidad que, operando en sistema BCD, realice las operaciones de suma, resta,
multiplicación y división.
Necesitaremos un sistema que dados dos valores de entrada de n dígitos BCD cada uno, x e
y, calcule el resultado z (de 2n dígitos BCD) de la operación que hayamos escogido
previamente mediante la señal de entrada operation. Además, contaremos con las señales
de entrada start (para iniciar el cálculo interno cuando sea necesario), reset (reiniciar el
sistema), clk (señal de reloj) y las de salida carry (acarreo de salida cuando sea necesario)
y done (indicador de resultado disponible).
Para ello, la primera idea es que deberemos crear el modelo necesario para poder ejecutar
cada operación.
Por consiguiente, nos centraremos primero en el diseño de los módulos primarios que
realizarán las diferentes operaciones y después los integraremos en la unidad principal.
- 20 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
3.2.1 Sumador/Restador
3.2.1.1 Sumador
La idea principal de este bloque es que, dadas dos entradas, a y b, que representan cada una
1 dígito decimal, tenemos una arquitectura cuya misión es realizar la suma de ambos
dígitos y dar como resultado (c) 1 dígito decimal de salida y un acarreo (carry_out) en caso
de ser necesario.
- 21 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Tenemos dos entradas, a y b, que pueden representar cualquier dígito decimal del 0 al 9,
una salida c que también será un dígito BCD, y un acarreo de salida (carry_out). También
hay un acarreo de entrada, carry_in, que nos permitirá interconectar diversos bloques.
Funcionamiento
Al realizar la suma binaria se nos pueden presentar dos casos: si el resultado de dicha suma
es igual o menor a 9 (‘1001’), el resultado es directo (es decir, a + b = c). Si la suma es
superior a 9, debemos realizar una corrección al valor obtenido.
1 1 1 decimal
0 1 0 1 → 5
+ 0 1 1 1 → 7
1 1 0 0 → 12
Vemos que este valor es superior a 9, y por tanto no es un valor BCD válido. Entonces
hemos de aplicar una corrección para obtener el valor correspondiente en BCD, donde el
número 12 se representaría con dos dígitos de cuatro bits cada uno; un primer grupo para el
1 ‘0001’, y otro grupo para el 2 ‘0010’. Para pasar de binario a BCD vamos a sumar 6 (en
binario ‘0110’):
1 1
1 1 0 0 → 12
+ 0 1 1 0 → 6
1 0 0 1 0
Obtenemos ‘10010’, donde debemos leer los últimos cuatro bits para el primer dígito
decimal ‘0010’ y que equivalen al número 2, y el bit de más peso, ‘1’, que formaría parte
del siguiente dígito decimal, que sería un 1. Por tanto, tendríamos como resultado dos
dígitos decimales, un dígito decimal de las decenas igual a 1, y otro para las unidades que
sería un 2. Hemos pasado del valor 12, ‘10010’ en binario, a su equivalente en
nomenclatura BCD, ‘0001 0010’.
- 22 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Decimal 12
Binario 1100
BCD 0001 0010
En resumen:
- 23 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
donde tendremos dos entradas, x e y, de n dígitos BCD (4n bits), y una salida z que será el
resultado de la operación. Además, en el caso de que haya desbordamiento en z, la salida
out_carry se pondrá a ‘1’. La entrada ini_carry en este bloque se corresponde con el
acarreo de entrada del primer sumador de 1 dígito BCD.
- 24 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Podemos ver como en la tercera operación (x = 3050, y = 8070), el acarreo de salida está a
nivel alto, lo que indica que el resultado es z = 11120.
- 25 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
3.2.1.2 Restador
El objetivo es crear un bloque que dados dos valores de entrada de n dígitos, x e y, calcule
la diferencia z, e indique mediante una señal de salida denominada carry_out si el
resultado ha sido positivo (carry_out = ‘0’) o negativo (carry_out = ‘1’),
Para ello, nos basaremos en dos operaciones básicas; una es la suma descrita en el apartado
anterior, por lo que utilizaremos el Sumador de n dígitos decimales, y la otra es la
utilización del complemento a 10n del valor y de entrada. El complemento a 10n de un
número se puede obtener a partir de calcular el complemento a 9 de cada dígito (con un
bloque que haga esta función) y sumando 1 al resultado.
y su complemento a 9 equivale a
Se puede calcular la resta mediante la expresión x + (10n – y), que plantea dos casos
posibles:
• Si x < y: x + (10n – y) < 10n , siendo z = 10n + (x – y), con carry_out = ‘0’ (3.7)
- 26 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Diseñamos un bloque que dado un dígito BCD de entrada (e), calcule su complemento a 9
(s). Este bloque estará controlado por una señal de entrada denominada add_sub,
encargada de habilitar o no la operación. Si su valor es ‘1’, s mostrará el complemento a 9
de e; en caso contrario s tomará el mismo valor que e.
Dado un dígito BCD e de cuatro bits (e3 e2 e1 e0), su complemento a 9 (s3 s2 s1 s0) se
obtiene mediante la operación ‘1001’ – e3 e2 e1 e0 (o su equivalente, ‘1001’ + e3’ e2’ e1’ e0’
+ 1, es decir, sumando al minuendo el complemento a 2 del sustraendo). Las expresiones
resultantes son las siguientes:
s0 = e0
s1 = e1
(3.8)
s2 = e1 ⊕ e2
s3 = e1 ⋅ e2 ⋅ e3
- 27 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Si nos fijamos en la Figura 3.12, podemos ver que la señal de control add_sub nos permite
realizar las operaciones de suma y resta:
Debido a que podemos realizar las dos operaciones con un mismo bloque, lo
denominaremos Sumador/Restador de n dígitos.
- 28 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Observemos otra vez en el último bloque creado (Figura 3.12). Hemos visto que esta
estructura nos permite realizar las operaciones de suma y resta. Pongamos un par de
ejemplos sobre la resta siendo n = 3:
En este último caso, para saber el resultado exacto de la operación debemos calcular el
complemento a 10n del valor z que hemos obtenido; es decir, calcular el complemento a 9
de cada dígito de z y sumar 1 al resultado obtenido. Esto lo hacemos mediante una
modificación de la arquitectura anterior, por lo que el diagrama de bloques final del
Sumador/Restador de n dígitos BCD será el siguiente:
y(4n-1:0) z1
4n add_sub 4n
Complemento Complemento
x(4n-1:0) a9 a9
‘1’
4n 4n 4n 4n
oc Sumador de n Sumador de n
carry_out ini_carry ini_carry
ini_carry ‘0’
dígitos decimales dígitos decimales
4n 4n
z1 z3
0 1
add_sub
4n
z(4n-1:0)
- 29 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Esta modificación implica un cambio en el significado del valor del acarreo de salida del
bloque (denominado carry_out), cuando realizamos la operación resta:
- 30 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
- 31 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
3.2.2 Multiplicador
Para ello lo primero que haremos será definir una estructura básica que realizará la
multiplicación de dos dígitos BCD (multiplicador de 1x1 dígitos BCD), después
realizaremos un bloque que multiplique un número de n por 1 dígitos BCD, y finalmente el
multiplicador de NxM dígitos BCD.
El producto decimal se puede obtener a través del producto binario y una etapa de
corrección posterior. La etapa básica sería un multiplicador de 1x1 dígitos BCD, es decir,
dos entradas de 1 dígito BCD cada una. Ésta se puede implementar a partir de un circuito
combinacional.
a(3:0) b(3:0)
4 4
Multiplicador de
1 dígito BCD
4 4
d(3:0) u(3:0)
- 32 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
A ⋅ B = D ⋅ 10 + U , (3.10)
A ⋅ B = P = p6 p5 p4 p3 p2 p1 p0 (3.11)
Son un máximo de 7 bits porque el resultado máximo que podemos tener en esta operación
es 81 en decimal, que corresponderá al caso de que A y B tengan su valor máximo, y este
es 9. La representación binaria del número 81 es ‘1010001’ (7 bits).
Podemos convertir el número binario P a código BCD mediante sumas binarias tras
corregir los términos descritos en la Figura 3.18. La primera fila indica el peso de cada
dígito BCD. Los pesos de p3 p2 p1 p0 son los mismos que para el valor binario. Pero los
pesos de p4 p5 y p6 se pueden descomponer en los valores BCD de la Figura 3.18.
Concretamente, p4 (cuyo peso es 16 en binario) se puede descomponer como (10, 4, 2), p5
(peso binario igual a 32) se puede descomponer en (20, 10, 2) y por último p6 (peso binario
64) como (40, 20, 4).
80 40 20 8 104 2 1
p3 p2 p1 p0
p4 p4 p4
+ p5 p5 p5
p6 p6 p6
d3 d2 d1 d0 u3 u2 u1 u0
Sumamos los términos y obtenemos las expresiones que nos darán el valor de las unidades
(uu) y las decenas (dd):
uu = p3 p2 p1 p0 + 0 p4 p4 0 + 0 p6 p5 0
(3.12)
dd = p6 p5 p4 + 0 p6 p5
Dada esta última expresión de uu, podemos ver que su valor estará entre 0 y 27 (según los
valores de p0, p1, p2, p3, p4, p5 y p6). Si el valor de uu es superior a 9 (con lo que se
necesitaría de más de 1 dígito BCD para representarse) deberemos realizar una corrección
para obtener un resultado correcto. A continuación definimos dichos términos de
corrección:
- 33 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Definiremos una variable para cada caso y mediante las siguientes expresiones booleanas
sabremos cual tenemos en cada momento.
gt 20 = uu 4 ⋅ (uu 3 ∨ uu 2 ) (3.14)
gt10st19 = gt 9 ⋅ gt 20 (3.15)
Por último obtenemos los valores finales para las decenas (d) y las unidades (u) al añadir
las correcciones pertinentes:
Simulación
- 34 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
x2 y x1 y x0 y
4 4 4 4 4 4
4 4 4
d2 u2 d1 u1 d0 u0
donde x será el número de 3 dígitos BCD (x2 x1 x0). Cada multiplicador genera un valor
para las unidades (ux) y uno para las decenas (dx); este último será el que deba sumarse a
las unidades del siguiente multiplicador. Esta estructura nos muestra que necesitaremos un
sumador de n + 1 dígitos BCD.
‘0’ d2 u2 d1 u1 d0 u0 ‘0’
4 4 4 4 4 4 4 4
4 4 4 4
z3 z2 z1 z0
Viendo este ejemplo podemos afirmar que, para un multiplicador de Nx1 dígitos BCD,
necesitaremos n multiplicadores 1x1 y n + 1 sumadores de 1 dígito.
- 35 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Tendremos dos señales de entrada: un valor x de n dígitos (xn-1 xn-2 … x2 x1 x0) y un valor y
de 1 dígito, lo que generará una señal de salida z (zn zn-1 zn-2 … z2 z1 z0).
Figura 3.22. Multiplicador de Nx1 dígitos. Incluye n multiplicadores 1x1 y n + 1 sumadores de 1 dígito
- 36 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
También tendremos las entradas start (indica inicio de operación), clk (señal de reloj) y
reset (que inicializa el bloque), y la salida done (que informa de operación realizada).
Para realizar esta operación vamos a crear un sistema secuencial (a diferencia de los que
habíamos hecho hasta ahora, que eran combinacionales) en el que mediante un bucle,
utilizaremos m veces el multiplicador de Nx1 dígitos (n_by_one_multiplier.vhd) y
sumaremos y almacenaremos los resultados parciales (mediante el bloque
n_adder_subs.vhd en modo suma y registros internos).
Que sea un sistema secuencial ayudará a reducir el coste del mismo, ya que utilizaremos un
solo multiplicador en lugar de utilizar m multiplicadores de Nx1.
z := 0;
for i in 1 .. m loop
z := z · 10 + x · ym-i;
end loop;
- 37 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
y(4m-1:0) ‘1111’
4m 4
x(4n-1:0)
int_y(m) load
4n 4
left shift register y shift
clk
Multiplicador Nx1
dígitos BCD
z_by_10
4(n+1) x_by_yi
4(n+m)
Sumador n
dígitos BCD
x 10
next_z
load
register z shift
clk
z(4(n+m)-1:0)
Este proceso se repite hasta que se detecta el dígito no decimal ‘1111’ en el registro de
desplazamiento que indica que se han leído todos los valores de y.
- 38 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
En la siguiente figura podemos ver una simulación del proceso, donde hemos establecido
n = 3 y m = 4:
Para controlar este sistema secuencial necesitaremos una unidad de control. Dicha unidad
recibirá como señales de entrada start, clk, reset y end_of_computation, y generará las
señales shift, load y done:
end_of_ computation = 1
start = 0 start = 1
E0 E1 E2 E3
- 39 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
E0 es el estado inicial (señal current_state), con un bucle de espera para que la señal start
pase a nivel bajo y avanzar al estado 1 (caso de que start se haya mantenido a ‘1’ como
consecuencia de una operación anterior).
Aquí se espera a que start sea igual ‘1’ (lo que hemos hecho ha sido detectar la transición
de ‘0’ a ‘1’ de esta señal). En E2 se cargan los valores iniciales en los registros (load = ‘1’).
Entonces pasamos a E3, donde se ejecutan las etapas de cálculo (shift = ‘1’) hasta que la
señal end_of_computation sea igual a ‘1’, lo que significará que el dígito leído int_y es 15
(‘1111’) y ha finalizado la operación, volviendo al estado inicial y poniendo la señal done a
‘1’, indicando que el proceso ha terminado.
- 40 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
3.2.3 Divisor
Dados dos números naturales x e y, siendo x < y, el algoritmo de división binaria genera
dos naturales q y r tales que:
Así
x = q ⋅ y ⋅ 2− p + r ⋅ 2− p , (3.19)
y
x r r
= q ⋅ 2 − p + ⋅ 2 − p , siendo ⋅ 2 − p < 2 − p (3.20)
y y y
Multiplicando la primera ecuación por 2p, la segunda por 2p-1, la tercera por 2p-2,…, y la
última por 20, y sumando las p ecuaciones tenemos que:
• 2 · ri-1 ≥ y : entonces
- 41 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
r := x; q := 0; ulp := 0.5;
for i in 1 .. p loop
two_r := 2*r; dif := two_r - y;
if dif < 0 then r := two_r;
else r := dif; q := q + ulp;
end if;
ulp := ulp/2;
end loop;
Las operaciones en BCD que utilizaremos serán la multiplicación por 2, la resta con
generación de signo y la suma. Además, la representación BCD de 1/2, 1/22, ..., 1/2p será
calculada sobre la marcha.
Si se ejecutan p etapas, el error es menor que 1/2p (según el algoritmo). Supongamos que el
objetivo sea que el resultado se escriba con m dígitos fraccionarios y que el error sea menor
que 1/10m (significa que el resultado obtenido es el cociente exacto truncado). Para ello
basta con que se cumpla la siguiente relación:
p m
⎛1⎞ ⎛1⎞
⎜ ⎟ < ⎜ ⎟ , es decir p > m ⋅ log 2 (10) , o sea que p > 3.3 ⋅ m (3.27)
⎝2⎠ ⎝ 10 ⎠
- 42 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
El divisor BCD será un módulo que realice la división entre dos valores de entrada, x / y,
donde x < y (para que el algoritmo funcione), dando como resultado el cociente q de m
dígitos decimales (qm-1 qm-2 … q2 q1 q0).
También tendrá como entradas las señales start (inicio de operación), clk (señal de reloj) y
reset (que inicializa el bloque), y la salida done (que informa de operación realizada).
Los valores de n (dígitos de los valores de entrada), m (dígitos y por tanto precisión del
resultado, el cociente), p (número de iteraciones que se realizarán) y logp (número de bits
necesario para representar p) serán los parámetros genéricos del modelo.
- 43 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
r ‘0010’
4n 4
Multiplicador
Nx1 dígitos BCD
4n+4
qq ulp
y(4n-1:0)
rr 4p 4p
4n ulp ‘0101’
4p 4
carry_out add_sub ‘1’ carry_out add_sub ‘0’
Sumador/Restador Sumador/Restador
n dígitos BCD n dígitos BCD Multiplicador
Nx1 dígitos BCD
rr_y(4n-5:0)
4p+4
4p
load
clk initially: 0.5
0 1 0 1
4p
4n 4p
ulp
load ini.: x(4n-1:0) initially: 0
clk
4p 4p
4n
qq
4p-4(p-m)
r
q(4m-1:0)
- 44 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
La señal ulp (Unit in the Least significant Position, unidad en la posición menos
significativa) es un número que al final del cálculo tendrá p dígitos. Su registro
(register_ulp) se inicializa con el valor 0.5 (‘0000 0101’ en código BCD). En cada
iteración irá tomando los valores 0.5, 0.25, 0.125, 0.0625, y así sucesivamente; es decir,
multiplicando el anterior valor por 5 (mediante el multiplicador de Nx1 dígitos,
n_by_one_multiplier.vhd) y desplazando el resultado 4 bits a la derecha (o lo que es lo
mismo, introduciendo un 0 decimal delante). Al ser la salida del multiplicador por 5 un
número de p + 1 dígitos, sólo utilizaremos los p dígitos de más peso (lo que equivale a
dividir por 10).
Unidad de control
Este sistema que hemos creado también es secuencial y necesitará de una unidad de control
que lo gobierne.
La unidad de control genera las señales load (escritura de los valores iniciales en los
registros), ce (actualización de los registros) y done (operación finalizada).
La señal zero vendrá controlada por un contador de p estados (este número se representa
con logp bits, como hemos dicho antes). Dicha señal se pondrá a ‘1’ cuando se ejecute el
paso p de la iteración.
- 45 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Simulación
- 46 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Podemos observar con mayor facilidad en la Figura 3.34 la transición entre estados, y
vemos como, desde el estado 0 (señal current_state) y dado que la señal start es ‘0’,
pasamos al estado 1 (en caso de que start se hubiera mantenido a ‘1’ como resultado de un
cálculo anterior, el sistema esperaría a que dicha señal se pusiera a ‘0’).
Tras un ciclo de reloj pasamos al estado 3 y se inicia el cálculo; aquí empieza a funcionar
el contador regresivo (count) de p estados (27 en el ejemplo, de 26 a 0) que determina el
número de iteraciones a realizar. También se activa la señal ce que permitirá actualizar los
registros. Cuando el contador llegue a 0, dejarán de actualizarse los registros (ce = ‘0’) y se
activará la señal zero informando del fin de cálculo (esto se puede ver en la Figura 3.33),
volviendo al estado 0 y poniéndose el indicador de operación realizada done a nivel alto.
- 47 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Este bloque estará controlado por una señal de entrada llamada operation, mediante la cual
se indicará a la unidad la operación a realizar:
Tanto para la suma como la resta z tendrá un tamaño de 4n + 1 bits (el bit de mayor peso
corresponde a la señal carry_out del bloque Sumador/Restador), mientras que para la
multiplicación y división el tamaño será de 8n bits.
- 48 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
x(4n-1:0)
y(4n-1:0)
operation1
operation0
start
4n 4n 4n 4n 4n 4n
carry_out add_sub
c_out Sumador/Restador
Multiplicador de Divisor de n
start1 NxM dígitos BCD start2 dígitos BCD
n dígitos BCD
clk clk
reset reset
4n 8n 8n
s2 done1 done2
s1 s3
‘1’
00 01 10 11 00 01 10 11 00 01 10 11
operation MUX-1 MUX-2 MUX-3
4n 4n 4n
Para habilitar el bloque multiplicador utilizaremos la señal start1, que es la salida de una
puerta AND de tres entradas (los dos bits de operation, con el de menor peso negado, y
start). Para el divisor utilizaremos start2, resultado de una puerta AND también de tres
entradas, pero esta vez sin negar el bit de menos peso de operation.
- 49 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
La salida del primer multiplexor (MUX-1) muestra el resultado de las operaciones suma
(operation = ‘00’) o resta (operation = ‘01’), y la parte baja del resultado de las
operaciones multiplicación (operation = ‘10’) o división (operation = ‘11’), que sería
z(4n-1:0).
El segundo multiplexor recibe a través de sus dos primeros canales el valor de la señal
carry_out del Sumador/Restador (llamada c_out). Como este valor ocupa 1 solo bit, los
otros bits del dígito de menos peso serán 0 (el dígito de menor peso, 4n+3:4n, estará
formado por ‘0 0 0 c_out’); los demás dígitos (8n-1:4n+4) serán 0. Para la multiplicación y
la división mostrará la parte alta del resultado, los dígitos de mayor peso (8n-1:4n).
MUX-3 muestra el valor actual de la señal done, que estará a nivel alto excepto cuando se
realice el cálculo de la multiplicación o de la división (periodo en que la señal se pondrá a
nivel bajo, debido a que done1 o done2 tomarán este valor).
En este ejemplo podemos ver las operaciones suma y resta. Los valores de entrada son x =
00867335 e y = 02350927 (ambos de 8 dígitos BCD, ya que habíamos establecido n = 8).
Primero se realiza la suma (operation = ‘00’), siendo el resultado z = 03218262; como no
hay desbordamiento en el resultado, c_out (acarreo de salida) es 0. Al cambiar operation a
‘01’ obtenemos la resta, siendo z = 01483592; en este caso el dígito de menor peso de la
parte alta de z es 1 (00000001), lo que indica que el resultado es negativo (z = – 1483592).
- 50 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria descriptiva
Al iniciarse el cálculo, la señal que lo indica (done1) se pone a ‘0’, lo que provoca que la
salida del sistema done también lo haga. Al acabar la ejecución, done1 vuelve a nivel alto y
done también. Vemos como start1 se activa habilitando el multiplicador, en cambio start2
sigue a nivel bajo.
- 51 -
Diseño sobre FPGA de una Unidad Aritmética Decimal
4. MEMORIA EXPERIMENTAL
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
- 53 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Para ello debemos estructurar un sistema completo, con una CPU que gobierne el sistema,
una memoria de programa con el juego de instrucciones que se ejecutarán, una interfaz que
visualice los datos en la pantalla de la placa, y nuestra unidad, como principales elementos.
4.2 Especificaciones
Consideremos las dos líneas de 16 caracteres cada una que posee la placa, y que se
distribuyen de la siguiente manera: en la primera línea, los 8 primeros dígitos (BCD)
corresponden al operando x, y los 8 últimos al operando y. La segunda línea será el
resultado z.
Un primer pulso (pulso 0) de synch (señal de sincronización) borra el display. Mediante los
interruptores SW3, SW2, SW1 y SW0 (pesos 8, 4, 2, 1 respectivamente) el dígito de
entrada, y con el pulsador synch procedemos a almacenarlo en el registro interno
correspondiente y visualizarlo en pantalla.
Tras haber introducido los 16 dígitos (los 8 primeros para el operando x y los 8 siguientes
para el operando y), un nuevo pulso de synch muestra en el display el resultado de la suma;
en los sucesivos pulsos de synch veremos los resultados de la resta, la multiplicación y la
división. Un último pulso (pulso 21) dará la señal para limpiar el visualizador.
- 54 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
pulso 0
pulso 1 0
pulso 2 02
pulso 3 028
...
pulso 16 0 2 8 6 7 3 3 5 5 0 2 9 9 7 2 3
pulso 17 0 2 8 6 7 3 3 5 5 0 2 9 9 7 2 3
0000000053167058
pulso 18 0 2 8 6 7 3 3 5 5 0 2 9 9 7 2 3
0000000147432388
...
pulso 21
• Interruptores SW3, SW2, SW1, SW0 para seleccionar el dígito BCD de entrada
data_in.
• Pulsadores para las señales synch (de sincronización) y reset.
• Visualizador LCD de la placa.
• Oscilador de 50 MHz.
• Una CPU que controle la entrada de dígitos, la codificación (a ASCII) de los datos
y la ejecución de las diferentes operaciones. Las operaciones se definirán mediante
un juego de instrucciones en lenguaje ensamblador, que posteriormente formarán la
memoria de programa.
• Una interfaz para el display LCD.
• La Unidad Aritmética Decimal.
- 55 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
data_in synch
mult_out
in_port done
15 …. 0
z (15:0)
PicoBlaze
reset port_id
(CPU and Unidad Aritmética
clk program memory) write_strobe start Decimal
reset
clk
Registro Registro
clk
temp_write i_write d_write
ready
lcd_interface
- 56 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
En este apartado hablaremos un poco sobre los dos componentes virtuales que utilizaremos
y que son suministrados por terceros.
Este módulo no requiere soporte externo y proporciona un entorno flexible para conectarlo
a otros componentes. Se suministra como descripción VHDL.
Estructura
- 57 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Arquitectura
ready
reset lcd_interface
clk
- 58 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
- 59 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
d_write temp_write
very_short very_long
short long
ce ce_cd
0 1 2 3 sel_delay
status cd(7..0)
(to control unit) load
load
counter
cd(7..4) cd(3..0)
time_out
1 0 (to control unit)
sel_nibble
señal dirección
z 00 a 0f
synch 10
data_in 11
ready 12
done 13
Tabla 4.2. Direcciones de entrada
- 60 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Y las de salida:
señal dirección
y 00 a 07
x 08 a 0f
temp_wr 10
id_write 11
start 12
operation 13
Tabla 4.3. Direcciones de salida
Con el objetivo de reducir el tamaño del código, se incluiría una subrutina (entre otras) que
mostrara el resultado z en el visualizador después de cada operación:
subroutine display z;
send command c0 (cursor address = 40) to display;
internal loop (16 times)
store z(i) in data;
encode data;
display character data;
end internal loop;
- 61 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
data_in synch
mult_out
in_port done
15 …. 0
z (15:0)
PicoBlaze
reset port_id
(CPU and Unidad Aritmética
clk program memory) write_strobe start Decimal
reset
clk
Registro Registro
clk
temp_write i_write d_write
ready
lcd_interface
• n = 8, lo que quiere decir que los operandos x e y serán de 8 dígitos BCD cada uno,
• p = 56, es el número de etapas que se ejecutarán para calcular el resultado cuando
realicemos la división,
• logp = 6, que son los bits necesarios para representar el valor de p.
- 62 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Utilizaremos 2 registros de 32 bits (8 dígitos BCD por 4 bits cada uno) para almacenar los
valores que se vayan introduciendo de los operandos x e y; en el caso de la señal operation
tendremos suficiente con un registro de 2 bits.
Otros 2 registros más serán necesarios para las señales temp_write y i_write/d_write de la
interfaz LCD.
El siguiente paso consiste en crear un archivo UCF (User Constraint File) que asigne las
señales que utilizamos a los pines correspondientes de la Spartan-3E. Las descripciones
necesarias para cada elemento de la placa se pueden encontrar en la Spartan-3E Starter Kit
Board User Guide.
Los interruptores SW3 (mayor peso), SW2, SW1 y SW0 (menor peso) serán asignados a
los siguientes pines (entre paréntesis):
- 63 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Pulsadores:
Señal de reloj:
- 64 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Ahora que disponemos del modelo VHDL del circuito completo (main.vhd), con los
diferentes componentes virtuales que lo integran (kcpsm.vhd, arithmetic_unit.vhd,
lcd_interface.vhd, program_memory.vhd) y del archivo de asignación de pines (pins.ucf),
procederemos a sintetizarlo e implementarlo en la FPGA.
Para ello utilizaremos la aplicación Xilinx ISE Design Suite 11, con dos de sus programas,
ISE Project Navigator para generar el archivo e iMPACT para grabarlo en la placa.
Para mayor comodidad nuestra, uniremos en un solo archivo VHDL todos los
componentes que conforman la Unidad Aritmética Decimal; este archivo será el
blocks_uad.vhd. Por tanto, el listado de programas utilizado será el siguiente:
• blocks_uad.vhd
• kcpsm.vhd
• lcd_interface.vhd
• main.vhd
• pins.ucf
• program_memory.vhd
- 65 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Abrimos el programa ISE Project Navigator y creamos un nuevo proyecto (New Project) y
escogemos un nombre para él. El siguiente paso es seleccionar las características del
dispositivo que estamos utilizando, que en nuestro caso serán las siguientes:
- 66 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
El primer paso consiste en sintetizar el modelo (Synthesize - XST); esto genera un reporte
que indica los recursos necesarios estimados para el dispositivo:
- 67 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
Grabaremos nuestro diseño (archivo main.bit) a través del puerto USB de la Spartan-3E.
Asignamos el archivo main.bit a la FPGA y los otros dos componentes los dejamos como
están (Bypass). Ejecutamos Program en xc3s500e y ya tenemos la unidad operativa (el led
DONE de la placa se enciende indicando que el proceso de implementación se ha
completado correctamente).
- 68 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Memoria experimental
- 69 -
Diseño sobre FPGA de una Unidad Aritmética Decimal
5. ANEXOS
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
- 71 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
----------------------------------------------------------------------
--Entidad del sumador de 1 dígito decimal
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
----------------------------------------------------------------------
--Arquitectura del sumador de 1 dígito decimal
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--Declaración de señales
SIGNAL d: STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL correction: STD_LOGIC_VECTOR(3 DOWNTO 0);
--Inicio
BEGIN
cy_out <= d(4) OR (d(3) AND (d(2) OR d(1))); --crea carry de salida
--si d>9
correction <= '0' & cy_out & cy_out & '0'; --se pone a '0110' si hay
--carry de salida
c <= d(3 DOWNTO 0) + correction; --aplica la corrección si
--hay carry de salida
END architecture_oda;
- 72 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
----------------------------------------------------------------------
--Entidad del bloque de complemento a 9
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY nine_complement IS
PORT(
e: IN STD_LOGIC_VECTOR(3 DOWNTO 0); --dígito de entrada
add_sub: IN STD_LOGIC; --señal de control del bloque
s: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); --dígito de salida
END nine_complement;
----------------------------------------------------------------------
--Arquitectura del bloque de complemento a 9
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
BEGIN
END architecture_nc;
----------------------------------------------------------------------
--Entidad del sumador/restador de n dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY n_adder_subs IS
GENERIC (n:natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
y: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
add_sub: IN STD_LOGIC; --operación: '0' suma y '1' resta
z: OUT STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --salida de n dígitos BCD
carry_out: OUT STD_LOGIC); --acarreo de salida
END n_adder_subs;
- 73 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
----------------------------------------------------------------------
--Arquitectura del sumador/restador de n dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--Declaración de constantes
CONSTANT i1: STD_LOGIC_VECTOR(4*n-1 DOWNTO 0) :=
CONV_STD_LOGIC_VECTOR(1,4*n);
--Declaración de señales
SIGNAL carries,carries2: STD_LOGIC_VECTOR(n DOWNTO 0);
SIGNAL y1: STD_LOGIC_VECTOR(4*n-1 DOWNTO 0);
SIGNAL z1,z2,z3: STD_LOGIC_VECTOR(4*n-1 DOWNTO 0);
SIGNAL oc, output_selection: STD_LOGIC;
--Declaración de componentes
COMPONENT one_digit_adder IS PORT(
a: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
b: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
c: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
cy_in: IN STD_LOGIC; --carry de entrada al bloque
cy_out: INOUT STD_LOGIC); --carry de salida del bloque
END COMPONENT;
--Inicio
BEGIN
carries(0) <= add_sub;
- 74 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
END architecture_nas;
----------------------------------------------------------------------
--Entidad del multiplicador de 1 dígito decimal
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
----------------------------------------------------------------------
--Arquitectura del multiplicador de 1 dígito decimal
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
- 75 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
--Declaración de señales
SIGNAL p: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL uu: STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL dd: STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL gt9, gt20, gt10st19: STD_LOGIC;
--Inicio
BEGIN
END architecture_odm;
----------------------------------------------------------------------
--Entidad del multiplicador de Nx1 dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY n_by_one_multiplier IS
GENERIC (n:natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
y: IN STD_LOGIC_VECTOR(3 DOWNTO 0); --entrada de 1 dígito BCD
z: OUT STD_LOGIC_VECTOR(4*n+3 DOWNTO 0)); --salida de n dígitos BCD
END n_by_one_multiplier;
----------------------------------------------------------------------
--Arquitectura del multiplicador de Nx1 dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--Declaración de señales
SIGNAL dd,uu: STD_LOGIC_VECTOR(4*n-1 DOWNTO 0);
SIGNAL ddc,uuc: STD_LOGIC_VECTOR(4*n+3 DOWNTO 0);
SIGNAL carries: STD_LOGIC_VECTOR(n+1 DOWNTO 0);
- 76 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
--Declaración de componentes
COMPONENT one_digit_multiplier IS PORT(
a: IN STD_LOGIC_VECTOR(3 DOWNTO 0); --entrada de 1 dígito BCD
b: IN STD_LOGIC_VECTOR(3 DOWNTO 0); --entrada de 1 dígito BCD
d: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --salida de 1 dígito BCD
u: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); --salida de 1 dígito BCD
END COMPONENT;
--Inicio
BEGIN
a_iteration: FOR i IN 0 TO n-1 GENERATE
multiplier: one_digit_multiplier PORT MAP(
a => x(4*i+3 DOWNTO 4*i),
b => y,
d => dd(4*i+3 DOWNTO 4*i),
u => uu(4*i+3 DOWNTO 4*i));
END GENERATE;
END architecture_nbom;
- 77 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
----------------------------------------------------------------------
--Entidad del multiplicador de N x M dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY n_by_m_multiplier IS
GENERIC (n,m:natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
y: IN STD_LOGIC_VECTOR(4*m-1 DOWNTO 0); --entrada de m dígitos BCD
start: IN STD_LOGIC; --señal de inicio
clk: IN STD_LOGIC; --señal de reloj
reset: IN STD_LOGIC; --inicializa la operación
z: INOUT STD_LOGIC_VECTOR(4*(n+m)-1 DOWNTO 0); --salida de N+M
--dígitos BCD
done: OUT STD_LOGIC); --resultado disponible
END n_by_m_multiplier;
----------------------------------------------------------------------
--Arquitectura del multiplicador de N x M dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--Declaración de estados
TYPE states IS RANGE 0 TO 3;
SIGNAL current_state: states;
--Declaración de constantes
CONSTANT initial_zeroes: STD_LOGIC_VECTOR(4*m-5 DOWNTO 0) := (OTHERS =>
'0');
--Declaración de señales
SIGNAL int_y: STD_LOGIC_VECTOR(4*m+3 DOWNTO 0); --registro y
--el registro z se declara en la entidad
SIGNAL x_by_yi: STD_LOGIC_VECTOR(4*n+3 DOWNTO 0);
SIGNAL next_z: STD_LOGIC_VECTOR(4*(n+m)-1 DOWNTO 0);
SIGNAL z_by_10, long_x_by_yi: STD_LOGIC_VECTOR(4*(n+m)-1 DOWNTO 0);
SIGNAL load, shift, end_of_computation: STD_LOGIC;
--Declaración de componentes
COMPONENT n_by_one_multiplier IS --multiplicador de Nx1 dígitos BCD
GENERIC (n:natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
y: IN STD_LOGIC_VECTOR(3 DOWNTO 0); --entrada de 1 dígito BCD
z: OUT STD_LOGIC_VECTOR(4*n+3 DOWNTO 0)); --salida de n dígitos BCD
END COMPONENT;
- 78 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
--Inicio
BEGIN
multiplier: n_by_one_multiplier
GENERIC MAP(n => n)
PORT MAP(
x => x,
y => int_y(4*m+3 DOWNTO 4*m),
z => x_by_yi);
--Sentencias secuenciales
register_y: PROCESS(clk)
BEGIN
IF clk'EVENT AND clk = '1' THEN
IF load = '1' THEN int_y <= y & "1111";
ELSIF shift = '1' THEN int_y <= int_y(4*m-1 DOWNTO 0) & "0000";
END IF;
END IF;
END PROCESS;
register_z: PROCESS(clk)
BEGIN
IF clk'EVENT AND clk = '1' THEN
IF load = '1' THEN z <= (OTHERS => '0');
ELSIF shift = '1' THEN z <= next_z;
END IF;
END IF;
END PROCESS;
- 79 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
--Unidad de control
control_unit_output: PROCESS(current_state, end_of_computation)
BEGIN
CASE current_state IS
WHEN 0 to 1 => shift <= '0'; load <= '0'; done <= '1';
WHEN 2 => shift <= '0'; load <= '1'; done <= '0';
WHEN 3 => IF end_of_computation = '0' THEN shift <= '1';
ELSE shift <= '0'; END IF; load <= '0'; done <= '0';
END CASE;
END PROCESS;
END architecture_nbmm;
----------------------------------------------------------------------
--Entidad del divisor de n dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY decimal_divider IS
GENERIC (n,m,p,logp:natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --dividendo
y: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --divisor
start: IN STD_LOGIC; --señal de inicio
clk: IN STD_LOGIC; --señal de reloj
reset: IN STD_LOGIC; --inicializa operación
q: OUT STD_LOGIC_VECTOR(4*m-1 DOWNTO 0); --resultado (cociente)
done: OUT STD_LOGIC); --operación realizada
END decimal_divider;
- 80 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
----------------------------------------------------------------------
--Arquitectura del divisor de n dígitos decimales
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--Declaración de estados
TYPE states IS RANGE 0 TO 3;
SIGNAL current_state: states;
--Declaración de constantes
CONSTANT initial_zeroes: STD_LOGIC_VECTOR(4*p-9 DOWNTO 0) := (
OTHERS => '0');
CONSTANT initial_zeroes_2: STD_LOGIC_VECTOR(4*p-5 DOWNTO 0) := (
OTHERS => '0');
--Declaración de señales
SIGNAL r, s1: STD_LOGIC_VECTOR(4*n-1 DOWNTO 0);
SIGNAL rr, rr_y, yy: STD_LOGIC_VECTOR(4*n+3 DOWNTO 0);
SIGNAL qq, ulp, qq_ulp, s2: STD_LOGIC_VECTOR(4*p-1 DOWNTO 0);
SIGNAL c_out: STD_LOGIC;
SIGNAL load, ce, zero: STD_LOGIC;
SIGNAL ulp_by_5: STD_LOGIC_VECTOR(4*p+3 DOWNTO 0);
SIGNAL count: STD_LOGIC_VECTOR(logp-1 DOWNTO 0);
--Declaración de componentes
COMPONENT n_by_one_multiplier IS --multiplicador de Nx1 dígitos BCD
GENERIC (n:natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
y: IN STD_LOGIC_VECTOR(3 DOWNTO 0); --entrada de 1 dígito BCD
z: OUT STD_LOGIC_VECTOR(4*n+3 DOWNTO 0)); --salida de n dígitos BCD
END COMPONENT;
--Inicio
BEGIN
- 81 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
register_qq: PROCESS(clk)
BEGIN
IF clk'EVENT AND clk = '1' THEN
IF load = '1' THEN qq <= (OTHERS => '0');--Valor inicial de qq es 0
ELSIF ce = '1' THEN qq <= s2; --Actualiza el valor de qq
END IF;
END IF;
END PROCESS;
register_ulp: PROCESS(clk)
BEGIN
IF clk'EVENT AND clk = '1' THEN
IF load = '1' THEN ulp <= "0101" & initial_zeroes_2;
--El valor inicial es 5, que representa 0.5
ELSIF ce = '1' THEN ulp <= ulp_by_5(4*p+3 DOWNTO 4);--Actualiza ulp
END IF;
END IF;
END PROCESS;
- 82 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
--Contador de p estados
counter_stages: PROCESS(clk)
BEGIN
IF clk'EVENT AND clk = '1' THEN
IF load = '1' THEN count <= CONV_STD_LOGIC_VECTOR(p-1, logp);
ELSIF ce = '1' THEN count <= count - 1;
END IF;
END IF;
END PROCESS;
--Unidad de control
control_unit: PROCESS(clk, reset, current_state, zero)
BEGIN
CASE current_state IS
WHEN 0 to 1 => load <= '0'; ce <= '0'; done <= '1';
WHEN 2 => load <= '1'; ce <= '0'; done <= '0';
WHEN 3 => load <= '0'; ce <= '1'; done <= '0';
END CASE;
IF reset = '1' THEN current_state <= 0;
ELSIF clk'EVENT AND clk = '1' THEN
CASE current_state IS
WHEN 0 => IF start = '0' THEN current_state <= 1; END IF;
WHEN 1 => IF start = '1' THEN current_state <= 2; END IF;
WHEN 2 => current_state <= 3;
WHEN 3 => IF zero = '1' THEN current_state <= 0; END IF;
END CASE;
END IF;
END PROCESS;
END architecture_divider;
----------------------------------------------------------------------
--Entidad de la unidad aritmética decimal
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY arithmetic_unit IS
GENERIC (n, p, logp: NATURAL);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --operando x
y: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --operando y
operation: IN STD_LOGIC_VECTOR(1 DOWNTO 0); --operación
start: IN STD_LOGIC; --señal de inicio
clk: IN STD_LOGIC; --señal de reloj
reset: IN STD_LOGIC; --inicializa
z: OUT STD_LOGIC_VECTOR(8*n-1 DOWNTO 0); --resultado
done: OUT STD_LOGIC); --operación lista
END arithmetic_unit;
- 83 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
----------------------------------------------------------------------
--Arquitectura de la unidad aritmética decimal
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--Declaración de señales
SIGNAL s1: STD_LOGIC_VECTOR(4*n-1 DOWNTO 0);
SIGNAL s2, s3: STD_LOGIC_VECTOR(8*n-1 DOWNTO 0);
SIGNAL c_out, done1, done2: STD_LOGIC;
SIGNAL start1, start2: STD_LOGIC;
--Declaración de componentes
COMPONENT n_adder_subs IS
GENERIC (n:natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
y: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
add_sub: IN STD_LOGIC; --operación: '0' suma y '1' resta
z: OUT STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --salida de n dígitos BCD
carry_out: OUT STD_LOGIC); --acarreo de salida
END COMPONENT;
COMPONENT n_by_m_multiplier IS
GENERIC (n, m: natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --entrada de n dígitos BCD
y: IN STD_LOGIC_VECTOR(4*m-1 DOWNTO 0); --entrada de m dígitos BCD
start: IN STD_LOGIC; --señal de inicio
clk: IN STD_LOGIC; --señal de reloj
reset: IN STD_LOGIC; --inicializa la operación
z: INOUT STD_LOGIC_VECTOR(4*(n+m)-1 DOWNTO 0); --salida de N+M
--dígitos BCD
done: OUT STD_LOGIC); --resultado disponible
END COMPONENT;
COMPONENT decimal_divider IS
GENERIC (n, m, p, logp: natural);
PORT(
x: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --dividendo
y: IN STD_LOGIC_VECTOR(4*n-1 DOWNTO 0); --divisor
start: IN STD_LOGIC; --señal de inicio
clk: IN STD_LOGIC; --señal de reloj
reset: IN STD_LOGIC; --inicializa operación
q: OUT STD_LOGIC_VECTOR(4*m-1 DOWNTO 0); --resultado (cociente)
done: OUT STD_LOGIC); --operación realizada
END COMPONENT;
--Inicio
BEGIN
- 84 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
addition_substraction: n_adder_subs
GENERIC MAP(n => n)
PORT MAP(
x => x,
y => y,
add_sub => operation(0),
z => s1,
carry_out => c_out);
multiplier: n_by_m_multiplier
GENERIC MAP(n => n, m => n)
PORT MAP(
x => x,
y => y,
start => start1,
clk => clk,
reset => reset,
z => s2,
done => done1);
divider: decimal_divider
GENERIC MAP(n => n, m => 2*n, p => p, logp => logp)
PORT MAP(
x => x,
y => y,
start => start2,
clk => clk,
reset => reset,
q => s3,
done => done2);
END architecture_au;
- 85 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
library IEEE ;
use IEEE.STD_LOGIC_1164.all ;
use IEEE.STD_LOGIC_ARITH.all ;
use IEEE.STD_LOGIC_UNSIGNED.all ;
library unisim ;
use unisim.vcomponents.all ;
entity program_memory is
port (
clk : in std_logic ;
reset : out std_logic ;
address : in std_logic_vector( 7 downto 0 ) ;
instruction : out std_logic_vector( 15 downto 0 )
) ;
end entity program_memory ;
- 86 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
- 87 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
begin
bram : component RAMB4_S8_S16
generic map (
INIT_00 =>
X"8322E2130200832B9D0561018339834BF210A211832B010F8340038083400301",
INIT_01 =>
X"83228347E212E2130203832B83228347E212E2130202832B8322E2130201832B",
INIT_02 =>
X"6000A010952B6000A01080809D2561018339834BB210010F834003C08100832B",
INIT_03 =>
X"8080E0110000E0110002E2108335808091356000A01280809532640104FF912E",
INIT_04 =>
X"808042309D50600AC020808091476000A0138080E0110000E0110001E3108335",
INIT_05 =>
X"0000000000000000000000000000000000000000000000000000808042406209",
INIT_06 =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_07 =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_08 =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_09 =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0A =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0B =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0C =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0D =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0E =>
X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0F =>
X"0000000000000000000000000000000000000000000000000000000000000000"
)
port map (
DIB => "0000000000000000",
ENB => '1',
WEB => '0',
RSTB => '0',
CLKB => clk,
ADDRB => address,
DOB => instruction( 15 downto 0 ),
- 88 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
----------------------------------------------------------------------
--Entidad del circuito completo
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
----------------------------------------------------------------------
--Arquitectura del circuito completo
----------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--Declaración de componentes
COMPONENT kcpsm IS PORT( --Procesador
instruction: IN STD_LOGIC_VECTOR(15 DOWNTO 0);
in_port: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
interrupt: IN STD_LOGIC;
reset: IN STD_LOGIC;
clk: IN STD_LOGIC;
address: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
port_id: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
out_port: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
write_strobe: OUT STD_LOGIC;
read_strobe: OUT STD_LOGIC);
END COMPONENT;
- 89 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
--Declaración de señales
SIGNAL port_id, in_port: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL mult_out: STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL ready, done: STD_LOGIC;
- 90 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
--Inicio
BEGIN
--Divisor de frecuencia
PROCESS(ext_clk)
BEGIN
IF reset = '1' THEN clk_2 <= '0';
ELSIF ext_clk'EVENT AND ext_clk = '1' THEN clk_2 <= NOT(clk_2);
END IF;
END PROCESS;
PROCESS(clk_2)
BEGIN
IF reset = '1' THEN clk_4 <= '0';
ELSIF clk_2'EVENT AND clk_2 = '1' THEN clk_4 <= NOT(clk_4);
END IF;
END PROCESS;
PROCESS(clk_4)
BEGIN
IF reset = '1' THEN clk_8 <= '0';
ELSIF clk_4'EVENT AND clk_4 = '1' THEN clk_8 <= NOT(clk_8);
END IF;
END PROCESS;
PROCESS(clk_8)
BEGIN
IF reset = '1' THEN clk <= '0';
ELSIF clk_8'EVENT AND clk_8 = '1' THEN clk <= NOT(clk);
END IF;
END PROCESS;
--Registros
register_temp_wr: PROCESS(clk)
BEGIN
IF clk'event AND clk = '0' THEN
IF port_id = "00010000" AND write_strobe = '1' THEN temp_wr <=
out_port;
END IF;
END IF;
END PROCESS;
- 91 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
register_id_write: PROCESS(clk)
BEGIN
IF clk'event AND clk = '0' THEN
IF reset = '1' THEN id_write <= "00";
ELSIF port_id = "00010001" AND write_strobe = '1' THEN
id_write <= out_port(1 DOWNTO 0);
END IF;
END IF;
END PROCESS;
register_x: PROCESS(clk)
BEGIN
IF clk'event AND clk = '0' THEN
IF port_id = "00001000" AND write_strobe = '1' THEN
x(3 DOWNTO 0) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00001001" AND write_strobe = '1' THEN
x(7 DOWNTO 4) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00001010" AND write_strobe = '1' THEN
x(11 DOWNTO 8) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00001011" AND write_strobe = '1' THEN
x(15 DOWNTO 12) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00001100" AND write_strobe = '1' THEN
x(19 DOWNTO 16) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00001101" AND write_strobe = '1' THEN
x(23 DOWNTO 20) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00001110" AND write_strobe = '1' THEN
x(27 DOWNTO 24) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00001111" AND write_strobe = '1' THEN
x(31 DOWNTO 28) <= out_port(3 DOWNTO 0);
END IF;
END IF;
END PROCESS;
register_y: PROCESS(clk)
BEGIN
IF clk'event AND clk = '0' THEN
IF port_id = "00000000" AND write_strobe = '1' THEN
y(3 DOWNTO 0) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00000001" AND write_strobe = '1' THEN
y(7 DOWNTO 4) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00000010" AND write_strobe = '1' THEN
y(11 DOWNTO 8) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00000011" AND write_strobe = '1' THEN
y(15 DOWNTO 12) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00000100" AND write_strobe = '1' THEN
y(19 DOWNTO 16) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00000101" AND write_strobe = '1' THEN
y(23 DOWNTO 20) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00000110" AND write_strobe = '1' THEN
y(27 DOWNTO 24) <= out_port(3 DOWNTO 0);
ELSIF port_id = "00000111" AND write_strobe = '1' THEN
y(31 DOWNTO 28) <= out_port(3 DOWNTO 0);
END IF;
END IF;
END PROCESS;
- 92 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
register_operation: PROCESS(clk)
BEGIN
IF clk'event AND clk = '0' THEN
IF port_id = "00010011" AND write_strobe = '1' THEN
operation(1 DOWNTO 0) <= out_port(1 DOWNTO 0);
END IF;
END IF;
END PROCESS;
main_component: arithmetic_unit
GENERIC MAP(n => 8, p => 56, logp => 6)
PORT MAP(
x => x,
y => y,
operation => operation,
start => start_op,
clk => clk,
reset => reset,
z => z,
done => done);
END architecture_main;
- 93 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
;direcciones de entrada
z0 DSIN $00
z1 DSIN $01
z2 DSIN $02
z3 DSIN $03
z4 DSIN $04
z5 DSIN $05
z6 DSIN $06
z7 DSIN $07
z8 DSIN $08
z9 DSIN $09
z10 DSIN $0a
z11 DSIN $0b
z12 DSIN $0c
z13 DSIN $0d
z14 DSIN $0e
z15 DSIN $0f
synch DSIN $10
data_in DSIN $11
ready DSIN $12
done DSIN $13
;direcciones de salida
y0 DSOUT $00
y1 DSOUT $01
y2 DSOUT $02
y3 DSOUT $03
y4 DSOUT $04
y5 DSOUT $05
y6 DSOUT $06
y7 DSOUT $07
x0 DSOUT $08
x1 DSOUT $09
x2 DSOUT $0a
x3 DSOUT $0b
x4 DSOUT $0c
x5 DSOUT $0d
x6 DSOUT $0e
x7 DSOUT $0f
temp_wr DSOUT $10
id_write DSOUT $11
start DSOUT $12
operation DSOUT $13
;registros internos
acc EQU s0
address EQU s1
data EQU s2
command EQU s3
counter EQU s4
- 94 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
;main program
begin:
load command, $01
call lcd_control ;send command 01 (clear) to display,
;borramos el display
load command, $80
call lcd_control ;send command 80 (cursor address = 00) to
;display, situamos el cursor al inicio de
;la primera fila
load address, $0f ;initial address = 15
;addition
call wait_for_synch ;wait for a positive edge on synch
load data, $00
out data, operation ;operation = 00
call display_z ;display x+y
;end of addition
;substraction
call wait_for_synch ;wait for a positive edge on synch
load data, $01
out data, operation ;operation = 01
call display_z ;display x-y
;end of substraction
;multiplication
call wait_for_synch ;wait for a positive edge on synch
load data, $02
out data, operation ;operation = 10
out data, start ;start computation
call wait_for_done
call display_z ;display x*y
;end of multiplication
;division
call wait_for_synch ;wait for a positive edge on synch
load data, $03
out data, operation ;operation = 11
out data, start ;start computation
call wait_for_done
call display_z ;display x/y
;end of division
- 95 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
;subroutines:
first_bis:
in data, address ;read z(address)
call encode_data ;data = ASCII code
call lcd_data ;display character data
sub address, $01 ;update address
jump NC, first_bis ;check whether address < 0
ret
wait_for_1:
in acc, synch
sub acc, $00
jump Z, wait_for_1
load counter, $ff
update_counter:
sub counter, $01
jump NZ, update_counter
ret
- 96 -
Diseño sobre FPGA de una Unidad Aritmética Decimal Anexos
;data = ASCII(data)
encode_data:
load acc, data
sub acc, $0a
jump NC, g_t_9
add data, $30
ret
g_t_9:
sub data, $09
add data, $40
ret
- 97 -
Diseño sobre FPGA de una Unidad Aritmética Decimal
6. BIBLIOGRAFÍA
Diseño sobre FPGA de una Unidad Aritmética Decimal Bibliografía
6. Bibliografía
[1] Serafín Alfonso Pérez, Enrique Soto, Santiago Fernández, “Diseño de Sistemas Digitales con VDHL”,
Editorial Thomson, 2002.
[2] Fernando Pardo Carpio, José A. Boluda Grau, “VHDL: Lenguaje para síntesis y modelado de
circuitos”, Editorial Ra-Ma, 1999.
[3] John F. Wakerly, “Diseño digital. Principios y prácticas”, Tercera edición, Editorial Prentice Hall,
2001.
[4] Thomas L. Floyd, “Fundamentos de sistemas digitales”, Novena edición, Editorial Prentice Hall,
2006.
[5] M. Vazquez, G. Sutter, G. Bioul, J.-P. Deschamps, “Decimal adders/substractors in FPGA: Efficient
6-input LUT implementations”.
[6] J.-P. Deschamps, G. Sutter, G. Bioul, M. Vazquez, “Decimal division: algorithms and FPGA
implementations”.
[7] G. Sutter, E. Todorovich, G. Bioul, M. Vazquez, J.-P. Deschamps, “FPGA Implementations of BCD
Multipliers”.
[9] ModelSim User’s Manual Software Version 6.5ª, Mentor Graphics, 2009.
[10] Spartan-3E FPGA Starter Kit Board User Guide, UG230 (v1.1), Xilinx, 2008.
[11] Spartan-3E FPGA Family: Functional Description, DS312-2 (v1.0), Xilinx, 2005.
[12] PicoBlaze 8-Bit Microcontroller for Virtex-E and Spartan-II/IIE Devices, XAPP213 (v2.1), Xilinx,
2003.
[13] http://www.model.com/
[14] http://www.xilinx.com/
- 99 -