Forum Discussion

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

Receive Ethernet Packets on DE-4 board with NIOS II

Hi, :)

I have a DE-4 board to which I would like to receive Ethernet packets from my PC. I have run the example provided with the tutorial (using triple-speed Ethernet on DE-4 boards) and it works as expected. I have got the exact same architecture as specified on that tutorial, with the NIOS II soft processor. But when I remove one end of the Ethernet cable and connect that end to my laptop's Ethernet port, ISR does not seem to be firing (Here I removed the cable on eth0 interface and kept the connection on eth1). I checked traffic on the Ethernet network using Wireshark and packets are sent out from the laptop (mostly broadcasts).

This is what I have got working now. (loopback on eth0)

#include <altera_avalon_sgdma.h>
# include <altera_avalon_sgdma_descriptor.h>
# include <altera_avalon_sgdma_regs.h>
# include "sys/alt_stdio.h"
# include "sys/alt_irq.h"
# include <unistd.h>
// Function Prototypes
void rx_ethernet_isr (void *context);
volatile char *onchip_control = (char *) 0x00000FFF;
volatile char *onchip_data_rx = (char *) 0x00001000;
volatile char *onchip_data_tx = (char *) 0x00008000;
// Global Variables
unsigned int text_length;
// Create a transmit frame
unsigned char tx_frame = {
	0x00,0x00, 						// for 32-bit alignment
	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 	// destination address (broadcast)
	0x01,0x60,0x6E,0x11,0x02,0x0F, 	// source address
	0x03,0xF0, 						// length or type of the payload data
	'\0' 							// payload data (ended with termination character)
};
// Create a receive frame
unsigned char rx_frame = { 0 };
// Create sgdma transmit and receive devices
alt_sgdma_dev * sgdma_tx_dev;
alt_sgdma_dev * sgdma_rx_dev;
// Allocate descriptors in the descriptor_memory (onchip memory)
alt_sgdma_descriptor tx_descriptor		__attribute__ (( section ( ".descriptor_memory" )));
alt_sgdma_descriptor tx_descriptor_end	__attribute__ (( section ( ".descriptor_memory" )));
alt_sgdma_descriptor rx_descriptor  	__attribute__ (( section ( ".descriptor_memory" )));
alt_sgdma_descriptor rx_descriptor_end  __attribute__ (( section ( ".descriptor_memory" )));
/********************************************************************************
 * This program demonstrates use of the Ethernet in the DE4 board.
 *
 * It performs the following:
 *  1. Records input text and transmits the text via Ethernet after Enter is
 *     pressed
 *  2. Displays text received via Ethernet frame on the JTAG UART
********************************************************************************/
int main(void)
{
	// Open the sgdma transmit device
	sgdma_tx_dev = alt_avalon_sgdma_open ("/dev/sgdma_tx");
	if (sgdma_tx_dev == NULL) {
		alt_printf ("Error: could not open scatter-gather dma transmit device\n");
		return -1;
	} else alt_printf ("Opened scatter-gather dma transmit device\n");
	// Open the sgdma receive device
	sgdma_rx_dev = alt_avalon_sgdma_open ("/dev/sgdma_rx");
	if (sgdma_rx_dev == NULL) {
		alt_printf ("Error: could not open scatter-gather dma receive device\n");
		return -1;
	} else alt_printf ("Opened scatter-gather dma receive device\n");
	// Set interrupts for the sgdma receive device
	alt_avalon_sgdma_register_callback( sgdma_rx_dev, (alt_avalon_sgdma_callback) rx_ethernet_isr, 0x00000014, NULL );
	// Create sgdma receive descriptor
	alt_avalon_sgdma_construct_stream_to_mem_desc( &rx_descriptor, &rx_descriptor_end, (alt_u32 *)rx_frame, 0, 0 );
	// Set up non-blocking transfer of sgdma receive descriptor
	alt_avalon_sgdma_do_async_transfer( sgdma_rx_dev, &rx_descriptor );
	// Triple-speed Ethernet MegaCore base address
	volatile int * tse = (int *) 0x00083000; //tse.control_port at Qsys address map
	// Initialize the MAC address
	*(tse + 3) = 0x116E6001;
	*(tse + 4) = 0x00000F02;
	// Specify the addresses of the PHY devices to be accessed through MDIO interface
	*(tse + 0x0F) = 0x10;
	*(tse + 0x10) = 0x00;
	// Write to register 20 of the PHY chip for Ethernet port 0 to set up line loopback
	*(tse + 0xB4) = 0x4000;
	// Set the PCS to operate at SGMII mode	and enable SGMII auto-negotiation
	*(tse + 0x94) = *(tse + 0x94) | 0x0003;
	// Set PHY address for accessing the PHY chip for Ethernet port 1
	*(tse + 0x10) = 0x01;
	// Write to register 16 of the PHY to enable automatic crossover for all modes
	*(tse + 0xB0) = *(tse + 0xB0) | 0x0060;
	// Software reset the PHY chip and wait
	*(tse + 0xA0) = *(tse + 0xA0) | 0x8000;
	while ( *(tse + 0xA0) & 0x8000  )
		;
	// Enable read and write transfers, gigabit Ethernet operation, and CRC forwarding
	*(tse + 2) = *(tse + 2) | 0x0000004B;
	alt_printf( "send> " );
	text_length = 0;
	while (1) {
		char new_char;
		tx_frame = '\0';
		//Read the PCIe received data
		int i;
        while( *onchip_control != 'B' ) ;// polling the control byte
        i = 0;
        while( (new_char = *(onchip_data_tx + i) ) != '\n' ) {
            if (text_length < 1007) {
                // Add the new character to the output text
                if ( new_char >= 'a' && new_char <= 'z' )
                    tx_frame = new_char - 'a' + 'A';
                else if ( new_char >= 'A' && new_char <= 'Z' )
                    tx_frame = new_char - 'A' + 'a';
                else
                    tx_frame = '#';
                text_length++;
                // Maintain the terminal character after the text
                tx_frame = '\0';
            }
            i++;
        }
		 *onchip_control = 'K' ; // keep the control in the board until receive
		// Create transmit sgdma descriptor
		alt_avalon_sgdma_construct_mem_to_stream_desc( &tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 1024, 0, 1, 1, 0 );
		// Set up non-blocking transfer of sgdma transmit descriptor
		alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
		// Wait until transmit descriptor transfer is complete
		while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0)
			;
	}
	return 0;
}
/****************************************************************************************
 * Subroutine to read incoming Ethernet frames
****************************************************************************************/
void rx_ethernet_isr (void *context)
{
	int i;
	// Wait until receive descriptor transfer is complete
	while (alt_avalon_sgdma_check_descriptor_status(&rx_descriptor) != 0)
		;
	// Clear input line before writing
	for (i = 0; i < (6 + text_length); i++) {
		alt_printf( "%c", 0x08 );		 // 0x08 --> backspace
	}
	// Output received text
	alt_printf( "\nreceive> %s\n", rx_frame + 16 );
    while( *onchip_control != 'K' ) ;// polling the control byte
    for (i = 0; i < (6 + text_length); i++) {
    *(onchip_data_rx + i) = rx_frame;
    }
	*onchip_control = 'H' ; // pass the control right to the host PC
	// Reprint current input line after the output
	alt_printf( "\nsend> %s", tx_frame + 16 );
	// Create new receive sgdma descriptor
	alt_avalon_sgdma_construct_stream_to_mem_desc( &rx_descriptor, &rx_descriptor_end, (alt_u32 *)rx_frame, 0, 0 );
	// Set up non-blocking transfer of sgdma receive descriptor
	alt_avalon_sgdma_do_async_transfer( sgdma_rx_dev, &rx_descriptor );
	text_length = 0;
}

How do I change the above to receive Ethernet traffic on DE-4? :( Sorry if this is too simple and thanks a lot in advance!

3 Replies

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

    Sorry for not mentioning this above. I've got the DE-4 connected to a PC through PCIe and what I want to do is get Ethernet traffic on the DE-4 board from my laptop and show the details on the PC.

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

    You need to use the ARP command on your PC to add an entry for your DE board. Normally this is taken care of by the network software in the OS, but since you don't have that you will need to add the entry manually.

    Getting networking going without an OS is tough. It is doable, but I wouldn't have done so unless I was forced. Look into running Linux or an RTOS with networking support. It will be way easier than re-inventing the wheel. Unless this is just a learning exercise you will be time/money ahead if you put in an OS with networking support already in place. Look specifically for support for the networking core and PHY chip you have on your board.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks a lot Galfonz!

    This is for a project at my university. We basically need to get live Ethernet traffic on the DE-4 board. Will look into using an RTOS the way you suggested.

    Again, thanks for the speedy reply. Saved us a lot of time and effort. :D