Curso VHDL – Sumador/Restador con operadores aritméticos

Se nota que me gustan los sumadores ¿verdad? En las anteriores entregas hemos armado sumadores a base de compuertas que se unieron para crear medios sumadores y a partir de estos sumadores completos. Posteriormente armamos un sumador de un bit a partir de su ecuación booleana, que utilizamos para armar un sumador de cuatro bits. En esta entrega veremos un circuito de suma más (que también resta), pero en esta ocasión haremos uso de los operadores aritméticos que VHDL pone a nuestra disposición. Sin más introducción, empecemos con nuestro proyecto.

Creamos un nuevo proyecto en ISE Project Navigator, lo nombramos SumaRestaVHDL, el módulo principal será de tipo HDL.

Ahora, agregamos un nuevo fuente, ya sea con el botón a la izquierda de la ventana Design o mediante el menú que aparece tras hacer clic derecho sobre el nombre de nuestro proyecto, el módulo será de tipo VHDL y por nombre le pondremos SumaResta:


Nuestro sumador/restador será de 4 bits, por lo que tiene dos entradas de 4 bits y una salida también de 4 bits, en VHDL podemos declarar puertos de varios bits a los que se denominan buses, el asistente para agregar un nuevo archivo fuente nos permite indicar los puertos que son buses de esta forma:

Marcamos la casilla en la columna Bus para indicar que el puerto es un bus, además, el número de bits del bus lo indicamos mediante un par de números en las columnas MSB (Most Significant Bit – bit más significativo) y LSB (Least Significant Bit – bit menos significativo), esto es, el número de bit que corresponde a los bits más y menos significativos. Recordemos, en electrónica digital los buses, registros o demás elementos compuestos por más de un bit generalmente se numeran del bit más a la derecha (el menos significativo) hacia la izquierda iniciando en cero, por ejemplo, un elemento de cuatro bits podría ser:

# bit 3 2 1 0
Valor X X X X


El bit menos significativo es el 0, mientras que el más signicativo es el bit 3, que son los que indicamos en el asistente para nuestro nuevo módulo. En cuanto terminemos de agregar el módulo usando el asistente veremos cómo se declara un bus en código VHDL.

Quizá alguien se haya preguntado para qué se utilizará la entrada denominada Sel. Recordemos que nuestro módulo debe sumar y restar, pero solo puede realizar una operación a la vez (solo tiene una salida), así que ¿cómo le indicamos si debe sumar o restar las entradas? La entrada Sel nos permitirá seleccionar la operación a realizar, si su valor es 1, la salida corresponderá a la resta (A – B), mientras que, cuando Sel tenga un valor de 0, la salida corresponderá a la suma (A + B), una vez aclarada la función de la entrada Sel finalicemos con el asistente y pongamos atención a la sintaxis para declarar un bus en VHDL:

A : in std_logic_vector( 3 downto 0 );

La diferencia contra las declaraciones que hasta el momento habíamos utilizado (puertos de 1 bit), es la utilización del tipo STD_LOGIC_VECTOR en lugar de STD_LOGIC, seguido de la indicación de los bits más y menos significativos indicados entre paréntesis (separados por la instrucción downto. VHDL nos permite numerar los bits de un bus del modo que nosotros deseemos, ya sea empezando por el menos significativo y aumentando hacia el más significativo o al revés, que el más significativo sea el bit 0 por ejemplo y el menos significativo el bit número 3 (para el caso de un bus de cuatro bits), para lo que se usaría la instrucción to en lugar de downto, o incluso empezar a numerar de un valor mayor a 0, a continuación pondremos algunos ejemplos de declaraciones de un puerto de cuatro bits:

puerto1 : in std_logic_vector( 3 downto 0 );
puerto2 : in std_logic_vector( 0 to 3 );
puerto3 : in std_logic_vector( 1 to 4 );
puerto4 : in std_logic_vector( 10 downto 7 );

Todas las instrucciones anteriores declaran puertos de entrada de cuatro bits, la diferencia estriba en la manera en la que podremos acceder a los bits individuales de cada uno de ellos, por ejemplo, para acceder al bit más significativo de puerto1 usaríamos:

puerto1(3);

mientras que para acceder al bit más significativo de puerto3 tendríamos que usar:

puerto3(1);

Pero como mencionamos, en electrónica digital generalmente se numera a partir de cero y empezando por el bit menos significativo, así que esa será la forma como trabajaremos las declaraciones de buses en este curso.

Continuemos ahora con el código de nuestro módulo SumaResta, tenemos que cuando la entrada Sel tenga un valor de 0 a la salida enviaremos el resultado de la suma de las entradas A y B, y cuando valga 1 enviaremos el resultado de la resta A – B. En los lenguajes de programación de PC podemos ejecutar una u otra porción de código dependiendo del resultado de la evaluación de una expresión empleando la sentencia if, en VHDL también existe dicha instrucción, pero solo puede utilizarse dentro de un bloque de proceso, los cuales veremos hasta la próxima entrega, así que por ahora no los usaremos ;). VHDL nos proporciona otra instrucción que consigue un efecto similar y que puede emplearse fuera de un proceso, se trata de la sentencia when-else, cuya sintaxis es la siguiente:

SALIDA <= (RESULTADO) when selector=VALOR else (OTRORESULTADO);

RESULTADO se encuentra entre paréntesis porque peude ser un valor constante o el resultado de una operación. Utilizando la sentencia when-else para asignar a la salida de nuestro módulo la suma o resta de las entradas A y B según el valor de la entrada Sel tendríamos lo siguiente en nuestro código:

Salida <= ( A - B ) when Sel = '1' else ( A + B );

Esto es, asigna a Salida el resultado de la operación (A - B) cuando Sel valga '1' (nótese que un valor de un bit va entre comillas simples), para otros valores de Sel asigna a la salida el resultado de la operación (A + B).

El código completo quedaría similar a este:

----------------------------------------------------------------------------------
-- Módulo sumador y restador de 4 bits
-- Mexchip - Tutorial VHDL
-- Diciembre 2011
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SumaResta is
	port (
		A : in  STD_LOGIC_VECTOR (3 downto 0);
      B : in  STD_LOGIC_VECTOR (3 downto 0);
      Sel : in  STD_LOGIC;
      Salida : out  STD_LOGIC_VECTOR (3 downto 0)
	);
end SumaResta;

architecture Behavioral of SumaResta is

begin

	Salida <= ( A - B ) when Sel = '1' else ( A + B );

end Behavioral;

Ahora si, guardemos el módulo, revisamos sintaxis y... ¡Error!

¿Qué ocurrió? Veamos los mensajes de error que nos arrojó Project Navigator:

ERROR:HDLParsers:808 - "E:/.../SumaResta.vhd" Line 22. - can not have such operands in this context.
ERROR:HDLParsers:808 - "E:/.../SumaResta.vhd" Line 22. + can not have such operands in this context.

Nos indica que ambos problemas se encuentran en la línea 22, indicando que no podemos tener operadores - o + en tal contexto, la línea 22 de nuestro código:

	Salida <= ( A - B ) when Sel = '1' else ( A + B );

Peri si seguimos la sintaxis indicada para la sentencia when-else, ¿cuál es el problema? El problema es que los operadores de suma y resta no se encuentran definidos por defecto en VHDL, sino que son parte de una biblioteca adicional, la biblioteca STD_LOGIC_UNSIGNED (para valores sin signo, también existe la biblioteca STD_LOGIC_SIGNED que utiliza valores con signo), la cual debemos incluir para poder utilizar estos operadores, entonces, incluyámosla:

----------------------------------------------------------------------------------
-- Módulo sumador y restador de 4 bits
-- Mexchip - Tutorial VHDL
-- Diciembre 2011
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SumaResta is
	port (
		A : in  STD_LOGIC_VECTOR (3 downto 0);
      B : in  STD_LOGIC_VECTOR (3 downto 0);
      Sel : in  STD_LOGIC;
      Salida : out  STD_LOGIC_VECTOR (3 downto 0)
	);
end SumaResta;

architecture Behavioral of SumaResta is

begin

	Salida <= ( A - B ) when Sel = '1' else ( A + B );

end Behavioral;

Revisamos sintaxis y en esta ocasión todo está correcto.

Muy bien, entonces procedamos a simular nuestro diseño, vamos a la vista Simulation en la ventana Design y hacemos doble clic sobre el proceso Simulate Behavioral Model:

Ahora tendremos abierto ISim:

Si observamos, los puertos que son buses en nuestro diseño tienen entre corchetes los números de los bits MSB y LSB, además, a la izquierda tienen una flecha, si hacemos clic sobre ella podremos ver desplegados en la ventana de formas de onda cada uno de los bits que componen el bus:

Ejecutemos ahora una primera simulación, sumaremos los valores 5 (entrada A) y 3 (entrada B), habrá también que indicar un valor de 0 para la entrada Sel. Utilizaremos la función Force Constant..., primero haremos clic derecho sobre el nombre de la señal a[3:0] y seleccionaremos Force Constant... del menú desplegable:

En la ventana que aparece indicaremos el valor en el campo Force to Value:, debemos indicar un valor que corresponda al formato indicada en el campo Value Radix, que en este caso es Binary, que nos indica valores binarios:

Pero también podemos indicar valores en formato decimal si cambiamos el campo Value Radix a Unsigned Decimal (también existe la opción Signed Decimal):

Repitamos la operación para las entradas B (0011 - 3) y Sel (0):


Ahora si, hacemos clic en el botón Run for the time specified on the toolbar y tendremos:

Como podemos observar, la salida tiene el valor binario 1000 que corresponde con la suma que esperábamos (5+3), también podemos cambiar el formato con el que se visualizan los valores en la ventana de formas de onda haciendo clic derecho sobre el nombre del puerto que deseamos modificar, luego vamos al menú Radix y seleccionamos el deseado, por ejemplo Unsigned Decimal:

Así, si modificamos el formato para los tres buses (A, B y Salida) a Unsigned Decimal nuestra ventana de simulación se vería así:

Ahora puede ser más fácil observar los resultados (sobre todo cuando los buses sean de más bits).
Muy bien, hagamos otra simulación, ahora modifiquemos el valor de la entrada Sel a 1:

Con lo que esperaríamos que ahora el resultado fuera la resta de A - B:

Al parecer, nuestro módulo funciona correctamente, como ejercicio pueden realizar algunas otras operaciones para asegurarse de que así sea, aquí nosotros continuaremos con la implementación en una tarjeta Nexys 2, la asignación de pines la hemos hecho de esta forma:

# Pines de la tarjeta Nexys 2
# para sumador/restador de 4 bits
NET "Sel" LOC = H13;
NET "A<3>" LOC = R17;
NET "A<2>" LOC = N17;
NET "A<1>" LOC = L13;
NET "A<0>" LOC = L14;
NET "B<3>" LOC = K17;
NET "B<2>" LOC = K18;
NET "B<1>" LOC = H18;
NET "B<0>" LOC = G18;
NET "Salida<3>" LOC = K14;
NET "Salida<2>" LOC = K15;
NET "Salida<1>" LOC = J15;
NET "Salida<0>" LOC = J14;

Y este es un breve video con unas pruebas (5 +/- 3) y ( 8 +/- 1) para observar el funcionamiento:

Muy bien, hasta aquí llegamos con esta entrega, ¡hasta la próxima!

Curso VHDL – Diseño esquemático, parte 2

En la anterior entrega comentamos que en esta seguiríamos con la simulación y descarga del proyecto a una tarjeta Nexys 2 de Digilent. Por si alguien tenía la duda, si, también podemos simular los módulos esquemáticos :).
Empecemos, abrimos nuestro proyecto (SumadorEsquematico) en ISE Project Navigator, seleccionamos la vista Simulation, seleccionamos el módulo principal de nuestro proyecto sumador_4bits y en la ventana de procesos encontraremos la opción Simulate Behavioral Model:

Hacemos doble clic en ella, se abrirá ISim:

Podemos ver que tenemos todas las entradas y salidas de nuestro sumador de 4 bits, para no ocupar mucho espacio veremos la simulación de unos cuantos casos, empecemos por sumar 4 (entrada A) + 5 (entrada B), en la tabla siguiente representamos la suma y el resultado que esperamos:

Acarreo
de entrada
Entrada A Entrada B Acarreo
de salida
Suma
Cin A3 A2 A1 A0 B3 B2 B1 B0 Cout S3 S2 S1 S0
0 0 1 0 0 0 1 0 1 0 1 0 0 1


Bien, para realizar la simulación, debemos indicar los valores a las entradas, lo haremos con la instrucción Force Constant que ya habíamos utilizado cuando simulamos las compuertas que hicimos en nuestro primer proyecto. Empecemos por Cin, hacemos clic derecho sobre esta señal en la ventana de simulación, se mostrará este menú:

Seleccionamos la opción Force Constant, aparecerá la ventana Force Selected Signal donde indicaremos que la señal tendrá un valor de 0, esto lo hacemos en el campo Force to Value:

Hacemos clic en OK para aceptar y cerrar la ventana, podemos notar que en la ventana Console se indica el comando que acabamos de ejecutar:

Ahora, vamos con A3, que en nuestra tabla indicamos debe tener un valor de 0, hacemos clic derecho sobre ella en la ventana de simulación, elegimos la opción Force Constant, indicamos un valor de 0 en el campo Force to Value y hacemos clic en OK, debemos repetir este procedimiento para A2 (1), A1 (0), A0 (0), B3 (0), B2 (1), B1 (0) y B0 (1).
Una vez que hayamos terminado de indicar el valor deseado para cada entrada, podemos ejecutar la simulación con el comando Run for the time specified on the toolbar:

Hacemos clic sobre el botón indicado y comparamos los resultados de la simulación con los que indicamos en nuestra tabla, en donde esperamos que S3 y S0 sean 1, mientras el resto (Cout, S2 y S1) sean 0:

Ahora hagamos que el acarreo de entrada valga 1, hacemos clic derecho sobre cin, seleccionamos la opción Force Cosntant… y en la opción Force to Value colocamos un 1, nuestra tabla ahora sería:

Acarreo
de entrada
Entrada A Entrada B Acarreo
de salida
Suma
Cin A3 A2 A1 A0 B3 B2 B1 B0 Cout S3 S2 S1 S0
1 0 1 0 0 0 1 0 1 0 1 0 1 0


Nuevamente hacemos clic en el botón Run for the time specified on the toolbar y observamos si la simulación corresponde con los valores de salida que esperamos: S3 y S2 en 1 y el resto de salidas en 0:

Muy bien, hagamos un par de simulaciones más, en esta ocasión sumaremos 8 + 7, esta sería la tabla de valores de entrada y las salidas esperadas:

Acarreo
de entrada
Entrada A Entrada B Acarreo
de salida
Suma
Cin A3 A2 A1 A0 B3 B2 B1 B0 Cout S3 S2 S1 S0
0 1 0 0 0 0 1 1 1 0 1 1 1 1


Modificamos los valores de entrada con la opción Force Cosntant de acuerdo a nuestra tabla, después hacemos clic en Run for the time specified on the toolbar y comparamos:

Perfecto, 8 + 7 = 15.
Ahora, para probar el acarreo de salida, hagamos que Cin valga 1:

Acarreo
de entrada
Entrada A Entrada B Acarreo
de salida
Suma
Cin A3 A2 A1 A0 B3 B2 B1 B0 Cout S3 S2 S1 S0
1 1 0 0 0 0 1 1 1 1 0 0 0 0


Modificamos solamente Cin con la opción Force Constant… ahora con un valor de 1, ejecutamos la simulación y tenemos:

Muy bien, al parecer todo está correcto, pueden probar correr más simulaciones, ya sea indicando los valores uno a uno, o utilizando de alguna manera ingeniosa la opción Force Clock en lugar de Force Constant para probar una gran variedad de casos, pero nosotros nos quedaremos aquí para ahora continuar con la implementación en la tarjeta Nexys 2, así que cerramos ISim o simplemente volvemos a ISE Project Navigator.
Lo primero que necesitamos hacer, es definir a qué pin del FPGA conectaremos cada una de las entradas y salidas de nuestro sumador de 4 bits, aquí estamos usando una tarjeta Nexys 2, y pretendemos realizar las conexiones así:

Utilizaremos cinco leds para las salidas Cout (E17), S3 (K14), S2 (K15), S1 (J15) y S0 (J14), los ocho interruptores para las entradas A y B: A3 (K17), A2 (K18), A1 (H18), A0 (G18), B3 (R17), A2 (N17), B1 (L13) y B0 (L14), así como un botón para Cin (H13) (habría sido preferible un interruptor, pero solo hay ocho en la tarjeta).
Ahora, asociemos las entradas y salidas del sumador con los pines respectivos del FPGA, esto lo podemos hacer tanto con el programa PlanAhead tal y como lo hicimos en la entrega Curso VHDL – Configurar el dispositivo o editando directamente el archivo de texto .ucf como en Curso VHDL – Configurando una tarjeta Nexys 2.
Nosotros lo haremos de la segunda forma, para seguir practicando un poco la sintaxis del archivo .ucf.
Agregaremos un nuevo fuente al proyecto, en esta ocasión será de tipo Implementation Constraints File, como nombre utilizaremos Pines:

Una vez agregado el archivo al proyecto, hacemos doble clic sobre él para abrirlo en el editor:

Editamos el archivo de texto que se abrió en blanco tal que nos quede así (recordemos que esto es para indicar los pines de una tarjeta Nexys 2):

Seleccionamos el módulo principal sumador_4bits y hacemos doble clic en el proceso Generate Programming File, iniciarán todos los procesos requeridos (Synthesize, Implement Design) y finalmente, si no hubo problemas, tendremos:

Ahora si, es hora de conectar la tarjeta Nexys 2 mediante el cable USB, abrir el programa Adept y debe reconocer los dispositivos conectados, haremos clic en el botón Browse a la derecha del icono que representa el FPGA de la tarjeta:

Navegamos hasta el directorio de nuestro proyecto, donde encontraremos un archivo .bit con el nombre de nuestro módulo principal:

Hacemos clic en Abrir y, en nuestro caso, nos aparece una ventana de advertencia:

El error se debe a que no configuramos la opción Start-Up Clock a JTAG Clock al generar el archivo de programación como si lo hicimos en Curso VHDL – Configurar el dispositivo. Podemos ignorar la advertencia y continuar, hasta el momento realmente no hemos visto algún problema, pero mejor lo arreglamos. Regresamos a ISE Project Navigator, seleccionamos el módulo principal y hacemos clic con el botón derecho en el proceso Generate Programming File y seleccionamos la opción Process Properties:

En la ventana que aparece, vamos a la categoría Startup Options y modificamos la opción FPGA Start-Up Clock de CCLK a JTAG Clock, debe quedar así:

Hacemos clic en OK y ahora veremos que el icono al lado del proceso Generate Programming File ha cambiado a un signo de interrogación, indicando que han habido cambios desde la última vez que se ejecutó el proceso:

Ejecutamos nuevamente el proceso Generate Programing File haciendo doble clic sobre él, una vez que termine con éxito volvemos al software Adept y buscamos el archivo a descargar al FPGA, en esta ocasión ya no debe mostrar el mensaje de advertencia y ahora si podemos hacer clic en el botón Program para iniciar la descarga del archivo .bit al FPGA:


Ahora si, probemos nuestro diseño en el FPGA:

Curso VHDL – Diseño esquemático

En esta entrega del curso, utilizaremos el editor de diagramas esquemáticos dentro de ISE Project Navigator para crear un sumador de cuatro bits.
Iniciemos, abrimos el programa ISE Project Navigator, creamos un nuevo proyecto, pero en esta ocasión indicaremos que el módulo principal será de tipo esquemático:

Ahora toca indicar el dispositivo al que pretendemos descargar este proyecto, en mi caso se trata de una tarjeta Nexys 2, por lo que la configuración del proyecto queda:

En el proyecto anterior iniciamos con la definición de algunas compuertas básicas, después las utilizamos como bloques de componentes poco a poco más complicados, primero un medio sumador, y a partir de este un sumador completo de 1 bit. Sin embargo, no es necesario siempre proceder así para crear nuestros diseños, por ejemplo, ahora nuevamente crearemos un sumador completo de 1 bit, pero en esta ocasión lo haremos utilizando las ecuaciones booleanas que lo definen en lugar de crealo a partir de la conexión de otros componentes. Para tal efecto, debemos conocer las ecuaciones que definen un sumador completo, veamos primero su tabla de verdad:

Acarreo
de entrada
Entrada B Entrada A Acarreo
de salida
Suma
Cin B A Cout S
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1


Y estas son las ecuaciones que definen el funcionamiento de un sumador completo de 1 bit:

S = A ⊕ B ⊕ Cin
Cout = AB + Cin( A ⊕ B )

(Como ejercicio pueden hacer el desarrollo para obtener estas ecuaciones, y si encuentran algún error, por favor coméntenlo).
Muy bien, teniendo las ecuaciones que definen un sumador completo de un bit, podemos ahora fácilmente crear uno en VHDL.
Agregamos un nuevo archivo fuente al proyecto, será un módulo VHDL de nombre sumador_completo:


El código, basado en las ecuaciones que tenemos del sumador completo de 1 bit, quedaría así:

----------------------------------------------------------------------------------
-- Sumador completo por comportamiento
-- Mexchip - Tutorial VHDL
-- Septiembre 2011
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity sumador_completo is
	port(
		Cin : in STD_LOGIC;
		A   : in STD_LOGIC;
		B   : in STD_LOGIC;
		Cout: out STD_LOGIC;
		S   : out STD_LOGIC
	);
end sumador_completo;

architecture Behavioral of sumador_completo is

begin

	S <= A xor B xor Cin;
	Cout <= ( A and B ) or ( Cin and ( A xor B ) );

end Behavioral;

Guardamos el archivo y le revisamos su sintaxis, si no hay problema continuamos. Vamos a simularlo, para comprobar que el código hace lo que debe:

Perfecto, ya hicimos nuestro componente sumador_completo de un bit y comprobamos que funciona. Ahora, vamos a utilizarlo para crear un sumador de 4 bits, pero no lo haremos mediante código, sino mediante un diseño esquemático. Antes de poder poder utilizar nuestro componente sumador_completo en un diseño esquemático, debemos generar su símbolo esquemático, lo cual es bastante sencillo: seleccionamos nuestro componente en la ventana de diseño, después, en la ventana de procesos, dentro de la categoría Design Utilities, encontraremos el comando Create Schematic Symbol, hacemos doble clic sobre él para generar el símbolo esquemático de nuestro componente:

Tras ejecutar el proceso Create Schematic Symbol aparece el siguiente icono al lado del nombre del proceso sabremos que el símbolo esquemático se ha creado exitosamente:

Ahora, agregaremos un nuevo módulo fuente al proyecto, pero en esta ocasión será de tipo Schematic, lo llamaremos sumador_4bits:

Una vez agregado el nuevo fuente al proyecto, se abrirá automáticamente el editor de diagramas esquemáticos donde, si hacemos clic en la pestaña Symbols, veremos en la parte de la izquierda, en la sección Categories la ruta completa a nuestro proyecto, si hacemos clic en ella para seleccionarla, dentro de la sección Symbols aparecerá el componente sumador_completo (si no hubiéramos creado el símbolo esquemático del componente sumador_completo, no aparecería listado aquí):

Si notamos, existen muchas otras categorías que ya vienen incluídas en ISE Project Navigator, cada una con muchos componentes que podemos utilizar en nuestros diseños, por ejemplo, en la categoría Logic podemos encontrar una gran variedad de compuertas lógicas con diferentes números de entradas (algunas con hasta 16 entradas).
Ahora, si hacemos clic en el nombre del componente sumador_completo, y movemos el cursor al área de edición del diagrama esquemático, veremos que el cursor cambia por una cruz y a su lado lleva un pequeño rectángulo con líneas que le sobresalen a la izquierda y a la derecha, si hacemos un clic en el área de edición, colocaremos el símbolo en el editor y podremos ver que corresponde a nuestro componente sumador_completo, y que las líneas que le sobresalen corresponden a sus entradas y salidas, como podemos ver en esta imagen en la que se ha hecho un acercamiento (zoom) al símbolo del componente para apreciarlo mejor:

Continuemos, como mencionamos al principio, nuestra intención es crear un sumador de 4 bits, para ello replicaremos cuatro veces el símbolo del sumador completo de 1 bit, y los conectaremos en cascada para construir un sumador completo de 4 bits (si no recuerdan cómo conectar los sumadores de un bit para crear uno de 4 bits, no se preocupen, solo sigan los pasos), primero coloquemos cuatro componentes sumador_completo:

Podemos apreciar que, en cada extremo de las líneas que sobresalen de cada símbolo, se encuentra un pequeño cuadro, esto indica que son puertos o puntos donde podemos crear una conexión mediante un cable. Para crear una conexión, utilizamos la herramienta Add Wire, que en la barra de herramientas se identifica por un lápiz que está dibujando una línea roja:

Hacemos clic en la herramienta Add Wire y luego movemos el cursor a la salida Cout del primer sumador, al colocar el cursor en el cuadro del extremo de esta salida, el cuadro cambia ahora por cuatro cuadrados más pequeños, indicando que podemos hacer clic para iniciar la conexión, hacemos clic y después movemos el cursor a la entrada Cin del segundo sumador, donde haremos clic en el recuadro del pin Cin para confirmar la unión entre estos dos pines (Cout del primer sumador y Cin del segundo). Mientras hacemos esto podemos hacer clic en los botones de acercamiento (Zoom o mover la rueda central del ratón mientras mantenemos presionada la tecla Control) para ayudarnos, debería quedarnos así:

Para apreciarlo mejor, podemos ver este video:



Como podemos ver, el editor de esquemáticos de ISE Project Navigator es similar a algunos otros editores, ya sea de diagramas o simuladores.
Bien, conectemos ahora los acarreos de salida de los siguientes sumadores:

Prácticamente ya hemos terminado con las conexiones de los sumadores de un bit para crear el sumador de 4 bits, pero, si recordamos, cuando creamos el módulo principal de nuestro anterior proyecto, los puertos del componente (dentro de la sección port en el código de la entidad) fueron los que usamos para asociar con pines del chip en el que está contenido el FPGA, que se encuentran conectados con elementos de entrada y salida en la tarjeta de desarrollo, ¿cómo indicamos en un módulo esquemático cuáles son esos puertos? Esta tarea se realiza con la herramienta Add I/O Marker

El acarreo de entrada de nuestro sumador de 4 bits será el acarreo de entrada del primer sumador, entonces agregaremos un marcador a este pin, hacemos clic en la herramienta Add I/O Marker y a continuación movemos el cursor al pin Cin del primer sumador y hacemos clic como si fuéramos a crear una conexión, aparecerá un marcador como este:

O nuevamente, queda más fácil con un video:


Con esto hemos agregado un puerto de entrada a nuestro sumador de 4 bits, el programa automáticamente le asigna un nombre (en la forma XLXN_X, donde X es un número consecutivo que aumenta según se vayan agregando marcadores), si deseamos modificarlo, debemos seleccionar la herramienta Select (el cursor negro) y hacer doble clic sobre el marcador, aparecerá la ventana Object Properties, aquí podemos editar algunas propiedades del marcador como su dirección, tamaño de fuente para el nombre y, si vamos a la categoría Nets, podremos editar el nombre del marcador en la propiedad Name:

Modificaremos el nombre para que ahora sea Cin, al aceptar el cambio se debe actualizar el nombre del puerto:

Muy bien, ahora procederemos agregando marcadores de entrada/salida a todos los puertos que nos faltan, vamos a numerar cada sumador completo de un bit a partir de 0, es decir, de 0 a 3. Las entradas de cada sumador serán AX y BX, donde X es el número del sumador, las salidas de suma serán SX y el acarreo de salida del último sumador se llamará Cout, que es el acarreo de salida de nuestro sumador de cuatro bits, nos debe quedar algo como esto:

Podemos observar que los marcadores de entrada/salida son diferentes según sea el caso de estar conectados a una entrada o a una salida: la conexión al pin cambia a la "punta" o a la parte posterior:

Recordemos que nuestro sumador completo de 4 bits tendrá una entrada de un bit Cin y dos entradas de cuatro bits: A y B, nosotros hemos numerado cada bit de estas entradas de 0 a 3, tenemos así que A0, A1, A2 y A3 son los cuatro bits de la entrada A, siendo A3 el más significativo; de manera similar, tenemos que B0, B1, B2 y B3 son los cuatro bits de la entrada B, siendo B3 el más significativo. Asimismo, tendremos una salida de cuatro bits, conformada por S0, S1, S2 y S3, siendo este último el más significativo; y una salida de un bit: Cout, que es el acarreo de salida de nuestro sumador de 4 bits.
Finalmente, guardamos nuestro sumador de 4 bits ya terminado. Si vamos a la vista Design, observaremos que aparecen anidados cuatro componentes sumador_completo dentro del módulo sumador_4bits, de manera similar a lo que ocurría cuando en nuestro anterior proyecto instanciábamos algún componente:

Como observamos, el programa ha asignado las etiquetas para cada instancia, si queremos modificarlas, volvemos al editor de esquemáticos, con la herramienta Select hacemos doble clic sobre el símbolo de alguno de los sumadores y podremos cambiar su nombre de instancia:

Yo he cambiado todos los nombres de XLXI_X a SUM_X, tras guardar el módulo esquemático y cambiar a la pestaña Design ha quedado así:

Muy bien, hemos llegado al final de esta entrega del curso, en la próxima continuaremos con la simulación y descarga del proyecto a una tarjeta Nexys 2, estén al pendiente.

Curso VHDL – Configurando una tarjeta Nexys 2

Hace poco conseguí una tarjeta Nexys 2, esta será con la que desarrollaremos los próximos ejemplos del curso :).
Para empezar, en este entrega realizaremos las modificaciones necesarias al proyecto que descargamos a la tarjeta Spartan 3 Starter para poder ahora configurar la tarjeta Nexys.
Continúa leyendo Curso VHDL – Configurando una tarjeta Nexys 2

Curso VHDL – Configurar el dispositivo

En esta entrega veremos cómo utilizar el diseño que hemos creado en nuestro primer proyecto para configurar un dispositivo, en concreto, un FPGA Spartan3.
Después de haber revisado que el código sea correcto y que los módulos funcionen como deseamos (mediante la simulación), el siguiente paso es indicar a qué pines de nuestro dispositivo programable corresponderán las entradas y salidas del módulo que hemos desarrollado. Como mencioné al inicio del curso, cuento con una tarjeta de desarrollo Spartan 3 Starter Kit de Digilent, así que será en el diseño de esta tarjeta en que me basaré para la asignación de pines del módulo que vamos a implementar.
Continúa leyendo Curso VHDL – Configurar el dispositivo

Curso VHDL – Diseño estructural

Una de las características más potentes del lenguaje VHDL, es la posibilidad de utilizar los módulos que hemos desarrollado para construir módulos más grandes, es decir, un módulo VHDL puede convertirse en componente de otro módulo, de esta forma reutilizamos o aprovechamos módulos ya diseñados con anterioridad, o podemos dividir un diseño complejo en varios diseños más simples.
Utilizar módulos VHDL para construir otros módulos se denomina diseño estructural, que difiere del diseño por comportamiento que hemos utilizado hasta este momento.
Continúa leyendo Curso VHDL – Diseño estructural

Curso VHDL – Simulación

En la tercera entrega de este tutorial, creamos nuestro primer módulo VHDL, una compuerta AND de dos entradas. Es un módulo muy simple y sencillo, pero crearlo nos permite familiarizarnos de manera más fácil con el entorno de trabajo.
Una vez que hemos verificado la sintaxis del código de nuestro módulo, una forma de verificar que funcione y se comporte como deseamos es realizar una simulación. Dependiendo del entorno de trabajo serán las herramientas de simulación que tendremos a nuestra disposición, nosotros usaremos ISim, un simulador que viene integrado en ISE Design Suite y que sirve perfectamente para nuestros propósitos.
Continúa leyendo Curso VHDL – Simulación

Curso VHDL – Primer proyecto

En esta tercera entrega del tutorial veremos el manejo de ISE Project Navigator, que es el software con el que desarrollaremos nuestros proyectos, empezaremos creando algunas compuertas básicas, las simularemos para comprobar su funcionamiento y después las utilizaremos para construir un componente más complejo. Veremos además la diferencia entre los dos tipos de descripción que se pueden utilizar en VHDL: el diseño estructural y el diseño por comportamiento.
Continúa leyendo Curso VHDL – Primer proyecto

Curso VHDL – Instalación de software

Xilinx ofrece una licencia gratuita de su entorno de desarrollo y diseño para sus dispositivos reconfigurables, la versión gratuita se conoce como Webpack, en últimas versiones no se trata de un software separado del principal sino de una licencia de uso especial para el mismo, aquí veremos los pasos necesarios para descargar el software y obtener la licencia gratuita.
Continúa leyendo Curso VHDL – Instalación de software