Showing results for 
Show  only  | Search instead for 
Did you mean: 
Registered: ‎04-16-2017

DMA transferring count up number skips some values after a certain amount of transfers



I want to design containing DMA which transfers continuous ADC values. To achieve this purpose, I have tried some DMA samples like

and these have worked fine.


And now, I have designed an IP block containing a 12-bit counter, that never stops counting and just wraps around. It’s connected to tlast_gen IP that creates tlast and converts to 32-bit width AXI4-Stream of count values. (Later the 12-bit counter will be replaced by data from an AD converter.) 


My tlast_gen IP is nearly identical to “original” tlast_gen IP which is contained in 3rd of above example. (A difference between mine and original is only data width.)


Then I consulted this forum below.


According to this forum, for continuous data transfer, I should use an asynchronous FIFO.


Therefore I inserted AXI4-Stream Data FIFO in asynchronous mode between the tlast_gen and a DMA.


I just want to stream the values to a DDR memory to a circular buffer continuously, and then transfer the data over UART or something.


So the data flow is counter -> tlast_gen -> FIFO -> DMA -> DDR3 -> UART -> PC.


For the purpose of checking any missing count values, I just let the counter “count” always and check.


The block diagram and software is shown below.


block diagram 2017-04-17 8.02.52.png

// Includes
#include <stdio.h>
#include <stdlib.h>
#include "platform.h"
#include "xuartps_hw.h"
#include "xil_cache.h"
#include "adc.h"
#include "dac.h"

// Defines
#define SAMPLES_PER_FRAME  1000
//#define SAMPLES_PER_FRAME  500
#define DATA_CORRECT       0
#define DATA_INCORRECT    -1

#define DATA_FREQ_DEV 32

// Function prototypes
void process_data(int samples_per_frame, int* dst, int* src);
int verify_data(int* src, int ii, int samples_per_frame);

// Main entry point
int main()
	// Local variables
	int     status;
	int     ii = 0;
	adc_t*  p_adc_inst;
	/*short*/ int     rcv_buf[SAMPLES_PER_FRAME];

	// Setup UART and caches
    xil_printf("\fHello World!\n\r");

    // Create ADC object
    p_adc_inst = adc_create
    if (p_adc_inst == NULL)
    	xil_printf("ERROR! Failed to create ADC instance.\n\r");
    	return -1;

    // Set the desired parameters for the ADC/DAC objects
    adc_set_bytes_per_sample(p_adc_inst, sizeof(/*short*/int));
    adc_set_samples_per_frame(p_adc_inst, SAMPLES_PER_FRAME);

	// Make sure the buffers are clear before we populate it (generally don't need to do this, but for proving the DMA working, we do it anyway)
	memset(rcv_buf, 0, SAMPLES_PER_FRAME*sizeof(/*short*/int));

	// Enable/initialize and dac

	// Process data
	xil_printf("Starting data processing...\n\r");
	int jj  = 0;
	for (ii = 0; 1; ii++)

		// Get new frame from ADC
		status = adc_get_frame(p_adc_inst, rcv_buf);
		if (status != ADC_SUCCESS)
			xil_printf("ERROR! Failed to get a new frame of data from the ADC.\n\r");
			return -1;

		// *********************** Insert your code here ***********************
        /* for continuous transfer of number */
		/*for (jj = 0; jj < SAMPLES_PER_FRAME; jj++){
			xil_printf("Sequence No. %d, Recieving Data: %d\n\r", jj, rcv_buf[jj]);
			//xil_printf("%d\n\r", rcv_buf[jj]);
        /* for checking transfer */
		status = verify_data(rcv_buf, ii, SAMPLES_PER_FRAME);
		if (status == -1){
			xil_printf("ERROR: unvalid data.\n\r");
			xil_printf("Frame: %d\n\r", ii);

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



    return 0;

void process_data(int samples_per_frame, int* dst, int* src)
	// Local variables
	int ii = 0;

	// Do something to the data
	for (ii = 0; ii < samples_per_frame; ii++)
		dst[ii] = src[ii]*2;

int verify_data(int* src, int ii, int samples_per_frame)
	int i = 0;
	for (i = 0; i < samples_per_frame; i++){
		if (i != 0){
			if (src[i] != 0){
				if(src[i] != src[i - 1] + 1){
					xil_printf("Sequence No. %d, Recieving Data: %d\n\r", i - 1, src[i - 1]);
					xil_printf("Sequence No. %d, Recieving Data: %d\n\r", i, src[i]);
					return -1;
			else if (src[i - 1] != 4095){
				xil_printf("Sequence No. %d, Recieving Data: %d\n\r", i - 1, src[i - 1]);
				xil_printf("Sequence No. %d, Recieving Data: %d\n\r", i, src[i]);
				return -1;
	return 0;

 When the software checks count value, after a certain amount of transfers, DMA skips the count numbers like 1002 -> 1003 -> 1004 -> 751.


 The amount that makes DMA skipping the numbers (described as "Total transfer data" in table below) seems to depend on a depth of AXI4-Stream Data FIFO and SAMPLES_PER_FRAME in software.




I think the problem happens in FIFO but I can't solve it.


Q. How to make DMA keeping continuous transfer?


Tags (2)
0 Kudos
2 Replies
Xilinx Employee
Xilinx Employee
Registered: ‎08-02-2011

Your approach is exactly what I would be doing as well. I think it is good.

The problem that you are trying to solve with the fifo is this: You have to periodically re-program the DMA after one transfer ends. This time period between the end of the last transfer and the start of the next (i.e. after the DMA has been re-programmed by the processor) will result in tready being low for some number of clock cycles (if I recall correctly, its on the order of a hundred or so cycles. Of course, that depends on a lot of factors). The FIFO is inserted to absorb those cycles where tready is deasserted because otherwise you'll drop samples.

If I were you, I'd use an ILA to probe the following signals/interfaces to see where you're losing data:
- FIFO Write side AXIS
- FIFO Read side/DMA S2MM AXIS
- FIFO over/underflow flags
- DMA AXI Lite interface
0 Kudos
Registered: ‎04-16-2017


Thank you for your reply, bwiec.

and sorry for my late reply.


I have tried to follow signals/interfaces using ILA before and after running software for each.


Before running the software, system resets which are active low signals were negated.


So all of count value was “0”.


But curiously, a data_count signal of FIFO was 0x00000002.


After running the software, system resets were asserted so the counts started.


The count value from counter worked fine and the FIFO Write side AXIS value was correctly counted.


However, FIFO Read side/DMA S2MM AXIS value was stopped counting up.


In “FIFOread_after.png” which is attached in this reply, it stopped counting at a value of “00000684”.


Additionally, TLAST signal had never asserted though my pkt_length (SAMPLES_PER_FRAME) is set to 1000 and ILA follow 8192 data point.


I think it caused this problem but a source code seems not to have any mistakes.


In the DMA AXI LITE Interface, after running the software, a write address was set to 0x034 and a write data was 0x00015003.


If my understanding  was correct, this address indicates the status register.


In spite of it, AXI_RDATA was 0x00000000 and AXI_WDATA was 0x00015003. Was it correct?


I couldn’t identify the cause of this problem.


Did I misunderstand some of this DMA system?


スクリーンショット 2017-04-19 18.25.18.png


Screenshot from 2017-04-19 16-54-21.png


Screenshot from 2017-04-19 16-54-57.png


Screenshot from 2017-04-19 16-55-20.png


Screenshot from 2017-04-19 16-55-39.png


Screenshot from 2017-04-19 17-00-09.png


Screenshot from 2017-04-19 17-00-23.png


Screenshot from 2017-04-19 17-21-59.png


Screenshot from 2017-04-19 17-22-26.png


If it’s not preferred to post such a lot of pictures, sorry.






0 Kudos