首页 > 代码库 > Learn ZYNC (6)
Learn ZYNC (6)
最近在关注的问题是怎么样从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 = 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; }测试结果如下:
下一步修改博主的逻辑到vivado自动生成的两个端口的verilog代码中。。。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。