| Simulando VHDL con herramientas GNU: GHDL+GTKWAVE | ||
|---|---|---|
| Anterior | ||
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.
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.
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 VeriBest™ 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);
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.
En VeriBest™ 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.
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.
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.
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.
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.
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.
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.