Buscar este blog

domingo, 16 de noviembre de 2014

PRACTICA # 13 CREACION E INTEGRACION DE UN IP CORE AXI


  • El objetivo de esta práctica es mostrar los pasos para crear nuestro propio IP core y enlazarlo con nuestro sistema PS por medio de AXI. 

  • Para ejemplificar el proceso pongamos el siguiente requerimiento:

  Mandar 3 datos de 32 bits llamados output_1, output _2 y output _3 desde la terminal SDK hacia el display OLED y visualizar su incremento cada segundo.
·         De la misma forma recibir 3 datos de 32 bits desde el sistema PL (input_1, input _2,  input _3) hasta el SDK e imprimirlos vía UART.
·         Crear nuestro MY_IP (IP CORE con AXI) para interconectar PS y PL.


  • La siguiente imagen muestra el flujo de diseño que llevaremos a cabo:



PASO # 1. Crear el sistema base.


El sistema base consiste en crear el diagrama de bloques con Zynq, generar nuestro IP CORE con AXI, obtener el archivo de sintesis MY_IP_CORE_wrapper.dcp y por ultimo exportar el proyecto a SDK de Xilinx.

·         Creando un nuevo proyecto:






·         Crear un diagrama de bloques:



·         Crear un paquete IP como se muestra en las siguientes figuras:



·         Escoger la opción de crear un periférico AXI:



·         Establecer 6 registros (3 para las entradas y 3 para las salidas):




·         Seleccionar la opción de editar el IP:



·         Agregar las lineas de la 19 a la 24, que corresponden a las entradas y salidas respectivamente.



·         Mapear los registros en el proceso de la linea 370, 377, 379 y 381.



·         Agregar las salidas en la linea 413 a 415.



·         Ahora en el archivo TOP declarar nuevamente la entradas y salidas. Lineas 19 a 24.



·         Declarar nuevamente en la arquitectura. Linea 64 a 69.



·         En la instanciacion mapear las entradas y salidas. Linea 105 a 110.



·         Configurar el paquete IP como las siguientes imágenes:











·         Crear el diagrama de bloques con Zynq y MY_IP_CORE:



·         Crear puertos para las entradas y salidas de MY_IP_CORE_0:



  • Diagrama de bloques completo:


·         Crear el HDL Wrapper y generar los products:



·         Como se observa en el diseno TOP. Las entradas y salidas ya están declaradas y nos servirá de enlace con el código generado por DK Design Suite de Handel-c. Como lo veremos mas adelante.



·         Creamos la interfaz MY_IP_CORE_wrapper en DK Design con sus entradas y salidas:



·         La dirección de memoria de nuestro IP CORE es:



·         Realizamos la síntesis:



·         Identificamos el archivo generado por la síntesis MY_IP_CORE_wrapper.dcp ya que lo utilizaremos en la segunda parte para unificarlo con los archivos generados por DK Design Suite.



·         Se correrá la implementacion con el objetivo de poder exportar el hardware a SDK:



·         Abrimos la implementacion:



·         Exportamos el Hardware:



·         No incluimos el bitstream:



·         Por ultimo lanzamos SDK y Cerramos proyecto:




PASO # 2. Fusionar sistema base y archivos de DK Design Suite

·         Crear un nuevo proyecto:





·         Agregar todos los archivos generados por DK, incluyendo la librería agility y el MY_IP_CORE_wrapper.dcp:





·         Eliminamos la declaración de componente externo duplicada:



·         Generamos el bistream para programar el Zynq:



·         Programamos el Zynq:



·         Abrimos el proyecto SDK que en el paso #1 generamos. Y hacemos una aplicación:





·         Vamos anuestra carpeta de proyecto donde se genero nuestro ip_repo:
C:\ MY_IP_CORE_AXI\ip_repo\MY_IP_CORE_1.0\drivers\MY_IP_CORE_v1_0\src



Copiamos ambos archivos MY_IP_CORE al proyecto:



·         El software para el proyecto es:

#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "MY_IP_CORE.h"

#define TEST_BASE XPAR_MY_IP_CORE_0_S00_AXI_BASEADDR

int main()
{
                        long int delay, ust_limit = 83333323;
                        int i, in_1, in_2, in_3;

    init_platform();

    printf("My IP CORE test begin.\r\n");
    printf("--------------------------------------------\r\n\n");

    while(1)
    {
                        for(i=0;i<255;i++)
                        {
                                                MY_IP_CORE_mWriteReg(TEST_BASE, MY_IP_CORE_S00_AXI_SLV_REG3_OFFSET, i);
                                                MY_IP_CORE_mWriteReg(TEST_BASE, MY_IP_CORE_S00_AXI_SLV_REG4_OFFSET, i+1);
                                                MY_IP_CORE_mWriteReg(TEST_BASE, MY_IP_CORE_S00_AXI_SLV_REG5_OFFSET, i+2);

                                                in_1 = MY_IP_CORE_mReadReg(TEST_BASE, MY_IP_CORE_S00_AXI_SLV_REG0_OFFSET);
                                                in_2 = MY_IP_CORE_mReadReg(TEST_BASE, MY_IP_CORE_S00_AXI_SLV_REG1_OFFSET);
                                                in_3 = MY_IP_CORE_mReadReg(TEST_BASE, MY_IP_CORE_S00_AXI_SLV_REG2_OFFSET);
                                                printf(" Input_1 = %i \n",in_1);
                                                printf(" Input_2 = %i \n",in_2);
                                                printf(" Input_3 = %i \n\n",in_3);
                                                for(delay=0;delay<ust_limit;delay++){};
                        }
    }
    return 0;
}




·         Construcción del proyecto:



·         Generamos el GDB para programar el ARM del Zynq:



·         Corremos el debugger y vemos satisfactoriamente la implementación en SDK:



·         Se observa en la tarjeta ZedBoard la salidas secuenciales funcionando correctamente!





























































































1 comentario:

  1. Muy útil esta entrada y el blog en general! Muchas gracias!

    ResponderEliminar