PROYECTO DIVISIÓN
Como Hacer Una División 8bits/4bits En Binarios
Al contrario de la
multiplicación, si necesitamos implementar una división entera, el operador ʺ/ʺ
no está soportado para la síntesis, por lo tanto tendremos que diseñar el
divisor.
Existen muchos algoritmos de
división, a continuación se explicará uno que es el que resulta más parecido a
nuestra forma de dividir a mano y es por tanto más sencillo de entender.
En la figura 1 se muestra una división entera realizada con
números enteros decimales y con números enteros binarios.
Figura 1: Ejemplo de división entera en
decimal y en binario
Veamos paso a paso el algoritmo para hacer la
división:
Primero desplazamos a la izquierda el divisor
lo más que podamos siempre que ʺquepaʺ en el dividendo (D>d). La cantidad de
veces que se ha desplazado la memorizamos. En electrónica digital, diríamos que
la guardamos en un registro que llamaremos Desplz.
En nuestro ejemplo de la "figura 2" el desplazamiento es 3.
Figura 2: Paso 1 de la división - cálculo
del desplazamiento inicial
Una vez que tenemos el divisor desplazado lo
más posible a la izquierda (Desplz=3),
restamos al dividendo el divisor y ponemos un 1 en el cociente (figura 8.22). En la figura
se han rellenado los ceros que faltan a la derecha provocados por el
desplazamiento. En el cálculo manual se hace implícitamente aunque no se ponen
para ahorrar la escritura de la resta completa.
Figura 3: Paso 2 de la
división
Ahora, el divisor, que hemos desplazado tres
veces a la izquierda, lo desplazamos una vez a la derecha, es decir, como si
del original lo desplazásemos dos veces a la izquierda. Por tanto Desplz=2. Probamos si cabe con el resultado de la resta
anterior, si cabe (D³d) ponemos un uno en el cociente.
Figura 4: Paso 3 de la división
Volvemos a desplazar el divisor a la derecha (ahora Desplz=1), y volvemos a ver si cabe en la nueva resta que hemos hecho.
Figura 5: Paso 4 de la división
Vemos que esta vez no cabe, por tanto pondremos un cero en el cociente, no hacemos la resta, y probamos desplazando el divisor a la derecha (ahora el Desplz=0, volvemos a como estaba al principio)
Figura 6: Paso 5 de la división
Tampoco cabe, y como el cociente ha vuelto a su posición original (Desplz = 0) la división se termina (pues no sacamos
decimales).
Figura 7: Paso 6 de la división
Ahora desplazando los restos a la izquierda
podríamos sacar decimales. En este caso podríamos sacar el primer decimal para
calcular el redondeo del cociente.
Así pues la implementación en hardware de este
algoritmo de división se podría hacer de manera secuencial, pero también se
podría ʺdesenrollarʺ y realizarla de manera combinacional o segmentada.
Si se realiza
de manera secuencial,
la división se
haría en varios
ciclos de reloj, que
dependerá del número de bits de
los operandos. Por tanto, igual que con el multiplicador secuencial, el divisor
necesitará de una parte de control que ordene la ejecución de las operaciones
que haya que realizar en cada momento. Una vez terminadas las operaciones deberá proporcionar una señal de
aviso que indique que el resultado está disponible.
Además, el módulo tendrá una señal de entrada que ordene la ejecución de
la división.
Para este ejemplo
no se va
a incluir el
esquema o el
código VHDL del
divisor. Te recomendamos que lo implementes por ti mismo y
que hagas el banco de pruebas. Con la información sobre el algoritmo de
división junto con las explicaciones del algoritmo de multiplicación y los
otros operadores de este capítulo, pensamos que lo podrías hacer por ti mismo.
Incluso te proponemos que implementes una
pequeña calculadora en la FPGA. Metiendo los datos por los pulsadores e
interruptores o por la UART. Por ejemplo, si usas la Nexys2, los interruptores podrían ser los operandos y los botones
la operación: suma, resta, multiplicación y división. El resultado se obtendría
por el display de siete segmentos.
Si usas la XUPV2P, como no hay tantos
pulsadores ni interruptores, puedes realizar la operación por la UART,
introduciendo primero el primer operador, luego la operación y por último el
segundo operador. El mayor problema aquí será el control de lo que llega por la
UART y la conversión en órdenes al módulo que realiza la operación. Para
simplificar, te recomendamos que los números que envíes estén codificados en
binario o en hexadecimal, pero no en decimal. Esto significa que desde el
hiperterminal68 enviarías
por ejemplo: ʺ1110/11=ʺ
ó ʺE/3=ʺ en
vez de ʺ14/3=ʺ.
Tu circuito debería
devolver:
ʺ1000
R10ʺ(en binario) ó ʺ4 R2ʺ (en hexadecimal). Elige una de las dos formas.
Este circuito de división o
calculadora por la UART tiene cierta complejidad debido al control,
conversiones y la unión de varios módulos, aparte de la propia complejidad del divisor. Sin embargo, podría ser un interesante proyecto que unificaría todo lo que hemos visto hasta ahora.
codigo en vhdl
En la imagen “Código VHDL De La Division De 7 Bits/4 Bits”, utiliza
un procedimiento VHDL para implementar el divisor de 7 bits mostrado en el Diagrama
de estados. Obsérvese que el procedimiento implementa el algoritmo division4
descrito anteriormente que Resulta en un cociente de 4 bits. Llamar a este
procedimiento dos veces en el proceso en la Programa implementará el circuito
mostrado en el diagrama de estados Tenga en cuenta que los procedimientos deben
ser llamados desde dentro de un proceso. No contienen procesos. Declaraciones
de procedimiento, por ejemplo, si Los bucles sólo se pueden utilizar dentro de
un procedimiento sin un proceso.
Circuito Anti Rebote
El uso de actuadores mecánicos como los pulsadores,
tiene muchas ventajas, sobre todo económicas, ya que son muy baratos. Sin
embargo, precisamente por su naturaleza mecánica, vienen acompañados de ciertos
problemas que dependiendo del uso que hagamos de ellos, pueden llegar a ser un
verdadero quebradero de cabeza. El mayor de estos inconvenientes es el rebote
o bouncing.
Al ser accionados, los pulsadores tardan cierto
tiempo en alcanzar un estado estable, es decir, que durante muy poco tiempo
(del orden de los milisengundos) pueden cambiar entre el estado pulsado y no
pulsado hasta que la señal se estabiliza. A pesar de ser muy poco tiempo, es el
suficiente para que un sistema digital lo detecte como varias pulsaciones. La
siguiente imagen muestra una señal de rebote típica.
Hay varias aproximaciones para solucionar este
problema, tanto hardware como software. En esta ocasión vamos a ver cómo atajar
este problema desde el punto de vista hardware y más concretamente con VHDL.
Obviamente, hablamos de un circuito secuencial que
debe recordar si el botón estaba pulsado en un momento anterior y compararlo
con el estado actual, así que es necesario el uso de biestables o flip flops. La idea general es que si durante un
periodo de tiempo lo suficientemente amplio (unos 10 u 11 milisegundos) el
valor actual del pulsador y el valor del flip flop que
almacena el estado anterior son iguales, podemos dar por sentado que el
pulsador ha llegado a un estado de pulsación estable. El siguiente código VHDL
implementa dicho circuito.
codigo en vhdl
Antirebote de pulsadores…
library ieee;
use
ieee.std_logic_1164.all;
use
ieee.std_logic_unsigned.all;
entity antirebote is
port (
clk :
in std_logic;
btn_in : in std_logic;
btn_out : out std_logic);
end antirebote;
architecture beh of
antirebote is
constant CNT_SIZE : integer := 19;
signal btn_prev : std_logic := '0';
signal counter : std_logic_vector(CNT_SIZE downto 0) :=
(others => '0');
begin
process(clk)
begin
if (clk'event and clk='1') then
if (btn_prev xor btn_in) = '1' then
counter <= (others => '0');
btn_prev <= btn_in;
elsif (counter(CNT_SIZE) = '0') then
counter <= counter + 1;
else
btn_out <= btn_prev;
end if;
end if;
end process;
end beh;
La señal btn_prev es el
biestable encargado de almacenar el estado anterior (entiéndase, el estado en
el pulso de reloj anterior). Para contar el tiempo se usa un contador de 20
bits .Dentro del proceso, en cada pulso de reloj se comprueba mediante una
puerta xor si el valor del pulsador es diferente al del pulso de reloj previo.
Si es así, el contador se pone a cero y vuelve a comenzar la cuenta de tiempo,
si no, se incrementa el contador, salvo que su último bit sea 1, en cuyo caso,
ha pasado el tiempo suficiente como para dar por hecho que la pulsación ya es
estable. Si este es el caso, ponemos el valor del biestable btn_prev en btn_out (que es
otro biestable que se conecta a la salida del circuito).
El tamaño del contador se ha ajustado para una
frecuencia de reloj de 50 MHz. En general, el tiempo que se consigue según el
tamaño del contador se puede aproximar con la siguiente fórmula.
Siendo n el número de bits del contador. Así pues,
en este caso tenemos un reloj de 50 MHz y un contador de 20 bits. Como en
realidad el contador no va a contar hasta el final sino hasta que su bit más
significativo sea 1, podemos usar un valor n=19 como una aproximación más que
aceptable.
Por lo tanto, estamos dejando un margen de algo más
de 10 milisegundos para que se estabilice el pulsador. Un valor muy razonable
para un pulsador normal.
Código VHDL De La Division De 7 Bits/4 Bits
Division4.
1. Almacene el numerador en la concatenación de 111: n2
2. Almacene el denominador en d
3. Repita 4 veces:
cambio n1&n2 corre a la izquierda un bit
Si n1> d
n1 = n1- d;
n2(0) = 1;
4. Cociente = n2
Residuo = n1 (3: 0);
El problema con el algoritmo division4 es que divide un numerador
de 7 bits
(Dividendo) por un denominador de 4 bits (divisor) y produce
un cociente de 4 bits y un 4-bit
recordatorio. Si el divisor es demasiado pequeño (menor que
los 4 bits superiores del dividendo) entonces el cociente no encajará en 4 bits
y tenemos una condición de desbordamiento. Lo que necesitamos es un Algoritmo que producirá un cociente de 7 bits y un resto de
4 bits, podemos hacerlo mediante Llamar al algoritmo Loop dos veces. Primero dividimos el
divisor en la "parte alta" de la Dividendo para obtener la "parte alta" del
cociente. El "alto resto" Se convierte en parte del dividendo restante que es dividido
por el divisor para obtener la "parte baja" Del cociente y el resto final.
Diagrama De Estados
División Ejemplo 1
División Ejemplo 2
Cuando
se llega al estado del decodificador se hace lo siguiente:
Debe pasar de binario
a BCD
Para lo cual se utiliza el siguiente método
En este método, que puede resultar muy
útil en electrónica o en computación, lo primero que se hace es comparar el
número binario con el número nueve, pero expresado en código BCD; enseguida, si
el número binario que queremos convertir a BCD es mayor que el número nueve,
entonces al número binario que se convertirá en BCD se le suma el número seis
(expresado también en BCD). Posteriormente, vamos a incrementar el número que
nos sirve para comparar (la referencia) y en lugar de nueve se convertirá en
diecinueve (expresado en BCD), y si el nuevo número obtenido sigue siendo mayor
al número con el cuál lo estamos comparando, nuevamente se le vuelve a sumar
seis. Reiteraremos el proceso cuantas veces sea necesario, y lo que se estará
realizando por medio de este método, es que después de que se ha ido sumando el número seis consecutivamente
a cada número binario que pretendemos convertir a BCD, se compararan estos resultados con los
números nueve (expresado en BCD), diecinueve (expresado en BCD), veintinueve
(expresado en BCD), treinta y nueve, y así sucesivamente, hasta que el nuevo
número que le hemos ido sumando sucesivamente el número seis en BCD, sea menor
o igual que el número con el cual lo estamos comparando.
110001 es mayor que (>) 001001, entonces se le
sumara el número 0110 (seis)
110001 > 00 1001
+ 0110
110111 >01 1001
+ 0110
111101 > 10 1001
+ 0110
1000011 > 11 1001
+ 0110
1001001 < 100 1001
110001 > 00 1001
+ 0110
110111 >01 1001
+ 0110
111101 > 10 1001
+ 0110
1000011 > 11 1001
+ 0110
1001001 < 100 1001
Ejemplo 2 numero 36
Al número 36 en binario se compara y se le suma seis si es mayor
110011 > 00
1001 =9
110
101010 > 01
1001 =25
110
110000 > 10
1001 =41
110
011 0110 > 11
1001 =57
3 6
De esta forma se realiza la codificación del número qué se va a mostrar en los display de siete segmentos,
multiplexados.
CODIGO VHDL