cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Ari_C
Visitor
Visitor
294 Views
Registered: ‎06-11-2021

Calling to function created in HLS

Jump to solution

I am currently attempting to program an FPGA with a pattern generator IP I developed in Vivado HLS (2019.2.1 specifically). The HLS program has a top level function that creates a static image with a box overlay. Below is the code that shows how my top level function works.

 

#include "video_pattern_generator.h"
#include "ap_axi_sdata.h"
#include "ap_int.h"
#include "hls_stream.h"




/*
 * This function makes a white box at the center of the color bars.
 * @param m_axis_video: the AXI stream
 * @param leftCornerX: the x-coordinate of the left upper corner of the box
 * @param boxDim: the length and width of the square box
 */
void box_overlay(AXI_STREAM& m_axis_video, int leftCornerX, int boxDim) {
	ap_axiu<24, 1, 1, 1> video;
	hls::rgb_8 pixel;

	for (int i = leftCornerX-1; i < (leftCornerX + boxDim); i++) {
		pixel.R = 255;
		pixel.B = 255;
		pixel.G = 255;
		video.data = set_rgb_8_pixel_value(pixel);
		m_axis_video << video;
	}

}
//Top Level Function

void video_pattern_generator(AXI_STREAM& m_axis_video, int leftCornerX, int leftCornerY, int boxDim) {
#pragma HLS INTERFACE axis register both port=m_axis_video
#pragma HLS INTERFACE axis both port=s_axis_video



	ap_axiu<24, 1, 1, 1> video;
	hls::rgb_8 pixel;

	
	//Add code for output video generation here
	// This will create the color bar pattern
	// Lets see if I can make a box appear over the color bars in the center of the screen
	//int boxDim = 50; // The dimensions of the box with be boxDim x boxDim

	// x and y coordinates for left corner of box
	//int leftCornerX = 375;
	//int leftCornerY = 275;

	for (int i = 0; i < HEIGHT; i++) {
		int j = 0;
		for (; j < WIDTH/8; j++) {
			// Start of frame, assert tuser
			if((i==0)&&(j==0)) {
				video.user=1;
			} else {
				video.user=0;
			}
			//End of line, assert tlast
			if (j==WIDTH-1) {
				video.last = 1;
			} else {
				video.last = 0;
			}
			if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
				box_overlay(m_axis_video, leftCornerX, boxDim);
				j = leftCornerX + boxDim ;
			} else {
				pixel.R = 255;
				pixel.B = 255;
				pixel.G = 255;
				video.data = set_rgb_8_pixel_value(pixel);
				m_axis_video << video;
			}
		}
		for (;j < WIDTH/4; j++) {
			// Start of frame, assert tuser
						if((i==0)&&(j==0)) {
							video.user=1;
						} else {
							video.user=0;
						}
						//End of line, assert tlast
						if (j==WIDTH-1) {
							video.last = 1;
						} else {
							video.last = 0;
						}
						if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
							box_overlay(m_axis_video, leftCornerX, boxDim);
							j = leftCornerX + boxDim;
						} else {
						pixel.R = 255;
						pixel.B = 0;
						pixel.G = 255;
						video.data = set_rgb_8_pixel_value(pixel);
						m_axis_video << video;
						}
		}
		for (;j < 3*WIDTH/8; j++) {
			// Start of frame, assert tuser
						if((i==0)&&(j==0)) {
							video.user=1;
						} else {
							video.user=0;
						}
						//End of line, assert tlast
						if (j==WIDTH-1) {
							video.last = 1;
						} else {
							video.last = 0;
						}
						if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
							box_overlay(m_axis_video, leftCornerX, boxDim);
							j = leftCornerX + boxDim ;
						} else {
						pixel.R = 0;
						pixel.B = 255;
						pixel.G = 255;
						video.data = set_rgb_8_pixel_value(pixel);
						m_axis_video << video;
						}
		}
		for (;j < WIDTH/2; j++) {
			// Start of frame, assert tuser
						if((i==0)&&(j==0)) {
							video.user=1;
						} else {
							video.user=0;
						}
						//End of line, assert tlast
						if (j==WIDTH-1) {
							video.last = 1;
						} else {
							video.last = 0;
						}
						if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
							box_overlay(m_axis_video, leftCornerX, boxDim);
							j = leftCornerX + boxDim ;
						} else {
						pixel.R = 0;
						pixel.B = 0;
						pixel.G = 255;
						video.data = set_rgb_8_pixel_value(pixel);
						m_axis_video << video;
						}
		}
		for (;j < 5*WIDTH/8; j++) {
			// Start of frame, assert tuser
						if((i==0)&&(j==0)) {
							video.user=1;
						} else {
							video.user=0;
						}
						//End of line, assert tlast
						if (j==WIDTH-1) {
							video.last = 1;
						} else {
							video.last = 0;
						}
						if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
							box_overlay(m_axis_video, leftCornerX, boxDim);
							j = leftCornerX + boxDim ;
						} else {
						pixel.R = 255;
						pixel.B = 255;
						pixel.G = 0;
						video.data = set_rgb_8_pixel_value(pixel);
						m_axis_video << video;
						}
		}
		for (;j < 3*WIDTH/4; j++) {
			// Start of frame, assert tuser
						if((i==0)&&(j==0)) {
							video.user=1;
						} else {
							video.user=0;
						}
						//End of line, assert tlast
						if (j==WIDTH-1) {
							video.last = 1;
						} else {
							video.last = 0;
						}
						if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
							box_overlay(m_axis_video, leftCornerX, boxDim);
							j = leftCornerX + boxDim ;
						} else {
						pixel.R = 255;
						pixel.B = 0;
						pixel.G = 0;
						video.data = set_rgb_8_pixel_value(pixel);
						m_axis_video << video;
						}
		}
		for (;j < 7*WIDTH/8; j++) {
			// Start of frame, assert tuser
						if((i==0)&&(j==0)) {
							video.user=1;
						} else {
							video.user=0;
						}
						//End of line, assert tlast
						if (j==WIDTH-1) {
							video.last = 1;
						} else {
							video.last = 0;
						}
						if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
							box_overlay(m_axis_video, leftCornerX, boxDim);
							j = leftCornerX + boxDim ;
						} else {
						pixel.R = 0;
						pixel.B = 255;
						pixel.G = 0;
						video.data = set_rgb_8_pixel_value(pixel);
						m_axis_video << video;
						}
		}
		for (;j < WIDTH; j++) {
			// Start of frame, assert tuser
						if((i==0)&&(j==0)) {
							video.user=1;
						} else {
							video.user=0;
						}
						//End of line, assert tlast
						if (j==WIDTH-1) {
							video.last = 1;
						} else {
							video.last = 0;
						}
						if ((i > leftCornerY-1 && i < leftCornerY + boxDim) && (j >= leftCornerX && j < leftCornerX + boxDim)) {
							box_overlay(m_axis_video, leftCornerX, boxDim);
							j = leftCornerX + boxDim ;
						} else {
						pixel.R = 0;
						pixel.B = 0;
						pixel.G = 0;
						video.data = set_rgb_8_pixel_value(pixel);
						m_axis_video << video;
						}
		}
	}
	//parameters for second box overlay
	//int overlayX = 0;
	//int overlayY = 0;
	//int overlayDim = 50;
	// print second box
	//another_overlay(m_axis_video, overlayX, overlayY, overlayDim);


}

ap_uint<24> set_rgb_8_pixel_value(hls::rgb_8 pixel) {
	ap_uint<24> pixel_out;

	pixel_out = (pixel.R << 16) + (pixel.B <<  + pixel.G;
	return pixel_out;
}

 

I have created a block design in Vivado and now I am in Vitis trying to get the image to generate on a monitor using the FPGA. To do this, I have been calling to my top level function I created in HLS but trying to include the header function causes errors so I am not sure if this is correct. If it is, I do not know how to call to the top-level function in Vitis as it has several input parameters and I am not sure if I have to define them myself in the Vitis program. Below is the program I have made in Vitis. 

 

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "video_pattern_generator.h" // Header file (causes errors if included)

int main(){
    init_platform();

    print("Hello World\n\r");
    print("Starting TPG!");
   // video_pattern_generator(); // where do i get the input parameters?


    cleanup_platform();
    return 0;
}

I have been stuck for a week just trying to get this program to work so any help would be appreciated. 

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
Ari_C
Visitor
Visitor
227 Views
Registered: ‎06-11-2021

I ended up answering my own question, so I am putting the answer here in case anyone in the future wants to know. I was including the wrong header file. In the hardware specification's include file, there is a generated API for the IP used in the block design. This is the file that needs to be included. This header file also shows all the functions for the IP block that are available. With these functions I was able to initialize the TPG I made and run the program properly.

/*
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xvideo_pattern_generator.h"

XVideo_pattern_generator xvpg_inst;
int Status;
int main(){
    init_platform();

    print("Hello World!\n\r");

    /* TPG Initialization */
   Status = XVideo_pattern_generator_Initialize(&xvpg_inst, XPAR_XSDPS_0_DEVICE_ID);
   if(Status != XST_SUCCESS) {
	   xil_printf("TPG configuration failed\r\n");
	   return(XST_FAILURE);
   }

    XVideo_pattern_generator_EnableAutoRestart(&xvpg_inst);
    XVideo_pattern_generator_Start(&xvpg_inst);

    xil_printf("Starting TPG!\r\n");



    cleanup_platform();
    return 0;
}

View solution in original post

0 Kudos
1 Reply
Ari_C
Visitor
Visitor
228 Views
Registered: ‎06-11-2021

I ended up answering my own question, so I am putting the answer here in case anyone in the future wants to know. I was including the wrong header file. In the hardware specification's include file, there is a generated API for the IP used in the block design. This is the file that needs to be included. This header file also shows all the functions for the IP block that are available. With these functions I was able to initialize the TPG I made and run the program properly.

/*
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xvideo_pattern_generator.h"

XVideo_pattern_generator xvpg_inst;
int Status;
int main(){
    init_platform();

    print("Hello World!\n\r");

    /* TPG Initialization */
   Status = XVideo_pattern_generator_Initialize(&xvpg_inst, XPAR_XSDPS_0_DEVICE_ID);
   if(Status != XST_SUCCESS) {
	   xil_printf("TPG configuration failed\r\n");
	   return(XST_FAILURE);
   }

    XVideo_pattern_generator_EnableAutoRestart(&xvpg_inst);
    XVideo_pattern_generator_Start(&xvpg_inst);

    xil_printf("Starting TPG!\r\n");



    cleanup_platform();
    return 0;
}

View solution in original post

0 Kudos