UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Contributor
Contributor
576 Views
Registered: ‎11-10-2017

Is it possible to set internal BRAM values using AXI4 protocol in HLS IP using AXI-Stream protocol?

Hi, I'm developing some HLS IP using AXI-Stream protocol, which have one AXI-Stream input and one AXI-Stream output.

I want to set parameter which is internally used in HLS IP by PS.

First, I use #pragma set interface bram directive and connect AXI Bram Controller and AXI Bram Generator on Vivado. This works fine.

But when my IP needs some parallel access to BRAM,  HLS code function has to have many input arguments, and I have to connect many BRAM controller to my HLS IP. The configurable minimum depth of BRAM seems to be 1024,  but my HLS IP requires only 63 depth for each BRAM.  I think connecting many large BRAMs to my HLS IP is wasting of resource.

 

Then, I tried to set parameter by AXI4. I wrore simple code. This is my code.

#include "/opt/Xilinx/Vivado/2018.2/include/gmp.h" //to pass C/RTL build on Vivado 2018.2
#include "hls_video.h"
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <iostream>
#include <string.h>

void bram_setparam_test(bool mode, int* inputparam,
		hls::stream<ap_axiu<32,1,1,1> >& instream, hls::stream<ap_axiu<32,1,1,1> >& outstream){
#pragma HLS INTERFACE axis port = instream
#pragma HLS INTERFACE axis port = outstream
#pragma HLS INTERFACE s_axilite port = mode
#pragma HLS INTERFACE m_axi port = inputparam offset=slave depth=100
#pragma HLS INTERFACE s_axilite port = mode
#pragma HLS INTERFACE s_axilite port = return
	static int internal_param[100];
#pragma HLS RESOURCE variable=internal_param core=RAM_1P_BRAM
	if(mode == true){
		//AXI4 set parameter mode
		memcpy(internal_param, inputparam, sizeof(int) * 100);
	}else{
		//AXI4-stream MODE
		for(int i = 0; i < 100; i++){
#pragma HLS PIPELINE II=1
			int inval = instream.read().data;
			ap_axiu<32,1,1,1> outval;
			outval.data = inval * internal_param[i];
			outval.last = (i == 99 ? 1 : 0);
			outstream.write(outval);
		}
	}
}

I also wrote some interface layer codes to control my HLS IP by PS.

This is my code.

#include "dma_simple.h"
#include <iostream>

using namespace std;

unsigned int *assignToPhysicalUInt(unsigned long address,unsigned int size){
  int devmem = open("/dev/mem", O_RDWR | O_SYNC);
  off_t PageOffset = (off_t) address % getpagesize();
  off_t PageAddress = (off_t) (address - PageOffset);
  return (unsigned int *) mmap(0, size*sizeof(unsigned int), PROT_READ|PROT_WRITE, MAP_SHARED, devmem, PageAddress);
}


#define INPUT_PARAM 0x06000000
unsigned int* inputparam;

int main(){
  int uio1_fd = open("/dev/uio1", O_RDWR);
  void *hls_regs = mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, uio1_fd, 0);

  int uio2_fd = open("/dev/uio2", O_RDWR);
  void *dma_regs = mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, uio2_fd, 0);
  printf("mmap end\n");
  struct udmabuf intake_buf;
  struct udmabuf outlet_buf;

  if(udmabuf_open(&intake_buf, "udmabuf0") == -1){
    printf("udmabuf_open failed\n");
    exit(1);
  }
  if(udmabuf_open(&outlet_buf, "udmabuf1") == -1){
    printf("udmabuf_open failed\n");
    exit(1);
  }
  inputparam = assignToPhysicalUInt(INPUT_PARAM, 100);
  for(int i = 0; i < 100; i++) inputparam[i] = i*2;
  //set bram input param
  regs_write32(hls_regs + 0x18, (uint32_t)inputparam);
  //set mode input bram (true)
  regs_write32(hls_regs + 0x10, (uint32_t)1);
  //start IP core
  regs_write32(hls_regs, 0x01);
  //wait IP core done
  while(1){
    cout << ".";
    uint32_t read_data = regs_read32(hls_regs);
    bool done = (read_data >> 1) & 0x1;
    if(done) break;
  }
  //set DMA input data
  for(int i = 0; i < 100; i++){
    ((int*) (intake_buf.buf))[i] = i;
  }
  //set stream mode(false)
  regs_write32(hls_regs + 0x10, (uint32_t)0);
  //start IP core
  uint32_t status = regs_read32(hls_regs) & 0x80;
  regs_write32(hls_regs, status | 0x01);
  //setup DMA
  dma_reset(dma_regs);
  regs_write32(hls_regs, 0x81);

  dma_setup(dma_regs, intake_buf.phys_addr, outlet_buf.phys_addr);
  
  dma_outlet_start(dma_regs, 100);
  dma_intake_start(dma_regs, 100);
  dma_wait_irq(dma_regs);
  dma_clear_status(dma_regs);

  for(int i = 0; i < 100; i++){
    int rst = ((int*) (outlet_buf.buf))[i];
    cout << rst << " ";
  }
  cout << endl;

  udmabuf_close(&outlet_buf);
  udmabuf_close(&intake_buf);
  close(uio2_fd);
  close(uio1_fd);
}

 

My interface layer code set parameter by AXI4, and then transfer AXI-stream data by using DMA.

But AXI-stream data transfer does not stop.

 

My question is, Is it originally possible to set internal BRAM values using AXI4 protocol in HLS IP using AXI-Stream protocol?

If it is possible, the reason my design doesn't work correctly is in other part than HLS.

I attached all my interface layer codes and driver codes generated by HLS.

 

Thanks in advanve.

0 Kudos
1 Reply
Scholar u4223374
Scholar
555 Views
Registered: ‎04-26-2015

Re: Is it possible to set internal BRAM values using AXI4 protocol in HLS IP using AXI-Stream protocol?

The normal approach here would be to define inputparam as a fixed-length array (eg. 100 elements), and set its interface mode to s_axilite. Then it'll show up as registers on the interface, so you can write data to it from the CPU. Is there any reason not to do that here?