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);//写发送缓冲区的内容到发送FIFOXLlFifo_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_AXISparameter integer C_S01_AXIS_TDATA_WIDTH = 32,// Parameters of Axi Master Bus Interface M00_AXISparameter 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_AXISinput 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_AXISinput 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 endsendmodule
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 32void 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#endifvoid 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_SGprintf("MM2S_CURDESC = 0x%x\n",*(p+MM2S_CURDESC));printf("MM2S_TAILDESC = 0x%x\n",*(p+MM2S_TAILDESC));#elseprintf("MM2S_SA = 0x%x\n",*(p+MM2S_SA));printf("MM2S_LENGTH = 0x%x\n",*(p+MM2S_LENGTH));#endifprintf("S2MM_DMACR =0x%x\n",*(p+S2MM_DMACR));printf("S2MM_DMACSR =0x%x\n",*(p+S2MM_DMASR));#if WITH_SGprintf("S2MM_CURDESC =0x%x\n",*(p+S2MM_CURDESC));printf("S2MM_TAILDESC= 0x%x\n",*(p+S2MM_TAILDESC));#elseprintf("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 dmawhile(*(p+MM2S_DMACR)&0x04);*(p+S2MM_DMACR) =0x04; //reset send axi dmawhile(*(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内容同步到cacheshow_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_AXISparameter integer C_S00_AXIS_TDATA_WIDTH = 32,// Parameters of Axi Master Bus Interface M00_AXISparameter 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_AXISinput 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_AXISinput 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_AXISmy_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_AXISmy_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 endsendmodule
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 portsinput 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 validwire axis_tvalid;//streaming data valid delayed by one clock cyclereg axis_tvalid_delay;//Last of the streaming data wire axis_tlast;//Last of the streaming data delayed by one clock cyclereg axis_tlast_delay;//FIFO implementation signalsreg [C_M_AXIS_TDATA_WIDTH-1 : 0] stream_data_out;wire tx_en;//The master has issued all the streaming data stored in FIFOreg tx_done;// I/O Connections assignmentsassign 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 pointeralways@(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 endsendmodule
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 Widthparameter 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: Clockinput wire S_AXIS_ACLK,// AXI4Stream sink: Resetinput wire S_AXIS_ARESETN,// Ready to accept data inoutput wire S_AXIS_TREADY,// Data ininput wire [C_S_AXIS_TDATA_WIDTH-1 : 0] S_AXIS_TDATA,// Byte qualifierinput wire [(C_S_AXIS_TDATA_WIDTH/8)-1 : 0] S_AXIS_TSTRB,// Indicates boundary of last packetinput wire S_AXIS_TLAST,// Data is in validinput 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);beginfor(clogb2=0; bit_depth>0; clogb2=clogb2+1)bit_depth = bit_depth >> 1;endendfunction// 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 FIFOparameter [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 variablereg mst_exec_state; // FIFO implementation signalsgenvar byte_index; // FIFO write enablewire fifo_wren;// FIFO full flagreg fifo_full_flag;// FIFO write pointerreg [bit_num-1:0] write_pointer;// sink has accepted all the streaming data and stored in FIFOreg writes_done;// I/O Connections assignments//********** my code ***************************************************reg [31:0] sum;assign S_AXIS_TREADY = axis_tready;// Control state machine implementationalways @(posedge S_AXIS_ACLK) begin if (!S_AXIS_ARESETN) // Synchronous reset (active low)beginmst_exec_state <= IDLE;end elsecase (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)beginmst_exec_state <= WRITE_FIFO;endelsebeginmst_exec_state <= IDLE;endWRITE_FIFO: // When the sink has accepted all the streaming input data,// the interface swiches functionality to a streaming masterif (writes_done)beginmst_exec_state <= IDLE;endelsebegin// The sink accepts and stores tdata // into FIFOmst_exec_state <= WRITE_FIFO;endendcaseend// 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)beginif(!S_AXIS_ARESETN)beginwrite_pointer <= 0;writes_done <= 1'b0;
// fifo_data <= 32'b0;//******************** MY CODE HERE ************************************
// sum <= 0;end elseif (write_pointer <= NUMBER_OF_INPUT_WORDS-1)beginif (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;endif ((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;endend end// FIFO write enable generationassign fifo_wren = S_AXIS_TVALID && axis_tready;// FIFO Implementationgenerate //开启3个线程,线程编号0~3,byte_indexfor(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 FIFOalways @( posedge S_AXIS_ACLK )beginif (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 endsendmodule
测试结果如下:
第二次则:
对于以下程序段的理解:
generate for(byte_index=0; byte_index<= (C_S_AXIS_TDATA_WIDTH/8-1); byte_index=byte_index+1)begin:FIFO_GENreg [(C_S_AXIS_TDATA_WIDTH/4)-1:0] stream_data_fifo [0 : NUMBER_OF_INPUT_WORDS-1];// Streaming input data is stored in FIFOalways @( posedge S_AXIS_ACLK )beginif (fifo_wren)// && S_AXIS_TSTRB[byte_index])beginstream_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)beginif(!S_AXIS_ARESETN)beginwrite_pointer <= 0;writes_done <= 1'b0;
// fifo_data <= 32'b0;//******************** MY CODE HERE ************************************sum <= 0;end elseif (write_pointer <= NUMBER_OF_INPUT_WORDS-1)beginif (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;endif ((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;endend end
而且,在generate代码段中声明的寄存器值可以一直保留。
转载于:https://www.cnblogs.com/shenerguang/p/3793215.html
Learn ZYNC (6)相关推荐
- 【Kaggle Learn】Python 1-4
[Kaggle Learn]Python https://www.kaggle.com/learn/python 一. Hello, Python A quick introduction to Py ...
- Blender赛车动画制作学习教程 Learn Race Car Animation with Blender
使用Blender 2.93创建您自己的惊人汽车动画 你会学到什么 Blender的界面和导航 建模 UV制图 材料 动画 照明设备 渲染 合成 要求 下载并安装Blender.免费下载和免费用于任何 ...
- Blender3.0动画制作入门学习教程 Learn Animation with Blender (2021)
要求 下载并安装Blender.免费下载和免费用于任何目的. 描述 加入我的动画课程. 在本课程中,我将从头开始讲述在Blender中创建动画场景的过程. 从第一步到最终渲染.在这个课程中,我们将使用 ...
- Unity与C#创建一个3D平台游戏 Learn to Create a 3D Platformer Game with Unity C#
游戏开发变得容易了.使用Unity学习C#并创建您自己的3D平台! 你会学到什么 学习现代通用编程语言C#. 了解Unity中3D开发的功能 发展强大的可转移的解决问题的技能 了解游戏开发过程 了解面 ...
- 学会在Unity中创建一个Match-3益智游戏 Learn To Create a Match-3 Puzzle Game in Unity
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:48场讲座(6h 38m) |大小解压后:2.8 G ...
- Unity中创建本地多人游戏完整案例视频教程 Learn To Create A Local Multiplayer Game In Unity
Unity中创建本地多人游戏完整案例视频教程 Learn To Create A Local Multiplayer Game In Unity MP4 |视频:h264,1280x720 |音频:A ...
- Unity 3D游戏代码编程学习教程 Full Guide To Unity 3D C#: Learn To Code Making 3D Games
Unity 3D游戏代码编程学习教程 Full Guide To Unity 3D & C#: Learn To Code Making 3D Games Full Guide To Unit ...
- 读书笔记2013第10本:《学得少却考得好Learn More Study Less》
<学得少却考得好Learn More Study Less>这本书最早是从褪墨网站上看到的,crowncheng翻译了全文.这本书介绍了不少学习方法,非常适合在校的学生,原文的作者Scot ...
- The Road to learn React书籍学习笔记(第三章)
代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() constructor() 构造函数只有在组件实例化并插入到 DOM ...
- Scikit Learn: 在python中机器学习
Warning 警告:有些没能理解的句子,我以自己的理解意译. 翻译自:Scikit Learn:Machine Learning in Python 作者: Fabian Pedregosa, Ga ...
最新文章
- different application signatures解决方法
- torchvision.transforms包的使用
- asp.net core 自定义 Content-Type
- 序列化加密字段_自动加密可序列化的类
- 20什么情况下会帮助他人的因素
- nasm实现的用vmware运行自做的linux启动盘的引导代码
- 关于对象和类的那些小事
- mql 查询多结果_详解Oracle分页查询概念、缘由及如何实现
- vue官方webpack模版多个打包环境搭建
- oracle join(比较全面的解释了join)
- Flash Remoting+ Visual Studio .NET学习总结
- 长沙理工大学c语言编程题,长沙理工大学2014年上期期末c语言编程题库.doc
- API函数简介 转自洪恩在线
- Smobiler中Poplist控件的用法
- 根据身份证判断男女(通用)
- JS定时器原理及案例
- 用html创建数独,数独做不出来怎么办
- html水晶按钮图片,PS按钮制作高级教程之网页常用水晶按钮
- 【经验贴】小汽车科目二科目三 经验
- 计算机网络体系批判,基于批判性思维的计算机网络概论课程改革.pdf
热门文章
- linux 离线 nfs,Linux 系统 NFS服务
- 【2018CPCP-Final G:】Pastoral Life in Stardew Valley
- 风控模型面试问题汇总
- 计算机房采用c02采灭火,[灭火器使用.doc
- 图像空域增强:卷积运算法
- 算法:螺旋矩阵算出N行N列的数组Spiral Matrix II
- tensorflow安装中踩到的坑protobuf、h5py、tensorboard、werkzeug
- 【机器学习系列】变分推断第三讲:基于随机梯度上升法SGD的变分推断解法
- a ppt of CRF
- matlab aug,H无穷控制中的augss命令和编写的程序