jueves, 5 de abril de 2012

Modelacion Funcional de Bus (Bus Functional Model)


Introducción

BFM es una sigla muy usada en el ámbito de diseño de HDL-FPGA, sin embargo no todos saben que es ni a que se refiere, otros diseñadores se dedican a escribir BFMs por lo que saben muy bien lo que es. Bueno, este blog es para los que pertenecen al grupo que dice “Qué es eso?” cuando escucha ‘BFM’.

Básicamente como su nombre lo indica, BFM es un modelo de simulación simplificado que describe correctamente la funcionalidad de I/O bus de un sistema normalmente complejo, sin inmiscuirse con el comportamiento interno de ese componente.

Este modelo se usa dentro del test bench como estimulo (stimulus) del sistema que se quiere testear (DUT), permitiendo en forma directa una comunicación entre el DUT y el sistema externo con el que se quiere interactuar, evitando de esta manera tener que escribir un muy complejo test bench. La siguiente figura muestra el sistema de simulación cuando se usa un BFM.


Figura 1 – Esquema de simulación usando BFM

Explico ahora los distintos componentes en la Figura 1:
Test Code: es el código del test bench en sí, escrito en VHDL. En este parte del test bench se escribe el código VHDL para estimular el DUT, principalmente haciendo uso de los procedimientos que modelan algún ciclo de I/O del componente BFM instanciado en el test bench. 
BFM: es el código BFM del sistema que interactúa con el DUT. Este código es provisto por el fabricante del sistema/memoria o escrito por alguno de nosotros. Dentro del test bench se crea una declaración de este componente y su respectiva instanciación. Actúa como generación de estimulo para el DUT al proveer un preciso estimulo del protocolo de comunicación, ciclo por ciclo en funcionalidad y tiempo. Al mismo tiempo el BFM acepta comandos para seleccionar la funcionalidad a ser modelada. Estos comandos son normalmente asignados a alguna señal en el test bench, declarada en el  paquete, y ejecutados por el procedimiento respectivo del BFM. Este bloque básicamente se codifica como una simple maquina de estados, cuyos estados por ejemplo pueden ser read, write, idle. Y de acuerdo a lo que el test code ‘solicita’ la máquina de estados pasa al respectivo estado y activa las I/O necesarias del sistema modelado (BFM).
DUT: es el device under test que queremos depurar.
Package: es la unidad de diseño que contiene todas las declaraciones y descripciones de las señales, funciones, procedimientos relacionadas al test bench y al BFM. Actúa como medio de comunicación entre las señales del test bench y los procedimientos/funciones del BFM.
El símbolo * lo uso para detallar que el código de test y el BFM ‘pueden’ (no es siempre el caso) proveer no solo el estimulo al DUT, sino también chequear la respuesta del DUT a cierto estimulo. Esta funcionalidad es opcional, sin embargo es altamente aconsejada para automatizar el test y proveer un rápido resultado del comportamiento del DUT bajo determinado estimulo.

Quién escribe un BFM?

Normalmente para componentes complejos, por ejemplo memorias DDR, Flash, dispositivos PCI, PCIe, etc; el fabricante ofrece un modelo BFM para que el diseñador pueda verificar que el protocolo que ha diseñado interactúa correctamente con el componente con el que quiere comunicarse.
Ahora, bien el BFM, es en sí un modelo escrito en VHDL por un ingeniero de la empresa fabricante, por lo que el modela será tan bueno como el ingeniero que lo escriba.
Debo aclarar que hay algunas empresas que escriben sus propios BFMs a fin de facilitar la simulación de componentes, normalmente varios, que tienen protocolos de comunicación complejos. En algunas de estas empresas tuve la oportunidad de escribir y usar algunos BFModels, tarea que al principio era linda, pero luego se transformó en tediosa… :) 

Porqué usar BFM?

El proceso de prueba (simulación) a veces es una tarea compleja que involucra muchas horas de escritura del código (test bench) y otras más de correr la simulación. Normalmente más de la mitad del tiempo de un proyecto involucra la simulación del mismo, y más se incrementa este tiempo cuando la complejidad del proyecto crece. Por ello es necesario usar métodos de prueba (test) más eficientes y que sigan asegurando un diseño libre de errores.
El uso de BFM habilita el test de complejos protocolos y funciones con un gran nivel de abstracción de la funcionalidad interna del componente simulado, menos instrucciones a simular, preciso timing de la interface, todo lo que resulta en un test más robusto, completo y sobre todo más rápido de ejecutar. Esta última es una característica que se destaca cuando se comparan los tiempos de simulación de sistemas complejos, IP cores, etc., que usualmente toman un largo tiempo en simular.

Características de un BFM

  • Provee un medio para modelar la interface del componente que se está modelando, SIN importar la estructura interna del componente o si el componente en si tiene un microprocesador, una o varias FSMs, etc.
  • Provee información de todos los tiempos del protocolo de comunicación de I/Os.
  • Provee chequeo funcional para verificar el correcto funcionamiento del protocolo (handshaking).
  • Normalmente son escritas usando las instrucciones típicamente usadas en Test Bench. Paquetes, funciones, procedimientos, registros y tipos son comúnmente encontradas en BFMs.
  • El alto nivel de abstracción que VHDL ofrece permite modelar complejos sistemas, en funcionalidad y tiempo, abstrayendo al diseñador de la complejidad interna del sistema modelado. 

Ejemplo Flujo de Uso de BFM

La siguiente figura detalla el procedimiento que se debería seguir cuando se usa un BFM.

 
Figura 2 - Pasos a seguir para usar los procedimientos del BFM

Paso 1: Dependiendo de la funcionalidad del BFM que se desea invocar, en el código del test bench se genera un llamado al procedimiento respectivo asignando los valores necesarios. Por ejemplo para comenzar un ciclo de escritura (Wr), habrá que asignar a la senal respectiva un ‘valor’ que entienda el procedimiento que se desea invocar.
Paso 2: El procedimiento invocado seguramente necesita generar algún dato o señal antes de invocar al procedimiento principal.
Paso 3: El procedimiento principal primero solicita la disponibilidad del bus de I/O, normalmente por medio de alguna señal de pedido (request) de bus. En caso que el bus no este disponible, por ejemplo porque todavía se está ejecutando algún otro procedimiento, deberá esperar hasta que el bus esté disponible.
Paso 4: Las I/O del BFM son controladas por el procedimiento principal con el comportamiento deseado (Wr/Rd, etc.) y con el respectivo timing. Una vez finalizado el ciclo, el procedimiento avisa por medio de la misma senal de ocupado (busy)  desacertándola. Permitiendo así el recomienzo del ciclo.

Escritura de BFMs

Uno de los principales usos de BFMs es por ejemplo para representar ciclos de Wr/Rd del bus del componente que se desea modelar. Estos ciclos normalmente se describen mediante el uso de funciones y procedimientos definidos en un paquete para permitir la accesibilidad no solo del BFM pero también del test bench y del código VHDL  en sí.
Los ciclos de Wr/Rd son fácilmente descriptos mediante el uso de procedimientos (procedures) que modelan perfectamente el comportamiento de los ciclos de Wr/Rd ya sea sobre memoria o sobre I/O, no solo funcionalmente sino también con los tiempos respectivos. La BFM debe ser capaz de leer un comando, por ejemplo, y devolver la respuesta a ese comando, de ese modo se prueba tanto la escritura como la lectura de mi componente sobre el componente modelado con BFM. Al usar procedimientos y ser un modelo de un sistema toda la potencia del lenguaje VHDL puede ser usada al escribir el BFM.
La entidad/arquitectura del BFM debe ser instanciada junto con nuestro componente (DUT) dentro del test bench. Mínima configuración del BFM a veces es necesaria al comienzo del TB, hasta que pueda comenzar el handshaking entre mi componente y el componente BFM.
Ejemplo del código escrito para una BFM.
Declaraciones en el paquete:

 1 -- declaraciones de type y señales --    
 2 type cycle_op is (idle, nop, read, write);
 3
 4 type instruction_op is record
 5    bus_cycle   : cycle_op;
 6    addr_bus    : std_logic_vector(15 downto 0);
 7    data_bus    : std_logic_vector(15 downto 0);
 8    rd_data     : std_logic_vector(15 downto 0);
 9    bus_request : std_logic;
10    busy        : std_logic;
11 end record;
12
13 signal cmd     : instruction_op :=  (idle,
14                                     (others => '0'),
15                                     (others => '0'),
16                                     (others => 'Z'),
17                                     '0',
18                                     'Z');
 
En este ejemplo el registro (record) declara las señales a ser usadas para generar el estímulo de las I/O, como así también información a pasar al procedimiento que debe ejecutar el ciclo seleccionado. Es decir se declara:
  • Tipo del ciclo (idle, nop, read, write)
  • Dirección a ser utilizada en el bus de direcciones
  • Dato a ser escrito si es un ciclo de escritura, o dato que se espera leer si es un ciclo de lectura
  • Data leído
  • Señal de pedido de bus (bus_request). Se activa para solicitar comienzo de un ciclo.
  • Señal de bus ocupado (busy). Se activa durante el proceso de ejecución de algún ciclo. 
Un procedimiento de un ciclo de escritura puede ser escrito tal como se detalla a continuación:

1 -- declaracion del procedimiento wr_cycle
2 procedure wr_cycle (
3    constant p_addr_bus : in std_logic_vector(15 downto 0);
4    constant p_data_bus : in std_logic_vector(15 downto 0);
5    signal   p_cmd_op   : inout instruction_op
6    ) is
7 begin
8     main_cycle(write,p_addr_bus, p_data_bus,p_cmd_op);
9 end wr_cycle;

 

Donde el procedimiento main_cycle es el siguiente:

 1 -- declaracion procedimiento main_cycle
 2 procedure main_cycle(
 3    constant p_cycle    : in cycle_op;
 4    constant p_addr_bus : in std_logic_vector(15 downto 0);
 5    constant p_data_bus : in std_logic_vector(15 downto 0);
 6    signal   p_cmd_op   : inout instruction_op
 7    ) is
 8 begin
 9   p_cmd_op.request <= '0';
10   if p_cmd_op.busy /= '0' then
11       wait on p_cmd_op.busy until p_cmd_op.busy = '0';
12   end if;
13   p_cmd_op.request   <= '1';
14   p_cmd_op.bus_cycle <= p_cycle;
15   p_cmd_op.addr      <= p_addr;
16   p_cmd_op.data      <= p_data;
17   if (p_cmd_op.busy = '0') then
18      wait on p_cmd_op.busy until p_cmd_op.busy = '1';
19   end if;
20   p_cmd_op.request    <= '0';
21 end;

Este procedimiento lleva a cabo las tareas de ‘handshaking’, usando las señales busy y request, y de comunicación entre el test code y el BFM.
Ahora, como invoco las distintas funciones del BFM dentro del test bench? La siguiente línea de código, escrita en el test bench, muestra como se puede invocar el procedimiento del ciclo de escritura:  

1 wr_cycle(x"0000",x"05ab",cmd_op);

Entonces lo que pasa es lo siguiente:
  • El procedimiento wr_cycle esta declarado en un paquete (ver figura 1)
  • El procedimiento wr_cycle le pasa los parámetros necesarios al procedimiento main_cycle
  • El procedimiento main_cycle lleva a cabo el handshaking, y pasa el comando (cmd_op) a la máquina de estados (FSM, Finite State Machine) de la BFM.
  • Al ser un comando de escritura la máquina de estado pasa al estado escritura donde procederá a activar las señales correspondientes del ciclo de escritura, y habilitar las de espera que el proceso se cumpla (ready). Este último paso es el que realmente ‘ve’ el DUT.
La siguiente figura detalla la modificación de la primer figura al ejecutarse un ciclo de escritura, mostrando gráficamente los pasos recién enumerados.


Figura 3 - Detalle de los procedimientos y código ejecutados durante un ciclo de escritura del BFM

Unos puntos a considerar de la Figura 3:
  • La línea punteada entre el bloque Test Code y Package se debe a que en realidad el procedimiento wr_cycle está definido en el paquete pero, como bien sabemos, cuando se compila el código de Test Code, el procedimiento definido en el paquete es ‘insertado’ en el lugar en que éste es invocado
  • Lo mismo sucede con el procedimiento main_cycle. El cual es también ejecutado desde Test Code
  • Tal como se puede deducir del código de los procedimientos detallados anteriormente (wr_cycle, main_cycle), la señal cmd_op, definida como un registro, contiene toda la información necesaria para que la FSM del componente BFM genere el correspondiente ciclo de escritura en las líneas de I/O de este bloque (recordar que el componente BFM está instanciado dentro del test bench).

Espero que este artículo sirva para, por lo menos, tener una idea de la pregunta: Qué es un BFM?

martes, 13 de marzo de 2012

VHDL 2008: Declaraciones de Contexto (Context Declarations)

En VHDL 2008 hay una nueva unidad de diseño (desgin unit) llamada Context Declaration, o Declaración de Contexto (DC). 

Que es y que hace la DC? 
En primer lugar el estándar VHDL-2008 pre-define una declaración de contexto de la siguiente manera para usar el paquete numeric_std:

1 context ieee_std_conext is
2   library ieee;
3   use ieee.std_logic_1164.all;
4   use ieee.numeric_std.all;
5 end;


 De este modo en mi proyecto puedo directamente escribir: 

1 context ieee.ieee_std_conext;
2
3 entity ...

Pero, así como está pre-definido el contexto arriba mencionado, VHDL2008 permite definir 'user defined' contextos, permitiendo de este modo juntar en un solo archivo TODOS los paquetes que se usan para un proyecto específico. Por ejemplo puedo definir:

1 context mis_paquetes is
2  library ieee;
3  use ieee.std_logic_1164.all;
4  use ieee.numeric_std.all;
5  use my_library.all;
6  use ieee.fixed_pkg.all;
7  .....
8 end;

Donde se escribe una DC?
Ahora bien, como ya dije al comienzo una DC es una design unit, tal como lo es una entidad, un paquete, una configuración, por lo que una DC DEBE escribirse en un archivo aparte, por ejemplo mis_paquetes_context.vhd, e incluirlo dentro del proyecto como cualquier otro desing unit (del mismo modo que se incluye un paquete por ejemplo, puedes ver el blog al respecto). 

Uso del DC?
Una vez definida, se debe incluir en el proyecto la design unit, para usarla en los diferentes componentes del proyecto. 
De este modo en cada otra design unit se debería escribir lo siguiente:

1 context work.mis_paquetes;
2
3 entity . . . .

El uso de 'work.' se debe a que por defecto la mayoría de las herramientas compilan los unidades de diseño en esa librería. Esto puede cambiarse a gusto por el diseñador.
 
Cuidado/Advertencia -> Compatibilidad
Antes de hacer uso de esta característica de VHDL 2008 deberías verificar que tu herramienta de síntesis soporte VHDL 2008. Debido q esto depende de q herramienta de síntesis estés usando, XST, Quartus, Synplify, Precision, etc; no te puedo guiar al respecto, pero normalmente es una tarea sencilla. 
El otro problema q uede presentarse es que la herramienta de síntesis soporte VHDL 2008, pero la de simulación no ! :) ... Por lo que directamente aconsejo verificar ambas herramientas antes de comenzar a trabajar con CD. 

Hasta pronto ! 

jueves, 19 de enero de 2012

Problemas con System Generator / Simulink - 2

Problema 2 - Importando Múltiples Sistemas generados por SysGen en un modulo top en ISE


Cuando se trabaja con sistemas complejos puede suceder que se genere el sistema Simulink-SysGen para cada uno de ellos, y luego en el ambiente ISE escribir el modulo (entity-architectura) que interconecta los diferentes sistemas. Teóricamente este proceso debería hacerse sin problemas, sin embargo HAY PROBLEMAS no documentados, q llevaron largas horas de debug  hasta encontrar primero la fuente del problema y luego la solución. 
El siguiente gráfico detalla los distintos archivos y flujo de síntesis en el caso de que múltiples sistemas generados por separado por System Generator desean ser integrados en un solo modulo de mas alto nivel. 




System Generator crea un archivo de proyecto con la extensión .sgp que puede agregarse como una fuente a Project Navigator en el ISE. Este archivo contiene toda la información necesaria sobre el diseño en System Generator.
Sin embargo, cuando se realiza un diseño jerárquico teniendo dos o más diseños de System Generator como componentes del modulo de mayor jerarquía, se deben renombrar las librerías HDL (autmaticamente generadas por System Generator) para evitar conflictos de nombres y otros comportamientos no deseados durante la simulación. 
System Generator tiene un comando que cambia los nombres de la librería para todos los archivos relacionados en el diseño de un proyecto de System Generator. Además, también hace una copia de seguridad en el caso de que se quiera recuperar el nombre de la biblioteca original. La siguiente es la sintaxis de este comando:

XLSWITCHLIBRARY (target_dir, FROM_LIB, TO_LIB)

Reemplaza todas las bibliotecas HDL referidas como FROM_LIB con TO_LIB en un diseño de System Generator ubicado en la carpeta target_dir.
Importante: este comando se debe ejecutar desde la consola de Matlab.


Modo de Uso 
Suponiendo que se tienen dos proyectos de System Generator cuyos nombres son 'delay_bram' y 'eco_bram', la ejecución del comando XLSWITCHLIBRARY para el cambio del nombre de la librería 'work' (nombre dado por defecto por SysGen) a otro nombre (dado por el usuario) se detalla a continuación: 



Una ejecutado este comando, los sistemas generados por SysGen pueden ser usados como componentes en ISE sin tener problemas.

PD: de nuevo gracias a Layla y Esteban por este aporte. 

miércoles, 30 de noviembre de 2011

Problemas con System Generator / Simulink - 1

Hace poco terminé de dictar uno de mis cursos favoritos basado en el flujo de diseño DSP/FPGA. El curso tuvo mucho éxito, pero como siempre que se implementa algo surgen problemas que solo aparecen cuando uno hace algo.... la teoría es muy linda hasta que  se tiene que implementar.... :) . . . 

Uno de los grupos de alumnos, Layla y Esteban, tuvieron problemas que no estaban documentados por ningún lado, y a fin de que Uds. no gasten tanto tiempo como ellos en encontrar soluciones, decidieron compartir problemas con soluciones. 

Problema 1- Error Debido a la Configuración de Idiomas de la PC
Dentro de un bloque Simulink cuando se le asigna una constante expresada en decimal a un bloque 'CMult' de System Generator, y luego al querer simular el sistema aparece un error relacionado al bloque pero cuyo mensaje es bastante encriptado.... 




Seguramente este mensaje de error es generado porque existe un problema de 'mal entendimiento' en la representación de números decimales: System Generator lo representa de un modo diferente al modo representado por el sistema operativo de la PC. Esto es muy común que nos pase a los que tenemos la PC configurada para el idioma español. Por defecto el número decimal, en todas las opciones del español, se representa con una coma. Mientras que System Generator lo representa con un punto. entonces !, existe una incongruencia que el compilador no sabe que hacer y genera el mensaje de error encriptado. En el ejemplo mostrado en la figura arriba el error se genera por querer asignar un valor de 2,3 a CMult. Si en su lugar se asigna 2.3  no existe ningún error. 

Solución
Cambiar la configuración regional de su PC a Inglés: Panel de Control -> Opciones Regionales y Lenguaje.

viernes, 11 de noviembre de 2011

Error: "Port 'clock' has illegal connections.This port is connected to an input buffer and other componentes"

Este mensaje de error realmente no de mucha idea de cual es el problema, es por ello que deseo aclararlo acá.

Lo que realmente significa este mensaje, es que la entrada de reloj () está siendo ruteada al buffer de entrada y de alli a un DCM, por ejemplo. Por ello no es posible usar esta misma señal de entrada, clock, como señal de reloj en cualquier componente sincrónico. Esto se debe a que cuando uno usa un DCM el ruteo entre el pin de entrada y el DCM es un ruteo dedicado de bajo skew y bajo retardo, y no tiene derivaciones, es decir no puede usarse esa señal en otro lugar porque no tiene ruteo disponible. Así, el unico reloj disponible es la salida del DCM. 

Un solución a este problema es usar otro pin de E/S por el que entra el mismo reloj, pero sin enviarlo a un DCM. En este caso se puede usar un pin E/S como entrada de reloj del DCM, y otro pin E/S, con el mismo reloj, que puede ser usado para los componentes sincronicos que necesiten ser controlados por este reloj. 

La otra solución es usar también dos pines E/S, y dos DCMs, uno para cada frecuencia de trabajo que se necesite.

Greetings..... 

viernes, 28 de octubre de 2011

Generando el Hex del ASCII para ROM/RAM usando Matlab

En un previo post , http://hdl-fpga.blogspot.com/2011/06/memorias-rom-fpga-vhdl-como.html, detallé la codificación en VHDL para inferir memorias ROM e implementarlas en FPGAs. Una de las partes mas 'aburridas' de esta codificación es primero pasar de la letra al ASCII y después del ASCII al Hex respectivo. Especialmente para el caso de un string o número muy largo, o varios strings. 
Por ello, en uno de mis últimos cursos que dicté uno de mis alumnos no quería 'aburrirse' realizando las dos conversiones, entonces uso sus conocimientos y me presentó una solución tan ingeniosa como efectiva: escribió una pequeña función en Matlab que hace no solo las mencionadas conversiones sino que también genera directamente la sintaxis VHDL respectiva para la asociación del arreglo ROM  con sus valores respectivos. Gracias Ihosvanni por evitar que nos aburramos !. Acá va un screenshot del .m:




Básicamente lo que hace este código .m es tomar tres mensajes, y convertirlos en ASCII y luego al Hex respectivo. Para este caso planteado el resultado de la ejecución es algo como esto: 

0=>x"56",1=>x"61",2=>x"6C",3=>x"6F",4=>x"72",
5=>x"65",6=>x"73",7=>x"20",8=>x"64",9=>x"65",
. . . . . .
51=>x"20",52=>x"21",others=>x"20"


Así, lo único que queda por hacer es copiar y pegar estos valores en el arreglo ROM declarado tal como se detalló en el previo bloq. 
Este .m se puede perfectamente adaptar a distintos casos, por ejemplo remover mensajes, agregar más mensajes, etc. Por supuesto tener la precaución de que si se remueve algún mensaje, se deben remover todas las referencias al mismo, si se agregan mensajes, agregar las referencias respectivas. También se puede usar para casos en los que se quiere inicializar una memoria tipo RAM con un arreglo definido tal como se detalla en el previo blog.

El código Matlab lo puedes bajar de este link: ascii2rom.m

Espero que sea de utilidad, si es así ... bueno, házmelo saber ! 

jueves, 27 de octubre de 2011

Mensaje de error: "Can't find net or instance name"

Este mensaje suele ser comun cuando queremos restringir (constraint) alguna net o componente de nuestro diseño mediante el uso de constraints en el .ucf. Usualmente eso se debe a que en el .ucf usamos un nombre, normalmente el nombre de la señal o componente en nuestro código VHDL/Verilog, que la herramienta de Síntesis o de Place and Route modificó y nosotros no nos enteramos y consecuentemente el constraint usado en el .ucf hace alusión a una señal o componente que no existe. 
Xilinx ofrece un programa, ejecutable desde comando de linea, llamado netgen, que lee el archivo .ngc o .ngd del sistema implementado y genera el .vhd o .v respectivo para llevar a cabo una simulación funcional (usando .ngc) o post place and route simulación (usando el .ngd). Aún cuando la idea no es llevar a cabo la simulación, el archivo .vhd/.v puede perfectamente ser usado para los fines que buscamos: encontrar los nombres de la señal o componente que necesitamos restringir. 
Los pasos a seguir para usar netgen son similares a los ya explicados anteriormente para pasar de .ngc a .vhd, pero acá los detallos de nuevo.

Pasos para usar 'netgen' (para pasar de .ngc a .vhd) 
  1. Abrir una ventana de 'comandos' o 'DOS': Inicio -> Ejecutar. En la ventanita que se abre escribir 'cmd' y presione 'Aceptar'. 
  2. La ventana de comandos de Window se abrirá normalmente en tu directorio de documentos. 
  3. Usando el viejo comando 'cd' ir hasta el directorio donde está el archivo .ngc que se desea convertir.
  4. Escribir 'netgen -ofmt vhdl mi_archivo.ngc' y presione enter para generar el archivo 'mi_archivo.vhd'. En caso de obtener un mensaje de error diciendo que no reconoce como ejecutable al programa 'netgen', deberá anteponerle el camino del directorio donde reside el ejecutable, por ejemplo:
  5. f:\mi_proyecto>f:\Xilinx\12.1\ISE_DS\ISE\bin\nt\netgen -ofmt  mi_archivo.ngc 
    Si deseas que el archivo .vhd tenga otro nombre usá el siguiente comando: 
    f:\mi_proyecto>f:\Xilinx\12.1\ISE_DS\ISE\bin\nt\netgen -ofmt  mi_archivo.ngc mi_vhd.vhd
Ahora si ya podés abrir el .vhd y buscar las señales o componentes de tu interés. Si bien el archivo .vhd, que en realidad es un modelo de simulación del  sistema implementado. Parece bastante complicado, pero se puede 'leer' e interpretar la implementación, notando el uso de componentes tipo 'primitivas'. Usando un 'search' o búsqueda podemos encontrar las señales o componentes que necesitamos.