Introduction

In many of my projects here on Hackster we have examined how we can easily use the programmable logic of a FPGA or SoC for image processing.

We can also use the PL for signal processing applications, indeed seven series and up devices also come with a low speed mixed signal converter in built in the XADC/Sysmon. However we can easily add others using the Pmod or FMC interfacs depending upon our board of choice.

For this example we will start out with a fairly simple board and use the XADC and Pmods.

The XADC/Sysmon allows us to capture and process analogue signals for use in out application.

How we use them depends upon the demands of the application, but some common applications include.

Perform signal processing within the Processing System.

Perform signal processing within the Programmable Logic.

Write the data to a file on the SD card.

Of course in reality we are likely to have a combination of all three. With the high bandwidth processing performed in the PL while the PS can be used to implement higher level decisions based upon the results.

When it comes to processing in the PL ideally once we have implemented our mixed signal converter interfaces we should leverage the power of High Level Synthesis (HLS) and using C or C++ to implement our signal processing algorithms,

In this project we are going to look at how we can create a test bed platform for our signal processing applications. Such that we can add in our own signal processing algorithms as we desire. We will do this for both when we receive the signal and when we generate a signal for output.

We will also look at how we can read and write data to a SD card for future analysis using tools like GNU Octave and Excel.

But First Some Sampling Theory

One of the key things we need to remember when we sample a signal is that of the sampling rate. If we want to capture a signal we need to be able to sample at twice the highest frequency in the signal.

As the XADC samples at 1 Mega Sample Per Second (MSPS) this means the maximum signal we can sample in the XADC is 500 kHZ.

If we try and sample signals above half of the sampling rate this results in aliasing, for this reason many mixed signal converters use Anti Aliasing Filters to prevent unwanted signals being converted.

However, for some applications aliasing can be very useful as it allows us to sample a signal normally in a higher Nyquist zone.

We achieve this by sampling the image (I in the diagram below) of the signal if interest (Fa in the diagram below)

Working across different Nyquist zones is useful for not only ADC but also DAC converters.

Nyquist Zones

Vivado Design

In the Vivado design we are going to include the XADC and the Pmod AD2 and Pmod DA4. However both the Pmods are only driven by application SW over SPI or I2C buses.

Our main input will be the XADC, for this we are going to use its streaming interface into the processor memory space. We will achieve the data movement using the

To use the XADC in its fastest mode we need to use the AXI streaming interface.

Enabling the XADC & AXI Streaming Interface

To correctly transfer the XADC samples into memory we need to use a Subset Converter. This is because the XADC stream output does not assert contain a TLast signal to indicate the end of a data packet. Without this the DMA cannot function correctly. Therefore we configure the subset converter to assert TLast after ever 255 packets of data from the XADC.

This means each DMA transfer will transfer 510 bytes of data to the PS DDR memory.

Setting the TLast Generation

Initial Application SW

to configure the XADC and the DMA, we need to create application SW using SDK. This is straight forward and can be achieved using the code below

SYSConfigPtr = XSysMon_LookupConfig(SYSMON_DEVICE_ID); if (SYSConfigPtr == NULL) { return XST_FAILURE; } CfgPtr = XAxiDma_LookupConfig(DMA_DEV_ID); if (!CfgPtr) { printf("No config found for %d\r

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

", Status); return XST_FAILURE; } XSysMon_CfgInitialize(SysMonInstPtr, SYSConfigPtr, SYSConfigPtr->BaseAddress); XSysMon_SetSequencerMode(SysMonInstPtr, XSM_SEQ_MODE_SAFE); XSysMon_SetAlarmEnables(SysMonInstPtr, 0x0); XSysMon_SetSeqChEnables(SysMonInstPtr, XSM_SEQ_CH_VPVN); XSysMon_SetAdcClkDivisor(SysMonInstPtr, 32); XSysMon_SetSequencerMode(SysMonInstPtr, XSM_SEQ_MODE_CONTINPASS); RxBufferPtr = (u8 *)RX_BUFFER_BASE; addr = (u32)RX_BUFFER_BASE; XAxiDma_Reset(&AxiDma); reset_done = XAxiDma_ResetIsDone(&AxiDma); while(reset_done != 1){ } XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); while(1){ Status = XAxiDma_SimpleTransfer(&AxiDma,(u32) &RX_BUFFER_BASE,MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA); if (Status != XST_SUCCESS) { printf("XFER failed %d\r

", Status); return XST_FAILURE; } while ((XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA))){ /* Wait */ } Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN);

Initial Testing XADC

To test the XADC is working correctly I used the analogue discovery to drive in specific DC values and then confirmed the XADC samples in DDR memory were as expected.

100 mv DC input

I also tested a ramp to ensure the captured data reflected an increasing value, again I checked this in the DDR Memory.

`1 kHz Ramp from 0 to 500 mV

Being satisfied we are reading in from the XADC the next step is to write the software which will log the data to the SD card.

Writing Data to the SD Card

Now we have the data captured in the DDR memory we want to be able to store it in a usable file format on a SD card.

This will allow us to perform offline analysis of the data using a analysis program.

To do this we will be using the Xilinx Fat File System library, we can enable the Library within the BSP configuration.

Enabling the library in the BSP

Once we have enabled this library we need to update our software application to write the file to the SD card.

To ensure we can use the data easily in our offline analysis programs the file will be saved as a CSV file.

static FIL fil; /* File object */ static FATFS fatfs; // Pointer to the filesystem object static char FileName[50] = "XADC.CSV"; static char *SD_File; char buffer[100] ; UINT *ByteRead; FRESULT Res; TCHAR *Path = "0:/"; u32 BuffCnt; Res = f_mount(&fatfs, Path, 0); //0 is the mounting option SD_File = (char *)FileName; Res = f_mount(&fatfs, Path, 0); //0 is the mounting option SD_File = (char *)FileName;

This means that as opposed to the binary values we need to write ASCII values to the file.

We can do this using the sprintf command which creates a correctly formatted ASCII string that we can then write to the file.

Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ); Res = f_lseek(&fil, 0); for(i=0;i<MAX_PKT_LEN/2;i++){ n=sprintf(Buffer, "%d,%04x\r

",i,RX_BUFFER_BASE[i]); Res = f_lseek(&fil, position); //find ext write position Res = f_write(&fil, (const void*)Buffer, Buffer_size,&NumBytesWritten); len = strlen(Buffer); position=position+len; } Res = f_close(&fil);

Offline Analysis

Once we have the file stored on the SD Card we can transfer the card into a PC or Laptop and analyse it using programs such as Octave or Excel.

Lets take a look at Octave first, we can read in the file easily is using the commands below. Once we have read in the file the next stage is to read each of the columns of data and plot them.

gnuplot(sample,data); data = csvread("xadc.csv"); sample = data(:,1) value = data(:,2); plot(sample,data);

For this example I have captured a Sine Wave to ensure we can see the waveform accurately.

Octave Plot of the SineWave

If we do not have Octave, we can also use Excel and read in the CSV file and plot the results.

Reading in the CSV

Using the Text Import Wizard

Once the data has been imported into the Excel I plotted the same sine wave. In this case noise has effected one sample which can be clearly seen on the plot.

Plot from Excel.

Now that we have the Vivado design and software application working we care able to do analysis on the signals.

However, we may also want to look at the

Potential Future Work

Use the lightweight IP Stack to serve the file over the Ethernet.

Use a similar approach to save a image file as a BMP to the SD card.

You can find the files associated with this project here:

https://github.com/ATaylorCEngFIET/Hackster

See previous projects here.

More on on Xilinx using FPGA development weekly at MicroZed Chronicles.