首页 > 代码库 > Learn ZYNC (6)

Learn ZYNC (6)

最近在关注的问题是怎么样从ps端丢数据到ram,

然后用ip核进行处理后再输送到ram,ps端可以读取。

参考文献:【OpenHW参赛手记】AXI-Stream接口开发详细流程

首先按照作者的探索思路在 VIVADO 2013.4 下实践了一下AXI-Stream-FIFO

bd:

image

standalone test:

#include "xparameters.h"#include "platform.h"#include "xllfifo.h"   //包含AXI-FIFO-Stream控制接口头文件#define r1 t1           //收发都是一个模块完成的,所以。。。XLlFifo t1;                 //AXI-FIFO Stream控制模块int sendram[8] = {1,2,3,4,5,6,7,8};   //发送缓冲区int recvram[8] = {0,0,0,0,0,0,0,0};    //接收缓冲区#define AXI_FIFO_BASE 0x7AA00000    //AXI-FIFO模块内存映射地址//下面都是寄存器偏移量(按字计,不是字节,因为这里使用unsigned int指针)#define ISR 0#define IER 1#define TDFR 2#define TDFV 3#define TDFD 4#define TLF 5#define RDFR 6#define RDFO 7#define RDFD 8#define RLF 9#define LLR 10//用于调试,打印关键寄存器的值void debug_register(unsigned int * p){ printf("ISR = 0x%x\n",*(p+ISR)); if(*(p+ISR)) {  unsigned int t = *(p+ISR);  *(p+ISR)=t&0xffffffff; } printf("ISR = 0x%x\n",*(p+ISR)); printf("IER = 0x%x\n",*(p+IER)); printf("TDFR = 0x%x\n",*(p+TDFR)); printf("TDFV = 0x%x\n",*(p+TDFV)); printf("TDFD = 0x%x\n",*(p+TDFD)); printf("TLF = 0x%x\n",*(p+TLF)); printf("RDFR = 0x%x\n",*(p+RDFR)); printf("RDFO = 0x%x\n",*(p+RDFO));// printf("RDFD = 0x%x\n",*(p+RDFD));// printf("RLF = 0x%x\n",*(p+RLF));   //千万别轻易读这个,会复位的! printf("LLR = 0x%x\n",*(p+LLR));}int main(){ int status=0; int rxlen;   //接收字节数    init_platform();    printf("Hello World\n\r");    debug_register((unsigned int *)AXI_FIFO_BASE);    XLlFifo_Initialize(&t1,AXI_FIFO_BASE);//初始化AXI-FIFO模块 //   XLlFifo_Initialize(&r1,0x74200000);//由于收发一体,故只需初始化一次    XLlFifo_Write(&t1,sendram,8*4);//写发送缓冲区的内容到发送FIFO    XLlFifo_TxSetLen(&r1,8*4);//启动发送过程    print("Transmit begin!\n\r");//    debug_register((unsigned int *)AXI_FIFO_BASE);    if(XLlFifo_RxOccupancy(&r1))   //如果接收FIFO中有内容    {     rxlen=XLlFifo_RxGetLen(&r1);//先获取其长度     printf("Rcv Length:%d\n",rxlen);     XLlFifo_Read(&r1, recvram,rxlen);//读取接收内容     int sum=0,i;     for(i = 0;i<8;i++)     {      if(recvram[i]!=sendram[i])//如果接收不等于发送      {       printf("Error in index %d\n",i);//那么就报错,并报告接收内容       sum++;//错误计数      }     }     if(sum==0)     {      printf("Success!\n");//无错,则成功     }    }    print("Transmit done!\n\r");    cleanup_platform();    return 0;}

然后把自己的ip核连接到axi-dma上去,实现STREAM到ps端的数据传输:

bd:

image

address:

image

暂时只是把博主的ip核复制过来测试,文件列表如下

image

顶层文件:

	module my_stream_ip_v1_0 #	(		// Users to add parameters here		// User parameters ends		// Do not modify the parameters beyond this line		// Parameters of Axi Slave Bus Interface S01_AXIS		parameter integer C_S01_AXIS_TDATA_WIDTH	= 32,		// Parameters of Axi Master Bus Interface M00_AXIS		parameter integer C_M00_AXIS_TDATA_WIDTH	= 32,		parameter integer C_M00_AXIS_START_COUNT	= 32	)	(		// Users to add ports here		// User ports ends		// Do not modify the ports beyond this line		// Ports of Axi Slave Bus Interface S01_AXIS		input wire  s01_axis_aclk,		input wire  s01_axis_aresetn,		output wire  s01_axis_tready,		input wire [C_S01_AXIS_TDATA_WIDTH-1 : 0] s01_axis_tdata,		input wire [(C_S01_AXIS_TDATA_WIDTH/8)-1 : 0] s01_axis_tstrb,		input wire  s01_axis_tlast,		input wire  s01_axis_tvalid,		// Ports of Axi Master Bus Interface M00_AXIS		input wire  m00_axis_aclk,		input wire  m00_axis_aresetn,		output wire  m00_axis_tvalid,		output wire [C_M00_AXIS_TDATA_WIDTH-1 : 0] m00_axis_tdata,		output wire [(C_M00_AXIS_TDATA_WIDTH/8)-1 : 0] m00_axis_tstrb,		output wire  m00_axis_tlast,		input wire  m00_axis_tready	);			my_stream_ip my_stream_ip_v1_0_S01_AXIS_inst (    		.ACLK(s01_axis_aclk),    		.ARESETN(s01_axis_aresetn),    		.S_AXIS_TREADY(s01_axis_tready),    		.S_AXIS_TDATA(s01_axis_tdata),    		.S_AXIS_TLAST(s01_axis_tlast),    		.S_AXIS_TVALID(s01_axis_tvalid),    		.M_AXIS_TVALID(m00_axis_tvalid),            .M_AXIS_TDATA(m00_axis_tdata),            .M_AXIS_TLAST(m00_axis_tlast),            .M_AXIS_TREADY(m00_axis_tready)    	);	// Instantiation of Axi Bus Interface S01_AXIS//	my_stream_ip_v1_0_S01_AXIS # ( //		.C_S_AXIS_TDATA_WIDTH(C_S01_AXIS_TDATA_WIDTH)//	) my_stream_ip_v1_0_S01_AXIS_inst (//		.S_AXIS_ACLK(s01_axis_aclk),//		.S_AXIS_ARESETN(s01_axis_aresetn),//		.S_AXIS_TREADY(s01_axis_tready),//		.S_AXIS_TDATA(s01_axis_tdata),//		.S_AXIS_TSTRB(s01_axis_tstrb),//		.S_AXIS_TLAST(s01_axis_tlast),//		.S_AXIS_TVALID(s01_axis_tvalid)//	);// Instantiation of Axi Bus Interface M00_AXIS//	my_stream_ip_v1_0_M00_AXIS # ( //		.C_M_AXIS_TDATA_WIDTH(C_M00_AXIS_TDATA_WIDTH),//		.C_M_START_COUNT(C_M00_AXIS_START_COUNT)//	) my_stream_ip_v1_0_M00_AXIS_inst (//		.M_AXIS_ACLK(m00_axis_aclk),//		.M_AXIS_ARESETN(m00_axis_aresetn),//		.M_AXIS_TVALID(m00_axis_tvalid),//		.M_AXIS_TDATA(m00_axis_tdata),//		.M_AXIS_TSTRB(m00_axis_tstrb),//		.M_AXIS_TLAST(m00_axis_tlast),//		.M_AXIS_TREADY(m00_axis_tready)//	);	// Add user logic here	// User logic ends	endmodule

ip核单个文件:

`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date: 06/17/2014 04:46:15 PM// Design Name: // Module Name: stream_ip// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// //////////////////////////////////////////////////////////////////////////////////module my_stream_ip   (    ACLK,    ARESETN,    S_AXIS_TREADY,    S_AXIS_TDATA,    S_AXIS_TLAST,    S_AXIS_TVALID,    M_AXIS_TVALID,    M_AXIS_TDATA,    M_AXIS_TLAST,    M_AXIS_TREADY,   );    input                                    ACLK;  input                                    ARESETN;  output                                   S_AXIS_TREADY;  input      [31 :0]                      S_AXIS_TDATA;  input                                    S_AXIS_TLAST;  input                                    S_AXIS_TVALID;  output                                   M_AXIS_TVALID;  output     [31 :0]                      M_AXIS_TDATA;  output                                   M_AXIS_TLAST;  input                                    M_AXIS_TREADY;        localparam NUMBER_OF_INPUT_WORDS  = 8;       localparam NUMBER_OF_OUTPUT_WORDS = 8;       localparam Idle  =3‘b100;     localparam Read_Inputs = 3‘b010;     localparam Write_Outputs  = 3‘b001;       reg [2:0] state;       reg [31:0] sum;       reg [NUMBER_OF_INPUT_WORDS -1:0] nr_of_reads;     reg [NUMBER_OF_OUTPUT_WORDS - 1:0] nr_of_writes;       assign S_AXIS_TREADY  =(state == Read_Inputs);     assign M_AXIS_TVALID = (state == Write_Outputs);       assign M_AXIS_TDATA = http://www.mamicode.com/sum;  >

完成,generate bit stream

sdk测试也是用的博主的测试文件:

    #include <stdio.h>    #include <stdlib.h>    #include "platform.h"    #include "xil_cache.h"          //必须包含该头文件,实现cache操作    #define sendram ((int *)0x10000000)          //发送缓冲区    #define recvram ((int *)0x10001000)          //接收缓冲区    #define sizeofbuffer 32    void print(char *str);    #define WITH_SG 0    #define AXI_DMA_BASE 0x40400000    #define MM2S_DMACR 0    #define MM2S_DMASR 1    #if WITH_SG    #define MM2S_CURDESC 2    #define MM2S_TAILDESC 4    #else    #define MM2S_SA 6    #define MM2S_LENGTH 10    #endif    #define S2MM_DMACR 12    #define S2MM_DMASR 13    #if WITH_SG    #define S2MM_CURDESC14    #define S2MM_TAILDESC16    #else    #define S2MM_DA 18    #define S2MM_LENGTH 22    #endif    void debug_axi_dma_register(unsigned int *p)    {     printf("MM2S_DMACR = 0x%x\n",*(p+MM2S_DMACR));     printf("MM2S_DMASR = 0x%x\n",*(p+MM2S_DMASR));    #if WITH_SG     printf("MM2S_CURDESC = 0x%x\n",*(p+MM2S_CURDESC));     printf("MM2S_TAILDESC = 0x%x\n",*(p+MM2S_TAILDESC));    #else     printf("MM2S_SA = 0x%x\n",*(p+MM2S_SA));     printf("MM2S_LENGTH = 0x%x\n",*(p+MM2S_LENGTH));    #endif     printf("S2MM_DMACR =0x%x\n",*(p+S2MM_DMACR));     printf("S2MM_DMACSR =0x%x\n",*(p+S2MM_DMASR));    #if WITH_SG     printf("S2MM_CURDESC =0x%x\n",*(p+S2MM_CURDESC));     printf("S2MM_TAILDESC= 0x%x\n",*(p+S2MM_TAILDESC));    #else     printf("S2MM_DA =0x%x\n",*(p+S2MM_DA));     printf("S2MM_LENGTH =0x%x\n",*(p+S2MM_LENGTH));    #endif    }    void init_axi_dma_simple(unsigned int * p)    {     *(p+MM2S_DMACR) = 0x04;  //reset send axi dma     while(*(p+MM2S_DMACR)&0x04);     *(p+S2MM_DMACR) =0x04;  //reset send axi dma     while(*(p+S2MM_DMACR)&0x04);     *(p+MM2S_DMACR)=1;     while((*(p+MM2S_DMASR)&0x01));     *(p+S2MM_DMACR)=1;     while((*(p+S2MM_DMASR)&0x01));     *(p+MM2S_SA) = (unsigned int )sendram;     *(p+S2MM_DA) =(unsigned int )recvram;     Xil_DCacheFlushRange((u32)sendram,sizeofbuffer); //将cache内容同步到DDR2     *(p+S2MM_LENGTH) =sizeofbuffer;//sizeof(recvram);     *(p+MM2S_LENGTH) = sizeofbuffer;//sizeof(sendram);     while(!(*(p+MM2S_DMASR)&0x1000)); //wait for send ok    }    void init_sendbuffer()    {     int i;     for(i=0;i< sizeofbuffer/4;i++)     {      sendram[i]=i*2;     }    }    void show_recvbuffer()    {     int i;     printf("Recv contents are:\n");     for(i=0;i< sizeofbuffer/4;i++)     {      printf("%d\t",recvram[i]);     }     printf("\r\n");    }    void show_sendbuffer()    {     int i;     printf("Send contents are:\n");     for(i=0;i< sizeofbuffer/4;i++)     {      printf("%d\t",sendram[i]);     }     printf("\r\n");    }    int main()    {     unsigned int status=0;     int rxlen;        init_platform();        init_sendbuffer();    init_axi_dma_simple((unsigned int *)AXI_DMA_BASE);        printf("Hello World\n\rPlease input data:");        while(1)        {         scanf("%x",&status);         printf("Got 0x%x\n",status);         debug_axi_dma_register((unsigned int *)AXI_DMA_BASE);         if(status==0)         {          break;         }        }        show_sendbuffer();    Xil_DCacheInvalidateRange((u32)recvram,sizeofbuffer);      //将DDR2内容同步到cache        show_recvbuffer();        cleanup_platform();    return 0;    }

测试结果如下:

image

下一步修改博主的逻辑到vivado自动生成的两个端口的verilog代码中。。。