标签: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