码迷,mamicode.com
首页 > 其他好文 > 详细

Learn ZYNC (6)

时间:2014-06-18 10:03:50      阅读:849      评论:0      收藏:0      [点我收藏+]

标签:des   style   class   blog   http   tar   

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

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

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

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

bd:

bubuko.com,布布扣

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:

bubuko.com,布布扣

address:

bubuko.com,布布扣

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

bubuko.com,布布扣

顶层文件:

	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 = sum;  
   assign M_AXIS_TLAST = (nr_of_writes == 1);  

   always @(posedge ACLK)  
   begin  // process The_SW_accelerator  
      if(!ARESETN)              // Synchronous reset (active low)  
        begin  
          state        <= Idle;  
           nr_of_reads <= 0;  
           nr_of_writes <=0;  
          sum          <= 0;  
        end  
      else  
        case (state)  
          Idle:  
            if (S_AXIS_TVALID== 1)  
            begin  
             state       <= Read_Inputs;  
             nr_of_reads <= NUMBER_OF_INPUT_WORDS - 1;  
             sum         <= 0;  
            end  
  
         Read_Inputs:  
            if(S_AXIS_TVALID == 1)  
            begin  
             sum         <= sum + S_AXIS_TDATA;  
             if (nr_of_reads == 0)  
               begin  
                 state        <= Write_Outputs;  
                 nr_of_writes <= NUMBER_OF_OUTPUT_WORDS - 1;  
               end  
             else  
               nr_of_reads <= nr_of_reads - 1;  
            end  
  
         Write_Outputs:  
            if(M_AXIS_TREADY == 1)  
            begin  
             if (nr_of_writes == 0)  
                state <= Idle;  
              else  
                nr_of_writes <= nr_of_writes - 1;  
            end  
        endcase  
   end  
  
endmodule  

完成,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;
    }

测试结果如下:

bubuko.com,布布扣

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

Learn ZYNC (6),布布扣,bubuko.com

Learn ZYNC (6)

标签:des   style   class   blog   http   tar   

原文地址:http://www.cnblogs.com/shenerguang/p/3793215.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!