Por último he decidido seguir el ejemplo del libro de Chu, el cual es una excelente referencia para aprender VHDL, y además tiene su versión para Verilog.
Programa a realizar
Se implementará un comparador de 2 bits(figura 1) basándonos en el programa realizado en el tutoral 1 (comparador de 1 bit).
Figura 1. Comparador de 2 bits. Fuente: libro de Chu
En este caso las entradas son dos vectores (a y b) y la salida es "aeqb" (a equal b). Los módulos eq1 se basan en el tutorial anterior.
Plataforma de desarrolloUtilizaremos la plataforma de desarrollo Basys2 (figura 2)
Figura 2. Placa de desarrollo Basys 2
A diferencia del elbert, esta placa tiene 8 switches y 4 pulsantes de ingreso, 8 leds de salida, un display de 7 segmentos de 4 dígitos, entrada PS2 para teclado y mouse, salida VGA para monitor, 16 salidas de propósito general, y un cristal de 100MHz ( el elbert tiene un cristal de 12MHz).
Es una placa más potente que el elbert, pero con las siguientes desventajas:
Precio elevado ($89, lo cual más el envío al Ecuador puede llegar a los $100).
El código del microcontrolador que programa la memoria del FPGA no es abierto.
Aunque se tengan más periféricos de salidas, esto puede llegar a ser malo, pues según se avanza en complejidad de los proyectos en VHDL, se requieren más salidas o ingresos, y no siempre requeriremos los periféricos que vienen por defecto en la placa.Por lo tanto, al crear el proyecto en ISE utilizaremos el dispositivo Spartan 3E XC3S250E en empaquetado CP132 con velocidad 4 (figura 3).
Figura 3. Configuración de proyecto para Basys2
Programación en VHDL
Primero utilizaremos el código del comparador de 1 bit del libro de Chu para cada módulo eq1:
En este código se modificó los nombres de los ingresos y salidas en comparación con el ejemplo del tutorial 1, es decir, los ingresos ahora son i0 e i1, y la salida es eq.
Ahora, creamos un nuevo documento VHDL y utilizamos el siguiente código para el comparador de 2 bits:
Analizando el código por partes:
Se declaran los vectores a y b como "std_logic_vector". Cada vector es de 2 bits, por lo que se declara "1 downto 0". Si el vector fuera por ejemplo de 8 bits, la declaración sería (7 downto 0).
Se cambia el tipo de arquitectura de sop_arch a struc_arch, esto pues estamos definiendo el módulo como una estructura basada en un módulo ya existente.
Se crean instancias del módulo existente "entity work.eq1(sop_arch)". Este principio es similar a la programación en Java, pues estamos instanciando una entidad para reutilizarla en el programa principal. el valor de respuesta del módulo existente o "eq" se cargará en eq_bit0_unit, y en eq_bit1_unit.
En cada instancia se mapea el puerto del módulo existente al módulo principal "port map(i0=>a(0), i1=>b(0), eq=>e0".
Por último se realiza la lógica para el resultado del módulo principal: "aeqb<= e0 and e1"Plataforma de programación
Debemos asegurarnos que el módulo eq2 sea el módulo principal o "top module" (figura 4)
Figura 4. Selección de módulo principal
Al momento de compilar, se crearán las instancias del módulo eq1, y la jerarquía de los módulos debe aparecer como en la figura 5.
Figura 5. Jerarquía de módulos
Simulación
Para simular los proyectos en VHDL tenemos que crear nuestro propio código de simulación, el cual se conoce como "testbench" o plataforma de simulación. Se puede mezclar los lenguajes de programación, es decir, puedo hacer el código para el FPGA en VHDL y el testbench en Verilog, lo cual es muy común para evitar algunos esfuerzos innecesarios de programación, pero, como se mencionó en la entrada anterior, lo haremos en VHDL.
La arquitectura que se utilizará para realizar la simulación se muestra en la figura 6.
Figura 6. Arquitectura de simulación. Fuente: libro de Chu
El generador de vectores nos dará los valores lógicos para los ingresos al módulo "eq2", y el monitor nos mostrará los resultados. En el caso del ISE, el monitor que se utiliza por defecto es el ISIM.
Primero, creamos un archivo testbench en VHDL para el proyecto. El código en VHDL para la simulación es el siguiente:
Analizando el código por partes:
Creamos la arquitectura tb_arch, es decir, tipo testbench para simulación
Creamos las señales de ingreso y salida del módulo de simulación o UUT (Unit Under Test). En este caso test_in0 y test_in1 como ingreso, y test_out como salida. Los ingresos son vectores de 2 bits.
Instanciamos el módulo que vamos a simular dentro de la unidad bajo test "uut: entity work.eq2(struc_arch)".
Mapeamos los puertos de entrada y salida del módulo a simular a la unidad de simulación: "a=>test_in0"
Puesto que necesitamos dar valores consecutivos a las señales de ingreso, inicializamos un proceso: process.
Cargamos los valores requeridos en los vectores y agregamos un tiempo de espera de 200ns. El tiempo ingresado es muy importante, pues debemos recordar que no estamos trabajando con un microcontrolador, es decir, no es una programación en secuencia, por lo tanto, estamos trabajando con lógica y el único tiempo de espera entre una entrada y salida es el causado por las compuertas (el silicón y los cables de oro internos) o también conocido como retardo de propagación. Si no ponemos un tiempo de espera, el compilador mostrará un mensaje de error indicando que un puerto (vector de salida o entrada) tiene múltiples valores al mismo tiempo.Una vez cargado el código del testbench al proyecto, nos ubicamos en la opción de simulación del ISE (figura 7).
Figura 7. Selección de modo de simulación
Hacemos doble click en "Behavioral Check Syntax" para depurar errores de sintaxis, y luego damos doble click en "Simulate Behavioral Model" con lo que podremos observar la simulación de nuestro circuito (figura 8).
Figura 8. Simulación del comparador de 2 bits en ISIM
Nota: Al inicio de la simulación en Isim, la base de tiempo es muy pequeña, por lo que se tiene que retirar el zoom para poder ver los bits cada 200ns.
Conexión del hardware
Para la Basys2 podemos descargarnos el archivo ucf de aquí. Si no tenemos el archivo ucf, también podemos guiarnos en el silkscreen de la placa, en el cual se indica los puertos del FPGA al que están conectados los periféricos.
Con esto, modificamos el archivo ucf de la siguiente manera:
NET "aeqb" LOC = G1;
NET "a<0>" LOC = N3;
NET "a<1>" LOC = E2;
NET "b<0>" LOC = F3;
NET "b<1>" LOC = G3;
Se puede observar que la declaración de cada puerto de un vector se realiza así: nombredelvector<bit>.
Programación del dispositivo
Para programar la Basys2 utilizamos el software Adept, el cual lo podemos descargar aquí. Una vez generado el archivo de programación, el cual en este caso es un archivo .bit (en el elbert era un .bin), lo cargamos en Adept (figura 9).
Figura 9. Software de programación para la Basys2 y cadena JTAG reconocida
Después de hacer click en "Initialize Chain", el software leerá la cadena de dispositivos conectados al JTAG, con lo que observaremos al FPGA y a la memoria de programación (figura 9). Con esto tenemos dos opciones:
Podemos programar el FPGA, con lo cual el programa se ejecutará únicamente mientras el dispositivo esté con energía, en el caso de apagar la fuente de poder, el programa se borrará de la memoria del FPGA.
Podemos programar la PROM, con lo cual el programa se ejecutará incluso después de apagar la fuente de poder.Nota: La programación en la Basys2 debe realizarse colocando el jumper de "MODE" en la posición "ROM", la posición "PC" se puede utilizar pero ésta es recomendable para simulación.
Esto es todo, si la programación se realizó de manera correcta, podremos observar el funcionamiento del circuito en la Basys2, los ingresos son SW7 a SW4 y la salida es el LD7. Si tienen alguna duda, por favor escribanla en los comentarios.
Fuente: este post proviene de Blog de davilamds, donde puedes consultar el contenido original.
¿Vulnera este post tus derechos? Pincha aquí.
Creado: