Juan Abelaira
Published

Using CORDIC and DMA on the Ultra96 board

Accelerate trigonometric calculations on hardware by using the classical CORDIC together with DMA

IntermediateFull instructions provided2 hours569
Using CORDIC and DMA on the Ultra96 board

Things used in this project

Hardware components

Ultra96-V2
Tria Technologies Ultra96-V2
×1
FTDI cable
×1

Software apps and online services

Vivado Design Suite
AMD Vivado Design Suite
Vitis Unified Software Platform
AMD Vitis Unified Software Platform

Story

Read more

Code

helloworld.c

C/C++
main software for the CORDIC and DMA project
#include "math.h"
#include "xaxidma.h"
#include "xparameters.h"
#include "xdebug.h"
#include "sleep.h"
#include "stdio.h"

#define DMA_DEV_ID			XPAR_AXIDMA_0_DEVICE_ID
#define DDR_BASE_ADDR		XPAR_PSU_DDR_0_S_AXI_BASEADDR
#define TX_BUFFER_BASE		(DDR_BASE_ADDR + 0x10000000)
#define RX_BUFFER_BASE		(DDR_BASE_ADDR + 0x00000200)

#define VALUE_COUNT				0x20
#define POLL_TIMEOUT_COUNTER    1000000U


#if (!defined(DEBUG))
extern void xil_printf(const char *format, ...);
#endif

int XAxiDma_SendValuesToCordic(u16 DeviceId);

XAxiDma AxiDma;

//*******************************************************************
int main()
{
	int Status;
	xil_printf("Program that sends values to CORDIC using DMA\n");
	xil_printf("and receives results with the same DMA\n\n");

	Status = XAxiDma_SendValuesToCordic(DMA_DEV_ID);

	xil_printf("That was it!\n");

	return XST_SUCCESS;

}

//*****************************************************************************

int XAxiDma_SendValuesToCordic(u16 DeviceId)
{
	XAxiDma_Config *CfgPtr;
	int Status;
	uint16_t i;
	u8 *TxBufferPtr;
	u8 *RxBufferPtr;
	int16_t *TxIntPtr;
	int16_t *RxIntPtr;
	int TimeOut = POLL_TIMEOUT_COUNTER;
	float x, values[VALUE_COUNT];
	//int16_t   ux, uy;
	char	  str1[16], str2[16], str3[16], str4[16];

	TxBufferPtr = (u8 *)TX_BUFFER_BASE ;
	RxBufferPtr = (u8 *)RX_BUFFER_BASE;
	TxIntPtr	= (int16_t*)TX_BUFFER_BASE;
	RxIntPtr	= (int16_t*)RX_BUFFER_BASE;

	// Initialize the XAxiDma device.
	CfgPtr = XAxiDma_LookupConfig(DeviceId);
	if (!CfgPtr) {
		xil_printf("No config found for %d\r\n", DeviceId);
		return XST_FAILURE;
	}

	Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
	if (Status != XST_SUCCESS) {
		xil_printf("Initialization failed %d\r\n", Status);
		return XST_FAILURE;
	}

	if(XAxiDma_HasSg(&AxiDma)){
		xil_printf("Device configured as SG mode \r\n");
		return XST_FAILURE;
	}

	// Disable interrupts
	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA);
	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE);

	// Fill array with angles from -pi/4 to pi/4 and fill Tx area with fix16_13 values
	xil_printf("value no.  angle(rad)  fix16_13\n");
	xil_printf("=================================\n");
	for(i = 0, x = -0.785; i < (VALUE_COUNT); i++) {
		values[i] = x;
		x += (1.57 / ((float)(VALUE_COUNT-1)) );
		TxIntPtr[i] = (int16_t)( x * 8192.0 + 0.5 );
		sprintf(str1, "%+8.6f", x);
		xil_printf("value %2d: %s    0x%08X\n", i+1, str1, TxIntPtr[i]);
	}
	xil_printf("\n");

	// Flush the buffers before the DMA transfer, in case the Data Cache is enabled
	Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, 2*VALUE_COUNT);
	Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, 4*VALUE_COUNT);

	Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr, 4*VALUE_COUNT, XAXIDMA_DEVICE_TO_DMA);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) TxBufferPtr, 2*VALUE_COUNT, XAXIDMA_DMA_TO_DEVICE);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*Wait till transfer is done or 1usec * 10^6 iterations of timeout occurs*/
	while (TimeOut) {
		if (!(XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA)) &&
		!(XAxiDma_Busy(&AxiDma,XAXIDMA_DMA_TO_DEVICE)))
			break;
		TimeOut--;
		usleep(1U);
	}

	xil_printf("Values sent and results received\n\n");
	xil_printf("received data\n\n");
	xil_printf("value no.     cordic_x       cos(a)       cordic_y       sin(a)\n");
	xil_printf("=================================================================\n");
	for(i = 0; i < VALUE_COUNT; i++){
		sprintf(str1, "%+8.6f", ((float)(RxIntPtr[2*i+0]))/16384.0);
		sprintf(str2, "%+8.6f", (cosf( (float)(TxIntPtr[i])/8192.0) ));
		sprintf(str3, "%+8.6f", ((float)(RxIntPtr[2*i+1]))/16384.0);
		sprintf(str4, "%+8.6f", (sinf( (float)(TxIntPtr[i])/8192.0) ));
		xil_printf("value %2i: X> %s sin: %s Y> %s cos: %s\n", i+1, str1, str2, str3, str4);
	}
	return XST_SUCCESS;
}

Credits

Juan Abelaira
7 projects • 19 followers
Electronics engineer focused on FPGA for accelerated computing and ML but with a wide background in electronics design and software design
Contact

Comments

Please log in or sign up to comment.