Forum Discussion

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

Reading external data using On-chip FIFO and NIOS II

Hi all,

I'm trying to read a 8-bit ADC with parallel output using NIOS II. I need to read the ADC at 24MHz to capture correct samples. I have been trying a 1K On-Chip FIFO to capture this data. I exported the FIFO in[31..0] signals and the in clock signal but the FIFO doesn't interrupt the NIOS. I attached my QSys File and the Circuit Diagram.

I linked the oscillator clock directly in the fifo_in_clk only for test purposes. The write signal is HIGH when I press a button, also for testing purposes.

Is there any problem in my design? Are the connections in qsys correct?

Can I use PIO directly to do this task (using DMA)?

Thanks

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Have you properly configured the CSR registers to generate the interrupts?

    Are you able to poll the CSR registers and see that data is being pushed onto the FIFO correctly?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I have configured the FIFO this way:

    int init_input_fifo()
    {
    	int code = ALTERA_AVALON_FIFO_OK;
    	code = altera_avalon_fifo_init(0x2001800, // Address
    								   0x3F, 		   // Enable interrupts
    								   1, 	   // Almost empty
    								   1000); 	   // Almost full
    	if (code == ALTERA_AVALON_FIFO_EVENT_CLEAR_ERROR)
    		printf("A\n");
    	else if (code == ALTERA_AVALON_FIFO_IENABLE_WRITE_ERROR)
    		printf("B\n");
    	else if (code == ALTERA_AVALON_FIFO_THRESHOLD_WRITE_ERROR)
    		printf("C\n");
    	//printf("CODE: %d\n", code);
    	printf("ALMOSTEMPTY = %d\n", altera_avalon_fifo_read_almostempty(0x2001800));
    	printf("ALMOSTFULL = %d\n", altera_avalon_fifo_read_almostfull(0x2001800));
    	void* input_fifo_wrclk_irq_event_ptr = (void*) &input_fifo_wrclk_irq_event;
    	alt_irq_register(16, input_fifo_wrclk_irq_event_ptr, handle_input_fifo_wrclk_interrupts);
    	return code;
    }

    The ALMOSTEMPTY and ALMOSTFULL printed in the console are correct. My interrupt:

    static void handle_input_fifo_wrclk_interrupts(void* context, alt_u32 id)
    {
    	volatile int* input_fifo_wrclk_irq_event_ptr = (volatile int*) context;
    	*input_fifo_wrclk_irq_event_ptr = altera_avalon_fifo_read_event(0x2001800, ALTERA_AVALON_FIFO_EVENT_ALL);
    	altera_avalon_fifo_clear_event(0x2001800, ALTERA_AVALON_FIFO_EVENT_ALL);
    	printf("INTERRUPT!!!");
    }

    Thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Are you able to poll the CSR registers and see that data is being pushed onto the FIFO correctly?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I tried

    
    while(1)
    {
        alt_u32 level = altera_avalon_fifo_read_level(0x2001800);
        printf("LEVEL = %d\n", level);
    }
    

    and received "LEVEL = 0" in the polling.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The level register will read as zero if the FIFO is empty or if the FIFO is completely filled. The status register will tell you which case it is.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi ted,

    I changed the ISR scheme from legacy to HAL Scheme. When I press the button the WRITE signal goes HIGH thus generating the interrupt. The interrupt occurs but the status isn't good after pressing the button.

    
    # include "alt_types.h"
    # include "altera_avalon_fifo_util.h"
    # include "altera_avalon_pio_regs.h"
    # include "altera_avalon_fifo_regs.h"
    # include "sys/alt_irq.h"
    # include "system.h"
    # include <stdio.h>
    # include <unistd.h>
    # define IN_CSR_ADDRESS  0x2001800
    # define OUT_CSR_ADDRESS 0x2001820
    # define OUT_ADDRESS     0x2001878
    volatile int edge_capture;
    volatile alt_u8 global; //SDRAM
    volatile int interrupted = 0;
    //static void handle_input_fifo_wrclk_interrupts(void* context, alt_u32 id)
    static void handle_input_fifo_wrclk_interrupts(void* context)
    {
    	volatile int* input_fifo_wrclk_irq_event_ptr = (volatile int*) context;
    	*input_fifo_wrclk_irq_event_ptr = altera_avalon_fifo_read_event(IN_CSR_ADDRESS, ALTERA_AVALON_FIFO_EVENT_ALL);
    	altera_avalon_fifo_clear_event(IN_CSR_ADDRESS, ALTERA_AVALON_FIFO_EVENT_ALL);
    	altera_avalon_fifo_clear_event(OUT_CSR_ADDRESS, ALTERA_AVALON_FIFO_EVENT_ALL);
    	altera_avalon_fifo_clear_event(OUT_ADDRESS, ALTERA_AVALON_FIFO_EVENT_ALL);
    	interrupted = 1;
    }
    volatile int input_fifo_wrclk_irq_event;
    int init_input_fifo()
    {
    	int code = ALTERA_AVALON_FIFO_OK;
    	code = altera_avalon_fifo_init(IN_CSR_ADDRESS,  // Address
    								   0x3F, 	   		// Enable interrupts
    								   500, 	   		// Almost empty
    								   1000); 	   		// Almost full
    	code = altera_avalon_fifo_init(OUT_CSR_ADDRESS, // Address
    								   0x3F, 	  		// Enable interrupts
    								   500, 	  		// Almost empty
    								   1000); 	  		// Almost full
    	printf("ALMOSTEMPTY = %d\n", altera_avalon_fifo_read_almostempty(IN_CSR_ADDRESS));
    	printf("ALMOSTFULL = %d\n", altera_avalon_fifo_read_almostfull(IN_CSR_ADDRESS));
    	printf("STATUS = %d\n", altera_avalon_fifo_read_status(IN_CSR_ADDRESS, ALTERA_AVALON_FIFO_STATUS_REG));
    	void* edge_capture_ptr = (void*) &edge_capture;
    	alt_ic_isr_register(0, 16, handle_input_fifo_wrclk_interrupts, edge_capture_ptr, NULL); //IN_CSR_IRQ
    	alt_ic_isr_register(0, 17, handle_input_fifo_wrclk_interrupts, edge_capture_ptr, NULL); //OUT_CSR_IRQ
    	return code;
    }
    int main(void)
    {
    	init_input_fifo();
        while(1)
        {
        	if (interrupted)
        	{
        		alt_u32 level = altera_avalon_fifo_read_level(0x2001800);
        		printf("LEVEL: %u\n", level);
        		printf("STATUS = %d\n", altera_avalon_fifo_read_status(IN_CSR_ADDRESS, ALTERA_AVALON_FIFO_STATUS_REG));
        		printf("\n");
        		interrupted = 0;
        	}
        }
        return 0;
    }
    

    The output is (BEFORE press the button):

    status = 0

    The output is (AFTER press the button):

    level: 0

    status = 1

    The FIFO seems full (i_status = 1) in the first press and in the first time when I check the "interrupted" flag. How can it occurs? NIOS is running a 100MHz. Is it slow for this application?

    Thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Maybe set your ALMOST_FULL threshold significantly lower?

    If it is a 1024 deep FIFO, and you set the threshold to 1000, then you only have (24) clocks to service the FIFO before it will fill. If you're pushing FIFO data at 24MHz and NIOS is running at 100MHz, then maybe you have around 100 clocks --- which is not a lot of time.