miércoles, 8 de septiembre de 2010

Como hacer una ALU en la Spartan 3

Según la revista Master Magazinel la Unidad Aritmético Lógica, o simplemente ALU (por Arithmetic Logic Unit) es una de las unidades que conforman la Unidad Central de Procesos (CPU) mediante la cual se pueden realizar un conjunto de operaciones aritméticas básicas (resta, suma, división y multiplicación) y de operaciones lógicas (OR, NOT, AND, etc.)

Los circuitos mediante los que la ALU ejecuta dichas operaciones pueden ser desde muy simples a muy complejos. Entre estos últimos se encuentran, por ejemplo, los de los chips de losmicroprocesadores. En general, la mayoría de las acciones de una computadora se realizan a través de una ALU. Y en dichos circuitos se encuentras diversos componentes que permiten que la ALU pueda efectuar las operaciones.

Para esta practica se realizo una ALU con las siguientes operaciones:
1.      NOT de 2 bits
2.      AND de 2 bits
3.      OR de 2 bits
4.      XOR de 2 bits
5.      Suma de 2 bits + 2bits
6.      Multiplicación de 2 bits * 2 bits
7.      Corrimiento a la izquierda
8.      Corrimiento a la derecha



Ahora para pasar a la realizacion del codigo se tiene que debido a que la tarjeta Spartan 3 solo tiene 8 switches se realizo un arreglo en la declaracion de variables como se explicara mas adelante.
En las variables todas las tuvimos que hacer un arreglo del mismo tipo aunque no usara todas las posibles combinaciones ya que si no marcaba algunos errores y de este modo ya no marco nada. Asi que es una recomendacion a seguir.

entity ALU is
    Port ( x : in  STD_LOGIC_vector(3 downto 0); --arreglo de 4 bits
           y : in  STD_LOGIC_vector(3 downto 0);
           Operation : in  STD_LOGIC_vector(3 downto 0);  
 result : out std_logic_vector(3 downto 0)
);
end ALU;

En este caso X y Y seran tus dos numeros de dos bits cada uno
Result sera el resultado a imprimir y Operation sera la variable que complementa el case y el process para que cuando esa variable cambie, todas las demas cambien.

architecture Behavioral of ALU is
signal Temp : STD_LOGIC;
begin

process (operation, x, y) --inicio del process
*Nota: lo que hace un process es como un arreglo donde los valores que estan dentro de parentesis cuando cambian lo inicializan y los valores que tenian asignados cambian.
begin
case operation is  -- el case son como tus condiciones a seguir dentro del programa
when "0000" => result <= "0000"; --NOT
result <= not x;
Este ejemplo de la primer linea dice que cuando tu numero binario sea "0000" tu variable result se le asignara la operacion negacion de X y "0000" que esta antes es solo para que cuando cambien las variables empiezen desde 0 y no haya error de que se les quedo guardado un valor de  la operacion anterior a la hora de cambiar a otra. Es por ello que  la parte de "0000" aparece en todo el codigo.

when "0001" => result <= "0000"; --AND
result(0) <= x(0) and y(0);
Esta segunda parte hace una simple compuerta AND de X y Y pero solo de su primer bit, es decir del menos significativo, ya que si recuerdan X y Y son numeros de dos bits pero aqui solo hace la AND de los dos primeros.
De aqui en adelante es la misma metodologia para las demas.
when "0010" => result <= "0000";
result(0) <= x(0) or y(0); --OR
when "0011" => result <= "0000";
result(0) <= x(0) xor y(0); --XOR

Esta linea es de las mas complejas de entender ya que si se fijaron en el principio tras el architecture se declaro una variable temporal, esta es para la suma ya que si ven el diagrama de una suma de un numero de dos bits con otro, encontraran que hay carrys que en este caso pasan a ser la variables temp y que las siguientes partes  es la secuencia logica que sigue un full adder.
when "0100" => result <= "0000"; --ADD
result(0) <= x(0) xor y(0);
Temp<= x(0) and y(0);
result(1) <= x(1) xor y(1) xor Temp;
result(2) <= (x(1) and y(1)) or (x(1) and Temp) or (y(1) and Temp);
Los corrimientos se hacen con una sustitucion ya que si saben como funciona un corrimiento quiere decir que el valor que venia antes de el pasa a ser su nuevo valor del actual, es decir si x=0 y el siguiente valor es 1 ahora x pasara a ser 1
when "0101" => result <= "0000"; --x<<y
result(0) <= x(1); --al primer valor pasale el valor que tiene x(1)
result(1) <= y(0); -- al siguiente valor pasale el valor que tiene y(0)
when "0110" => result <= "0000"; --x>>y
result(0) <= y(0);
result(1) <= x(0);
La parte mas compleja de visualizar es la multiplicacion ya que para llevarla acabo tienes que deducir una logica similiar a cuando multiplicas con numeros base 10, ya que vas multiplicando bit por bit y luego tienes que sumar los resultados que te van saliendo en caso de ser posible.
Para darte una idea aqui esta el siguiente ejemplo:


Cuando multiplicas 1*1= 1, luego 1*0=0 y asi sucesivamente, te daras cuenta de que multiplicas el primer bit por todos los de arriba y continuas con el procedimiento como mencionaba antes como si fuera base 10 y asi te da el resultado de la multiplicacion pero en binario, posteriormente tienes que sumar los valores para obtener una sola expresion y el numero final es el que tienes que visualizar. 




Para saber que compuertas tienes que usar aqui esta el siguiente ejemplo:

 Si te das cuenta la multiplicacion de un bit por un bit se asemeja a la compuerta AND por lo tanto las compuertas que usas para multiplicar son ANDs y EXORs para hacer las sumas de los bits temporales tal como vimos en la parte del adder. Con esta logica encuentras el siguiente codigo para la multiplicacion de dos bits por dos bits.


when others => result <= "0000"; --multiplicación
result(0) <= x(0) and y(0);
result(1) <= (x(1) and y(0)) xor (y(1) and x(0));
Temp <= (x(1) and y(0)) and(y(1) and x(0));
result(2)<= ((x(1) and y(1)) xor Temp);
result(3)<=((x(1) and y(1)) and Temp);
end case; --cierre de los case
   end process; -cierre de process
end Behavioral; --cierre de programa

Por último cabe resaltar que a la hora de programar te marcara el código unos warnins pero puedes hacer caso omiso de ellos pues pese a esto el codigo funciona muy bien y hace las operaciones que se especifican de manera correcta. 
Recuerda tambien con el planAhead asignar pines y con el programa adept bajarlo a tu tarjeta para probarlo.

domingo, 5 de septiembre de 2010

Como hacer un multiplexor en la Spartan 3

Un multiplexor es la función inversa a un decodificador, es decir, tienes n numero de entradas que se seleccionan  con otras entradas denominadas de selección y lo que tienes a la entrada lo deja pasar a su unica salida. De modo grafico se ve asi:
En modo de bloque:
Este es el ejemplo de un mux de 4 a 1. Con las entradas de seleccion puedo seleccionar que entrada quiero que aparesca a la salida del mux, es decir si pongo 00 en este caso seleccionaria la entrada 1, si selecciono 01 en las entradas de seleccion ahora escogeria la entrada numero 2 y asi sucesivamente.

Con base en estos principios pasamos a programar la FPGA
Se declararon las variables iniciales
entity Mux is
    Port ( A1 : in  bit;
           A2 : in  bit;
           A3 : in  bit;
           A4 : in  bit;
           S1 : in  bit;
           S2 : in  bit;
           O  : out bit);
end Mux;

Dentro de esta arquitectura declaramos variables temporales ya que cuando programas una FPGA todos los comandos del codigo se realizan al mismo tiempo por lo tanto esta es una forma de decirle que asigne de manera secuencial, es decir que primero declare las variables temporales y luego define cual de todas ellas usas, es como hacerlo en bloques. La forma de declarar variables temporales es con la palabra reservada signal luego el nombre de la variable: bit_vector(3 downto 0) lo que significa cuantas variables declararas como temporales, es como hacer un arreglo de variables en forma de vectores.

architecture Behavioral of Mux is
signal tmp:  bit_vector (3 downto 0); --declaracion de variables temporales
begin --aplicacion de variables temporales
tmp(0)<= ((NOT S1) AND (NOT S2) AND A1);
tmp(1)<= ((NOT S1) AND S2 AND A2);
tmp(2)<= (S1 AND (NOT S2) AND A3);
tmp(3)<= (S1 AND S2 AND A4);
O<= tmp(0) or tmp(1) or tmp(2) or tmp(3); --salida del mux
end Behavioral;


Cabe resaltar que esta es una forma de hacer un multiplexor ya que conforme avanzas en codigo te daras cuenta de que existen muchas formas mas de hacerlo pero todo depende de la logica que tu encuentres. Mas adelante les mostraremos mas tipos de codigos para hacer un mux y otras cosas interesantes.

miércoles, 1 de septiembre de 2010

Como hacer un decodificador en la spartan 3

Antes de empezar a programar tienes que entender como funciona un decodificador, en este caso  analizaremos el deco de 3 a 8.
Para los que no saben mucho acerca de sistemas digitales un decodificador es un dispositivo que acepta una entrada digital codificada en binario y solo activa una de sus salidas, es decir, si yo ingreso el numero 000 en binario en un decodificador de 3 a 8 podras encontrar activa la primer salida, si el caso fuera 001 encontrarias activa la segunda salida y asi sucesivamente. Un deco de 3 a 8 significa que tiene tres entradas donde puedes ingresar un numero binario de 3 bits (desde 0 hasta 7 en decimal ) y de acuerdo a la combinacion que ingrese encontraras la salida activa correspondiente.

Un decodificador por dentro esta compuesto de compuertas AND y NOT con lo cual te das cuenta que a la salida de cada uno de los pines encontraras una funcion booleana correspondiente, con este principio ahora puedes empezar a programar tu FPGA.

Tras hacer los pasos mencionados en otras ocasiones de como empezar a programar pasaremos a la parte de codigo. Cuando encuentras la deduccion de las variables te das cuenta que a la salida numero 1 de las 8 posibles tienes (NOT A0) AND (NOT A1) AND (NOT A2) donde A0, A1 y A2 son tus entradas binarias.
a la segunda salida te queda NOT A0) AND (NOT A1) AND (A2), dando como resultado un codigo como el siguiente:


entity DECO is
    Port ( S0 : out  STD_LOGIC;
           S1 : out  STD_LOGIC;
           S2 : out  STD_LOGIC;
           S3 : out  STD_LOGIC;
           S4 : out  STD_LOGIC;
           S5 : out  STD_LOGIC;
           S6 : out  STD_LOGIC;
           S7 : out  STD_LOGIC;
           A0 : in  STD_LOGIC;
           A1 : in  STD_LOGIC;
           A2 : in  STD_LOGIC);
end DECO;

architecture Behavioral of DECO is

begin
S0<= (NOT A0) AND (NOT A1) AND (NOT A2);
S1<= (NOT A0) AND (NOT A1) AND (A2);
S2<= (NOT A0) AND (A1) AND (NOT A2);
S3<= (NOT A0) AND (A1) AND (A2);
S4<= (A0) AND (NOT A1) AND (NOT A2);
S5<= (A0) AND (NOT A1) AND (A2);
S6<= (A0) AND (A1) AND (NOT A2);
S7<= (A0) AND (A1) AND (A2);

end Behavioral;

Con este código programado en tu tarjeta tendras un decodificador de 3 a 8 listo para ser usado en tu tarjeta.

Como hacer un full adder en la spartan 3

Un full adder es un circuito lógico que suma dos bits y además se complementa con un “carry” de entrada y uno de salida, al conectar los “carry” en cascada, se logra un sumador de n bits. Se logra con dos compuertas Xor, dos AND's y una compuerta OR tal como se muestra acontinuacion.

Ahora para programar un sumador de 4 bits se tiene el siguiente diagrama:



Con esta deduccion podemos empezar a programar el sumador completo

Para empezar a programar cualquier cosa en la Spartan 3 debes de abrir tu programa, y crear un nuevo proyecto, posteriormente asignarle un nombre y en seguida te arrojara una pantalla donde tienes que ingresar las especificaciones de tu tarjeta las cuales vienen en el integrado, por ejemplo la que estamos usando sus especificaciones son:

Device Family: Spartan3

Device: xc3s200
Package: ft256
Speed: -4
Synthesis Tool: XST (VHDL/Verilog)
Simulator: Modelsim-XE VHDL
Preferred Language: VHDL
Property Specification in Project File: Store all values
Manual Compile Order: false
VHDL Source Analysis Standard: VHDL-93

Despues de poner tus especificaciones encontraras una pantalla que te indica que ingreses los nombres que le quieres asignar a las variables que vas a usar asi como tambien denominarlas como de entrada(in), salida(out)  o de entrada-salida(inout). (Aunque no crees todas tus variables al principio en esta pantalla las puedes designar despues dentro del programa)

Tras finalizar la declaracion de variables iniciales se te creara en automatico la libreria que necesitas por default, luego aparecera la estructura de tus variables que declaraste y al final comenzaras a programar tu codigo que buscas compilar. A continuacion se pone el ejemplo del programa para que puedas ver como se soluciona a grandes rasgos.


Sum0 <= A0 xor B0 xor Cin after 10 ns;
C(1) <= (A0 and B0) or (A0 and Cin) or (B0 and Cin) after 10 ns; --se pueden omitir los Cin
Sum1 <= A1 xor B1 xor C(1) after 15 ns;
C(2) <= (A1 and B1) or (A1 and C(1)) or (B1 and C(1)) after 15 ns; --notese que se dam as tiempo para que se logre un procedimiento secuencial
Sum2 <= A2 xor B2 xor C(2) after 20 ns;
C(3) <= (A2 and B2) or (A2 and C(2)) or (B2 and C(2)) after 20 ns;
Sum3 <= A3 xor B3 xor C(3) after 25 ns;
C<= (A3 and B3) or (A3 and C(3)) or (B3 and C(3)) after 25 ns;
Sin olvidar que primero hay que declarar las variables fijas
Port (A0,A1,A2,A3,B0,B1,B2,B3: in bit;
                Sum0, Sum1, Sum2, Sum3, C: out bit);

Los valores como Sum0 son variables de salida, otro ejemplo son las variables A0 y B0 que son variables de entrada y los signos de and y xor corresponden a las compuertas que usas en el metodo fisico y son como palabras reservadas. Por ultimo los signos <= es como si fuese un solo simbolo que en este caso quiere decir asignacion como si pusieras Sum0 = A0 xor B0 y el valor que resulta se guarda en la variable Sum0

Para compilar tu programa en design en tu creador de planAhead podras asignar los pines,switches, leds o lo que tu vayas a usar de tu tarjeta a cada una de tus variables. Para ello usas I/O properties y vas seleccionando cada una de acuerdo a lo que tu quieres, los nombres de cada componente que vayas a usar vienen nombrados en la tarjeta entre parentesis. Por ultimo creas tu archivo.bit y lo programas en tu tarjeta con el programa adept y esta listo para probarse.

De esta forma ahora podras programar tu FPGA para que tengas un sumador completo.



VHDL

Cuando programas en VHDL puedes usar el programa Xilinx que puedes descargar de internet completamente gratuito. Tambien un hardware que se lleva bien con el programa es la tarjeta FPGA Spartan 3 o en sus modelos mas recientes como la Spartan 3E lo unico que cambia a la hora de programar la tarjeta son las especificaciones que determinas al inicio de un proyecto.

Ademas cuando programas una FPGA como la spartan debes de adquirir el programa adept que lo puedes encontrar de igual manera en internet con el cual ya una vez que hayas asignado pines y terminado tu programa de forma exitosa puedes programarla. Al principio solo la reconoce, luego la buscas con el programa adept y buscas tu archivo.bit que creaste con tu programa en xilinx y le das program y automaticamente quedara lista y la podas probar.

Algunos problemas que puedes tener

Un inconveniente de Xilinx es que desde que surgio a crecido notablemente el programa lo cual lo deja con un peso de descarga de aprox 3 GB y de instalacion alrededor de 10GB por lo cual debes tener espacio en tu disco duro y una buena conexion a internet si quieres instalarlo, asi como tambien adquirir la licencia para que funcione correctamente (la licencia esta disponible de forma gratuita)

Otro problema que surgio fue que aparentemente se habia desconfigurado con lo cual no salian algunas aplicaciones del programa y no podia compilar mis archivos pero al desinstalarlo y volverlo a instalar todo quedo excelente.