Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
17 years ago

Fill FIFO with DMA transfers (SOPC)

Hello,

I’m trying to fill a FIFO with DMA. The write side of the FIFO is connected to the Avalon bus:

avs_avalon_fifo_slave_clk > FIFO clk

avs_avalon_fifo_slave_reset > aclr

avs_avalon_fifo_slave_writedata > data

avs_avalon_fifo_slave_write_n > wrreq

avs_avalon_fifo_slave_readyfordata_n > full

The idea is that the FIFO is constantly filled with data and it must never get empty. The FIFO depth is 8192 words. When I start a DMA transfer to the FIFO. I see in signaltab that the FIFO is filled with data. When the FIFO is full a read process starts reading the FIFO. This done a 9 MHz, the write side is clocked at 100 MHz. After some time the FIFO gets empty (not the intention). I thought that by means of DMA transfers, the FIFO could keep full enough. Do I need a bigger FIFO depth (I thought that the used depth would be enough).

To optimize the Avalon bus arbitration for the DMA transfers to the FIFO, I changed the default settings. The DMA controller is connected to the SDRAM. From the DMA controller the Avalon Read Master is connected to the SDRAM, the Avalon Write Master is connected to the FIFO. The Control port of the DMA controller is connected to the NIOS CPU Data Master.

The Arbitration values related to the SDRAM. As the FIFO component requires a high continuous bandwidth the FIFO should have priority over the processor. To set this, I edited the arbitration view in the SOPC editor window by view->arbitration. There you see some values for each bus on each component. The SDRAM lists 3 values. 2 from the NIOS for Data and Code one from the DMA controller. I set 2 for the NIOS busses and 8 for the DMA controller. This results in a 4 times priority access to the DMA controller. But with this Avalon bus arbitration the FIFO still gets empty.

My question is how can I optimize my system, that the DMA transfers keep the FIFO full enough (it never gets empty)?

The code that starts the DMA transactions:

#include <stdio.h>
# include <stddef.h>
# include <stdlib.h>
# include <stdbool.h>
# include "system.h"
# include "sys/alt_dma.h"
# include "sys/alt_cache.h"
# include "alt_types.h"
# include "io.h"
# include "main.h"
# define FRAME_SIZE 0x1000 //(480 * 272)
# define DMA_BUFF_BYTESIZE FRAME_SIZE//(3 * FRAME_SIZE )
volatile int dma_complete = 0;
static void dma_done (void* handle, void* data) { dma_complete = 1; }
int main()
{
  int i;
  int rc;
  //int ret_code = 0;
  int pattern, offset;
  alt_dma_txchan txchan;
  void* data_written;
  bool running = true;
  
  /* Get a couple buffers for the test */
  /* Using the "uncached" version of malloc to avoid cache coherency issues */
  if( (data_written = (void*)alt_uncached_malloc(DMA_BUFF_BYTESIZE)) == NULL )
  {
	printf ("Failed to malloc buffer\n");
	exit (1);	
  }
  
  printf("Size of int: %i\n", (int)sizeof(int));
  printf("Size of frame: %i and data_written in bytes: %i\n", FRAME_SIZE, (int)DMA_BUFF_BYTESIZE);
  /* Fill write buffer with known values */
  for (i = 0, pattern = 1, offset = 0; offset < DMA_BUFF_BYTESIZE; i++, pattern++, offset+=4)
  {
	IOWR_32DIRECT((int)data_written, offset, pattern);
	//printf("Number: %08i offset: 0x%08X pattern: 0x%08X\n", i, offset, pattern);
  }
  printf("+-----------------------------------------+\n");
  printf("| Nios II CPU							 |\n");
  printf("+-----------------------------------------+\n");
  
	// Create the transmit channel
	if ((txchan = alt_dma_txchan_open(PSP_LCD_DMA_NAME)) == NULL)
	{
	  printf ("Failed to open transmit channel\n");
	  exit (1);
	}  
	// Post the transmit request
	if ((rc = alt_dma_txchan_ioctl(txchan, ALT_DMA_TX_ONLY_ON, (void*)PSP_LCD_DMA_BASE)) < 0)
	{
	  printf ("Failed to set ioctl, reason = %i\n", rc);
	  exit (1);
	}
	if ((rc = alt_dma_txchan_ioctl(txchan, ALT_DMA_SET_MODE_32, (void*)PSP_LCD_DMA_BASE)) < 0)
	{
	  printf ("Failed to set ioctl, reason = %i\n", rc);
	  exit (1);
	}   
  printf("DMA test.\n");
  while(running){
	 
	
	// Use DMA to transfer from write buffer to memory under test
	// Post the transmit request
	if ((rc = alt_dma_txchan_send (txchan, data_written, DMA_BUFF_BYTESIZE, (void*)dma_done, NULL)) < 0)
	{
	  printf ("Failed to post transmit request, reason = %i\n", rc);
	  exit (1);
	}
   
	// Wait for the transaction to complete
	printf("Wait DMA complition...\n");
	while( !dma_complete );
	printf("Transaction complete\n");
  }
	if (alt_dma_txchan_close(txchan) < 0 )
	{
	  printf ("Failed to closing transmit channel\n");
	  exit (1);
	}
  printf("+-----------------------------------------+\n");
  printf("| Nios II END							 |\n");
  printf("+-----------------------------------------+\n");
  return 0;
}
No RepliesBe the first to reply