标签:des style class blog http tar
最近在关注的问题是怎么样从ps端丢数据到ram,
然后用ip核进行处理后再输送到ram,ps端可以读取。
参考文献:【OpenHW参赛手记】AXI-Stream接口开发详细流程
首先按照作者的探索思路在 VIVADO 2013.4 下实践了一下AXI-Stream-FIFO
bd:
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:
address:
暂时只是把博主的ip核复制过来测试,文件列表如下
顶层文件:
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; }
测试结果如下:
下一步修改博主的逻辑到vivado自动生成的两个端口的verilog代码中。。。
标签:des style class blog http tar
原文地址:http://www.cnblogs.com/shenerguang/p/3793215.html