Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12590 Discussions

Gigabit Ethernet Interface (via Marvell 88E1111) with Cyclone IVE FPGA

Altera_Forum
Honored Contributor II
4,927 Views

Hello Everybody, 

 

I am using Altera DE2-115 Board (CyloneIVE device) and want to connect some other device running in Gbps via its Gigabit Ethernet Transceiver (Marvell 88E1111) interface. 

 

Can I get some idea about how can I proceed for this project? 

 

If some body have already done this project, then please contact me at sceneryofnature@gmail.com

 

_regards 

Sheikh
0 Kudos
37 Replies
Altera_Forum
Honored Contributor II
375 Views

Hi Daixiwen, 

I increased the frame length from 62 to 1480 and Speed I am getting is 760 Mbps, quite good! (Which shows in the networking of Task Manager of my PC). But this frame is raw and yet to add IP Header and UDP Header to the frame by modifying the C program code. 

I am wondering how I can modify this C program (available in previous attachment) to achieve this. 

I am also wondering if this speed (760 Mbps) drops too much after adding IP Header and UDP Header. I think may be little but not too much. Isn't it? 

 

one more thing, if I integrate this ethernet port with FPGA (Lets say giving input to ethernet port from FPGA after doing some processing on A/D converter output), will it still be compatible? I mean it doesn't affect in the current speed?
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Oh yes I didn't notice in your code that you used the DMA driver directly and wasn't using a TCP/IP stack at all. 

Indeed if you want to generate a correct UDP packet you will need to add the headers. 

I suggest to change the length "0x00,0x2E" to an IP EtherType ("0x08, 0x00") so that you don't have to worry about the frame size and your packet is recognized as an IP packet. 

Then instead of just the payload, you will need to put 20 bytes for the IP header and 4 or 8 more bytes for the UDP header. You can find the header definitions on Wikipedia: 

https://en.wikipedia.org/wiki/internet_protocol_version_4#packet_structure https://en.wikipedia.org/wiki/user_datagram_protocol#packet_structure
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Hi, 

 

The ethernet transmit frame after changing the original code to ether type IP is: 

 

unsigned char tx_frame[1024] = {  

0x00,0x00, // for 32-bit alignment 

0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // destination address (broadcast) 

0x01,0x60,0x6E,0x11,0x02,0x0F, // source address 

0x08,0x00, // length or type of the payload data  

'\0' // payload data (ended with termination character) 

}; 

 

 

According to some internet source: 

 

// The packet length# define PCKT_LEN 1024 

 

 

// The IP header's structure 

struct ipheader { 

unsigned char iph_ihl:5, iph_ver:4; 

unsigned char iph_tos; 

unsigned short int iph_len; 

unsigned short int iph_ident; 

unsigned char iph_flag; 

unsigned short int iph_offset; 

unsigned char iph_ttl; 

unsigned char iph_protocol; 

unsigned short int iph_chksum; 

unsigned int iph_sourceip; 

unsigned int iph_destip; 

}; 

 

// UDP header's structure 

struct udpheader { 

unsigned short int udph_srcport; 

unsigned short int udph_destport; 

unsigned short int udph_len; 

unsigned short int udph_chksum; 

}; 

 

// The checksum 

 

unsigned short csum(unsigned short *buf, int nwords) 

{ // 

unsigned long sum; 

for(sum=0; nwords>0; nwords--) 

sum += *buf++; 

sum = (sum >> 16) + (sum &0xffff); 

sum += (sum >> 16); 

return (unsigned short)(~sum); 

 

 

char buffer[PCKT_LEN]; 

 

// Our own headers' structures 

struct ipheader *ip;  

struct udpheader *udp; 

 

// Fabricate the IP header or we can use the 

// standard header structures but assign our own values. 

ip->iph_ihl = 5; 

ip->iph_ver = 4; 

ip->iph_tos = 16; // Low delay 

ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader); 

//ip->iph_ident = htons(54321); 

ip->iph_ident = 54321; 

ip->iph_ttl = 64; // hops 

ip->iph_protocol = 17; // UDP 

// Source IP address, can use spoofed address here!!! 

ip->iph_sourceip = 0xa074; 

// The destination IP address 

ip->iph_destip = 0xa073; 

 

// Fabricate the UDP header. Source port number, redundant 

udp->udph_srcport = 0x80; 

// Destination port number 

udp->udph_destport = 0x70; 

udp->udph_len = sizeof(struct udpheader); 

// Calculate the checksum for integrity 

ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader)); 

 

memcpy(buffer,&ip, sizeof(ip)); 

memcpy((buffer+ sizeof(ip)),&udp, sizeof(udp)); 

 

 

Now I am wondering how I can add this IP and UDP header to the raw data. I mean there is no any socket number or something like that. So where I have to map the variable buffer now? 

 

Is it to change some parameters here(below) in original code? If yes, how? If not what is alternative? 

 

// Create transmit sgdma descriptor 

alt_avalon_sgdma_construct_mem_to_stream_desc( &tx_descriptor, &tx_descriptor_end, tx_frame, 1480, 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; 

}
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Before filling up your IP and UDP header structures, you need to be sure that they point to the correct part of your buffer in tx_frame. ip should point to the area just after the Ethernet header that you already filled, and udp should point just after ip. Then your packet data should follow. Something like this: ( top level) # define ETH_HEADER_SIZE 16 // 14 for the Ethernet header, + 2 for the 32-bit alignment packing bytes ( in your function, just after the struct ipheader *ip; and struct udpheader *udp; lines) ip = (struct ipheader*)(tx_frame + ETH_HEADER_SIZE); udp = (struct udpheader*)(tx_frame + ETH_HEADER_SIZE + sizeof(struct ipheader)); and write your data starting at tx_frame + ETH_HEADER_SIZE + sizeof(struct ipheader) + sizeof(struct udpheader) 

 

You can set the destination port number in the udpheader structure (udph_destport)
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Hi Daixiwen, 

 

Here I just want to add IP and UDP header on the Raw Ethernet frame. The Ethernet is working at 760 Mbps with Raw data. 

 

I edited the code as you suggested but not getting the desired result.  

 

Could you please have a look on the code (attachment) to find where is the mistake?
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

There are several things I see in your code:[list][*]all the fields in the header must be big endian, but the Nios II CPU is little endian. There is no change for byte fields, but for 16-bit words fields (such as ident and len) you must use the htons() function[*]the iph_chksum is only the checksum of the IP header, and shouldn't include the UDP header[*]You calculate the checksum on the "buffer" table before you copy the data to it[/list]further more, most of the current PC hardware has some network offloading, which means that malformed packets (especially IP packets with bad checksums) will be dropped by the network card before it has a chance to reach Wireshark. This means that if you send packets with bad checksums, you will probably never see them and think that nothing has been sent. Check in the driver options if you can disable IP/UDP/TCP hardware checksum verification. I know you can do this on some Intel cards. If not, check if you have an old low-cost network card that you could use in your PC instead, maybe it will work better at accepting anything ;)

0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Hi, 

I need one information. 

There are two ways to program FPGA for Hardware: 

1. JTAG (Temporary) 

2. Active Serial (Permanent) 

 

In this ethernet case, If I run some application program written in C language (Software) using NIOS ii Eclipse on this generated hardware, How I can load this application software program on FPGA permanently? 

This is clear to me that: 

1. For Hardware programming: Choose Active Serial 

2. But for Software: ???? I mean as long as I am connected to the FPGA board with NIOSII Eclipse via USB Blaster, it works but when I quit NIOSII Eclipse, it will no works anymore. Is there anyway to load also this application program software to the FPGA permanently alongside the Hardware. So that both Hardware and software work independently on the FPGA board regardless of whether they are connected to Quartus II and NIOS ii Eclipse or not. 

 

I am sorry if my question is so obvious.
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

If the EPCS is the only flash you have on the board, you can boot from it if you have enough space left in it. 

 

http://www.altera.com/literature/an/an458.pdf
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Hi, 

I am following the tutorial "using Triple speed Ethernet" and programmable file it generated is ...._time_limited.sof. I am able to run it on the board via JTAG. Now, I wanted to flash the board in Active serial mode and getting following popup window:  

some devices in current device list cannot be added to selected programming mode active serial programming? do you want to clear all devices in current device list and switch to selected mode. 

 

Beside this, there is also no .pof file generated to flash the board in active serial mode. 

 

I know this is some kind of licence limitation. 

 

I would like to flash the board with Hardware configuration file(.pof) and run application software program(C file) on it in active serial mode (standalone mode) to fulfill complete Gigabit Ethernet Implementation. 

 

My question is: 

Which licence is exactly needed and how much approximately does it cost?
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

When you compile the project, in the report go to Analysis & Synthesis > IP Cores Summary, and you will see a list of all the licensed IPs. That way you can see which ones you need. 

You'll probably need at least the TSE core for Ethernet, the Nios CPU if you aren't using the /e version, and maybe a memory controller. 

For the prices you should contact your local distributor for a proposal. In some cases they have packages with licenses for several IPs at a reduced price.
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Hi, 

In IP core summary, it shows NIOSII Processor and Triple speed Ethernet with license type: OpenCorePlus and other components licence type: N/A. 

 

With the DE2-115 board, Quartus II DVD is also delivered Which contain Megacore IP LIbrary. I think those required IP could be available in this DVD. 

Is it true that the licence for this Megacore IP Library delivered with the board expires after 1 year?? 

 

Actually, I am using QuartusII 12.1 Web edition but not the one delivered with the board as it is older version (Quartus II v10.0).  

 

Probably I have to switch to this older but Subscription edition Quartus to use the feature of IP library. Does this older version (Quartus II v10.0) also support Tripple speed ethernet? 

or  

Is it also possible to implement Gigabit Ethernet completely in Hardware? I mean to write the complete VHDL code for both the system and application running on it? I mean not using any software like C/C++.
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Quartus 10 supports TSE. 

 

Implementing the complete Ethernet protocol in VHDL is possible but will take time. Alternatively you can have a look at the Ethernet MAC available at Opencores, or buy the license for the TSE ($500 per year if I remember correctly).
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Because people often want to use a NIOS along side the Ethernet, it sometimes makes sense to purchase the IPS-EMBEDDED bundle: 

http://www.altera.com/devices/processor/nios2/ipsuite/ni2-ip-suite.html 

 

As far as licensing terms go, every IP we have purchased has had perpetual use with 1 year of updates. 

 

Regarding doing everything in HDL, see the UDP Offload example: 

http://www.alterawiki.com/wiki/nios_ii_udp_offload_example 

You can start with a scheme like that and then hardcode / trim down everything to get rid of the NIOS + software if you are working with a closed system (e.g. you just want a point-to-point link to broadcast/receive streaming data between two boards using Ethernet as the transport).
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

 

--- Quote Start ---  

 

e.g. you just want a point-to-point link to broadcast/receive streaming data between two boards using Ethernet as the transport. 

--- Quote End ---  

 

 

Yes, I just want a point-to-point link to broadcast/receive streaming data from FPGA board to another device (lets say PC at the beginning) using Ethernet as the transport and Speed should be like 500 Mbps at least. 

 

I read the link you have provided, but how can I trim down NIOS and software part from it for my purpose?
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

My suggestion would be to get it all working with your new IP and with the NIOS in place, and then later work on removing the NIOS (i.e. leave the NIOS there as a short term debug aid). Removing the NIOS is basically going to boil down to hardcoding most/all of the initialization/setup tasks that it performs (PHY, TSE, new IP blocks).

0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Hi, 

This means better is to buy IP cores. 

 

Anyway, i would like to modify the tutorial but first I didn't understand completely the application program written in C. 

I didn't understand which values are assigned to pointer *tse and how the address of pointer is incremented below? 

// Triple-speed Ethernet MegaCore base address 

volatile int *tse =(int *) 0x00102000; 

// 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 = 0x11; 

// Write to register 20 of the PHY chip for Ethernet port 0 to set up line loopback 

*(tse + 0x94) = 0x4000; 

// Write to register 16 of the PHY chip for Ethernet port 1 to enable automatic crossover for all modes 

*(tse + 0xB0) = *(tse + 0xB0) | 0x0060; 

// Write to register 20 of the PHY chip for Ethernet port 2 to set up delay for input/output clk 

*(tse + 0xB4) = *(tse + 0xB4) | 0x0082; 

// Software reset the second 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; 

 

can anybody please clarify me?
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

Those are the TSE's configuration registers. You'll find a list in the datasheet here: http://www.altera.com/literature/ug/ug_ethernet.pdf 

By the way this is a bad way of doing it. The TSE's base address and the register numbers are hard coded in the source code, which makes it difficult to read and maintain. 

I'd recommend instead to include the <system.h> file, which should include a TSE_BASE (if your TSE component is called "tse" in your project) definition with the base address to use instead of the hard coded 0x00102000. 

Then if you include the <triple_speed_ethernet_regs.h> file you will find a np_tse_mac structure that you can use to access all the configuration registers. Just replace the first line with something like np_tse_mac *tse = (np_tse_mac*) TSE_BASE; and then use tse->xxx to access the different registers.
0 Kudos
Reply