zoukankan      html  css  js  c++  java
  • Learn ZYNC (6)

    最近在关注的问题是怎么样从ps端丢数据到ram,

    然后用ip核进行处理后再输送到ram,ps端可以读取。

    参考文献:【OpenHW参赛手记】AXI-Stream接口开发详细流程

    首先按照作者的探索思路在 VIVADO 2013.4 下实践了一下AXI-Stream-FIFO

    bd:

    image

    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
    ",*(p+ISR));
     if(*(p+ISR))
     {
      unsigned int t = *(p+ISR);
      *(p+ISR)=t&0xffffffff;
     }
     printf("ISR = 0x%x
    ",*(p+ISR));
     printf("IER = 0x%x
    ",*(p+IER));
     printf("TDFR = 0x%x
    ",*(p+TDFR));
     printf("TDFV = 0x%x
    ",*(p+TDFV));
     printf("TDFD = 0x%x
    ",*(p+TDFD));
     printf("TLF = 0x%x
    ",*(p+TLF));
     printf("RDFR = 0x%x
    ",*(p+RDFR));
     printf("RDFO = 0x%x
    ",*(p+RDFO));
    // printf("RDFD = 0x%x
    ",*(p+RDFD));
    // printf("RLF = 0x%x
    ",*(p+RLF));   //千万别轻易读这个,会复位的!
     printf("LLR = 0x%x
    ",*(p+LLR));
    }
    int main()
    {
    
     int status=0;
    
     int rxlen;   //接收字节数
        init_platform();
    
        printf("Hello World
    
    ");
    
        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!
    
    ");
    //    debug_register((unsigned int *)AXI_FIFO_BASE);
        if(XLlFifo_RxOccupancy(&r1))   //如果接收FIFO中有内容
        {
         rxlen=XLlFifo_RxGetLen(&r1);//先获取其长度
         printf("Rcv Length:%d
    ",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
    ",i);//那么就报错,并报告接收内容
           sum++;//错误计数
          }
         }
         if(sum==0)
         {
          printf("Success!
    ");//无错,则成功
         }
        }
        print("Transmit done!
    
    ");
    
        cleanup_platform();
    
        return 0;
    }

    然后把自己的ip核连接到axi-dma上去,实现STREAM到ps端的数据传输:

    bd:

    image

    address:

    image

    暂时只是把博主的ip核复制过来测试,文件列表如下

    image

    顶层文件:

    	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
    ",*(p+MM2S_DMACR));
         printf("MM2S_DMASR = 0x%x
    ",*(p+MM2S_DMASR));
        #if WITH_SG
         printf("MM2S_CURDESC = 0x%x
    ",*(p+MM2S_CURDESC));
         printf("MM2S_TAILDESC = 0x%x
    ",*(p+MM2S_TAILDESC));
        #else
         printf("MM2S_SA = 0x%x
    ",*(p+MM2S_SA));
         printf("MM2S_LENGTH = 0x%x
    ",*(p+MM2S_LENGTH));
        #endif
         printf("S2MM_DMACR =0x%x
    ",*(p+S2MM_DMACR));
         printf("S2MM_DMACSR =0x%x
    ",*(p+S2MM_DMASR));
        #if WITH_SG
         printf("S2MM_CURDESC =0x%x
    ",*(p+S2MM_CURDESC));
         printf("S2MM_TAILDESC= 0x%x
    ",*(p+S2MM_TAILDESC));
        #else
         printf("S2MM_DA =0x%x
    ",*(p+S2MM_DA));
         printf("S2MM_LENGTH =0x%x
    ",*(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:
    ");
         for(i=0;i< sizeofbuffer/4;i++)
         {
          printf("%d	",recvram[i]);
         }
         printf("
    ");
        }
        void show_sendbuffer()
        {
         int i;
         printf("Send contents are:
    ");
         for(i=0;i< sizeofbuffer/4;i++)
         {
          printf("%d	",sendram[i]);
         }
         printf("
    ");
        }
        int main()
        {
         unsigned int status=0;
    
         int rxlen;
            init_platform();
            init_sendbuffer();
    
        init_axi_dma_simple((unsigned int *)AXI_DMA_BASE);
            printf("Hello World
    
    Please input data:");
            while(1)
            {
             scanf("%x",&status);
             printf("Got 0x%x
    ",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;
        }

    测试结果如下:

    image

    下一步修改博主的逻辑到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

    测试结果如下:

    test1

    第二次则:

    test2

    对于以下程序段的理解:

          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

    理解(图):

    IMG_20140618_113109

    重点:经过测试发现,只有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代码段中声明的寄存器值可以一直保留。

  • 相关阅读:
    数据结构和算法(Golang实现)(14)常见数据结构-栈和队列
    数据结构和算法(Golang实现)(20)排序算法-选择排序
    数据结构和算法(Golang实现)(18)排序算法-前言
    数据结构和算法(Golang实现)(22)排序算法-希尔排序
    数据结构和算法(Golang实现)(21)排序算法-插入排序
    数据结构和算法(Golang实现)(27)查找算法-二叉查找树
    关于SpringMVC映射模型视图的几点小事
    关于spring中事务管理的几件小事
    关于spring中AOP的几件小事
    关于spring中bean配置的几件小事
  • 原文地址:https://www.cnblogs.com/shenerguang/p/3793215.html
Copyright © 2011-2022 走看看