Images

Uso del ChipScope para el código en VHDL LEDA_blog (II): Tutorial ejemplo de uso ChipScope

Una vez hecha en la anterior entrada, pasamos al desarrollo del tutorial.

Paso 1: Creación del proyecto y chequeo de la sintaxis.

En el caso en que desconozcas como crear un proyecto con el software de XILINX,  puedes basarte en las entradas cuyo links dejo a continuación o echar un vistazo en los numerosos tutoriales que hay en Internet partiendo de código VHDL (también se puede hacer partiendo de esquemáticos del diseño digital con puertas OR, AND, XOR… MULTIPLEXORES, CONTADORES… etc, pero eso ya es otra historia).

http://ecalamartronico.blogspot.com.es/2016/08/introduccion-al-kit-open3s250e-6-crear.html


Pero ojo, el código que usaremos en esta ocasión es muy similar al que describo en esas entradas anteriores, pero ligeramente modificado por mí, así que lo dejaré a continuación para que puedas copiar y pegar al crear tu módulo VHDL en el proyecto.


---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity LEDA_blogChSc0 is Port ( clk : in STD_LOGIC; led1_0 : out STD_LOGIC; led1_1 : out STD_LOGIC; led1_2 : out STD_LOGIC; led1_3 : out STD_LOGIC); --LCD_N : out STD_LOGIC; --LCD_P : out STD_LOGIC); end LEDA_blogChSc0; architecture light_blogChSc0 of LEDA_blogChSc0 is SIGNAL clk1:std_logic :='0'; SIGNAL CLK2:std_logic :='0'; SIGNAL clka:std_logic :='0'; begin --LCD_N<='0'; --LCD_P<='0'; P1:PROCESS (clk) VARIABLE count:INTEGER RANGE 0 TO 9999999; BEGIN IF clk'EVENT AND clk='1' THEN IF count<=4999999 THEN clk1<='0'; count:=count+1; ELSIF count>=4999999 AND count<=9999999 THEN clk1<='1'; count:=count+1; ELSE count:=0; END IF; END IF; END PROCESS ; P3:PROCESS(CLK1) Begin clk1 <= clk1; IF clk1'event AND clk1='1'THEN clk2<=not clk2; END IF; END PROCESS P3; P2:PROCESS(clk2) variable count1:INTEGER RANGE 0 TO 16; BEGIN IF clk2'event AND clk2='1'THEN if count1<=4 then if count1=4 then count1:=0; end if; CASE count1 IS WHEN 0=> led1_0<='0'; led1_1<='1'; led1_2<='1'; led1_3<='1'; WHEN 1=> led1_0<='1'; led1_1<='0'; led1_2<='1'; led1_3<='1'; WHEN 2=> led1_0<='1'; led1_1<='1'; led1_2<='0'; led1_3<='1'; WHEN 3=> led1_0<='1'; led1_1<='1'; led1_2<='1'; led1_3<='0'; WHEN OTHERS=> led1_0<='1'; led1_1<='1'; led1_2<='1'; led1_3<='1'; END CASE; count1:=count1+1; end if; end if; end process; end light_blogChSc0;

Disculpa si no entro mucho en detalle en esta sección, pero es que si lo hago esto se puede hacer demasiado largo, denso y pesado tanto para ti como para mí.

 Además créeme que este paso no es demasiado difícil y muy probablemente encontrarás muy poca dificultad en esto (hay muchos tutoriales con ejemplos más sencillos en los que también te puedes basar si lo deseas).

Paso 2: Creación del archivo .ucf (user constraints).

De nuevo voy a dejar otro enlace para este paso. 


---------------------------------------------------------------------------------------------------------
Nota importante:

El momento en que se va abrir el PlanAhead a mí me tarda más que bastante, en el pasado me he llegado a impacientar, he hecho clic varias veces en I/O Planing (PlanAhead…) y transcurrido un tiempo se me han abierto varios PlanAhead.
Si te ocurre como a mí que sepas que es relativamente normal, quizás no estemos trabajando en las mejores condiciones: el PC está saturado, la RAM no es muy potente, nuestro software no es el mejor… que se yo, la cuestión es que no te impacientes como yo las primeras veces please, al final se abre.
---------------------------------------------------------------------------------------------------------

Yo lo estoy haciendo con versiones de ISE porque he trabajado con ellas más y voy justo de tiempo, pero si puedes investigar un poco y hacerlo con las últimas versiones de XILINX, es decir con Vivado, mucho mejor aunque el proceso no es exactamente como aquí lo describo, hay que hacer lo que se llama un “Migrating to Vivado Logic Debug Cores”, pero al menos muchos conceptos son similares o iguales, y espero que esta entrada te ayude. Dejo un link que te puede ser de ayuda si trabajas con Vivado. 


En el  link


que ya dejé anteriormente, ahí trabajo con una versión más antigua de ISE que la que estoy usando esta vez, es por eso que cambia ligeramente el interfaz del PlanAhead. No es difícil manejar este nuevo interfaz conociendo el otro, no obstante dejo un mini-tutorial en forma de clip para que facilitar las cosas:



Filmar con una mano y trabajar con la otra, y encima con poca luz y una cámara mala no da resultados muy óptimos, pero espero y deseo que el clip sea suficiente para ilustrar el proceso.

Se repite el proceder del clip anterior (si te equivocas asignando los pines de la FPGA se puede corregir de forma fácil e intuitiva) hasta obtener la configuración que se muestra en la siguiente figura:



---------------------------------------------------------------------------------------------------------

Notas:

Si las imágenes las ves muy pequeñas, puedes hacer clic en ellas para verlas más grandes y luego en la flecha de retroceder de tu navegador (apuntando a la izquierda)  para volver a la entrada. Normalmente está en la parte superior izquierda del navegador dónde estés viendo el blog.

En otras ocasiones se abre la imagen con el fondo del blog oscurecido, en esos casos basta con dar al icono con forma de aspa (típico para cerrar) que aparece en la parte superior derecha y volverás al blog.

Estos pequeños detalles como que los post sean cómodos de leer, es algo que a veces se te escapa y sin embargo es muy importante.





---------------------------------------------------------------------------------------------------------

La asignación de pines no es en absoluto arbitraria, si trabajas con una Core3S250E la explicación la puedes obtener en el siguiente link:


Si estás trabajando con otro hardware seguro que encuentras información similar en Internet. Me extraña que no haya información de este tipo para placas como la Basys o Nexys, y si eres tan máquina que has hecho tu propia placa, seguro que has visto el datasheet de la FPGA que estés usando y la configuración de la PCB la sabrás mejor que nadie.

 Ahora se guarda (en el icono de la parte superior izquierda con la forma característica de los iconos “save”) y puedes ya cerrar el PlanAhead si quieres.

Al volver al ISE o el Vivado verás que se ha añadido un archivo con extensión “.ucf”. Si es así y has seguido los pasos correctamente todo va bien.

Paso 3: Conexión del hardware.

En realidad esto se puede hacer un poco más tarde, pero no está de más que lo hagamos ya.
Por aquello de que “una imagen vale más que mil palabras” en este paso no va a haber mucha "literatura". 



No olvidar dar a la clavija de ON (el led de la DLC9G de XILINX blanca tiene color naranja en off):


En la anterior imagen ya le hemos puesto la clavija de la Core3S250E en ON, por eso se nos enciende un LED en dicha placa y en la DLC9G (artefacto blanco) el led ahora está en verde (mis disculpas por la escasa calidad de las fotos).

Si usas otro tipo de hardware no creo que encuentres muchos problemas para conectarlo al ordenador, suelen estar diseñados para que las conexiones al PC sean fáciles, además el fabricante suele dejar algún enlace para que descargues algún manual.

 Paso 4: Creando el Inserter del ChipScope.

Aquí ya no valen atajos en forma de enlaces, clips o fotos de dudosa calidad, esto es parte ya esencial de la entrada, así que toca “remangarse la camisa”.

En estos momentos tendremos algo como esto, 

Si usas Vivado la interfaz cambia, y el proceso no es exactamente como aquí lo describo, como ya dije hay que hacer lo que se llama un “Migrating to Vivado Logic Debug”, no obstante ver este tutorial te puede facilitar luego trabajar con Vivado (queda pendiente hacer más cosas con Vivado, ojala no me caduque pronto el trial que tengo):

Obsérvese en la anterior imágen, que está seleccionado el “LEDA_blogChSc0.vhd”, y si no lo tienes seleccionado te sugiero que lo hagas porque lo necesitamos seleccionado para los siguientes pasos:



También se puede observar que de la raíz de dicho archivo está el archivo con extensión “.ucf” que tiene que ver con la configuración de pines que hemos hecho del hardware mediante el PlanAhead.

Hacemos clic botón derecho del ratón en dicho archivo seleccionado. 


Nos aparece el siguiente cuadro de diálogo:


Dentro de él seleccionamos “ChipScope Definition and Connection File”:


Por supuesto es imprescindible que el casillero “Add to Project” esté seleccionado, lo más normal es que esté ya seleccionado por defecto, sino lo está haz clic en él.

Ahora en el campo “File name”, le damos el nombre que queramos, yo que soy un poco sesudo a veces le voy a llamar TestChSc0.

Clic en “Next”.

Ahora tenemos la siguiente ventana emergente que tiene una función meramente informativo, en ella clic en “Finish”.


Después de un ratito no muy largo de procesamiento ya tenemos un nuevo fichero en la ventana superior izquierda llamada Design dónde está el Hierachy (jerarquía en inglés, haciendo alusión a la jerarquía en el “árbol” de ficheros del proyecto).



Este archivo o fichero (con extensión “.cdc”), es lo que se llama el “Inserter”, y lo vamos a usar para definir qué es lo que queremos visualizar de la simulación del proyecto.

---------------------------------------------------------------------------------------------------------

Yo decido mostrar la simulación que concierne al proceso P2, que es el que gestiona las salidas a los leds: led1_0,  led1_1, led1_2 y led1_3.  Dichas salidas se gestionan con el “reloj” CLK2, y pongo reloj entrecomillado porque el auténtico reloj del sistema es una entrada de este notada como clk. CLK2 es una señal resultado de procesar la señal de reloj de entrada clk para que la transición entre led encendido, led apagado y siguiente led encendido pueda detectarla el ojo humano (clk tiene una frecuencia demasiado alta para eso).

¿Porque decido mostrar esa parte del algoritmo y no toda u otra parte?, porqué de entre las diversas simulaciones que  he hecho en los últimos días esta es la que tiene mejor presentación sin tener que complicar mucho el proceso, y quiero que la persona que lea esto le guste el ChipScope, no que empiece a "tomarle ojeriza" desde el principio.

Si usas algún hardware (Nexys o Basys por ejemplo) compatible con el software Diligent Adept  todo se simplifica mucho y las visualizaciones son mucho mejores.

---------------------------------------------------------------------------------------------------------

Hacemos doble clic en el archivo TesChSc0, tras lo cual no tendremos inmediatamente un cuadro de diálogo sino que el programa empezará a procesar cosas la síntesis, el análisis HDL… etc (esto nos va apareciendo en la consola que normalmente ocupa todo lo largo de la parte inferior del interfaz.



En un momento dado (sin que haya acabado el procesamiento), surge la secuencia de cuadros de diálogo que tenemos que cumplimentar.

En la primera ventana ya está todo cumplimentado por defecto, así que Next.


En esta otra ventana tampoco hay nada que hacer, puro trámite en este caso, Next.



En este otro cuadro de diálogo si nos tenemos que fijar mejor, haremos especial hincapié en lo que circulo en rojo en la siguiente figura:



 1 - Number of Input Trigger Ports: la traducción al castellano podría ser algo como “Número de Puertos de Disparo en la Entrada” o también podríamos llamarlo “Número de Puertos de Activación en la Entrada”.

Para entender mejor que son los “Input Trigger Ports” vamos a usar el caso concreto de este tutorial. Dije anteriormente que pretendemos visualizar la simulación del proceso P2:
Si nos fijamos en el código del proceso P2 vemos que se activa mediante en el momento en que se ejecuta la lista sensible de dicho proceso (indicada al principio entre paréntesis tras la palabra reservada de VHDL PROCESS).


En la implementación de código en el hardware, si en cualquier otro lugar del código se ejecuta una instrucción en la que aparezca CLK2, de forma paralela y casi inmediatamente se empezará a ejecutar el proceso P2.

Esto es una característica propia de los sistemas digitales y del lenguaje VHDL -que viene a ser una forma más de describir esos sistemas digitales como pueden ser los FPGA- A esta característica la llamamos ejecución de instrucciones concurrente o concurrencia.

En la simulación, como la hace el ordenador, en principio se ejecutan las instrucciones de forma secuencial, así que de alguna manera la concurrencia se implementaría como una llamada a la “función” P2 en cuanto se activa CLK2.

Para decirlo de una forma simple y resumida: el proceso P2 se pondrá en marcha en cuanto se active la señal CLK2.

Por tanto nuestra Input Trigger Ports aquí será CLK2.

Pero el espacio a rellenar no nos indica quién en el Input Trigger Port, sino cuantos usaremos, como sólo usamos CLK2 en el desplegable que activamos a la derecha del casillero (y aquí seguro que se denomina en inglés drop-down list), debemos buscar el 1 o dejarlo en 1 si te viene por defecto como es mi caso.

Por tanto:

Number of Input Trigger Ports = 1


2 – Trigger Width:

 

Podemos tener un solo puerto para la señal de activación de entrada (Input trigger port), pero el puerto puede – por ejemplo- ser un bus en el que se mandan 8 bits en paralelo (la señal de entrada en este caso sería un vector de tamaño 8).

No es el caso, CLK2 es una señal que funciona como un reloj, de manera que en un instante de tiempo t0 hay un 0 lógico, en el siguiente t1 hay un 1 lógico… etc.


Es decir, CLK2 es un tren de pulsos de una sola línea

---------------------------------------------------------------------------------------------------------

Nota importante:

Pero ojo, y esto es importante, cuando se ejecuta el proceso P2, se ejecuta para el valor que tenga en ese momento CLK2,  es decir un 1 o un 0 (recordemos que CLK2 es la "lista" sensible del proceso P2).

De manera que todos los parámetros (señales, variables… etc) que hay dentro del proceso P2 trabajarán o bien con un 1 lógico fijo en CLK2, o bien con un 0 lógico fijo en CLK2, hasta que se ejecute el proceso completo.

Será cuando vuelva a ejecutarse o “llamarse” al proceso P2, cuando ese valor 0 o 1 pueda cambiar.

Es por eso que si pretendiéramos en este ejercicio visualizar CLK2, veríamos una línea recta con valor 1 o 0 en lugar del tren de pulsos que esperaríamos encontrar (puedes hacer la prueba después de este tutorial si lo deseas).

Y ahí es donde entra el rol del reloj del sistema o de la señal que tomemos como reloj de la simulación (que en este caso será también CLK2).

Si el reloj (que es un tren de pulsos), está en un 0 lógico -por ejemplo-, P2 se simulará con CLK2 = 0, pero si en el siguiente instante de tiempo muestreado la señal de reloj (CLK2 en nuestra simulación), cambia a 1, entonces P2 se ejecutará con CLK2 = 1.

Entender bien esto es importante porque cuando simulamos en un proceso, lo hacemos para un “Trigger Input Port” determinado, y no para todos los tránsitos de la señal de reloj.

Es por eso que si hemos hecho nuestro código en VHDL de forma funcional o algorítmica, que es normalmente mediante procesos, no va a ser fácil simular para comparar señales, señales como las de trenes de pulsos por ejemplo (que es la forma que tendrá en nuestro caso tanto clk, como clk1, como clk2). 

---------------------------------------------------------------------------------------------------------

Por tanto:

Trigger Width = 1



3 – Match Type:


En este caso no es importante, podemos dejarlo tal y como está por defecto. Pero no está mal considerarlo para otros casos, para ello dejo la siguiente tabla:En este caso no es importante, podemos dejarlo tal y como está por defecto. Pero no está mal considerarlo para otros casos, para ello dejo la siguiente tabla:


El resto de casilleros y cuadros se dejan igual que como vienen por defecto.

Por consiguiente nos queda:


Ahora clic en Next.


Nos fijamos en lo que está señalado en rojo en la siguiente figura.



Data Same As Trigger: Se usa para que los datos a simular sean a la vez los "trigger".  Normalmente viene por defecto su casillero activado (como en la figura anterior). Si está activado en esta ocasión interesa que lo desactives.

Teniendo ahora:



Fijémonos en los dos parámetros que señalo con rojo en la siguiente figura:



Data Width: vamos a simular el comportamiento de las cuatro señales de salida que van a los leds, esto es: led1_0, led1_1, led1_2 y led1_3.

De lo que se deduce:

Data Width = 4




Data Depth: para entender lo que significa este parámetro, hay que entender que el software que simula tiene que tomar un número finito de muestras. Cuantas más muestras se toman, más y mejor definidas estarán las señales que visualicemos en la simulación, pero por el contrario más memoria consumimos y la ejecución de los resultados también puede tardar más.

 Así que esto depende de cada diseño y de nuestro criterio. En este caso vamos a visualizar trenes de pulsos que no son señales complejas que necesiten muchas muestras, no obstante para “curarnos en salud” tomamos 1024.



Por último veamos el parámetro Sample On (Clock Edge).



Este indica si las modificaciones de las señales vienen dadas por los cambios de reloj en flanco de subida o flanco de bajada.


Lo dejamos con el flanco de subida, es decir, Rising.

Con lo que tenemos:


Ahora Next.



En el campo central (la ventana Net Conections), nos encontramos UNIT, CLOCK PORTS Y DATA PORTS en rojo porque aún no les hemos dado valores, para ello hacemos doble clic en cualquiera de ellos.


Se abre la siguiente ventana emergente:



Vamos a darle valor al Trigger Signals, para lo cual tenemos que encontrar CLK2 en esa lista enorme de señales y variables que encontramos.

Un truco para hacerlo es teclear clk2 en el campo a la derecha de dónde pone Pattern (patrón en inglés).


Ahora seleccionamos esa única señal en que se ha quedado la lista y clic en Make Conections.




Ahora hacemos clic en la pestaña Clock Signals y seguimos exactamente el mismo procedimiento:




De la misma manera le damos valores led1_0, led1_1, led1_2 y led1_3 a Data Signals.



Ahora clic en OK y nos queda:



Si nos fijamos ahora tanto CLOCK PORT, como TRIGGER PORT, como DATA PORT, como UNIT están en negro señal de que han sido cumplimentados.

A continuación hacemos clic en Return Project Navigator tras lo cual emerge una ventana llamada Save Project en la que hacemos clic en SI.



Con lo cual volvemos al ISE Project Navigator con el Insert ChiScope ya configurado.




Paso 5: Conectamos mediante el ChipScope con el hardware.

Seleccionamos en la ventana superior izquierda denominada Design el archivo LEDA_blogChSc0-light_blogChSc0.vhd, y luego en la ventana inferior izquierda de Processes deslizamos el scroll hacia abajo hasta encontrar el icono Analyze Design Using ChipScope.

Doble clic en dicho icono.


Ahora empecerá a procesarse el Análisis. La primera vez a mí me lleva un buen rato, empiezan a aparecer comandos en la consola y a veces parece que el programa se ha quedado “colgado”, pero luego sigue sin problemas. Si te ocurre lo mismo piensa que es relativamente normal, no ha ido nada necesariamente mal.

Ten en cuenta que en el proceso se está sintetizando, implementando, generando el archivo de programa… y eso con todos los pasos intermedios que conllevan cada uno de estos pasos.
Es un proceso largo, y si no tienes un ordenador “en forma” (al mío no le vendría mal una limpia) y potente es fácil que ocurra.

Si todo ha ido bien nos surgirá la siguiente ventana:



Hacemos clic en el extremo superior izquierda en el icono Open Cable/Search JTAG Chain.

Ahora debería salir un cuadro de diálogo como en el de la siguiente figura en el que daremos en OK.



Si sigue yendo bien las cosas te dirá en la ventana de consola inferior algo como:

MyDevice0 (XC3S250E) is not configured
 (sin ningún mensaje de error en rojo).

Para configurar seguimos los siguientes pasos:

Seleccionamos dónde se señala con fondo azulado en la siguiente imagen. Es decir, DEV:0 MyDevice0 (XCS3S250E) en mi caso, si estás usando un hardware diferente al mío dónde aparece (XCS3S250E) saldrá otra cosa diferente. 

En donde hemos seleccionado hacemos clic en el botón derecho del ratón y tendremos un desplegable como en la figura de a continuación:



En dicho desplegable clic en Configure…





Nuevamente aparece una ventana emergente dónde haremos clic en el botón que señalo con una flecha roja a continuación:

Tras esto navegamos hasta encontrar el archivo con extensión “.bit” (en mi caso lo encuentro inmediatamente y se llama leda_blogchsc0.bit).

Lo seleccionamos y le damos a abrir. 

Tras esto volvemos a encontrarnos con la ventana anterior pero esta vez pulsamos en OK.


Finalmente podemos comprobar que el hardware empieza a hacer exactamente lo que esperábamos de él (los leds se van encendiendo y apagando secuencialmente).

Dejo un clip para demostrar esto que acabo de decir.


Normalmente esto sería suficiente, pero el objetivo de este tutorial no es demostrar que nuestro código funciona (cosa que por otra parte ya he demostrado en otras entradas), sino familiarizarnos con el uso del ChipScope, así que aún nos queda simular por software.

Paso 6: Simulamos.

El interfaz del ChipScope tendrá ahora el siguiente aspecto:


Vemos que en la ventana pequeña superior izquierda ahora tenemos las opciones:

- Trigger Setup
- Waveform
- Listing
- Bus Plot

Hacemos doble clic en Trigger Setup, y luego en Waveform.

La cuestión es que yo ya simulé esto y se “de buena tinta” que no es necesario 1024 muestras para tener una visualización aceptable de los resultados, de hecho si simulamos con 1024 tardará más en mostrarse los resultados y prefiero hacerte ganar tiempo. Pongamos mejor 128 muestras aunque parezca demasiado poco. 



Ahora clic en el icono que señalo con la flecha roja llamado “Apply Settings and Arm Trigger”.



Hay un impasse de espera en el que el buffer se va cargando con las muestras obtenidas por el programa ChipScope.

 Y finalmente tenemos:

La visibilidad de esto aún se puede mejorar. Para ello seleccionamos la opción Waveform en la ventana superior izquierda y luego le damos el zoom in.

 También podemos jugar con el zoom-out (a la derecha del zoom-in) y con la barra de desplazamiento lateral hasta tener 5 transiciones, suficiente para comprobar que se reproduce la realidad.

Una forma de verlo, es además de acercarlo suficientemente, usar los cursores verticales X y O.



Y así sucesivamente, de forma que podemos tener una secuencia tal y como vemos en la siguiente figura:

Espero que los dos siguientes videos sean suficiente descriptivos de lo que acabo de explicar:



Si no se ven  suficientemente claros los clips, puedes hacer clic en dónde señalo en la siguiente imagen y lo podrás ver en modo pantalla completa (Full Screen).

Y ahora si, pondré como en las películas antiguas:

- THE END -

0 comentarios: