Ir al contenido principal

Cómo trabajar con vhdl usando software libre

Las clases de ingeniería electrónica suelen dictarse usando herramientas popietarias, así que siempre paso algunas horas buscando hacer mis trabajos con software libre. Por esta razón, he decidido compartir la siguiente guía.





Instalando lo necesario

Para compilar y simular nuestros programas usaremos GHDL un compilador libre basado en GCC. Para ver los resultados de la simulación, usaremos GTKWAVE. Como editor recomiendo Geany ya que reconoce casi todos los lenguajes de programación.

sudo apt-get install ghdl gtkwave geany


Un proyecto de ejemplo

Utilicemos como ejemplo este comparador:



Antes de crear un proyecto, comencemos creando una carpeta donde se alojarán todos los archivos. En este caso, /home/usuario/vhdl. Allí guardaremos el código fuente de nuestros programas con extensión .vhd.

Luego, escribimos nuestro programa usando Geany, como se ve en la captura de pantalla. Antes de seguir, no olvides descargar el código fuente del programa que vamos a crear para poder seguir su evolución paso a paso.



Lo guardamos como compara.vhd.

No olviden guardar el programa con la extensión .vhd para que Geany reconozca el formato y coloree las palabras reservadas.

Ahora necesitaremos crear las señales para la simulación. Para ello, crearemos un componente que use el bloque anterior y le especificaremos las señales.



Las lineas A <= "0011" after 0 ns,"0111" after 5 ns, "0111" after 10 ns; son las que configuran las señales de entrada en el tiempo

Guardamos los archivos en /home/usuario/vhdl. Luego, abrimos un terminal y a compilar:

ghdl -a compara.vhd

Si no hay mensajes de error, la compilación es exitosa.

Ahora compilamos el “componente”

ghdl -a compara_tb.vhd

Si no hay errores, creamos el ejecutable:

ghdl -e compara_tb

Finalmente, resta realizar la simulación y guardar los resultados en el con nombre “compara.vcd”

ghdl -r compara_tb --vcd=compara.vcd

Para poder ver los resultados usaremos gtkwave:

gtkwave compara.vcd

Una vez abierto, señalar con la tecla Ctrl y el mouse las señales que nos interesan y presionar insertar. Luego, doble clic en los vectores para ver las señales separadas. Después, clic derecho en los señales para elegir el formato (binario, hex, octal, decimal, etc.)

En caso de que sea necesario, el botón con forma de lupa con un cuadrado en el centro ajusta la gráfica a la pantalla.




ALU: arithmetic and logic unit

Bien, ahora hagamos algo más interesante: un ALU (aritmethic and logic unit). Será una unidad lógica, una unidad aritmética y un multiplexor.

Unidad lógica (LoU.vhdl)

     LIBRARY ieee;
     USE IEEE.STD_LOGIC_1164.all;
     USE IEEE.NUMERIC_STD.all;
        
ENTITY lou IS
     PORT(op1 : IN std_logic_vector(7 DOWNTO 0);
          op2 : IN std_logic_vector(7 DOWNTO 0);
          proceso : IN std_logic_vector(3 DOWNTO 0);
          res : OUT std_logic_vector(7 DOWNTO 0));
     END lou;

     ARCHITECTURE synth2 OF lou IS
     SIGNAL a,b:UNSIGNED(op1'range);
     SIGNAL c:UNSIGNED(res'range);
     BEGIN
       PROCESS (a, b, proceso)
       BEGIN
         CASE proceso IS
           WHEN "0000" => c <= RESIZE((not a),c'length);
           WHEN "0001" => c <= RESIZE((a and b),c'length);
           WHEN "0010" => c <= RESIZE((a or b),c'length);
          
           WHEN "0011" => c <= RESIZE((a xor b),c'length);
           WHEN "0100" => c <= RESIZE((a nand b),c'length);
           WHEN "0101" => c <= RESIZE((a nor b),c'length);
           WHEN OTHERS => null;
         END CASE;
       END PROCESS;

       a <= UNSIGNED(op1);
       b <= UNSIGNED(op2);
       res <= std_logic_vector(c);

     END synth2;

Unidad aritmetica (ArU.vhd)

     LIBRARY ieee;
     USE IEEE.STD_LOGIC_1164.all;
     USE IEEE.NUMERIC_STD.all;
    
          ENTITY aru IS
     PORT(op1 : IN std_logic_vector(7 DOWNTO 0);
          op2 : IN std_logic_vector(7 DOWNTO 0);
          proceso : IN std_logic_vector(3 DOWNTO 0);
          res : OUT std_logic_vector(7 DOWNTO 0));
     END aru;

     ARCHITECTURE synth OF aru IS
     SIGNAL a,b:UNSIGNED(op1'range);
     SIGNAL c:UNSIGNED(res'range);
     BEGIN
       PROCESS (a, b, proceso)
       BEGIN
         CASE proceso IS
           WHEN "0000" => c <= RESIZE((a + b),c'length);
           WHEN "0001" => c <= RESIZE((a - b),c'length);
           WHEN "0010" => c <= RESIZE((a * b),c'length);
          
           WHEN "0011" => c <= RESIZE((a / b),c'length);
           WHEN "0100" => c <= RESIZE((a + "1"),c'length);
           WHEN "0101" => c <= RESIZE((b + "1"),c'length);
           WHEN OTHERS => null;
         END CASE;
       END PROCESS;

       a <= UNSIGNED(op1);
       b <= UNSIGNED(op2);
       res <= std_logic_vector(c);

     END synth;

Multiplexor (muxVector.vhd)

     LIBRARY ieee;     USE IEEE.STD_LOGIC_1164.all;
     USE IEEE.NUMERIC_STD.all;
    
 ENTITY muxVector IS
     PORT(desdeARU : IN std_logic_vector(7 DOWNTO 0);
          desdeLOU : IN std_logic_vector(7 DOWNTO 0);
          switch : IN std_logic;
          salida : out std_logic_vector(7 DOWNTO 0));
     END muxVector;

     ARCHITECTURE cambio OF muxVector IS
     BEGIN
     with switch select
     salida <= desdeARU when '0' , desdeLOU when others;
     END cambio;

Componente ALU (aluComponente.vhd)

     LIBRARY ieee;     USE IEEE.STD_LOGIC_1164.all;
     USE IEEE.NUMERIC_STD.all;
        
     ENTITY aluComponente IS
     END aluComponente;

     ARCHITECTURE entradas_aluComponente OF aluComponente IS
    
       COMPONENT aru
       PORT(op1 : IN std_logic_vector(7 DOWNTO 0);
          op2 : IN std_logic_vector(7 DOWNTO 0);
          proceso : IN std_logic_vector(3 DOWNTO 0);
          res : OUT std_logic_vector(7 DOWNTO 0));
          END COMPONENT;
        
        
          COMPONENT lou
       PORT(op1 : IN std_logic_vector(7 DOWNTO 0);
          op2 : IN std_logic_vector(7 DOWNTO 0);
          proceso : IN std_logic_vector(3 DOWNTO 0);
          res : OUT std_logic_vector(7 DOWNTO 0));
          END COMPONENT;
        
        
       COMPONENT muxVector
     PORT(desdeARU : IN std_logic_vector(7 DOWNTO 0);
          desdeLOU : IN std_logic_vector(7 DOWNTO 0);
          switch : IN std_logic;
          salida : out std_logic_vector(7 DOWNTO 0));
          END COMPONENT;
        
        

       SIGNAL salidaARU  : std_logic_vector(7 DOWNTO 0);
       SIGNAL salidaLOU  : std_logic_vector(7 DOWNTO 0);     
       signal Switch : std_logic;
       signal proceso : std_logic_vector(3 DOWNTO 0);
       signal salida : std_logic_vector(7 DOWNTO 0);
       SIGNAL A : std_logic_vector(7 DOWNTO 0);
       SIGNAL B : std_logic_vector(7 DOWNTO 0);
      
     BEGIN 
u0: aru PORT MAP (A,B,proceso,salidaARU);
u1: lou PORT MAP (A,B,proceso,salidaLOU);
u2: muxVector PORT MAP (salidaARU,salidaLOU,switch,salida);

A <= "00000011" after 0 ns,"00000111" after 5 ns, "00000111" after 10 ns, "00001001" after 15 ns, "00000000" after 20 ns, "00000101" after 25 ns, "00001111" after 30 ns, "00000101" after 35 ns;
B <= "00000010" after 0 ns,"00000100" after 5 ns, "00000010" after 10 ns, "00000011" after 15 ns, "00000100" after 20 ns, "00000110" after 25 ns, "00001111" after 30 ns, "00000011" after 35 ns; 
switch <= '1' after 0 ns,'0' after 5 ns,'1' after 10 ns, '0' after 15 ns,'1' after 20 ns,'0' after 25 ns,'1' after 30 ns,'0' after 35 ns,'1' after 40 ns;
proceso <= "0000" after 0 ns,"0001" after 5 ns, "0010" after 10 ns, "0011" after 15 ns, "0100" after 20 ns, "0101" after 25 ns, "0110" after 30 ns;
     END entradas_aluComponente;

Para no perder tiempo compilando comando por comando mientras trabajamos en el programa, guardamos en la misma carpeta un archivo llamado compilar.sh con el siguiente contenido:

ghdl -a lou.vhd && ghdl -a aru.vhd && ghdl -a muxVector.vhd &&  ghdl -a aluComponente.vhd  && ghdl -e aluComponente && ghdl -r aluComponente --vcd=aluComponente.vcd && gtkwave aluComponente.vcd

Abrir un terminal, entrar a la carpeta y ejecutar el script:

cd /home/usuario/vhdl
sh compilar.sh

Si no hay errores se abrirá gtkwave y podremos ver las señales:



Estas herramientas me han sido muy útiles y mas fáciles de usar que las herramientas propietarias que usamos en clase, las que sospechosamente tardan demasiado para copilar. Con ghdl tardo más en cambiar de ventana que en compilar.


Entradas populares de este blog

Fallo al obtener la lista de compartición del servidor

 - Ubuntu Karmic Koala El problema. El detalle es que a veces tengo que revisar archivos que están en otras computadoras que utilizan windows. Al momento de darle en el menú Lugares - Red - Red de Windows y al elegir el grupo de trabajo en el que están mis equipos me aparece el siguiente error. No se puede montar el lugar. Fallo al obtener la lista de compartición del servidor. La solución . La encontré en este articulo de los Foros de Ubuntu, lo voy a copiar tal cual, espero que no le moleste al autor y solo a manera de respaldo. # — Aquí inicia el articulo de los foros de Ubuntu – 1- En principio es necesario que estén instalados: samba samba-common smbclient winbind   2- Luego editar el archivo /etc/samba/smb.conf sudo gedit /etc/samba/smb.conf   A los cambios necesarios para adaptar el sistema, según los tutoriales de samba es necesario tener presente que: a- Donde dice workgroup = WORKGROUP, reemplazar WORKGROUP por el nombre de grupo de trabajo de los

Rootear en Ubuntu un teléfono Android

Tengo un teléfono con Android, concretamente un Motorola Defy, y resulta que en Android, basado en Linux, eres un simple usuario y solo puedes realizar algunas tareas. Otras te están vetadas. Conseguir los permisos de superusuario, se llama entre los entendidos rootear el móvil. En principio es una operación que no entraña riesgos, pero en esta vida todo puede fallar. Así que debe quedar claro que si decides rootear el teléfono, lo haces bajo tu propia responsabilidad. También debes entender, que si rooteas el teléfono, los SAT aprovechan para lavarse las manos de cualquier problema y anular la garantía. Y por último, debes saber que es posible que ya no recibas las actualizaciones automáticas de Android. Para rootear teléfonos se utiliza una aplicación llamada Superoneclick . En mi caso, esta parece ser la única solución. Pero este es un programa para Windows, por lo que.... Afortunadamente, esta escrito en .NET, por lo que vamos a poder ejecutarlo con MONO en nuestro

Descargar Packet Tracer 5.2 [Windows y Linux]

Packet Tracer 5.2 [Windows y Linux] Packet Tracer es la herramienta de aprendizaje y simulación de redes interactiva para los instructores y alumnos de Cisco CCNA. Esta herramienta les permite a los usuarios crear topologías de red, configurar dispositivos, insertar paquetes y simular una red con múltiples representaciones visuales. Packet Tracer se enfoca en apoyar mejor los protocolos de redes que se enseñan en el currículum de CCNA. Este producto tiene el propósito de ser usado como un producto educativo que brinda exposición a la interfaz comando – línea de los dispositivos de Cisco para practicar y aprender por descubrimiento. Packet Tracer 5.2 es la última versión del simulador de redes de Cisco Systems, herramienta fundamental si el alumno está cursando el CCNA o se dedica al networking. En este programa se crea la topología física de la red simplemente arrastrando los dispositivos a la pantalla. Luego clickando en ellos se puede ingresar