Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Ethernet #97

Open
sy2002 opened this issue Aug 29, 2020 · 4 comments
Open

Add support for Ethernet #97

sy2002 opened this issue Aug 29, 2020 · 4 comments
Assignees
Labels

Comments

@sy2002
Copy link
Owner

sy2002 commented Aug 29, 2020

Add support for Ethernet: The first goal is to have an alternative to the serial connection to transfer data between a host computer and the QNICE-FPGA.

The MEGA65 consumer version for example is not having a serial port that is easily available for end users (you can have a JTAG based serial port though). So Ethernet would be really fine here.

@sy2002
Copy link
Owner Author

sy2002 commented Aug 30, 2020

For V1.7: The "simple" version as Michael described in #95 (comment)

@MJoergen
Copy link
Collaborator

As I already have a working Ethernet solution in a different project, I propose the following "simple" design for the QNICE (based on the other project I made), which can be made ready in just a few calendar weeks.

The Ethernet hardware module will take care of FCS (the 32-bit CRC), and will check the FCS (and strip it away) on the Rx path, and will append a correct FCS on the Tx path.

The frames will contain the 14 byte MAC header, 20 byte IP header, as well as any other headers.

The Ethernet module will not do any additional checksum validation and/or calculation. Nor will it do any MAC address filtering.

Register Map

0 : Rx address
1 : Rx data
2 : Rx control and length
3 : Rx good frames
4 : Rx overflow errors
5 : Rx CRC errors
6 : Reserved
7 : Reserved

8 : Tx address
9 : Tx data
A : Tx control and length
B : Tx good frames
C : Reserved
D : Reserved
E : Reserved
F : Reserved

Buffer access

The Rx and Tx path will operate in similar way, but completely independent of each other.

The register address is an offset into a word-based buffer. The register data is the 16-bit value at the specified offset. In this way the CPU accesses the Ethernet frame one word at a time (little-endian). This means the first byte in the frame is in bits 7-0 and the second byte in the frame is in bits 15-8.

Each buffer is 1k words in size, i.e. 2 kbytes, which is larger than the maximum Ethernet frame size of 1514 bytes.

Buffer control

Each buffer (Rx and Tx) has an associated "ownership" bit. A zero indicates the buffer is owned and controlled by the CPU, while a one indicates the buffer is owned and controlled by the Ethernet module. Ownership can only be given away, not taken.

To receive frames, the CPU must first give ownership to the Ethernet module by setting bit 15 of the Rx control register. When an Ethernet frame is received with errors, the frame data is copied to the Rx buffer, and the Ethernet module sets the length of the frame in the Rx control register and clears bit 15, thereby granting ownership to the CPU. No more frames can be received as long as the CPU has ownership. When the CPU is finished with the frame the CPU again grants ownership to the Ethernet module by setting bit 15.

A similar process happens during transmit. Initially, the Tx path is idle. When the CPU wants to send a frame, the CPU must copy the data to the Tx buffer, write the length to the Tx control register and set bit 15. This grants ownership to the Ethernet module, which transmits the frame. While this is happening, the CPU is not allowed to write to the Tx buffer. When the frame is sent,
the Ethernet module automatically clears bit 15, thereby granting ownership back to the CPU.

Possible optimizations

Since the Ethernet works at a rate of 100 Mbit/s, this corresponds to 8 CPU clock cycles per word (assuming 50 MHz CPU clock), and even more when the CPU speed increases.

To increase throughput and avoid the CPU idling, it is possible to insert fast FIFOs (running at the CPU clock speed) inside the Ethernet module. This is not strictly necessary in the first implementation, but can be considered as an option if needed.

Furthermore, it is possible to add interrupt generation, e.g. every time buffer ownership is granted to the CPU. Again, this is not strictly necessary, but can be added later if needed.

Software considerations

On the receive side the software needs to perform MAC address filtering as well as IP address filtering. Furthermore, the software may (should?) perform IP header checksum validation as well as TCP/UDP payload checksum validation.

On the transmit side, the software is required to generate a correct IP header checkum, as well as a correct TCP/UDP payload checksum.

@sy2002
Copy link
Owner Author

sy2002 commented Sep 1, 2020

@MJoergen Thank you - this spec sounds very fine! I do not have experience with Ethernet nor with writing an own TCP/IP stack but I guess we can simplify a lot of things for our first use case with is: pure point-to-point data transfer.

@bernd-ulmann I am always getting confused with big/little endian: Is the endian-ness described here "QNICEcy"?

the register data is the 16-bit value at the specified offset. In this way the CPU accesses the Ethernet frame one word at a time (little-endian). This means the first byte in the frame is in bits 7-0 and the second byte in the frame is in bits 15-8.

@bernd-ulmann
Copy link
Collaborator

That is a great match for QNICE regarding the endianness (and everything else). :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants