最近在关注的问题是怎么样从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代码中。。。

ip核顶层文件my_stream_ip_v1_0.v

	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 S00_AXIS
parameter integer C_S00_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 S00_AXIS
input wire s00_axis_aclk,
input wire s00_axis_aresetn,
output wire s00_axis_tready,
input wire [C_S00_AXIS_TDATA_WIDTH-1 : 0] s00_axis_tdata,
input wire [(C_S00_AXIS_TDATA_WIDTH/8)-1 : 0] s00_axis_tstrb,
input wire s00_axis_tlast,
input wire s00_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
); wire [31 : 0] fifo_data; // Instantiation of Axi Bus Interface S00_AXIS
my_stream_ip_v1_0_S00_AXIS # (
.C_S_AXIS_TDATA_WIDTH(C_S00_AXIS_TDATA_WIDTH)
) my_stream_ip_v1_0_S00_AXIS_inst (
.S_AXIS_ACLK(s00_axis_aclk),
.S_AXIS_ARESETN(s00_axis_aresetn),
.S_AXIS_TREADY(s00_axis_tready),
.S_AXIS_TDATA(s00_axis_tdata),
.S_AXIS_TSTRB(s00_axis_tstrb),
.S_AXIS_TLAST(s00_axis_tlast),
.S_AXIS_TVALID(s00_axis_tvalid),
.fifo(fifo_data)
); // 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),
.fifo(fifo_data)
); // Add user logic here // User logic ends endmodule

ip核axi stream master口对应verilog文件my_stream_ip_v1_0_M00_AXIS.v

	module my_stream_ip_v1_0_M00_AXIS #
(
// Users to add parameters here // User parameters ends
// Do not modify the parameters beyond this line // Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH.
parameter integer C_M_AXIS_TDATA_WIDTH = 32,
// Start count is the numeber of clock cycles the master will wait before initiating/issuing any transaction.
parameter integer C_M_START_COUNT = 32
)
(
// Users to add ports here // User ports ends
// Do not modify the ports beyond this line // Global ports
input wire M_AXIS_ACLK,
//
input wire M_AXIS_ARESETN,
// Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted.
output wire M_AXIS_TVALID,
// TDATA is the primary payload that is used to provide the data that is passing across the interface from the master.
output wire [C_M_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA,
// TSTRB is the byte qualifier that indicates whether the content of the associated byte of TDATA is processed as a data byte or a position byte.
output wire [(C_M_AXIS_TDATA_WIDTH/8)-1 : 0] M_AXIS_TSTRB,
// TLAST indicates the boundary of a packet.
output wire M_AXIS_TLAST,
// TREADY indicates that the slave can accept a transfer in the current cycle.
input wire M_AXIS_TREADY, wire [31:0] fifo
);
//Total number of output data.
// Total number of output data
localparam NUMBER_OF_OUTPUT_WORDS = 8; // function called clogb2 that returns an integer which has the
// value of the ceiling of the log base 2.
function integer clogb2 (input integer bit_depth);
begin
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
bit_depth = bit_depth >> 1;
end
endfunction // WAIT_COUNT_BITS is the width of the wait counter.
localparam integer WAIT_COUNT_BITS = clogb2(C_M_START_COUNT-1); // bit_num gives the minimum number of bits needed to address 'depth' size of FIFO.
localparam bit_num = clogb2(NUMBER_OF_OUTPUT_WORDS); // Define the states of state machine
// The control state machine oversees the writing of input streaming data to the FIFO,
// and outputs the streaming data from the FIFO
parameter [1:0] IDLE = 2'b00, // This is the initial/idle state INIT_COUNTER = 2'b01, // This state initializes the counter, ones
// the counter reaches C_M_START_COUNT count,
// the state machine changes state to INIT_WRITE
SEND_STREAM = 2'b10; // In this state the
// stream data is output through M_AXIS_TDATA
// State variable
reg [1:0] mst_exec_state;
// Example design FIFO read pointer
reg [bit_num-1:0] read_pointer; // AXI Stream internal signals
//wait counter. The master waits for the user defined number of clock cycles before initiating a transfer.
reg [WAIT_COUNT_BITS-1 : 0] count;
//streaming data valid
wire axis_tvalid;
//streaming data valid delayed by one clock cycle
reg axis_tvalid_delay;
//Last of the streaming data
wire axis_tlast;
//Last of the streaming data delayed by one clock cycle
reg axis_tlast_delay;
//FIFO implementation signals
reg [C_M_AXIS_TDATA_WIDTH-1 : 0] stream_data_out;
wire tx_en;
//The master has issued all the streaming data stored in FIFO
reg tx_done; // I/O Connections assignments assign M_AXIS_TVALID = axis_tvalid_delay;
assign M_AXIS_TDATA = stream_data_out;
assign M_AXIS_TLAST = axis_tlast_delay;
assign M_AXIS_TSTRB = {(C_M_AXIS_TDATA_WIDTH/8){1'b1}}; // Control state machine implementation
always @(posedge M_AXIS_ACLK)
begin
if (!M_AXIS_ARESETN)
// Synchronous reset (active low)
begin
mst_exec_state <= IDLE;
count <= 0;
end
else
case (mst_exec_state)
IDLE:
// The slave starts accepting tdata when
// there tvalid is asserted to mark the
// presence of valid streaming data
if ( count == 0 )
begin
mst_exec_state <= INIT_COUNTER;
end
else
begin
mst_exec_state <= IDLE;
end INIT_COUNTER:
// The slave starts accepting tdata when
// there tvalid is asserted to mark the
// presence of valid streaming data
if ( count == C_M_START_COUNT - 1 )
begin
mst_exec_state <= SEND_STREAM;
end
else
begin
count <= count + 1;
mst_exec_state <= INIT_COUNTER;
end SEND_STREAM:
// The example design streaming master functionality starts
// when the master drives output tdata from the FIFO and the slave
// has finished storing the S_AXIS_TDATA
if (tx_done)
begin
mst_exec_state <= IDLE;
end
else
begin
mst_exec_state <= SEND_STREAM;
end
endcase
end //tvalid generation
//axis_tvalid is asserted when the control state machine's state is SEND_STREAM and
//number of output streaming data is less than the NUMBER_OF_OUTPUT_WORDS.
assign axis_tvalid = ((mst_exec_state == SEND_STREAM) && (read_pointer < NUMBER_OF_OUTPUT_WORDS)); // AXI tlast generation
// axis_tlast is asserted number of output streaming data is NUMBER_OF_OUTPUT_WORDS-1
// (0 to NUMBER_OF_OUTPUT_WORDS-1)
assign axis_tlast = (read_pointer == NUMBER_OF_OUTPUT_WORDS-1); // Delay the axis_tvalid and axis_tlast signal by one clock cycle
// to match the latency of M_AXIS_TDATA
always @(posedge M_AXIS_ACLK)
begin
if (!M_AXIS_ARESETN)
begin
axis_tvalid_delay <= 1'b0;
axis_tlast_delay <= 1'b0;
end
else
begin
axis_tvalid_delay <= axis_tvalid;
axis_tlast_delay <= axis_tlast;
end
end //read_pointer pointer always@(posedge M_AXIS_ACLK)
begin
if(!M_AXIS_ARESETN)
begin
read_pointer <= 0;
tx_done <= 1'b0;
end
else
if (read_pointer <= NUMBER_OF_OUTPUT_WORDS-1)
begin
if (tx_en)
// read pointer is incremented after every read from the FIFO
// when FIFO read signal is enabled.
begin
read_pointer <= read_pointer + 1;
tx_done <= 1'b0;
end
end
else if (read_pointer == NUMBER_OF_OUTPUT_WORDS)
begin
// tx_done is asserted when NUMBER_OF_OUTPUT_WORDS numbers of streaming data
// has been out.
tx_done <= 1'b1;
end
end //FIFO read enable generation assign tx_en = M_AXIS_TREADY && axis_tvalid; // Streaming output data is read from FIFO
always @( posedge M_AXIS_ACLK )
begin
if(!M_AXIS_ARESETN)
begin
stream_data_out <= 1;
end
else if (tx_en)// && M_AXIS_TSTRB[byte_index]
begin
// stream_data_out <= read_pointer + 32'b1;
stream_data_out <= fifo;
end
end // Add user logic here // User logic ends endmodule

ip核axi stream slave口对应的verilog文件my_stream_ip_v1_0_S00_AXIS.v

	module my_stream_ip_v1_0_S00_AXIS #
(
// Users to add parameters here // User parameters ends
// Do not modify the parameters beyond this line // AXI4Stream sink: Data Width
parameter integer C_S_AXIS_TDATA_WIDTH = 32
)
(
// Users to add ports here // User ports ends
// Do not modify the ports beyond this line // AXI4Stream sink: Clock
input wire S_AXIS_ACLK,
// AXI4Stream sink: Reset
input wire S_AXIS_ARESETN,
// Ready to accept data in
output wire S_AXIS_TREADY,
// Data in
input wire [C_S_AXIS_TDATA_WIDTH-1 : 0] S_AXIS_TDATA,
// Byte qualifier
input wire [(C_S_AXIS_TDATA_WIDTH/8)-1 : 0] S_AXIS_TSTRB,
// Indicates boundary of last packet
input wire S_AXIS_TLAST,
// Data is in valid
input wire S_AXIS_TVALID, wire [31:0] fifo
);
// function called clogb2 that returns an integer which has the
// value of the ceiling of the log base 2.
function integer clogb2 (input integer bit_depth);
begin
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
bit_depth = bit_depth >> 1;
end
endfunction // Total number of input data.
localparam NUMBER_OF_INPUT_WORDS = 8;
// bit_num gives the minimum number of bits needed to address 'NUMBER_OF_INPUT_WORDS' size of FIFO.
localparam bit_num = clogb2(NUMBER_OF_INPUT_WORDS-1);
// Define the states of state machine
// The control state machine oversees the writing of input streaming data to the FIFO,
// and outputs the streaming data from the FIFO
parameter [1:0] IDLE = 1'b0, // This is the initial/idle state WRITE_FIFO = 1'b1; // In this state FIFO is written with the
// input stream data S_AXIS_TDATA
wire axis_tready;
// State variable
reg mst_exec_state;
// FIFO implementation signals
genvar byte_index;
// FIFO write enable
wire fifo_wren;
// FIFO full flag
reg fifo_full_flag;
// FIFO write pointer
reg [bit_num-1:0] write_pointer;
// sink has accepted all the streaming data and stored in FIFO
reg writes_done;
// I/O Connections assignments
//********** my code ***************************************************
reg [31:0] sum; assign S_AXIS_TREADY = axis_tready;
// Control state machine implementation
always @(posedge S_AXIS_ACLK)
begin
if (!S_AXIS_ARESETN)
// Synchronous reset (active low)
begin
mst_exec_state <= IDLE;
end
else
case (mst_exec_state)
IDLE:
// The sink starts accepting tdata when
// there tvalid is asserted to mark the
// presence of valid streaming data
if (S_AXIS_TVALID)
begin
mst_exec_state <= WRITE_FIFO;
end
else
begin
mst_exec_state <= IDLE;
end
WRITE_FIFO:
// When the sink has accepted all the streaming input data,
// the interface swiches functionality to a streaming master
if (writes_done)
begin
mst_exec_state <= IDLE;
end
else
begin
// The sink accepts and stores tdata
// into FIFO
mst_exec_state <= WRITE_FIFO;
end endcase
end
// AXI Streaming Sink
//
// The example design sink is always ready to accept the S_AXIS_TDATA until
// the FIFO is not filled with NUMBER_OF_INPUT_WORDS number of input words.
assign axis_tready = ((mst_exec_state == WRITE_FIFO) && (write_pointer <= NUMBER_OF_INPUT_WORDS-1));
//******************** MY CODE HERE ************************************
// reg [31 : 0] fifo_data;
// assign fifo = fifo_data;
always@(posedge S_AXIS_ACLK)
begin
if(!S_AXIS_ARESETN)
begin
write_pointer <= 0;
writes_done <= 1'b0;
// fifo_data <= 32'b0;
//******************** MY CODE HERE ************************************
// sum <= 0;
end
else
if (write_pointer <= NUMBER_OF_INPUT_WORDS-1)
begin
if (fifo_wren)
begin
//******************************************************************
// sum <= sum + S_AXIS_TDATA;
// fifo_data <= sum;
// write pointer is incremented after every write to the FIFO
// when FIFO write signal is enabled.
write_pointer <= write_pointer + 1;
writes_done <= 1'b0;
end
if ((write_pointer == NUMBER_OF_INPUT_WORDS-1)|| S_AXIS_TLAST)
begin
// reads_done is asserted when NUMBER_OF_INPUT_WORDS numbers of streaming data
// has been written to the FIFO which is also marked by S_AXIS_TLAST(kept for optional usage).
// fifo_data <= sum;
writes_done <= 1'b1;
end
end
end // FIFO write enable generation
assign fifo_wren = S_AXIS_TVALID && axis_tready; // FIFO Implementation
generate
//开启3个线程,线程编号0~3,byte_index
for(byte_index=0; byte_index<= (C_S_AXIS_TDATA_WIDTH/8-1); byte_index=byte_index+1)
begin:FIFO_GEN
//reg [7:0] stream_data_fifo [0:7]数组;
reg [(C_S_AXIS_TDATA_WIDTH/4)-1:0] stream_data_fifo [0 : NUMBER_OF_INPUT_WORDS-1];
reg [31 : 0] fifo_data;
assign fifo = fifo_data;
// Streaming input data is stored in FIFO always @( posedge S_AXIS_ACLK )
begin
if (fifo_wren)// && S_AXIS_TSTRB[byte_index])
begin
// stream_data_fifo[write_pointer] <= S_AXIS_TDATA[(byte_index*8+7) -: 8];
//对于stream_data_fifo[i][8]的赋值,由write_pointer作为游标(在S_AXIS_ACLK和fifo_wren时递增1->8),
//取对于每个stream_data_fifo[write_pointer][8 down to 0]的赋值,取S_AXIS_TDATA的[(b_i*8+7):(b_i*8)]
stream_data_fifo[write_pointer] <= S_AXIS_TDATA[(byte_index*8+7) -: 8];
fifo_data <= fifo_data + S_AXIS_TDATA;
end
end
end
endgenerate // Add user logic here // User logic ends endmodule

测试结果如下:

第二次则:

对于以下程序段的理解:

      generate
for(byte_index=0; byte_index<= (C_S_AXIS_TDATA_WIDTH/8-1); byte_index=byte_index+1)
begin:FIFO_GEN
reg [(C_S_AXIS_TDATA_WIDTH/4)-1:0] stream_data_fifo [0 : NUMBER_OF_INPUT_WORDS-1]; // Streaming input data is stored in FIFO
always @( posedge S_AXIS_ACLK )
begin
if (fifo_wren)// && S_AXIS_TSTRB[byte_index])
begin
stream_data_fifo[write_pointer] <= S_AXIS_TDATA[(byte_index*8+7) -: 8];
end
end
end
endgenerate

理解(图):

重点:经过测试发现,只有generate 代码块中声明的reg才会将S_AXIS_TDATA的数据存好,并且在接到Master口中读取的时候才能够被读出,而如果将计算sum和存储改到如下段落,在Master端只能读到0:

	reg  [31 : 0] fifo_data;
assign fifo = fifo_data;
always@(posedge S_AXIS_ACLK)
begin
if(!S_AXIS_ARESETN)
begin
write_pointer <= 0;
writes_done <= 1'b0;
// fifo_data <= 32'b0;
//******************** MY CODE HERE ************************************
sum <= 0;
end
else
if (write_pointer <= NUMBER_OF_INPUT_WORDS-1)
begin
if (fifo_wren)
begin
//******************************************************************
sum <= sum + S_AXIS_TDATA;
fifo_data <= sum;
// write pointer is incremented after every write to the FIFO
// when FIFO write signal is enabled.
write_pointer <= write_pointer + 1;
writes_done <= 1'b0;
end
if ((write_pointer == NUMBER_OF_INPUT_WORDS-1)|| S_AXIS_TLAST)
begin
// reads_done is asserted when NUMBER_OF_INPUT_WORDS numbers of streaming data
// has been written to the FIFO which is also marked by S_AXIS_TLAST(kept for optional usage).
fifo_data <= sum;
writes_done <= 1'b1;
end
end
end

而且,在generate代码段中声明的寄存器值可以一直保留。

最新文章

  1. Android下/data/data/&lt;package_name&gt;/files读写权限
  2. [LeetCode] Reverse Linked List II 倒置链表之二
  3. html5 data
  4. 关于json 的那些知识点
  5. 【转】java 注释规范
  6. linux 配置静态IP
  7. 如何在eclipse使用StaggeredGridView
  8. 转:Stimulsoft Reports.Fx 2013.3新增 Email、AutoPageScale支持以及图表组件Funnel Weighted Slices
  9. Mac Dock 效果及原理(勾股定理)
  10. OC基础 点语法的使用
  11. Redis配置成系统服务(CentOS7)
  12. ecstore中kvstore之memcached
  13. Build your own linino system 编译你自己的linino系统
  14. 基于HTML5及WebGL开发的2D3D第一人称漫游进行碰撞检测
  15. bzoj:1457: 棋盘游戏
  16. [Code+#4]最短路 解题报告
  17. 【转】学习Linux守护进程详细笔记
  18. 求有向图的强连通分量个数 之 Kosaraju算法
  19. 【Unity】10.3 创建类人动画角色
  20. POJ-1959 Darts

热门文章

  1. 练习:使用nmcli 配置网络连接
  2. 【转】PHP curl CURLOPT_HTTPHEADER设置HOST
  3. mongo-c-driver使用VS2013编译
  4. django orm字段和参数
  5. python之路三
  6. nginx访问不了zabbix安装配置界面
  7. Redis 复制、Sentinel的搭建和原理说明
  8. mysql 外键 级联
  9. Spring+SpringMvc+Mybatis框架集成搭建教程五(项目源码发布到GitHub)
  10. socket通信之eofexception