Simulando VHDL con herramientas GNU: GHDL+GTKWAVE

Este documento no tiene aún una política de licencia. Úselo bajo su única y exclusiva responsabilidad. No se ofrecen garantías ni explícitas ni implícitas sobre ninguna parte de este manual y menos aun sobre los productos aquí descritos.


Tabla de contenidos
1. Herramientas GNU
2. Requisitos
3. Descargas
4. Compilación
5. Documentación
6. Instalación
7. Compatibilidad
8. Probar la instalación
9. Trucos

1. Herramientas GNU

GHDL es un compilador y simulador de VHDL que soporta el estándar VHDL'87 y casi todo el VHDL'93. Está basado en GNAT, el magnífico compilador Ada de libre distribución, que a su vez está basado en GCC. Es por esto último que resulta un poco grande para propósitos educativos y de uso ocasional; no obstante, todos sus componentes son libres y de alta calidad, si bien se echa en falta un depurador o soporte avanzado para depuración con GDB.


2. Requisitos


3. Descargas

GHDL es un magnífico proyecto de Tristan Gingold . Puedes descargarlo de esta página. También encontrarás allí la documentación y el código fuente, aunque compilarlo no es demasiado fácil. Lee el documento INSTALL, es importante.

GTKWAVE podrás descargártelo aquí en su versión más actualizada, en binario o en código fuente. Yo la he compilado para que use mi versión de glibc, ya que no tengo la última. Ten esto en cuenta si es tu caso; también puedes tener problemas al ejecutar, si tu versión de GTK+ no es muy nueva, por lo que te recomiendo compilar los fuentes. Si tienes (como mínimo) GLIBC-2.2.3 y un procesador de arquitectura i686, puedes descargarte una versión totalmente traducida al español aquí, gracias a Esperanza Pérez Sánchez. Actualmente hay dos versiones: la 1.3.24, muy estable y probada pero con interfaz GTK 1.2 y la versión 2.0.0pre3, última versión, aun sin traducir al español, pero que tiene nuevas facilidades muy interesantes (p. e. posibilidad de guardar las trazas y cargarlas automáticamente al arrancar).

GNAT es un compilador comercial de Ada95 fabricado por Ada Core Technologies, pero no encontrarás ninguna versión libre en su página; únicamente distribuye de vez en cuando una versión y la hace pública, pero no en su sitio. La versión que os recomendamos es la 3.15p. Es muy importante que sea completa, de lo contrario no funcionará; usa preferiblemente los binarios, ya que compilarlo puede ser una pesadilla. Lo puedes descargar aquí. Es bastante pesado (35Mb instalado) pero así aprovechas y aprendes algo de Ada...


4. Compilación

Probablemente hayas empezado ya con tu primer proyecto grande en VHDL. Si es así, seguramente echas en falta un procedimiento rápido y cómodo para compilar. Te proponemos dos opciones para automatizar el proceso de generación y prueba de unidades de simulación. La primera es más rápida; la segunda, a pesar de requerir más trabajo inicial, es más cómoda.

Con GHDL:

GHDL dispone de un método muy sencillo para detectar las dependencias entre ficheros (la opción -i) y para elaborar la unidad de simulación (la opción -m). Si dispones de todos los ficheros fuente de la unidad, ejecutando:

$ ghdl -i *.vhd

importarás todos los componentes definidos en los ficheros. La importación no es más que la generación de un fichero de configuración de proyecto llamado normalmente work-obj93.cf, si no especificaste estándar forzado VHDL'87, o work-obj87.cf, si añadiste --std=87 a la orden anterior. Una vez generado este fichero, GHDL ya sabe las dependencias entre entidades, arquitecturas y configuraciones de tu unidad y es capaz de generarla. Para ello sólo tienes que ejecutar la orden:

$ ghdl -m unidad-de-simulación

No especifiques la extensión del archivo, ya que GHDL ya sabe qué fichero la contiene. Este método tiene la ventaja de que, si modificas un fichero de entidad, arquitectura o configuración, GHDL sabe qué es necesario compilar y no compilará más de lo que sea imprescindible. Para simular, una vez que la elaboración haya tenido éxito, tendrás que ejecutar la unidad de simulación con los parámetros adecuados. Echa un vistazo a Sección 8.2; el procedimiento es equivalente.

Con make:

Quizás prefieras, además, automatizar el proceso de simulación. Si tienes un mínimo (o nulo) conocimiento de GNU make, te proponemos usar un makefile genérico, vhdl.mk, que puedes incluir en el makefile de tu proyecto. Te incluyo en este paquete varios ejemplos que pueden servirte como punto de partida y, de paso, para compilar las prácticas obligatorias 1, 2 y 3 del curso 2002-2003 (Ing. Téc. Infca. Sistemas/UNED). Tiene muchos comentarios y puede servirte como base para hacer tus proyectos además de, porqué no, aprender un poco sobre la excelente herramienta make.


5. Documentación

GHDL tiene una página info (info ghdl) y manuales en línea en su sitio oficial. Puedes bajarte parte de esa documentación aquí.

GTKWAVE incluye documentación en formato HTML, aunque es muy intuitivo y sencillo. La versión 1.3.24 también tiene una ayuda en línea totalmente traducida al español que describe la funcionalidad de las opciones de menú; puede servirte como punto de partida.

GNAT viene con dos manuales en formato HTML: la referencia básica y la guía de usuario, instaladas en el directorio /usr/gnat/doc, aunque si no vas a programar en Ada no los necesitarás; puedes borrarlos y así ganar algo de espacio.


6. Instalación

  1. GHDL: Descomprime los ficheros ghdl-0.5-i686-pc-linux-bin.tar.gz y gnat-3.15p-i686-pc-linux-gnu-bin.tar.gz como root con:

    $ tar zxvCf / ghdl-0.5-i686-pc-linux-bin.tar.gz
    $ tar zxvf gnat-3.15p-i686-pc-linux-gnu-bin.tar.gz

    Si quieres estar seguro de lo que haces no causará problemas, puedes saber dónde se van a instalar los archivos ejecutando:

    $ tar zvtf ghdl-0.5-i686-pc-linux-bin.tar.gz

    que te mostrará las rutas completas de dónde colgará la jerarquía, probablemente /usr/local.

  2. GTKWAVE: El fichero gktwave-1.3.24-i686-pc-linux-bin.tar.gz tienes que descomprimirlo en un directorio que esté incluido en la variable PATH, aunque no es imprescindible. En este último caso, para ejecutar GTKWAVE necesitarás especificar la ruta completa. Si se descomprime en un directorio incluido en la variable PATH, bastará con ejecutar gtkwave. Es recomendable descomprimirlo en /usr/local/bin o en $HOME/bin con las órdenes:

    $ tar zxvCf /usr/local/bin gktwave-1.3.24-i686-pc-linux-bin.tar.gz

    o

    $ tar zxvCf $HOME/bin gktwave-1.3.24-i686-pc-linux-bin.tar.gz

    Si has elegido bajarte la última versión de la serie 2.0.0, te recomiendo la última instantánea (snapshot) de los ficheros fuente, ya que siempre soluciona pequeños errores. Tendrás que compilarlo e instalarlo, aunque es muy fácil.

  3. Instala ahora GNAT cambiándote al directorio recién creado, gnat-3.15p-i686-pc-linux-gnu-bin y ejecutando:

    $ cd gnat-3.15p-i686-pc-linux-gnu-bin
    $ ./doconfig
    $ ./doinstall

    Recomendamos la ubicación que se indica en la opción 2 del procedimiento doconfig que instala GNAT en /usr/gnat, ya que así bastará borrar dicho directorio para desinstalarlo completamente. Lamentablemente el nombre del compilador de Ada, usado por GHDL, es gcc, igual que el del compilador de C, de modo que tendrás que insertar al principio de tu variable de entorno PATH la ruta /usr/gnat/bin, de otro modo fallará el proceso de elaboración del ejecutable con un mensaje parecido a este:

    /usr/gnat/lib/gcc-lib/i686-pc-linux-gnu/2.8.1/adalib//libgnat.a(a-raise.o):
    In function `_gnat_builtin_longjmp': a-raise.o(.text+0x1d): undefined reference to `__dummy'
    collect2: ld returned 1 exit status
    ghdl: compilation error

    Otro método consiste en renombrar el ejecutable ghdl como, por ejemplo, ghdl.bin y crear un shell script de este estilo:

    #!/bin/sh
    PATH=/usr/gnat/bin:$PATH /usr/local/bin/ghdl.bin $*

    y después darle permisos de ejecución con la orden:

    $ chmod ugo+x /usr/local/ghdl

    de ese modo al invocar a ghdl se usará el compilador gcc de GNAT y no el de GNU/GCC. Claro que también es posible usar un alias para la orden ghdl, opción más elegante:

    $ alias ghdl="PATH=/usr/gnat/bin:$PATH /usr/local/bin/ghdl"

    que puedes añadir en tu perfil de sesión .profile, .bashrc o el que uses. De este modo no haría falta renombrar el ejecutable ghdl ni cambiar permanentemente la variable PATH. Si, además, quieres seleccionar siempre el estándar VHDL'87 (u otro) para compilar; puedes entonces crear una función de shell (e incluir su creación en tu perfil de sesión) con la orden:

    $ function ghdl () {\
    > local accion
    > accion=$1
    > shift
    PATH=/usr/gnat/bin:$PATH /usr/local/bin/ghdl $accion --std=87 $*
    }

  4. Si aceptaste la anterior recomendación e instalaste GNAT en /usr/gnat, ahora no habrá nada que configurar. En caso contrario, será necesario editar el fichero /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2.1/vhdl/lib/grt.lst para sustituir la linea:

    -L/usr/gnat/lib/gcc-lib/i686-pc-linux-gnu/2.8.1/adalib/

    por

    -Lubicación-donde-instalaste-gnat/lib/gcc-lib/i686-pc-linux-gnu/2.8.1/adalib/


7. Compatibilidad

Una de tus primeras preocupaciones con ghdl probablemente será: "¿podré compilar y simular este código con otros compiladores como, por ejemplo, VeriBestTM (Mentor Graphics Corp, Wilsonville, OR USA, 1997-2003)?". La respuesta es sencilla, pero merece un poco de literatura.

La diferencia entre VeriBestTM y ghdl (en cuanto a compilación y simulación) es el grado de rigidez en cuanto a sus implementaciones de los estándares VHDL'87 y VHDL'93. Para ser más concisos: ghdl es menos estricto, ya que relaja ligeramente el estándar VHDL'93 para permitir formaciones de VHDL'87, cosa que VeriBestTM no hace. Ésto se traduce en que, si no usas la opción --std de ghdl, puedes encontrarte que algunas descripciones no compilarán en VeriBestTM. Por ejemplo:

FILE f: TEXT IS IN "FICHERO.DAT"

es una formación perfectamente válida en VHDL'87, de modo que compilará correctamente con ghdl si no especificas la opción --std. Sin embargo, al llevarla a VeriBestTM (si no tienes marcada la opción VHDL'87 en las propiedades del proyecto) recibirás un mensaje de error diciendo que dicha formación no es válida en VHDL'93. Si tu intención es que compile bien tanto en ghdl como en VeriBestTM, necesitás la sintaxis VHDL'93 de la declaración de ficheros que es:

FILE f: TEXT OPEN READ_MODE IS "FICHERO.DAT"

Por supuesto, es posible evitar esta imcompatibilidad simplemente haciendo buen uso, tanto en ghdl como en VeriBestTM, de la opción para forzar un estándar u otro, de modo que la sintaxis cumpla completamente el estándar elegido.

En las pruebas de compilación que hemos realizado de varios ficheros creados para ghdl y llevados a Windows para ser compilados con VeriBestTM, no ha sido necesario convertir los ficheros de descripción VHDL del formato UNIX (código de fin de línea LF) al formato Windows (código de fin de línea CR+LF). Hemos tenido la precaución de usar la extensión .vhd que funciona bien en ambos compiladores y el resultado ha sido excelente: ningún error de compilación ni de simulación.


8. Probar la instalación

8.1. Compilar

Descomprime los archivos de ejemplo adder.tar.gz con:

$ tar zxvf adder.tar.gz

y compila y crea el proyecto adder_tb (forzando la sintaxis VHDL'87) con las órdenes:

$ ghdl -a --std=87 adder.vhdl
$ ghdl -a --std=87 adder_tb.vhdl
$ ghdl -e --std=87 adder_tb

Las dos primeras órdenes son para analizar (determinar qué componente contiene cada fichero y generar un objeto) y la última hace el proceso de elaborar adder_tb (genera un fichero ejecutable que es la unidad de simulación) restringiendo la sintaxis al estándar VHDL'87. Si todo ha ido bien, esta última orden no mostrará salida alguna y habrá creado el fichero ejecutable (unidad de simulación) adder_tb.


8.2. Simular

Para simular el recién creado modelo, puedes ahora generar un fichero de onda (VCD) y después verlo con GTKWAVE o ejecutar al mismo tiempo ambos programas. Para el primer caso primero ejecuta:

$ ./adder_tb --vcd=adder.vcd

a lo que el sistema responderá:

adder_tb.vhdl:52:7:(assertion note): end of test

lo que significa que la simulación ha terminado con éxito. Se habrá creado el fichero adder_tb.vcd que contiene un seguimiendo de onda cuadrada en respuesta a la simulación. Para poder verlo y verificar los datos ejecuta:

$ gtkwave adder.vcd

y usa las opciones de menú en Search->Signal Search...para añadir señales y poder verificar las salidas del modelo. Si estás usando la versión 2.0.0pre3 de gtkwave y dispones de un fichero con trazas salvadas de una anterior ejecución (p.e. llamado adder.trc) puedes ejecutar la simulación cargando automáticamente las trazas con la llamada:

$ gtkwave adder.vcd adder.trc

Para ejecutar la simulación y al mismo tiempo ver la onda también puedes usar:

$ ./adder_tb --vcd=- | gtkwave -vcd

Lo que arrancará directamente GTKWAVE, de modo que puedas añadir las señales que quieras, y comprobar que tu modelo funciona adecuadamente.


9. Trucos

Nuestra experiencia usando ghdl y gtkwave no es muy amplia, pero quizá te sirvan un par de consejos para avanzar más rápidamente y no cometer algunos errores habituales. Sin embargo, son sólo sugerencias; no hay nada mejor que la experimentación para aprender a manejar una herramienta. Si tienes trucos para compartir, no dudes en ponerte en contacto con el autor. Estaremos encantados de publicarlos.


9.1. GHDL

9.1.1. Peligros del modelo de compilación:

ghdl es (dentro de lo restrictivo en cuanto a tipos y sintaxis del estándar VHDL) un tanto permisivo en cuanto a la resolución de referencias. En ocasiones, delega dicha resolución al proceso de enlace de objetos de código binario, sin exigir, en tiempo de compilación, que se satisfagan. Ésto puede ocasionar comportamientos anómalos en ejecución o, lo que es peor, en simulación. Para evitar este peligro recomendamos usar, cuando sea posible, un fichero o definición CONFIGURATION o, en su defecto, la sentencia FOR id: entidad USE paquete.entidad(arquitectura). De este modo el compilador conoce de modo anticipado como enlazar las entidades y arquitecturas correctas.


9.1.2. Cómo usar librerías propias con ghdl

Es posible reutilizar componentes propios de otros proyectos en proyectos nuevos. No es necesario para ello crear un paquete. Desaconsejamos especialmente copiar el componente o incluir el fichero objeto en el proyecto. Este método parece funcionar, pero lleva a errores como los anteriormente mencionados. La manera correcta y compatible es usar la opción de ghdl, --work. Con esta opción se puede dar un nombre distinto de WORK al proyecto (lo que equivale en VeriBestTM a dar un nombre lógico a una librería añadida) de modo que, en otros proyectos, sea posible referirse a sus componentes. En el proyecto que usa el componente será necesario incluir las siguientes líneas (p. e. en un fichero de definición de configuración):

LIBRARY proyecto_componentes;
FOR ALL: componente USE ENTITY proyecto_componentes.componente(componente_arquitectura);


9.1.3. Evitar declarar señales en bloques PROCESS

Si bien la sintaxis VHDL permite declarar señales en la sección de declaraciones de un bloque PROCESS, se debería intentar evitarlo, ya que no es correcto en otros compiladores y lleva a un error de ejecución en simulación con Violación de segmento.


9.1.4. Uso de tiempo de simulación finito

En VeriBestTM es normal realizar bancos de pruebas con tiempo de ejecución indeterminado, lo que significa que no se detienen automáticamente; el simulador siempre tiene un horizonte temporal (ampliable) por defecto. En ghdl podemos especificar, en tiempo de simulación la opción equivalente --stop-time=X[m|n|p|f]s, si bien es más recomendable que el banco aplique las pruebas por un tiempo determinado. De este modo el proceso de simulación se detendrá automáticamente cuando, por ejemplo, todos los casos de prueba hayan sido procesados. Recomendamos ejecutar la simulación con la opción --help; existen otras opciones de depuración y simulación muy interesantes.


9.1.5. Atributos no soportados

Como ya se ha mencionado, ghdl soporta casi todo el estándar VHDL'93; algunos atributos de señal no están soportados. Si recibes algún mensaje de error en compilación de como estos,

iterator_decl: can't handle IIR_KIND_IMPLICIT_SIGNAL_DECLARATION (fichero.vhd:2:1)
identifier: can't handle IIR_KIND_DELAYED_ATTRIBUTE (fichero.vhd:50:27)
raised ERROROUT.INTERNAL_ERROR : sem_names.adb:2117

es que la descripción VHDL usa un atributo que ghdl no soporta. Verifica que la sintaxis es correcta antes de darte por vencido.


9.2. GTKWAVE

9.2.1. Restricción de trazas

No es posible monitorizar variables VHDL ni señales de tipos distintos de bit o bit_vector. Ésta no es una restricción de GTKWAVE, sino de GHDL. Una solución de compromiso pasaría por declarar señales paralelas a las que queramos monitorizar (pero de tipo bit_vector) aprovechando, por ejemplo, las funciones de conversión del paquete IEEE.NUMERIC_BIT. Para las señales de tipo enumerado también podemos usar señales paralelas en combinación con atributos de usuario (p.e. creando un atributo de una señal de tipo enumerado que tiene tipo bit_vector y que podemos asignar a una señal de depuración.


9.2.2. Formato decimal

Una función cómoda y muy útil para los que no estamos acostumbrados a los números hexadecimales o binarios, es la de poder convertir las trazas a formato decimal. Es posible seleccionar todas las trazas y pulsar ALT+D, lo que hará que se muestren sólo las trazas de tipo bit_vector en base decimal y el resto en formato bit.


9.2.3. Ver nombres de traza cortos

Si ya has usado GTKWAVE alguna vez, sabrás que usa una nomenclatura jerárquica para las trazas; por ejemplo, el terminal a de una puerta AND perteneciente a un sumador con arquitectura algorítmica lo denominaría sumador.algoritmica.miand1.miand.a. En ocasiones esta notación es excesiva y difícil de leer. Recomendamos establecer el parámetro máximo número de jerarquías (en el menú Editar) a 1, ya que, casi siempre, seremos capaces de distinguir a qué componente pertenece cada puerto solamente con su nombre.


9.2.4. Reordenar trazas

Después de añadir unas cuantas trazas a tu pantalla, probablemente te cueste seguirlas. Con la opción Editar->Ordenar en GTKWAVE 1.3.24 (o Traces->Sort de la versión 2.0.0pre3) podrás ordenar automáticamente las trazas. También puedes hacerlo manualmente: selecciona la traza o trazas a mover y pincha con el botón derecho en la traza debajo de la cual quieres poner la o las seleccionadas. No intentes arrastrar y soltar.


9.2.5. Añadir trazas

Para añadir trazas a la ventana de seguimiento puedes hacerlo de tres maneras (dos en la versión 2.0.0pre3): usando una vista en árbol jerárquico (Buscar->Buscar en árbol, eliminada en la versión 2.0.0pre3), una lista de componentes (Buscar->Buscar en jerarquía o Traces->Add traces->Signal Hierarchy) o con una expresión regular (Señales->Buscar por expresión regular o Traces->Add Traces->Regexp Signal Match en 2.0.0pre3). Esta última es la más flexible aunque difícil de usar para los noveles. Una expresión regular es un patrón que representa un subconjunto de valores de un conjunto mayor. En nuestro caso actúa como un filtro que restringe la lista a los valores que coincidan con el patrón dado únicamente. El patrón que no restringe nada es ".*" (todos los valores coinciden). El punto "." representa un sólo carácter, pero coincide con cualquiera; con "*" detrás representa cualquier número de un carácter cualquiera. A partir de aquí es fácil hacer combinaciones sencillas. Por ejemplo: ".*_s" seleccionaría las señales de la lista que terminan con "_s", etc.


Última modificación:
Roberto (raragon1 en alumno punto uned punto es):26-10-2003
Nº visitas: