Mostrando entradas con la etiqueta HARDWARE. Mostrar todas las entradas
Images

Ejercicio Sencillo para Comunicaciones Vía Bluetooh con Microcontroladores de Arquitectura ARM7 de 32 bits.

Introducción:

Lo que vamos a ver en el tutorial de esta entrada es un ejercicio que he visto hecho con Arduino y PIC y excelentemente explicado en tutoriales en Internet. La cuestión es que no lo he visto mucho con micros de 32 bits y arquitectura ARM7, y de ahí que veo la utilidad de publicarlo.

El ejercicio consiste básicamente en encender y apagar un LED mediante un dispositivo con sistema operativo Android como podría ser una Tablet (con bluetooth) o un móvil (o también conocido en castellano como celular). En el siguiente clip se ilustra lo que acabo de decir. 





Para hacer esto usaremos un módulo hardware ampliamente conocido y de unas excelentes prestaciones considerando su bajo precio que es el HC-05.

Con el fin de no alargar mucho el tutorial daré las indicaciones necesarias que considero claves o que no se explican en otros lugares de Internet.


Como siempre vamos a lo relativamente sencillo, rápido y barato con el fin de que el lector tenga una base para realizar proyectos más complejos. 

Como viene siendo habitual últimamente dejo el tutorial en un enlace en formato PDF.

Tutorial Ejercicio Sencillo HC-05 y Micro 32 bits.

También dejo el código en C para que se pueda copiar y pegar..

//************************************************************ // Nombre: main1_BT_LED.c //Descripción: //Encendido y apagado de un LED dándo la orden // al micro mediante un dispositivo android vía bluetooth // con un módulo tipo HC-05. /* Si en nuestro celular o móvil pulsamos un 1, el led se enciende, si pulsamos un 0, el led se apaga. */ //Target: STM32F407VG //ToolChain: MDK-ARM //IDE: uVision 5 //************************************************************ #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" #include #include #include "stm32f4xx.h" #include "defines.h" #include "tm_stm32f4_usart.h" #include "tm_stm32f4_delay.h" #define USARTx USART2 //Puerto que se usará. /* Esta función se utiliza para trasmitir una cadene de caracteres a través * El USART especificado en USARTx * La cadena tiene que ser pasado a la función como un puntero porque * El compilador no conoce el tipo de datos string. En C una cadena es sólo * un conjunto de caracteres. */ //Función para configurar el periférico USART2 void Config_USARTx(void){ /* TX = GPIOA_Pin_2 (RX) RX = GPIOA_Pin_3 (TX) RTS = GPIOA_Pin_1 (CTS) CTS = GPIOD_Pin_3 (RTS) */ //Estructuras para configurar los puertos, el USART2 y las interrupciones NVIC GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //Activación del reloj del APB1 para el USART2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //Ativación del reloj del periférico para los pines utilizadas por la //USART2, PA3 para TX y RX PARA pa2 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Conecta los pines a la UART //GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_USART2); //RTS (no usado) GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); //TX GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); //RX //GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_USART2); //TX //Configura los pines GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; GPIO_Init(GPIOA, &GPIO_InitStructure); //Configura la USART USART_InitStructure.USART_BaudRate = 9600; //Velocidad en buadios USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8 Bits USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USARTx, &USART_InitStructure); //Hace efectiva la configuración. //Activación de la interrupción del receptor USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //Inte del receptor de activa //Configura interrupción por el USART NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //Configura la interrupción NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //Prioridad de USART NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //Subprioridad NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //Habilitador global de inte. NVIC_Init(&NVIC_InitStructure); //La configuración se pasa a NVIC_Init() USART_Cmd(USARTx, ENABLE); //Finalmente se habilita la USART2 } void Configurar_LED(void){ //Configura pin donde está el LED (PD15) GPIO_InitTypeDef GPIO_LED; //Estructura para configurar Puerto D RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //Habilita el bus AHB1 GPIO_LED.GPIO_Pin = GPIO_Pin_15; //Pin que deseamos configurar GPIO_LED.GPIO_Mode = GPIO_Mode_OUT; //Configura como salida GPIO_LED.GPIO_OType = GPIO_OType_PP; //Configura el pin tipo push/pul //(opuesto a open drain) GPIO_LED.GPIO_Speed = GPIO_Speed_100MHz; //Configura el pin a 100 MHz GPIO_LED.GPIO_PuPd = GPIO_PuPd_NOPULL; //Desactiva los pull-up, no hacen falta GPIO_Init(GPIOD, &GPIO_LED); //Hacer efectiva configuración del puerto } //Función principal int main(void){ Config_USARTx(); //Enviar_String("Esperando datos..."); //Mensaje inicial. Configurar_LED(); //TM_USART_Puts(USARTx, "OK\n\r"); while(1){ //Espera por la interrupción } } //ISR (rutina de servivio de interrupción) para todas las interrupciones de USART2 void USART2_IRQHandler(void){ //GPIO_SetBits(GPIOD, GPIO_Pin_15); //GPIO_ResetBits(GPIOD, GPIO_Pin_15); if(USART_GetITStatus(USART2, USART_IT_RXNE)){ char caracter = USART2->DR; //El dato recibido es salvado en caracter USART_SendData(USART2, caracter); //Re-envia el dato recibido if(caracter == '1') GPIO_SetBits(GPIOD, GPIO_Pin_15); if(caracter == '0') GPIO_ResetBits(GPIOD, GPIO_Pin_15); } }


Por el momento lo dejamos aquí, espero que este tutorial resulte útil :).

-Fin-
Images

Ejercicio sencillo con sensor de luz y micro de 32 bits.

Introducción:

La idea de esta entrada al blog -con la que adjunto un enlace a un PDF al final-, es hacer un ejercicio con un sensor de luz tipo LDR (Light Dependent Resistor) modelo GL5528, que cumpliera los siguientes requisitos:

- Que sea sencillo para las personas que empiezan a introducirse en esto.

- Que sea lo más barato posible.

- Que no sea un plagio de otras cosas que hay por Internet.

- Que se pudiera hacer en un lapso de tiempo no muy largo. Tenga en cuenta el lector que entre explorar que cosas son factibles en poco tiempo a la vez que interesantes (buscar la idea), y en documentar se me va más tiempo que en realizar este tipo de ejercicios y también tengo que contar con eso.

El tutorial completo lo dejo en formato PDF a través de un enlace al final de esta introducción.

¿Qué necesitas para realizar este ejercicio práctico?.

•Hardware:

- Una placa de desarrollo STM32F4-Discovery. Precio aproximado 18,72 euros (aproximadamente 20 dólares USA al cambio del día que en que escribo esto).

- Un sensor de luz LDR modelo GL5528. Precio aproximado 1,36 euros (1,45 dólares USA).

- Dos resistencias de orificio pasante de unos 220 ohmios. Precio aproximado de la unidad 0,059 euros (0,06 dólares USA).  Las dos unidades unos 0,118 euros (0,12 dólares USA).

- Un LED normal para protoboard. Precio aproximado unos 0,18 euros o menos (0,19 dólares USA).

- Un protoboard. Precio aproximado 8,36 euros (8,92 dólares USA).
Monto total: 28,738 euros o 30,66 dólares USA. Redondeando puede salir todo por unos 30 euros o 32 dólares.

•Software:

- IDE para programar la placa STM32, preferentemente el Keil µVision 5 que es el que yo uso en este tutorial.

- Una aplicación para desarrollo de PCBs, la que yo uso en este tutorial es el Altium Designer.

¿Qué hará exactamente el sistema que desarrollaremos?.

Nuestro sistema será sensible a la luz –que será el Input del sistema – de manera que a mayor cantidad de luz detectada un LED (Output del sistema) parpadeará con una frecuencia menor, esto es, más lentamente, y a menor cantidad de luz el LED parpadeará con mayor frecuencia (más deprisa).


Gráficamente:

   
• A mayor luz registrada parpadeo del LED más lento.
• A menor luz registrada parpadeo del LED más rápido.

Para ilustrarlo mejor y de paso dar fe de que funciona, dejo un clip:




Este ejercicio ya lo hice con un Arduino Uno, ¿entonces que novedoso tiene esto si se puede hacer con un micro de 8 bits?, pues la novedad es que no encuentro tantos tutoriales sobre micros de 32 bits sobre este tipo de ejercicios (menos aún en castellano), por eso me parece interesante para el que quiera introducirse en la programación de micros de 32 bits.

Además, al final aprovecho todo esto para hacer un ejercicio de desarrollo de PCBs que -dada las limitación de tiempo que me he impuesto- se considerará como sólo eso, un ejercicio que me sirve además de excusa para hacer hincapié en conceptos que considero fundamentales en el desarrollo de un PCB, algo con lo que hubiera tenido menos tiempo si lo hubiera elaborado más.

Por otro lado, para el que se está introduciendo en este tipo de temas es siempre mejor empezar de lo sencillo para ir a lo complejo.

Aquí va el enlace al tutorial:


Images

Mostrando por display la entrada en tensión regulada por un potenciómetro.


En esta entrada vamos a ver un ejemplo muy sencillo para aprender a manejar la placa STM32F4-Discovery. Dicha tarjeta de desarrollo puede ser una excelente herramienta para introducir al lector en la programación de microcontroladores de 32 bits (con arquitectura ARM).

Básicamente en primer lugar se trata de hacer lo que se muestra en el siguiente clip.



Además en este tutorial se incluye un posible diseño de un circuito impreso (o PCB por su acrónimo en inglés). El layout del mencionado PCB implementaría este sistema sin la tarjeta de desarrollo STM32F4-Discovery, con los elementos esenciales para realizar lo que el ejercicio propone.

 Viene a ser algo así como un voltimetro sencillo que mide la tensión entre los terminales del potenciómetro. Recordemos que el potenciómetro no es más que una resistencia que podemos variar entre cero y el límite máximo de ohmios de dicho potenciómetro. 

He pensado que tal y como trabajo las publicaciones de este blog, quizás es más interesante que deje enlaces para que se pueda ver la mayor parte en PDF, de forma que no resulte tan largo y más legible.

El post lo he dividido en dos partes, Una intraducción y el tutorial en sí. 

En la introducción comento principalmente el hardware y el software que se necesita así como una aproximación del dinero que te puede costar. 

En el tutorial se da las indicaciones de como ir  realizando este ejercicio que propongo. Aviso que se hace más hincapié en la parte de programación del micro que en el diseño del PCB que tan sólo se esboza.

Si haces clic o pulsas los siguientes enlaces lo verás:



Espero que resulte útil y más cómodo de leer. ¡Hasta la próxima!.
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 -