martes, 22 de noviembre de 2016

PROYECTO DIVISIÓN

FUNCIONALIDAD


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.




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



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.



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

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
















No hay comentarios:

Publicar un comentario