Haciendo periféricos para microcontroladores, ¡Al estilo Xilinx!

Raul Gerardo Huertas Paiva Ing. Electrónico Universidad Tecnológica del Perú rax20037 at gmail Abril 2011

Aquí se va a describir el proceso de la creación de un periférico para el Microblaze con interfaces AXI y su integración con la herramienta “Xilinx Platform Studio”. Elegí este tema porque ha requerido un tiempo considerable de mi parte encontrar el modo hacerlo, he tenido que recolectar información de una y otra parte de la Web para tener un ejemplo básico con todos los requisitos que quería. Finalmente lo obtuve y quiero escribir eta guía para que cualquiera de ustedes puedan hacerlo más rápidamente en sus proyectos. Cualquier duda o consulta siéntanse en confianza de preguntarlo en los comentarios pues con gusto los ayudaré. ¡Empezemos! Entonces, ¿Qué se va a hacer aquí? Bueno estaba diseñando un módulo para el procesamiento de imágenes y este puede recibir los píxeles de forma serial e igualmente expulsar los datos de forma serial. El procesamiento está segmentado (Pipelined) y entra en la categoría de procesadores de flujo (Stream Processors). Además de los píxeles, este módulo necesita un par de parámetros más con los cuales se controla su funcionamiento: Param 1 Param 2 Param 3

Procesador de Píxeles

Entrada

Salida

Memoria Principal

Para su implementación se usará un kit SP605 Embedded Edition de Xilinx, con una memoria DDR3 de 128MB, la única en la tarjeta capaz de almacenar una imagen de al menos 16MP. Para la entrada/salida de datos las únicas interfaces con una velocidad aceptable podían ser PCI Express(2Gb/s), Ethernet (1Gb/s). Tanto la memoria como las entradas y salidas necesitan de controladores nada triviales de diseñar e implicarían un tiempo considerable de desarrollo. ¡Pero!, aquí comienza la historia, Xilinx provee una interfaz AXI para todos estos módulos. Adaptando mi módulo a esta interfaz tendría más facilidad para la comunicación de datos. Y de acuerdo a Xilinx, junto con sus herramientas, este sería un proceso simple y tendría una solución “Plug & Play” para todos mis proyectos. Puedes encontrar información completa sobre AXI en la página de Xilinx y su especificación completa en la página de ARM.
http://www.xilinx.com/support/documentation/white_papers/wp379_AXI4_Plug_and_Play_IP.pdf http://www.arm.com/products/system-ip/amba/amba-open-specifications.php

Teniendo conocimiento de esto el diseño de mi módulo tendría las siguientes interfaces:

Interfaz AXI Stream – Slave Param 1

Interfaz AXI-Lite Slave Param 2 Param 3

Interfaz AXI Stream – Master

Procesador de Píxeles

Al final de esta guía se tendrá un ejemplo funcional de un periférico con estas interfaces para con el cual se podrá seguir implementando el periférico que se desee.

¿Qué se necesita para programar estas interfaces?
Necesitas de estos programas para seguir los pasos que voy a describir:  ISE Design Suite 13.1, Embedded Edition .- Disponible la versión de prueba en la página de Xilinx. Si adquieres un kit estos vienen con una licencia permanente para el programa, con la única limitación de sólo poder usarla para un modelo de FPGAs (¡el que viene en el kit!) Un editor sencillo de texto, te recomiendo el Notepad++.

También necesitas descargar los siguientes archivos con plantillas para los diseños:

¿How to create a custom AXI IP Core? , archivos con las plantillas de las interfaces AXI de la página de Xilinx.

Además, necesitas un proyecto en XPS listo para poder simplemente agregar nuestro módulo. Es decir, ya debes de tener un procesador, la memoria y demás periféricos básicos (timer, uart, leds, botones, …) para poder trabajar sólo en este periférico. Junto a este documento estaré adjuntando el archivo .mhs con el que empecé trabajar. No te recomiendo usar el diseño que se crea con el asistente de XPS pues, en mi experiencia, ¡no funcionan! Hay un problemita con la interfaz a la memoria DDR, que ya está solucionado en el diseño que adjunto. Al parecer sólo se trata de seleccionar correctamente el orden de los pines de dirección. De cualquier forma yo baso mi diseño en el que viene junto al kit Spartan 6 Embedded Development de Xilinx, y lo he actualizado por completo a la interfaz AXI. Como extra, te recomiendo empezar a reproducir un poco de música relajante como el Pop , así no te estresas ni te cansas demasiado =). Esta es la vista de los buses del diseño:

Como se ve en la figura, para la verificación del diseño se usará un par de interfaces stream del microblaze en modo AXI, M0_AXS y S0_AXIS.

Instalando las plantillas
Una vez que hayas descargado las plantillas tienes que guardarlas en el directorio pcores de tu proyecto en XPS:
pcores >

axi_lite_master_v1_00_a axi_lite_slave_v1_00_a axi_master_v1_00_a axi_slave_v1_00_a axi_stream_v1_00_a

Las dos plantillas resaltadas son las que vamos a usar en este proyecto. Revisa el documento Platform Specification Format Reference Manual para poder entender cada detalle de esos archivos. Aquí sólo se describirá lo necesario para lograr la conexión. Una vez copiados regresa a XPS ve al Project>Rescan user repositores para que el programa los reconozca. Deberán aparecer en el catálogo de IPs los siguientes componentes:

CREACION DE LA PLANTILLA PARA EL MÓDULO El siguiente paso es crear una plantilla nueva la cual se va a modificar para convertirla en nuestro periférico. Iniciamos el asistente de Xilinx mediante el comando Hardware>Create or Import Peripheral . Aparecerá la ventana de introducción del asistente, pulsamos en Next:

La siguiente pestaña es la Peripheral Flow. Debemos seleccionar la opción Create template for a new peripheral para crear la plantilla. Luego has click en Next:

La siguiente pestaña será Repository or Project. Aquí seleccionamos To an XPS repository pues no será necesario exportarlo a otros proyectos, así lo mantenemos de forma local. Click en Next.

En la pestaña Name and Version toca elegir un nombre a nuestra IP. Rellena los siguientes datos:

Click en Next.

Ahora toca elegir el tipo de bus a usar. Desafortunadamente, por ahora, este asistente sólo nos ayudara en crear la interfaz AXi-Lite, las interfaces stream las agregaremos manualmente en un paso posterior. Selecciona AXI4-Lite y haz click en siguiente:

Aparecerá la pestaña de IPIF Services, tenemos tres opciones:  Software reset .- Una señal de reset que puede reiniciar el módulo por completo el módulo. Personalmente no uso este tipo de señales en el diseño por la cantidad der recursos necesarios que usualmente necesitan(escribiré sobre esto después) así que para este ejemplo no lo seleccionaré.  User logic software register.- Si la comunicación a nuestro módulo será por registros. Esto es lo que se necesita para el módulo, una serie de registros mediante los cuales se envían parámetros al módulo. Esta opción se activa.  Include data phase timer.- Si se activa esta opción se va a crear un temporizador que notificará al sistema si el módulo se está demorando mucho en responder. Por ahora se deja esta opción sin seleccionar. Después de marcar las opciones necesarias, hacer click en Next:

La siguiente pestaña es User S/W registers. Para este ejemplo tendremos suficiente con cuatro registros. Luego haz click en siguiente:

En la pestaña IP InterConnect se especifican las señales del bus van a necesitarse. Dejamos las señales por defecto. Click en siguiente:

En la pestaña Peripheral Simulation Support se decide o no crear modelos de simulación para nuestro periférico. No se realizará la simulación en esta guía así que por ahora dejaremos esta opción deseleccionada. Click en siguiente:

La última pestaña es la de Peripheral Implementation Support. Aquí se va a necesitar la opción Generate ISE and XST Project Files to help you implement the peripheral using XST flow. Esto permite la posterior uso del ISE para la organización de los archivos del proyecto.

Esta es la última pestaña en la que tenemos que seleccionar alguna opción. Luego aparecerá la pestaña de Congratulations con un resumen de la plantilla creada. Revísala y a continuación hazle click en siguiente.

En la carpeta pcores del proyecto XPS aparecerá el directorio my_first_ip_v1_00_a con todas las plantillas del proyecto. En my_first_ip_v1_00_a\hdl se han creado las plantillas con el código para el periférico, my_first_ip_v1_00_a\data contiene los archivos con que se importa este periférico al EDK y en my_first_ip_v1_00_a\devl se encuentran los archivos del ISE para organizar el proyecto.

EXPLORANDO EL CÓDIGO DE LA PLANTILLA
En la carpeta my_first_ip_v1_00_a\devl\projnav se encuentra el proyecto de ISE my_first_ip, ábrelo. Este no es el proyecto del diseño completo, sino sólo para editar el código de tu periférico.

Trata de sintetizarlo y encontrarás alrededor de 19 errores. No sé realmente a que se debe esto. Para solucionarlo en la vista de diseño selecciona el archivo ‘counter_f’, botón derecho, en el menú que aparece elige Source Properties… Activa la acción ‘Include as Global file in Compile list’ y luego haz click en OK. Haz lo mismo con el archivo or_gate128. Cuando sintetices todo de nuevo los errores deben de haber desparecido.

Ahora es tiempo de explorar las fuentes Para este proyecto veras que se han creado dos archivos en VHDL: my_first_ip.vhd user_logic.vhd El primero tiene referencias a librerias externas que implementan la interfaz AXI, muy bueno, así no hay que invertir mucho tiempo lidiando con los detalles de este protocolo. Es importante la importación de las librerías proc_common_v3_00_a y axi_lite_ipif_v1_01_a pues, aun si no las

usas, EDK no va a poder reconocer tu módulo si no están estas presentes. Como mencionamos más arriba, sólo contiene la implementación de la interfaz AXI-Lite. El archivo user_logic.vhd es más comprensible. Alrededor de la línea 182 vas está el código para almacenar los datos en los registros :
case slv_reg_write_sel is when "1000" => for byte_index in 0 to (C_SLV_DWIDTH/8)-1 loop if ( Bus2IP_BE(byte_index) = '1' ) then slv_reg0(byte_index*8+7 downto byte_index*8) <= Bus2IP_Data(byte_index*8+7 downto byte_index*8); end if; end loop; when "0100" => …

El bucle con el iterador byte_index sirve para seleccionar, hacienda usaso de la señales AXI-STRB que bytes de tu registro deben cambiar sus datos. Te recomiendo retirar este bucle y actualizar todo el contenido del registro, así obtienes un núcleo más ligero. Más abajo en el código, alrededor de la línea 218, verás la sección en que se realiza la lectura de los registros:
case slv_reg_read_sel is when "1000" => slv_ip2bus_data when "0100" => slv_ip2bus_data when "0010" => slv_ip2bus_data when "0001" => slv_ip2bus_data when others => slv_ip2bus_data end case; <= <= <= <= <= slv_reg0; slv_reg1; slv_reg2; slv_reg3; (others => '0');

Para este ejemplo vamos a modificar el comportamiento de esta operación. En vez de leer el mismo dato que ha escrito, vamos a hacer que lea de regreso el complemento binario de este dato. Estos archivos VHDL se han agregado a la librería my_first_ip_v1_00_a del proyecto. Cualquier otro código fuente que agreguemos a nuestro proyecto debemos agregarlo a esta librería (Source properties>…).

MODIFICANDO LAS FUENTES
Antes de proseguir voy a hacer una observación. Al principio estaba usando la siguiente jeraquía para agrupar las partes del periférico: my_first_ip

stream_logic (Donde se implementa la lógica de los streams)

user_logic (Donde se implementa la interfaz slave)

No sé cuál es el problema, pero pase un buen par de noches tratando de que esto pudiera ser reconocido por el EDK pero no obtuve ningún resultado. Era muy frustante. El error que me aparecía era NGDBuild604. El EDK no generaba la netlist para el stream_logic. Finalmente modifiqué el modulo con la siguiente jerarquía:

my_first_ip

user_logic (Donde se implementa la interfaz slave y se exportan las señales de la interfaz stream)

stream_logic (Donde se implementa la lógica de los streams) user_logic ha de usarse como la raíz a partir de la cual se va a implementar el resto de nuestra lógica. Para mi sorpresa, funcionó a la primera… PERSONALIZANDO LA INTERFAZ AXI-Lite: Ya que tenemos una plantilla funcionando vamos hacer algo más interesante con ellas. Para hacer que se devuelva el complemento de los valores escritos en el registro, simplemente podemos modificar el código con lo siguiente:
case slv_reg_read_sel is when "1000" => slv_ip2bus_data when "0100" => slv_ip2bus_data when "0010" => slv_ip2bus_data when "0001" => slv_ip2bus_data when others => slv_ip2bus_data <= NOT slv_reg0; <= NOT slv_reg1; <= NOT slv_reg2; <= NOT slv_reg3; <= (others => '0');

end case;

Esto funciona, pero vamos a hacerlo instanciando un complemento declarado en otro archivo, esto para mostrar como agregar más archivos con las fuentes para nuestro periférico. Creamos el archivo ‘MiComplemento.vhd’ y lo agregamos al proyecto. Va a tener el siguiente código:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity MiComplemento is Port ( Entrada : in Salida : out end MiComplemento; STD_LOGIC_VECTOR (31 downto 0); STD_LOGIC_VECTOR (31 downto 0));

architecture Behavioral of MiComplemento is begin Salida <= NOT Entrada; end Behavioral;

Este archivo debe de agregarse a la librería de nuestro periférico, asi que seleccionamos este archivo en la vista de diseño, botón derecho>Source Proeprties y en Source Library seleccionamos nuestra librería:

Click en OK. En user_logic.vhd vamos a importar ese componente:
library my_first_ip_v1_00_a; use my_first_ip_v1_00_a.MiComplemento;

Agregamos la siguiente señal y componente a su arquitectura:
signal slv_reg0_operated : std_logic_vector(C_SLV_DWIDTH-1 downto 0); component MiComplemento is Port ( Entrada : in STD_LOGIC_VECTOR (31 downto 0); Salida : out STD_LOGIC_VECTOR (31 downto 0) ); end component MiComplemento;

Y finalmente instanciamos el componente:
--Mi operador operacion : entity my_first_ip_v1_00_a.MiComplemento port map( Entrada => slv_reg0, Salida => slv_reg0_operated );

Lo último que queda es devolver esta señal a la hora de leer los registros:
case slv_reg_read_sel is when "1000" => slv_ip2bus_data <= slv_reg0_operated;

… Sintetiza esto. No deberían haber más errores. PERSONALIZANDO LAS INTERFACES STREAM: Ahora solo queda agregar las interfaces stream al periférico. Al igual que en la interfaz AXI4-Lite vamos a hacer que a la salida devuelva el complemento de los datos que ingresan. Este es el código fuente de la lógica del stream, StreamLogic.vhd:
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library proc_common_v3_00_a; use proc_common_v3_00_a.proc_common_pkg.all; entity StreamLogic is generic( C_M_AXIS_DATA_WIDTH : integer := 32; C_S_AXIS_DATA_WIDTH : integer := 32 ); port( axi_aclk : in std_logic; axi_resetn : in std_logic; -- Master Stream Ports m_axis_tdata : out std_logic_vector(C_M_AXIS_DATA_WIDTH-1 downto 0); m_axis_tstrb : out std_logic_vector((C_M_AXIS_DATA_WIDTH/8)-1 downto 0); m_axis_tvalid : out std_logic; m_axis_tready : in std_logic; m_axis_tlast : out std_logic; -- Slave Stream Ports s_axis_tdata : in std_logic_vector(C_S_AXIS_DATA_WIDTH-1 downto 0); s_axis_tstrb : in std_logic_vector((C_S_AXIS_DATA_WIDTH/8)-1 downto 0); s_axis_tvalid : in std_logic; s_axis_tready : out std_logic; s_axis_tlast : in std_logic ); attribute SIGIS : string; attribute SIGIS of axi_aclk : signal is "CLK"; end entity StreamLogic; architecture StreamIMP of StreamLogic is signal outputSignal: std_logic_vector(C_M_AXIS_DATA_WIDTH-1 downto 0); signal registeredSignal: std_logic_vector(C_M_AXIS_DATA_WIDTH-1 downto 0); begin m_axis_tdata <= not s_axis_tdata; m_axis_tstrb <= s_axis_tstrb; m_axis_tvalid <= s_axis_tvalid; s_axis_tready <= m_axis_tready; m_axis_tlast <= s_axis_tlast; end StreamIMP;

Coloca agrega el código de StreamLogic a la librería del periférico (Botón derecho>Source Properties…). Este componente crea doce señales nuevas que tiene que agregarse a los archivos my_first_ip.vhd y user_logic.vhd:
axi_aclk : in std_logic; axi_resetn : in std_logic; -- Master Stream Ports m_axis_tdata : out std_logic_vector(C_M_AXIS_DATA_WIDTH-1 downto 0); m_axis_tstrb : out std_logic_vector((C_M_AXIS_DATA_WIDTH/8)-1 downto 0); m_axis_tvalid : out std_logic; m_axis_tready : in std_logic; m_axis_tlast : out std_logic; -- Slave Stream Ports s_axis_tdata : in std_logic_vector(C_S_AXIS_DATA_WIDTH-1 downto 0); s_axis_tstrb : in std_logic_vector((C_S_AXIS_DATA_WIDTH/8)-1 downto 0);

s_axis_tvalid s_axis_tready s_axis_tlast

: in std_logic; : out std_logic; : in std_logic

En user_logic, una vez que se han agregado las señales, se instancia este componente de la misma forma que ‘MiComplemento.vhd’ y conecta las señales y generics de la siguiente forma:
LogicaStreaming : StreamLogic generic map( C_S_AXIS_DATA_WIDTH => C_S_AXIS_DATA_WIDTH, C_M_AXIS_DATA_WIDTH => C_M_AXIS_DATA_WIDTH ) port map( --Interfaz axi stream axi_aclk => axi_aclk, axi_resetn => axi_resetn, -- Master Stream Ports m_axis_tdata => m_axis_tdata, m_axis_tstrb => m_axis_tstrb, m_axis_tvalid => m_axis_tvalid, m_axis_tready => m_axis_tready, m_axis_tlast => m_axis_tlast, -- Slave Stream Ports s_axis_tdata => s_axis_tdata, s_axis_tstrb => s_axis_tstrb, s_axis_tvalid => s_axis_tvalid, s_axis_tready => s_axis_tready, s_axis_tlast => s_axis_tlast );

La jerarquía final ha de ser: my_first_ip

user_logic (Donde se implementa la interfaz slave y se exportan las señales de la interfaz stream)

stream_logic (Donde se implementa la lógica de los streams)

MiComplemento

La síntesis de este proyecto ha de realizarse sin errores.

IMPORTAR EL PERIFIERICO AL EDK Ahora que ya tienes completas las fuentes del periférico es hora de agregarlas al diseño principal de tu sistema. Regresa al XPS y vuelve a abrir el asistente de creación/importación de periféricos. En la pestaña Peripheral Flow esta vez selecciona Import Existing Peripheral. Luego haz click en siguiente hasta que llegues a la pestaña Name and Version.

Usa los datos de la siguiente fugura y haz click en siguiente, Al hacerlo te va a advertir que vas a sobre-escribir un componente anterior, haz click en OK.

En la pestaña Source File Types selecciona que solo vas a necesitar de archivos VHDL. Click en siguiente.

En la siguiente pestaña se debe introducir el proyecto a partir del cual se va a importar el periférico.  En HDL languages used to implement your peripheral selecciona VHDL.  Deja desactivado Use Data (.mpd)…, este lo editaremos de forma manual en un paso posterior.  En el bloque de How to locate your HDL source files and dependent library files selecciona la opción Use XST project file. Haz click en Browse y selecciona el archivo my_first_ip.prj en la carpeta my_first_ip_v1_00_a\devl\projnav. Haz click en siguiente.

La siguiente pestaña es la de HDL Analisys information. Aquí te dirá si ha podido encontrar todas las fuentes y librerías de tu proyecto. Click en Next.

En la siguiente pestaña, Bus Interfaces, se selecciona los buses a identificar en nuestro periférico. Selecciona AXI4-Lite- Slave. Click en Next.

Pulsa siguiente hasta llegar a la pestaña S_AXI4LITE: Parameter. Activa Register Space, como dirección base selecciona C_BASEADDR y como dirección límite selecciona C_HIGHADDR. Click en Next:

En la pestaña Identify Interrupt signals deselecciona Select and Configure interrupts y haz click en next.

En la pestaña Parameter Attributes ve hacia el parámetro C_FAMILY en Default escribe Spartan6(o el nombre de tu dispositivo). Click en Next.

En la última pestaña revisa tu diseño y haz click en finish. Tu periférico apareceré en junto a las otras plantillas.

Agrégalo al proyecto de XPS haciéndole doble click. Deja los parámetros por defecto y cuando te aparezca el diálogo Instantiate and Connect IP selecciona User will make necessary conenctions and settings. Una vez agregado veraz que sólo aparece con la interfaz AXI4-Lite:

Hasta aquí se acabaron los aistentes.. todo se editará de forma manual. En la vista System Assembly View, click derecho en my_first_ip_0 y selecciona View MPD. Aquí aparecerá el archivo que usa XPS para reconocer los puertos de tu periférico. Casi al final verás las interfaces axi stream con la siguiente declaración:
PORT axi_aclk = "", DIR = I, SIGIS = CLK PORT axi_resetn = "", DIR = I PORT m_axis_tdata = "", DIR = O, VEC = [(C_M_AXIS_DATA_WIDTH-1):0], ENDIAN = LITTLE PORT m_axis_tstrb = "", DIR = O, VEC = [((C_M_AXIS_DATA_WIDTH/8)-1):0], ENDIAN = LITTLE PORT m_axis_tvalid = "", DIR = O PORT m_axis_tready = "", DIR = I PORT m_axis_tlast = "", DIR = O PORT s_axis_tdata = "", DIR = I, VEC = [(C_S_AXIS_DATA_WIDTH-1):0], ENDIAN = LITTLE PORT s_axis_tstrb = "", DIR = I, VEC = [((C_S_AXIS_DATA_WIDTH/8)-1):0], ENDIAN = LITTLE PORT s_axis_tvalid = "", DIR = I PORT s_axis_tready = "", DIR = O

Esto hace que no sean reconocidas como puertos funcionales en el XPS. Borra estas líneas y reemplázalas por lo siguiente:
############################################################################################ ##########################PARAMETROS DE LA INTEFAZ AXI-Stream################################# ############################################################################################ BUS_INTERFACE BUS = M_AXIS, BUS_STD = AXIS, BUS_TYPE = INITIATOR #Interfaz axi master stream BUS_INTERFACE BUS = S_AXIS, BUS_STD = AXIS, BUS_TYPE = TARGET #interfaz axi slave stream PARAMETER C_M_AXIS_DATA_WIDTH = 32, DT = INTEGER, BUS = M_AXIS PARAMETER C_S_AXIS_DATA_WIDTH = 32, DT = INTEGER, BUS = S_AXIS PARAMETER C_M_AXIS_PROTOCOL = XIL_AXI_STREAM_ETH_DATA, DT = STRING, BUS = M_AXIS PARAMETER C_S_AXIS_PROTOCOL = XIL_AXI_STREAM_ETH_DATA, DT = STRING, BUS = S_AXIS PORT axi_aclk = "", DIR = I, SIGIS = CLK, BUS = M_AXIS:S_AXIS PORT axi_resetn = ARESETN, DIR = I, SIGIS = RST, BUS = M_AXIS:S_AXIS #PORT m_axis_aresetn = ARESETN, DIR = O, BUS = M_AXIS PORT m_axis_tdata = TDATA, DIR = O, VEC = [C_M_AXIS_DATA_WIDTH-1:0], BUS = M_AXIS, ENDIAN = LITTLE PORT m_axis_tstrb = TSTRB, DIR = O, VEC = [(C_M_AXIS_DATA_WIDTH/8)-1:0], BUS = M_AXIS, ENDIAN = LITTLE PORT m_axis_tvalid = TVALID, DIR = O, BUS = M_AXIS PORT m_axis_tready = TREADY, DIR = I, BUS = M_AXIS PORT m_axis_tlast = TLAST, DIR = O, BUS = M_AXIS #PORT s_axis_aresetn = ARESETN, DIR = I, BUS = S_AXIS PORT s_axis_tdata = TDATA, DIR = I, VEC = [C_S_AXIS_DATA_WIDTH-1:0], BUS = S_AXIS, ENDIAN = LITTLE PORT s_axis_tstrb = TSTRB, DIR = I, VEC = [(C_S_AXIS_DATA_WIDTH/8)-1:0], BUS = S_AXIS, ENDIAN = LITTLE PORT s_axis_tvalid = TVALID, DIR = I, BUS = S_AXIS PORT s_axis_tready = TREADY, DIR = O, BUS = S_AXIS PORT s_axis_tlast = TLAST, DIR = I, BUS = S_AXIS

En el menú Project haz click en Rescan User Repositories. Ahora tu módulo estará con las otras dos interfaces agregadas:

Finalmente ya tenemos nuestro periférico listo para ser usado en un proyecto. El siguiente paso será verificar su funcionamiento.

VERIFICACION DEL FUNCIONAMIENTO DEL MODULO Vamos a realizar la conexión entre el microblaze y nuestro periférico. Ya que la interfaz stream del microblaze no usa las señales STRB, no puede hacerse la conexión directamente en la vista de interfaz de buses, tiene que pasarse a la vista Puertos. En esta se conectan las señales del periférico con las respectivas señales del microblaze del siguiente modo:

Aun habiendo hecho estas conexiones, no se reflejara en la vista de Interfaces de bus. Revisa las conexiones de los relojes y la asignación de direcciones de memoria. El diseño está listo para compilarse y grabarse en el FPGA.

SOFTWARE DE VERIFICACION Exporta el diseño al SDK Eclipse para programar el software del microblaze que se encarga de verificar el funcionamiento de este módulo. Usa el siguiente programa para verificar el diseño:
#include #include #include #include #include #include <stdio.h> "platform.h" "xparameters.h" "xbasic_types.h" "xutil.h" "fsl.h"

int main() { int j; printf("Hello World\n\r"); unsigned int readed; for(j=0; j< 4; j++){ myNor[j] = 0x01U; readed = (myNor[j]); } volatile unsigned int* myNor = XPAR_MY_FIRST_IP_0_BASEADDR; init_platform(); unsigned int writed = 0x32U; putfslx(writed, 0, FSL_NONBLOCKING); getfslx(readed, 0, FSL_NONBLOCKING); cleanup_platform(); return 0; }

Al momento de depurar el programa revisa los valores de la variable readed, versa que va cambiando de acuerdo a lo que se espera del diseño.

ENLACES
 Documentación de Xilinx sobre sus http://www.xilinx.com/support/documentation/ herramientas de desarrollo:

Sign up to vote on this title
UsefulNot useful