Buscar este blog

miércoles, 28 de agosto de 2019

FPGA + MQTT + ALEXA




Objetivo:
Implementar el stack del protocolo MQTT en un FPGA Virtex 4. Los métodos desarrollados en hardware son conectar, publicar y subscribir. Desarrollar la comunicación wifi por medio del módulo esp8266, control de pantalla OLED 64x128, y demás periféricos como switches y relojes. Desplegar el servidor broker mosquitto para gestionar la comunicación endpoint con el FPGA. Desarrollar un Skill Alexa para ejecutar los comandos por voz y el procesamiento de los algoritmos de comunicación y conexión MQTT en la nube con el servidor Lambda.

Introducción:
MQTT es un protocolo abierto, sencillo, ligero y fácil de implantar.
Es ideal para responder a las siguientes necesidades:
  • Está especialmente adaptado para utilizar un ancho de banda mínimo
  • Es ideal para utilizar redes inalámbricas
  • Consume muy poca energía
  • Es muy rápido y posibilita un tiempo de respuesta superior al resto de protocolos web actuales
  • Permite una gran fiabilidad si es necesario
  • Requiere pocos recursos procesadores y memorias
El MQTT no es el único protocolo que intenta imponerse: otros como XMPP, REST API y CoAp también tienen ciertas ventajas.



MQTT: ¿cómo funciona?

MQTT es un servicio de publicación/suscripción TCP/IP sencillo y sumamente ligero. Se basa en el principio cliente/servidor.
El servidor, llamado broker, recopila los datos que los publishers (los objetos comunicantes) le transmiten. Determinados datos recopilados por el broker se enviarán a determinados publishers que previamente así se lo hayan solicitado al bróker.
El principio de intercambio se parece mucho al de Twitter. Los publishers envían los mensajes a un canal llamado topic. Los subscribers (suscriptores) pueden leer esos mensajes. Los topics (o canales de información) pueden estar distribuidos jerárquicamente de forma que se puedan seleccionar exactamente las informaciones que se desean.
Los mensajes enviados por los objetos comunicantes pueden ser de todo tipo, pero no pueden superar los 256 Mb.

 Funciones principales que tendrá el FPGA:

1.- Control exacto y sincronización de la señal de reloj y registros.
2.- Implementar stack MQTT.
3.- Manejo del ESP8266
4.- Control de pantalla OLED 128x64, switches, leds, etc.
5.- debug usb.


Metodología:

 La descripción del Hardware se hará en lenguaje C utilizando para ello una metodología propietaria de integración de herramientas.

Nota:
El stack del protocolo MQTT fue implementado y validado antes de la implementación en el FPGA en un microcontrolador microchip en lenguaje C de tal forma que se partiera de una base confiable de funcionamiento.

Destacar que el ciclo completo de diseño desde la simulación hasta la implementación en el FPGA es en minutos. Esto quiere decir que por cada cambio que haga en el código a nivel descripción de hardware hasta la puesta en marcha se hace de manera secuencial y casi sin intervención. Ya que las herramientas son muy configurables y se atan unas a otras.

El flujo de secuencia y metodología usando diversas herramientas se puede ver en la siguiente figura.





Herramientas a utilizar:

FPGA:
1.- DK Design Suite 5.0.  Plataforma de validación rápida y eficiente para diseñadores que utilizan lenguaje C/C++
2.- Synplify Pro H-2013. Software de síntesis estándar en la industria para FPGA de alto rendimiento.
3.- Xilinx Design Tools ISE Suite 14.7. Plataforma de flujo de diseño completo para los FPGA de xilinx

PC:
1.- Mosquitto broker. Agente de mensajes de código abierto (con licencia EPL / EDL) que implementa el protocolo MQTT versiones 5.0, 3.1.1 y 3.1. Mosquitto es liviano y es adecuado para usar en todos los dispositivos, desde computadoras de una sola placa de baja potencia hasta servidores completos.

2.- Alexa SDK. Es el servicio de voz ubicado en la nube de Amazon disponible en los dispositivos de Amazon y dispositivos de terceros con Alexa integrada. Con Alexa, se puede crear experiencias de voz naturales para ofrecer a los clientes una forma más intuitiva de interactuar con la tecnología que usan a diario. Gracias a su conjunto de herramientas, APIs, soluciones de referencia y documentación, cualquier persona puede crear skills de forma sencilla con Alexa.


En la siguiente figura se muestra en forma general el flujo de diseño del proyecto y sus diferentes componentes:




1)      Desarrollo del software para el Virtex 4 en la plataforma DK Design Suite:

2)   Síntesis e implementación del diseño en el FPGA Virtex 4:

3)  Alexa SDK

4)    Conexión del FPGA:


5)   Conclusiones:
Se logró satisfactoriamente hacer la implementación del protocolo MQTT en el FPGA y el desarrollo de la skill de Alexa para el monitoreo y control de las variables internas del Virtex 4.

 Con este tipo de metodologías se puede hacer cualquier proyecto por más complejo que sea en un FPGA aprovechándose de las ventajas en velocidad, paralelismo y alta densidad de recursos que poseen estas arquitecturas. 

6)   Video demostrativo:



domingo, 30 de noviembre de 2014

QUIEN USA DK HANDEL-C

  • Durante el año 2005 el detector el Gran Colisionador de Hadrones (GCH) ubicado en la Organización Europea para la Investigación Nuclear (CERN) desarrollo la tecnología de adquisición y transmisión de datos basado en FPGA para su sistema de detección ATLAS. Diseñado para que detecte y mida el mayor intervalo posible de energías así como sus propiedades. Véase figura donde se muestra las características principales de este sistema. 

  • La plataforma en hardware GETB por la cual procesaría y transmitirá toda la información del detector ATLAS se ve en la figura xx, la cual hace uso de un FPGA Stratix de ALTERA. Un punto relevante de este desarrollo fue el hecho de utilizar la metodología de programación en C utilizando para ello el lenguaje Handel-C al 90%.




Research Seminar, Fermi National Accelerator Laboratory

November 2005








sábado, 29 de noviembre de 2014

La tecnología detrás de DK

  • Introducción.

Handel-C [1] es un lenguaje de programación síncrono donde la noción del tiempo es fundamental. La construcción de circuitos síncronos usa relojes globales que continuamente ofrecen ticks. El lenguaje es similar en abstracción a RTL (Register Transfer Language) y se inclina hacia un estilo de programación del comportamiento en lugar de un lenguaje de descripción de hardware estructural tal como VHDL.
Handel-C capta los programas a un nivel de transformaciones simples en los datos y la circulación de los mismos entre variables (registros). El paralelismo puede ser definido explícitamente. La semántica del lenguaje está basada sobre Occam/CSP [2,3] y la sintaxis se basa en lenguaje C [4].

  • La ruta de datos.


Todas las variables en el programa de usuario son mapeadas a registros en hardware. Estos se construyen a partir de conjuntos de flip-flop. La arquitectura exacta de los flip-flop es específica de cada dispositivo destino. Un flip-flop básico de tipo D es mostrado en la figura 1. Un flipflop se construye para cada bit de una variable de programa. Cada franco ascendente del reloj se copia el valor de entrada D hacia el flip-flop, el estado actual del flip-flop se emite de forma continua a Q. Los relojes globales son usados para activar todos los flip-flops conectados a ese reloj al mismo tiempo como una acción atómica.

Figura 1

Los registros tienen multiplexores de entrada si tienen múltiples fuentes, por ejemplo, si son objeto de una asignación o comunicación en el programa Handel-C. Los circuitos de control en las declaraciones del programa generan las señales de control del multiplexor y la habilitación de las señales de reloj para los registros de destino. Todas las expresiones son implementadas con lógica combinacional. La ruta de los datos generada por esta estrategia coincide exactamente con el flujo de datos del programa original del usuario.

  • La ruta de control.

         En los circuitos de control siguientes la caja con un triángulo en la esquina superior izquierda se utiliza para referirse a una sola instancia de un circuito de control. El enlace de control se realiza mediante una sola entrada y una sola salida para cada circuito de control.

         El circuito de control para una construcción de retardo (delay) es mostrado en la figura 2. Esta construcción no tiene ningún efecto sobre el estado de la computación. Se tarda exactamente 1 ciclo de reloj para completar.

         El circuito de control para la instrucción de asignación R = exp; se muestra en la figura 3. La señal de arranque se forma por la señal de reloj CLK y la señal de habilitación CE para la correcta asignación del registro. Al final del ciclo en el que está prevista la asignación de la expresión de hardware se ha calculado el nuevo valor y este pasara al registro destino. La señal de arranque se retrasa por un solo ciclo de reloj para proporcionar la señal de finalización para este procedimiento de control. Esto se deduce del hecho de que la asignación siempre está programada inmediatamente y siempre se completa en exactamente un ciclo de reloj. Generalmente asignaciones Handel-C son libres por diseño de bucle. Se crea lógica combinacional suficiente para llevar a cabo la asignación en un ciclo de reloj incluso si la expresión es compleja. Un método para la refinación de programas en Handel-C es dividir las tareas complejas de expresiones para evaluarlas a través de múltiples ciclos de reloj.

El circuito de la figura 4 muestra la parte de la ruta de los datos generada por dos instrucciones de asignación R = Exp1; R = Exp2; que tienen como objetivo el mismo registro. Una señal de arranque dirige la expresión del valor apropiado por medio del multiplexor de la entrada del registro destino. El multiplexor es un solo disparo con una habilitación para cada línea de datos. De igual manera sea cual sea el inicio de la señal esta es activada hacia el destino vía compuerta OR.



         El circuito de control para la ejecución secuencial de estados es trivialmente sencillo. Las señales de salida y llegada de los procesos están conectadas entre sí en una conexión en cadena como se muestra en la figura 5. La estrategia de control es básicamente el de una codificación del estado de control “one-hot” modificado. Este esquema particular es muy adecuado para las implementaciones FPGA ya que requieren pocos recursos de cableado y de lógica, en comparación con las representaciones codificadas de estado de control. De hecho, el compilador puede tomar ventaja de la arquitectura específica, tales como registros de desplazamiento para optimizar aún más su aplicación.


En la figura 6 se muestra la construcción de un control utilizado para la ejecución en paralelo de los estados par{S1; S2;… Sn } ; Este circuito pasa el control al mismo tiempo a todas las declaraciones paralelas S1, S2, … Sn para que inicien su ejecución. El constructor par{} termina solo cuando todos los componentes constituyentes han terminado. Así, el circuito de control en paralelo recoge las señales de finalización en un conjunto de flip-flops y produce su propia señal de acabado tan pronto como se genera la última señal de los estados paralelos. Además, esta señal reestablece la sincronización de los flip-flops y que estén listos para la próxima vez que se utilicen en el circuito.
Las composiciones paralelas y secuenciales pueden ser anidadas arbitrariamente.


[1] Handel-C Language Reference Manual.
[2] C.A.R. Hoare, Communicating Sequential Processes, International Series in Computer Science, Prentice-Hall, 1985.
[3] Inmos, The occam2 Programming Manual, Prentice-Hall,1988.
[4] B.W. Kernigham and D.M. Ritchie, The C Programming Language, Prentice-Hall,1988.





viernes, 28 de noviembre de 2014

METODOLOGÍA DE PROGRAMACIÓN FPGA EN C CON DK HANDEL-C

  • En la literatura existen innumerables ejemplos de uso de lenguajes de alto nivel para la descripción de Hardware.

 Se mencionan algunos como los siguientes:

          C-Based System level languages
          Commercial
          SystemC --  The Open SystemC Initiative
          Handel C -- Celoxica Ltd.
          Impulse C  -- Impulse Accelerated Technologies
          Carte C – SRC Computers
          Research
          Streams-C -- Los Alamos National Laboratory
          SA-C -- Colorado State University, University of California, Riverside, Khoral Research, Inc.
          SpecC – University of California, Irvine and SpecC Technology Open Consortium
          Matlab-based
          AccelChip DSP Synthesis -- AccelChip
          System Generator for DSP -- Xilinx
          GUI Data-Flow based
          Corefire -- Annapolis Microsystems
          Java-based
          Commercial
          Forge -- Xilinx
          Research
          JHDL – Brigham Young University


  • En la metodología de DK Handel-C, la siguiente figura muestra en qué posición se encuentra comparado con otros lenguajes tanto de descripción en HW como meramente de SW.


Ventajas de Handel-C

·         Muy fácil de aprender y usar
·         Las instrucciones son basadas en ANSI C
·         Oculta detalles complejos de implementación
·         Muy flexible, no tiene limitaciones en paralelismo y tipos de datos.
·         Tiene operadores extendidos para la manipulación de bits
·         Tiene un modelo de tiempos bien definido
·         Tiene diversidad de dispositivos FPGA abarcados
·         Códigos heredados de lenguaje C previos son portados con facilidad.
·         Cada asignación toma un ciclo de reloj en ser ejecutada.


  • La metodología DK Handel-C se muestra en la siguiente figura:


  • Ejemplo de la metodología:



El ejemplo consistirá en realizar un sumador de 8 bits utilizando para ello un CORE VHDL llamado AddVHDL.vhd cuyo código fuente es: 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity AddVHDL is
    Port ( x : in  STD_LOGIC_VECTOR (7 downto 0);
           y : in  STD_LOGIC_VECTOR (7 downto 0);
           z : out  STD_LOGIC_VECTOR (7 downto 0));
end AddVHDL;

architecture Behavioral of AddVHDL is
begin
                        z <= x + y;       
end Behavioral;


  • Las herramientas necesarias para realizar estos ejemplos son:

Ø  Xilinx Design Tools ISE Suite 14.7
Ø  DK Desing suite  5.0 SP5
Ø  Synplify Pro H-2013.03
Ø  Tarjeta Spartan 3AN (XC3S700AN)


  • El siguiente esquema muestra el proceso de obtención del archivo final suma.bit para el FPGA


Pasos:


I.           Hacer un nuevo proyecto en DK Handel-C llamado suma. El código de main.hcc es el siguiente:

#include "delay.hch"
set clock = external "E12";
unsigned 8 LEDS,n,m;
interface bus_out() salida(LEDS) with {data = {"W21","Y22","V20","V19","U19","U20","T19","R20"}};

interface AddVHDL(unsigned 8 z)
AddVHDL(unsigned 8 x = n, unsigned 8 y = m) with {vhdl_type = "std_logic_vector",busformat="B(I)"};
void main(void)
{  
   par
   {
       while(1)
       {
           LEDS = AddVHDL.z;
       }
      
       while(1)
       {
           par
           {
               n++;
               m++;
           }
           delay_ms(C_MHZ,1000); //1000 ms
       }
   }
}

CONFIGURACIÓN DK


I.             II.        Hacer un proyecto en ISE de Xilinx llamado suma y agregar los archivos AddVHDL.vhd, main_hcc.vhd, agility.vhd, suma.vhd, suma.ufc.



I.                  III.       Cambiar en la línea 197 del archivo main_hcc.vhd I0_AddVHDL_main_32 : AddVHDL por I0_AddVHDL_main_32 : entity work.AddVHDL. Después guardar e implementar todo el proceso.



  • Implementación satisfactoria.









jueves, 27 de noviembre de 2014

INTERFAZ CON TECLADO AT-PS2 CON SPARTAN-3AN


  • Por la red existe una vasta información acerca del teclado at-ps2 y su forma de comunicarse con microcontroladores.


  • En el siguiente link se encuentra un documento donde se explica de manera detallada  todo acerca del teclado at-ps2 y su estándar de comunicación:



  • La conexión con la tarjeta spartan-3AN es la siguiente:


  • teclado.hch


interface bus_clock_in(unsigned 1 clk)  PS2_Clk() with {data = {"W12"}};
interface bus_clock_in(unsigned 1 data) PS2_Data() with {data = {"V11"}};

void decode(char sc);

static char unshifted[67][2] = {
0x0d,9,
0x0e,' ',
0x15,'q',
0x16,'1',
0x1a,'z',
0x1b,'s',
0x1c,'a',
0x1d,'w',
0x1e,'2',
0x21,'c',
0x22,'x',
0x23,'d',
0x24,'e',
0x25,'4',
0x26,'3',
0x29,' ',
0x2a,'v',
0x2b,'f',
0x2c,'t',
0x2d,'r',
0x2e,'5',
0x31,'n',
0x32,'b',
0x33,'h',
0x34,'g',
0x35,'y',
0x36,'6',
0x39,',',
0x3a,'m',
0x3b,'j',
0x3c,'u',
0x3d,'7',
0x3e,'8',
0x41,',',
0x42,'k',
0x43,'i',
0x44,'o',
0x45,'0',
0x46,'9',
0x49,'.',
0x4a,'-',
0x4b,'l',
0x4c,' ',
0x4d,'p',
//0x4e,''',
0x52,' ',
0x54,'`',
0x55,' ',
0x5a,13,
0x5b,'+',
0x5d,' ',
0x61,'<',
0x66,8,
0x69,'1',
0x6b,'4',
0x6c,'7',
0x70,'0',
0x71,'.',
0x72,'2',
0x73,'5',
0x74,'6',
0x75,'8',
0x79,'+',
0x7a,'3',
0x7b,'-',
0x7c,'*',
0x7d,'9',
0,0
};

static char shifted[68][2] = {
0x0d,9,
0x0e,' ',
0x15,'Q',
0x16,'!',
0x1a,'Z',
0x1b,'S',
0x1c,'A',
0x1d,'W',
0x1e,'"',
0x21,'C',
0x22,'X',
0x23,'D',
0x24,'E',
0x25,'$',
0x26,' ',
0x29,' ',
0x2a,'V',
0x2b,'F',
0x2c,'T',
0x2d,'R',
0x2e,'%',
0x31,'N',
0x32,'B',
0x33,'H',
0x34,'G',
0x35,'Y',
0x36,'&',
0x39,'L',
0x3a,'M',
0x3b,'J',
0x3c,'U',
0x3d,'/',
0x3e,'(',
0x41,';',
0x42,'K',
0x43,'I',
0x44,'O',
0x45,'=',
0x46,')',
0x49,':',
0x4a,'_',
0x4b,'L',
0x4c,' ',
0x4d,'P',
0x4e,'?',
0x52,' ',
0x54,'^',
0x55,' ',
0x5a,13,
0x5b,'*',
0x5d,' ',
0x61,'>',
0x66,8,
0x69,'1',
0x6b,'4',
0x6c,'7',
0x70,'0',
0x71,'.',
0x72,'2',
0x73,'5',
0x74,'6',
0x75,'8',
0x79,'+',
0x7a,'3',
0x7b,'-',
0x7c,'*',
0x7d,'9',
0,0
};

void init_teclado(void)
{
   unsigned 1 flag_1,flag_0;
   unsigned 8 bitcount;
   unsigned 8 data;
                        data=0;
                        bitcount=11;
   flag_1=1;
   flag_0=0;

   while(1)
   {
      if(~PS2_Clk.clk && flag_1) //ext_int_edge(H_TO_L);
      {
                                                if(bitcount < 11 && bitcount > 2)
                                                {
                        data = (data >> 1);
                        if( PS2_Data.data == 1)
                                                data = data | 0x80;
                                                }
        --bitcount;
                                                if(bitcount == 0)
                                                {
                        decode((char)data);
                        data = 0;
                        bitcount = 11;
                                                }
                                                flag_1=0;
                                                flag_0=1;
      }
      else if(PS2_Clk.clk && flag_0)
      {
          flag_1=1;
                                                  flag_0=0;
      }
                          else
                             delay;
   }  
}

void decode(char sc)
{
   static unsigned 1 is_up=0,shift=0;
   unsigned 7 i;                              

   //is_up=0;
   //shift = 0;
  
   //-------- El ltimo dato recibido fue el identificador de Up-Key
   if (!is_up)
      {
         switch (sc)
            {
            //-------- Identificador de Up-Key
               case 0xF0 :
                  is_up = 1;
                  break;
               //-------- SHIFT Izquierdo
               case 0x12 :
                  shift = 1;
                  break;
               //-------- SHIFT Derecho
               case 0x59 :
                  shift = 1;
                   lcd_gotoxy(1,1);
                  break;
               //-------- ENTER
               case 0x5A :
                  //printf("\n\r");
                    lcd_gotoxy(1,2);
                    break;
               default:
                  if(!shift)
                     {
                        for(i = 0; i<=67; i++)
                        {
                           if (unshifted[i][0] == sc)
                           {
                              //printf("%c", unshifted[i][1]);
                                lcd_putc(unshifted[i][1]);
                           }
                        }
                     }
                  else
                    {
                        for(i = 0; i<=68; i++)
                        {
                           if (shifted[i][0] == sc)
                           {
                               //printf("%c", shifted[i][1]);
                                 lcd_putc(shifted[i][1]);
                           }
                        }
                     }
                 break;
            }
     }
     else
         {
         //-------- No se permiten 2 0xF0 en una fila
         is_up = 0;
         switch (sc)
            {
               //-------- SHIFT Izquierdo
               case 0x12 :
                  shift = 0;
                  break;
               //-------- SHIFT Derecho
               case 0x59 :
                  shift = 0;
                  break;
            }
         }
}



  • El driver fue elaborado en DK Design Suite en Handel-C :



  • La síntesis fue hecha con SynplifyPro y la implementacion con ISE:


  • La programación del FPGA a través de iMPACT:


  • Resultados: