sábado, 5 de diciembre de 2009

Sumador/Restador a 2 bits. Electrónica Digital


Viernes 04 Diciembre 2009

Como práctica de laboratorio, se me dejo implementar un sumador/restador de dos bits; es decir, un circuito que tiene dos entradas A y B (cada una de dos bits) que pueden ser sumadas ó restadas entre sí, el resultado se mida en la variable S (también de dos bits).

Se me ocurrieron dos cosas, implementar el circuito en base al CLA (Carry Look Ahead), usando el complemento a 1, mediante un programa en VHDL, o bien, una opción más fácil (y que les recomiendo si quieren hacerlo rápido) es mediante una tabla de verdad, planteo las opciones:

Sumador/Restador:

Definamos variables:
A: Entrada de dos bits
B: Entrada de dos bits
Cin: Carry (Acarreo) de entrada
S: Salida de dos bits
Cout: Carry (Acarreo) de salida.

Definidas las variables, tracemos las opciones.

Opción 1

Tabla de verdad de un sumador/Restador a dos bits:

Según los libros un sumador completo de dos bits es aquel que a parte de las dos variables de dos bits, se toma en cuenta el carry de entrada, entonces, traducido a un sumador sería realizar la suma tanto de A, B y Cin, lo que se traduce en una tabla de 32 combinaciones, ahora el truco que podemos aplicar aquí para nuestro Sumador/Restador es que, cuando el carry de entrada sea '0' cumpla la función de suma, en caso contrario, osea, cuando Cin este en '1' funcione como un restador, claro en complemento a dos, entonces la tabla de verdad nos quedaría así:

El código en VHDL no lo pongo, es muy sencillo de hacer, sólo tienes que poner como variable de selección al carry de entrada, de ahí te vas haciendo caso por caso, hasta que cumplas las 32 combinaciones algo sencillo, no?

Opción dos:

Sumador/Restador de dos bits usando el CLA (carry Look Ahead)

En este caso implementé las ecuaciones que nos posibilita el CLA, el programa es:

library IEEE ;

use IEEE.std_logic_1164.all;

entity sumador_restador is

port(

A,B : in std_logic_vector(1 downto 0);

Ci : in std_logic;

X : in std_logic; ---Selector de operación

S : out std_logic_vector(1 downto 0);

Co : out std_logic

);

end sumador_restador;

architecture recurrente of sumador_restador is

signal C :std_logic_vector(2 downto 0); --Acarreos intermedios

signal P :std_logic_vector(1 downto 0); --Complemento de B

signal V :std_logic_vector(1 downto 0); --Inversion

begin

process(A,B,Ci,X,P,V)

begin

V<=(others=> X); --Vector X de 2 bits

P<= B XOR V; --Complemento a dos

C(0)<= Ci XOR X;

FOR i IN 0 TO 1 loop

S(i)<=(A(i) XOR P(i)) XOR C(i); --Suma recurrente

C(i+1)<= ((A(i) AND P(i)) OR (A(i) AND C(i))) OR (P(i) AND C(i)); --Acarreo recurrente

end loop;

end process;

Co<= C(2);

end recurrente;

Como puedes observar, el código se puede generalizar a más bits, ahora bien, el código funciona muy bien para el caso de la suma, en cuanto a la resta, como ya te habrás dado cuenta usa el complemento a uno, si quieres que use el complemento a dos, sólo modifica las líneas centrales.

Entonces, ya tenemos nuestro código VHDL, compilamos, simulamos y todo bien!, ahora para determinar su síntesis uso el GALAXY de cypress, cuando lo sintetizo me salta un error!
¿Cómo puede ser eso posible, si el compilador del vhdl me dijo que todo andaba bien?
La respuesta es sencilla, todo tiene que ver con las macroceldas de nuestra GAL22V10, el archivo RPT creado te da una explicación, te dice que sobrepasas una función con veinte términos, si máxime son dieciséis, ahora ...
¿cómo resolver el problema?
Ya viste que el galaxy aunque te devuelva un error te devuelve un archivo RPT, ahi en ese archivo aunque no lo sintetice te muestra las funciones lógicas correspondientes, lo que tienes que hacer es tomar esas funciones, las vuelves a meter al vhdl y la función más larga, osea la de 20 OR's, partirla en dos funciones y externamente unirlas, todo es "talacha", te muestro el código que hice:

library IEEE ;

use IEEE.std_logic_1164.all;

entity sumador_restador is

port(

A,B : in std_logic_vector(1 downto 0);

Ci : in std_logic;

x : in std_logic; ---Selector de operación Sumador '0'/ Restador '1'

S : out std_logic_vector(2 downto 0);

Co : out std_logic -- Sumador/Restador '0'

);

end sumador_restador;

architecture recurrente of sumador_restador is

begin

process (A,B,Ci,x)

begin

co <= (A(0) and A(1) and (not (B(1))) and ci)OR

(A(0) and (not (B(0))) and (not (B(1))) and x ) OR

(A(0) and A(1) and B(0) and (not (ci))) OR

(A(1) and (not (B(0))) and (not (ci)) and x) OR

(A(0) and (not(B(1))) and (not(ci)) and x) OR

((not (B(0))) and (not (B(1))) and (not (ci)) and x)OR

(B(0) and B(1) and ci and (not (x))) OR

(A(1) and B(0) and ci and (not (x))) OR

(A(0) and B(1) and ci and (not (x))) OR

(A(0) and B(0) and B(1) and (not (x))) OR

(A(1) and (not (B(1))) and x) OR

(A(1) and B(1) and (not (x)));

s(0)<= (a(0) and b(0) and ci) OR

((not (a(0))) and (not(b(0))) and ci) OR

((not(a(0))) and b(0) and (not(ci))) OR

(a(0) and (not(b(0))) and (not(ci)));

s(1) <= ((not(a(0))) and a(1) and b(1) and ci and x) OR

((not (a(0))) and a(1) and b(0) and b(1) and x) OR

(a(0) and (not (a(1))) and (not(b(0))) and b(1) and x) OR

((not(a(0))) and (not(a(1))) and (not(b(1))) and ci and x) OR

((not(a(0))) and (not(a(1))) and b(0) and (not(b(1))) and x) OR

(a(0) and a(1) and (not(b(0))) and (not(b(1))) and x) OR

(a(0) and (not(a(1))) and b(1) and (not(ci)) and x) OR

(a(0) and a(1) and (not(b(1))) and (not(ci)) and x) OR

(a(0) and a(1) and b(1) and ci and (not(x))) OR

(a(0) and a(1) and b(0) and b(1) and (not(x))) OR

((not(a(0))) and (not(a(1))) and (not(b(0))) and b(1) and (not(x))) OR

(a(0) and (not(a(1))) and (not(b(1))) and ci and (not(x))) OR

(a(0) and (not(a(1))) and b(0) and (not(b(1))) and (not(x))) OR

((not(a(0))) and a(1) and (not(b(0))) and (not(b(1))) and (not(x))) OR

((not(a(0))) and (not(a(1))) and b(1) and (not(ci)) and (not(x))) OR

((not(a(0))) and a(1) and (not(b(1))) and (not(ci)) and (not(x)));

s(2) <= (a(1) and b(0) and b(1) and ci) OR

((not(a(1))) and b(0) and (not(b(1))) and ci) OR

((not(a(1))) and (not(b(0))) and b(1) and (not(ci))) OR

(a(1) and (not(b(0))) and (not(b(1))) and (not(ci)));

end process;

end recurrente;


Todo este choro para una méndiga suma y resta de sólo dos bits!!!
El código lo metes al vhdl, compilas, después al galaxy, copiar el .jed y lo pasas a la gal22v10, te guías con el "patigrama" o "mapa de fusibles" del .rpt y realizas las conexiones correspondientes, recuerda que es un TTL, por tanto su funcionalidad debe estar dentro del rango de 0 a 5 V, tomé algunas fotos:





Sumador. Cin '0' A= '10' B= '01' ; S='011'




Restador. Cin '1' A= '10' B='01'; S='001'

Y así se implementa un sumador/restador de dos bits, cabe mencionar que la primera opción es la más fácil, en su implementación sólo necesita 1 gal22v10 mientras que con la segunda opción se requiere una 74LS32 (OR de dos entradas) para poder sumar las funciones externamente, aún así sólo te ofrezco dos posibilidades, seguro existen más.

Me he cansado de tanto escribir, espero que les sea de utilidad y cualquier comentario háganmelo saber, hasta luego :)