Buscar este blog

domingo, 30 de noviembre de 2014

INTRODUCCIÓN A ZEDBOARD Y ZYNQ

Antes de comenzar con el listado de prácticas se hará una breve descripción de lo que es la tecnología Soc ZynQ-7000 de Xilinx.


 El SoC Zynq es el primer dispositivo comercial que combina microprocesadores de doble núcleo ARM Cortex-A9, estructura de FPGA y periféricos claves en un solo dispositivo (Figura 1). El procesador y la estructura del FPGA se comunican con más de 10,000 interconexiones internas, ofreciendo un rendimiento entre el microprocesador y FPGA que es físicamente imposible de lograr con un procesador discreto y un FPGA implementado en una tarjeta de circuito impreso.

El SoC Zynq no es llamado un “FPGA” porque es único en el sentido de que el sistema de procesamiento es el que está a cargo, en lugar de la estructura del FPGA. Es decir, el sistema de procesamiento arranca primero y controla la funcionalidad de la estructura del FPGA. Esto significa que los usuarios no tienen que estar profundamente familiarizados con técnicas de diseño de FPGA para ejecutar una aplicación en el subsistema del procesador del SoC Zynq. El SoC Zynq ofrece a los clientes la habilidad para crear sus diseños en C, C++ o SystemC usando el software de desarrollo de su elección y programar su diseño en el sistema de procesamiento del SoC Zynq. Si una parte de su diseño no se está ejecutando lo suficientemente rápido, los diseñadores pueden usar la herramienta Vivado High-Level Synthesis (HLS) de Xilinx o HANDEL-C de Mentor Graphics para traducir un algoritmo o parte de un algoritmo que desarrollaron a un nivel de C a VHDL y probar ese código ejecutándose en la sección de FPGA del SoC Zynq. Al descargar las funciones adecuadas del procesador a la estructura del FPGA y liberar el procesador para realizar las funciones que hace mejor, los clientes pueden alcanzar un incremento de 700 veces más rendimiento del sistema en comparación con los diseños basados en procesadores.


    ZedBoard (Figura 2) es una placa de desarrollo de bajo costo para el Xilinx Zynq-7000 Extensible Processing Platform (EPP). Esta tarjeta contiene todo lo es necesario para crear un proyecto basado en Linux, Android, Windows u otro sistema operativo / RTOS. Además, varios conectores de expansión exponen para uso fácil el sistema de procesamiento y E / S de la lógica programable. 

sábado, 29 de noviembre de 2014

viernes, 28 de noviembre de 2014

PRACTICA # 1 LEDS SECUENCIALES UTILIZANDO AXI

Encender los 8 leds de la tarjeta Zedboard utilizando el PS (Process System), PL (Programmable Logic) y SDK.

Objetivo:

Por medio de las herramientas que ofrece vivado crear un sistema base para el Soc Zynq de la tarjeta ZedBoard utilizando los GPIO para comunicación externa y generar un código en SDK para que encienda secuencialmente los leds.

Requerimientos:

·         Tarjeta ZedBoard
·         Cable microusb para programación y debug de la tarjeta
·         Vivado 2013.4 o superior
·         Mucha paciencia xD


Parte # 1. Generando el sistema base PS

      En esta parte de la práctica se creara un sistema base utilizando el PS y un core GPIO que permitirá la comunicación directa con los leds de la tarjeta de desarrollo. Dicho core se implementara en la parte PL y tendrá comunicación con el sistema PS por medio del bus de interconexión AXI.

 Ø  Iniciamos vivado


Ø Creamos un nuevo proyecto haciendo clic en Create New Project, clic en next y se desplegara una ventana para poner nombre al proyecto y ubicación del mismo.


  Ø Hacemos clic en next y en la siguiente pantalla escogemos la opción RTL Project, al no tener otros archivos fuente seleccionamos la única casilla que se encuentra en esa opción. 



  Ø Al darle clic en “Next” aparecerá la ventanilla de “Default Part” donde seleccionaremos la tarjeta de desarrollo que estamos ocupando, en nuestro caso es la tarjeta Zedboard. 


  Ø Al dar clic en “Next” de la ventana anterior, el wizard de Vivado nos entrega un resumen del proyecto creado como se muestra a continuación.


   Ø Damos clic en “Finish” y se abrirá el entorno de vivado


   Ø Para comenzar crearemos un “Block Design” para ello iremos a la parte izquierda de la pantalla donde encontramos el “Flow Navigator” dentro de él iremos a la sección de “IP integrator” y seleccionamos la opción “Create Block Design”  y Por ultimo le damos nombre a nuestro Bloque.


   Ø Al hacer esto se abrirá un nuevo entorno de trabajo en donde agregaremos nuestros “IP Blocks”



    Ø Para agregar un nuevo “IP Block”  damos clic en el icono AddIP y dentro del cuadro de texto escribimos zynq y hacemos doble clic en ZYNQ7 Processing System.


 Ø Ahora agregaremos un bloque genérico de entradas y salidas para ello realizamos el mismo procedimiento con la diferencia de que ahora escribiremos AXI. Con el botón “Regenerate Layout” podemos ordenar los componentes.


  Ø En el lienzo de trabajo hacemos clic sobre la opción Run Block Automation y seleccionamos /precessing_system7_0. Dejamos las opciones por default y damos clic en aceptar.


  Ø Hacemos clic en Run Connection Automation y seleccionamos /axi_gpio_0/S_AXI y después en aceptar. De igual manera lo hacemos para /axi_gpio_0/GPIO



  Ø  El lienzo de trabajo queda de la siguiente forma


  Ø Hacer doble clic sobre el bloque processing_system7_0.  Como no se utilizara todas las conexiones de las tarjeta de desarrollo las deshabilitaremos en la opción MIO Configuration. Y clic en aceptar.


  Ø Ahora pasaremos a validar el diseño por medio del DRC (Design Rule Check) haciendo clic en el icono  


  Ø Generaremos los archivos de salida seleccionando LEDS.bd y haciendo clic derecho seleccionar la opción Generate Output Products… y después clic en Generate en la ventana que aparece.


 Ø Una vez concluido el proceso anterior volver a seleccionar LEDS.bd y hacer clic derecho y escoger Create HDL Wrapper… En la siguiente ventana dejar la opción por default: Let vivado manager wrapper and auto-update.



Ø Hacer clic en Generate Bitstream en el flow navigator. 



  Ø Una vez terminado el proceso anterior abrimos el diseño en la pestaña Open Implemented Design



PARTE # 2. SDK

  Ø Seleccionamos la base de datos LEDS.bd y escogemos Export Hardware for SDK


Ø Seleccionamos las 3 opciones mostradas:



Ø Como resultado se abrirá el SDK xilinx en eclipse. Nota*: Es muy importante que el nombre del directorio en donde se almacene el proyecto no contenga espacios ej; C:\Descripciones_SoC.


  Ø El proyecto se realizara en C++. Primero vamos a la opción en FILE à NEW àApplication Project. Escribimos el nombre del proyecto y seleccionamos como lenguaje C++. Hacemos clic en next y luego finish.


  Ø Abrimos el archivo main.cc y agregamos el siguiente código:
/*****************************************************************************/
/*                         I N C L U D E   F I L E S                         */
/*****************************************************************************/

#include "xparameters.h"
#include "xgpio.h"

/*****************************************************************************/
/*                           C O N S T A N T S                               */
/*****************************************************************************/

//The following constant maps to the name of the hardware instances that
// were created in the Vivado system.

#define GPIO_EXAMPLE_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID

// The following constant is used to determine which channel of the GPIO is
// used for the LED if there are 2 channels supported.

#define LED_CHANNEL 1


/*****************************************************************************/
/*                            V A R I A B L E S                              */
/*****************************************************************************/


XGpio Gpio;        // The Instance of the GPIO Driver


/*****************************************************************************/
/*                                M A I N                                    */
/*****************************************************************************/


int main(void)
{
    int Status,i;
    long int ust_limit = 50000000;
    volatile long int delay;
    // Initialize the GPIO driver

    Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    // Clear the LEDs
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0);

    while (1)
    {

                        for(i=0;i<255;i++)
                        {
                                                  XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, i);
                                                  for(delay=0;delay<ust_limit;delay++){};
                        }
    }

    return XST_SUCCESS;
}


  Ø Ahora pasaremos a programar la tarjeta Zedboard, debemos de tener la tarjeta conectada a la fuente de alimentación así como en su conector usb hacia la pc. Además de asegurarnos que los jumpers de los modos de configuración estén ubicados para utilizar el JTAG. En la barra de herramientas del SDK Xilinx Tools seleccionamos Program FPGA.


  Ø Por ultimo Seleccionar Run as à Launch on Hardware (GDB)


  Ø Aplicación corriendo en la tarjeta de desarrollo Zedboard



























jueves, 27 de noviembre de 2014

PRACTICA # 2 MANEJO DE MEMORIA BRAM

En esta práctica se elaborara una interfaz AXI para el control de memoria BRAM de la parte PL. Para este ejemplo se especificara solo 8kbyte de memoria. Y se comparara las velocidades de transmisión de este tipo de memoria con la DDR.


  • La parte PS (VIVADO diagrama de bloques) queda de la siguiente manera:



  • Tanto la dirección otorgada por vivado así como su rango de memoria se ve en la siguiente imagen:



  • Des habilitamos todos los periféricos a excepción del UART 1:
                                       


  • Establecemos el UART 1 como 115200 bps:


  • Deshabilitamos periféricos a excepción de UART 1:


  • El código para la parte de SDK eclipse C/C++ es el siguiente:

#include <stdio.h>


#include <stdlib.h>
#include <string.h>

#include "xparameters.h"
#include "xparameters_ps.h"
#include "xil_types.h"
#include "xtime_l.h"
#include "xil_testmem.h"
#include "xstatus.h"

typedef unsigned long ulong;
typedef unsigned char uchar;

#define CPU_CLOCK_FREQ                                             XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ
#define FPGA_CLOCK_FREQ                   100000000
#define BRAM_BASE_ADDR                                             0x40000000

const int COPY_BYTES = 8*1024;  //8K
const int num_word = COPY_BYTES / 4;

uchar buff1[COPY_BYTES];
uchar buff2[COPY_BYTES];                                   // Memoria DDR
//uchar *buff2 = (uchar *) BRAM_BASE_ADDR;    // Memoria BRAM


bool TestMemory();

int main()
                        {

                        printf("Hello World %s\n", (buff2 == (uchar *) BRAM_BASE_ADDR) ? "BRAM" : "DDR");

                        XTime t1, t2;

                        XTime_GetTime(&t1);                                                                                                          // Get time before memcpy
                        memcpy(buff1, buff2, COPY_BYTES);       // Copy bytes from BRAM or DDR3
                        XTime_GetTime(&t2);                                                                                                          // Get time after memcpy
                        ulong clocks = 2 * (t2 - t1);                           // Compute time for memcpy (Note: ARM PERIPHCLK is twice period of CPU clock)

                        double dt = clocks / double(CPU_CLOCK_FREQ);       // Compute clock time
                        double rate = COPY_BYTES / dt;                                                                                                               // Compute throughput

                        double cpu_clocks_per_word = double(clocks) / num_word;

                        double fpga_clocks_per_word = (double(FPGA_CLOCK_FREQ) / CPU_CLOCK_FREQ) * cpu_clocks_per_word;

    printf("  buff1            = 0x%08X\n", buff1);
    printf("  buff2            = 0x%08X\n", buff2);
    printf("  CPU clock        = %.1f MHz\n", CPU_CLOCK_FREQ / 1.0e6);
    printf("  FPGA clock       = %.1f MHz\n", FPGA_CLOCK_FREQ / 1.0e6);
                        printf("  num_byte         = %d\n", COPY_BYTES);
                        printf("  num_word         = %d\n", num_word);
                        printf("  CPU clocks       = %d\n", clocks);
                        printf("  CPU clocks/word  = %.1f\n", cpu_clocks_per_word);
                        printf("  FPGA clocks/word = %.1f\n", fpga_clocks_per_word);
                        printf("  rate             = %.1f MB/s\n", rate / 1.0e6);
                        printf("  Memory Tests     = %s\n", TestMemory() ? "PASSED" : "FAILED");

                        TestMemory();

                        return 0;
                        }

/*
 * Memory check to verify functionality.
 */
bool TestMemory()
                        {
                        XStatus status;

                        status = Xil_TestMem8(buff2, COPY_BYTES, 0xA5, XIL_TESTMEM_ALLMEMTESTS);
                        if(status != XST_SUCCESS)
                                                return false;

                        status = Xil_TestMem32((u32 *) buff2, COPY_BYTES/4, 0xAAAA5555, XIL_TESTMEM_ALLMEMTESTS);
                        if(status != XST_SUCCESS)
                                                return false;

                        // Simply test
                        memset(buff1, 0, COPY_BYTES);

                        for(int i = 0; i < COPY_BYTES; i++)
                                                buff2[i] = i % 256;

                        memcpy(buff1, buff2, COPY_BYTES);

                        return memcmp(buff1, buff2, COPY_BYTES) == 0;
                        }

  • Entorno de eclipse funcionando:


  • Resultados:

Hello World BRAM

  buff1            = 0x00124224
  buff2            = 0x40000000
  CPU clock        = 666.7 MHz
  FPGA clock       = 100.0 MHz
  num_byte         = 8192
  num_word         = 2048
  CPU clocks       = 38034
  CPU clocks/word  = 18.6
  FPGA clocks/word = 2.8
  rate             = 143.6 MB/s
  Memory Tests     = PASSED

Hello World DDR
  buff1            = 0x00124224
  buff2            = 0x00126224
  CPU clock        = 666.7 MHz
  FPGA clock       = 100.0 MHz
  num_byte         = 8192
  num_word         = 2048
  CPU clocks       = 6026
  CPU clocks/word  = 2.9
  FPGA clocks/word = 0.4
  rate             = 906.3 MB/s
  Memory Tests     = PASSED