Ethernet work mechanism, the relationship between different interface types (MII, GMII, RGMII), leanrn how to transmission and reception of data, zynq xc7z030 board – FII-PE7030 Experiment 13
Experiment 13 Ethernet
13.1 Experiment Objective
- Understand what Ethernet and how it works
- Familiar with the relationship between different interface types (MII, GMII, RGMII) and their advantages and disadvantages (here uses RGMII)
- Combine the development board to complete the transmission and reception of data and verify it
13.2 Experiment Implement
- Perform a loopback test to check if the hardware is working properly.
- Perform data receiving verification
- Perform data transmission verification
13.3 Experiment
13.3.1 Introduction to Experiment Principle
Ethernet is a baseband LAN technology. Ethernet communication is a communication method that uses coaxial cable as a network media and uses carrier multi-access and collision detection mechanisms. The data transmission rate reaches 1 Gbit/s, which can satisfy the need for data transfer of non-persistent networks. As an interconnected interface, the Ethernet interface is very widely used. There are many types of Gigabit Ethernet MII interfaces, and GMII and RGMII are commonly used.
MII interface has a total of 16 lines. See Figure 13. 1.
RXD(Receive Data)[3:0]: data reception signal, a total of 4 signal lines;
TX_ER(Transmit Error): send data error prompt signal, synchronized to TX_CLK, active high, indicating that the data transmitted during the valid period of TX_ER is invalid. For 10Mbps rate, TX_ER does not work;
RX_ER(Receive Error): receive data error prompt signal, synchronized to RX_CLK, active high, indicating that the data transmitted during the valid period of RX_ER is invalid. For 10 Mbps rate, RX_ER does not work;
TX_EN(Transmit Enable): send enable signal, only the data transmitted during the valid period of TX_EN is valid;
RX_DV(Reveive Data Valid): receive data valid signal, the action type is TX_EN of the transmission channel;
TX_CLK: transmit reference clock, the clock frequency is 25 MHz at 100 Mbps, and the clock frequency is 2.5 MHz at 10 Mbps. Note that the direction of TX_CLK clock is from the PHY side to the MAC side, so this clock is provided by the PHY;
RX_CLK: receive data reference clock, the clock frequency is 25 MHz at 100 Mbps, and the clock frequency is 2.5 MHz at 10 Mbps. RX_CLK is also provided by the PHY side;
CRS: carrier Sense, carrier detect signal, does not need to be synchronized to the reference clock. As long as there is data transmission, CRS is valid. In addition, CRS is effective only if PHY is in half-duplex mode;
COL: collision detection signal, does not need to be synchronized to the reference clock, is valid only if PHY is in half-duplex mode.
GMII interface is shown in Figure 13. 2.
Compared with the MII interface, the data width of the GMII is changed from 4 bits to 8 bits. The control signals in the GMII interface such as TX_ER, TX_EN, RX_ER, RX_DV, CRS, and COL function are the same as those in the MII interface. The frequencies of transmitting reference clock GTX_CLK and the receiving reference clock RX_CLK are both 125 MHz (1000 Mbps / 8 = 125 MHz).
There is one point that needs special explanation here, that is, the transmitting reference clock GTX_CLK is different from the TX_CLK in the MII interface. The TX_CLK in the MII interface is provided by the PHY chip to the MAC chip, and the GTX_CLK in the GMII interface is provided to the PHY chip by the MAC chip. The directions are different.
In practical applications, most GMII interfaces are compatible with MII interfaces. Therefore, the general GMII interface has two transmitting reference clocks: TX_CLK and GTX_CLK (the directions of the two are different, as mentioned above). When used as the MII mode, TX_CLK and 4 of the 8 data lines are used.
See Figure 13.3 for RGMII interface.
RGMII, or reduced GMII, is a simplified version of GMII, which reduces the number of interface signal lines from 24 to 14 (COL/CRS port status indication signals are not shown here), the clock frequency is still 125 MHz, and the TX/RX data width is changed from 8 to 4 bits. To keep the transmission rate of 1000 Mbps unchanged, the RGMII interface samples data on both the rising and falling edges of the clock. TXD[3:0]/RXD[3:0] in the GMII interface is transmitted on the rising edge of the reference clock, and TXD[7:4]/RXD[7:4] in the GMII interface is transmitted on the falling edge of the reference clock. RGMI is also compatible with both 100 Mbps and 10 Mbps rates, with reference clock rates of 25 MHz and 2.5 MHz, respectively.
The TX_EN signal line transmits TX_EN and TX_ER information, TX_EN is transmitted on the rising edge of TX_CLK, and TX_ER is transmitted on the falling edge. Similarly, RX_DV and RX_ER are transmitted on the RX_DV signal line, and RX_DV is transmitted on the rising edge of RX_CLK, and RX_ER is transmitted on the falling edge.
14.3.2 Hardware Design
Figure 13.4 Schematics of 88E1512
A 88E1512 chip is used on the experimental board to form a Gigabit Ethernet module. The schematics is shown in Figure 13.4. The PHY chip is connected to the FPGA by receiving and transmitting two sets of signals. The receiving group signal prefix is PL_PHY_RX, and the transmitting group signal prefix is PL_PHY_TX, which are respectively composed of a control signal CTL, a clock signal CK and four data signals 3-0. PL_PHY_ LED0 and PL_PHY_LED1 are respectively connected to the yellow signal light and the green signal light of the network port. At the same time, the FPGA can configure the PHY chip through the clock line NPHY_MDC and the data line NPHY_MDIO.
14.3.3 Program Introduction
- Configure IP address
Before verification (the default PC NIC is a Gigabit NIC, otherwise it needs to be replaced). PC IP address needs to be confirmed first. In the DOS command window, type ipconfig -all command to check it. Example is shown in Figure 13. 5.
Figure 13.5 PC end IP information
To facilitate subsequent experiments, PC is provided a fixed IP address. Take this experiment as an example, IP configuration is 192.169.0.100(could be revised, but needs to be consistent to the IP address of target sending module, for Internet Protocol reason, IP address 169.XXX.X.X is not suggested). Find Internet Protocol Version 4(TCP/IPv4) in Network and Sharing center. See Fig 13. 6.
Figure 13.6 Configure PC end IP address
Since there is no ARP protocol content (binding IP address and MAC address of the develop board) in this experiment, it needs to be bound manually through the DOS command window. Here, the IP is set to 192.168.0.2 and the MAC address is set to 00-0A-35-01-FE-C0, (can be replaced) as shown in Figure 13. 7, the method is as follows: (Note: Run the DOS command window as an administrator)
Run the command: ARP -s 192.168.0.2 00-0A-35-01-FE-C0
View binding results: ARP -a
Figure 13.7 Address binding method 1
If a failure occurs while running the ARP command, another way is available, as shown in Figure 13.8:
- Enter the netsh i i show in command to view the number of the local connection, such as the “23” of the computer used this time.
- Enter netsh -c “i i” add neighbors 23 (number) “192.168.0.2” “00-0A-35-01-FE-C0”
- Enter arp -a to view the binding result
Figure 13.8 Address binding method 2
Next, the DOS command window is also used for connectivity detection, as shown in Figure 13. 9. Ping is an executable command that comes with the Windows family. Use it to check if the network can be connected. It can help analyze and determine network faults. Application format: Ping IP address (not host computer IP).
Figure 13.9 Send data
- Loopback test
The first step: program introduction
The loopback test only needs to output the input data directly. Refer the project file “loopback”. In the project, two IP cores, IDDR and ODDR, are used to complete the receiving and transmitting functions.
module loopback(
input rst, input rxc, input rxdv, input [3:0] rxd, output txc, output txen, output [3:0] txd ); wire pll_locked; wire rx_clk; wire clk_125m, clk_125m_90; wire [7:0] e_rxd; wire rxdv1, rxdv2; clk_wiz_0 clk_wiz_0_inst( .clk_in1 (rx_clk), .reset (1’b0), .locked (pll_locked), .clk_out1 (clk_125m), .clk_out2 (clk_125m_90) ); ddio_in ddio_in_inst ( .data_in_from_pins ({rxdv, rxd}), .data_in_to_device ({rxdv2, e_rxd[7:4], rxdv1, e_rxd[3:0]}), .clk_in (rxc), .clk_out (rx_clk), .io_reset (1’b0) ); ddio_out ddio_out_inst ( .data_out_from_device ({rxdv2, e_rxd[7:4], rxdv1, e_rxd[3:0]}), .data_out_to_pins ({txen, txd}), .clk_in (clk_125m_90), .clk_out (txc), .io_reset (1’b0) ); endmodule |
Because it is the RGMII interface, the data is bilateral along 4-bit data. Therefore, when data processing is performed inside the FPGA, it needs to be converted into 8-bit data. Go to Installed IP > Library > Basic Functions > I/O to find ALTDDIO_IN and ALTDDIO_OUT. To implement it, IP core (ddio_in) is called, and after internal data processing, IP core is passed (ddio_out) to convert 8-bit data into bilateral edge 4-bit data transfer. It should be noted that, considering the enable signal and data signal synchronization, the enable signal is entered to ddio for conversion at the same time. The specific settings are shown in Figure 13. 10 and Figure 13. 11.
Figure 13.10 ddio_in setting
Figure 13.11 ddio_out setting
The secons step: assign pins, run implementation, verify the board
See Table 13.1 for the pin assignment.
Table 13.1 Ethernet experiment pin mapping table
Signal Name | Network Name | FPGA Pin | Port Description |
rst | GPIO_SW_2 | F4 | Reset |
rxc | PL_PHY_RX_CLK | J4 | Receive clock |
rxdv | PL_PHY_RX_CTRL | L3 | Receive enable clock |
rxd[0] | PL_PHY_RXD[0] | K3 | Receive data (4-bit bilateral) |
rxd[1] | PL_PHY_RXD[1] | K1 | |
rxd[2] | PL_PHY_RXD[2] | H2 | |
rxd[3] | PL_PHY_RXD[3] | G1 | |
txc | PL_PHY_TX_CLK | N3 | Transmit clock |
txen | PL_PHY_TX_CTRL | K5 | Transmit enable clock |
txd[0] | PL_PHY_TXD[0] | M2 | Transmit data (4-bit bilateral) |
txd[1] | PL_PHY_TXD[1] | L2 | |
txd[2] | PL_PHY_TXD[2] | L4 | |
txd[3] | PL_PHY_TXD[3] | L5 |
As shown in Figure 13.12, after setting the correct address and data type, the detection information (love you!) is sent through the host computer. The data packet is captured by Wireshark, as shown in Figure 13.13. The data is correctly transmitted back to the PC.
Figure 13.12 Host computer transmits the test data
Figure 13.13 PC end receives data correctly
- Complete Ethernet data transmission design
For complete Ethernet data transmission, it is necessary to have the receiving part of the data and the transmitting part of the data. For the convenience of experiment, the data transmitted by the PC is stored first in the RAM. After reading via the transmitting end, send it to the PC. For a series of data unpacking and packaging during the process, refer to the project file “ethernet”. A brief introduction to each module follows.
- Data receiving module (ip_receive)
This module is to detect and identify the data frame, unpack the valid data frame, and store the real data in the RAM.
always @ (posedge clk) begin
if (clr) begin rx_state <= idle; data_receive <= 1’b0; end else case (rx_state)
idle : begin valid_ip_P <= 1’b0; byte_counter <= 3’d0; data_counter <= 10’d0; mydata <= 32’d0; state_counter <= 5’d0; data_o_valid <= 1’b0; ram_wr_addr <= 0; if (e_rxdv == 1’b1) begin if (datain[7:0] == 8’h55) begin //Receive the first 55// rx_state <= six_55; mydata <= {mydata[23:0], datain[7:0]}; end else rx_state <= idle; end end
six_55 : begin //Receive 6 0x55// if ((datain[7:0] == 8’h55) && (e_rxdv == 1’b1)) begin if (state_counter == 5) begin state_counter <= 0; rx_state <= spd_d5; end else state_counter <= state_counter + 1’b1; end else rx_state <= idle; end
spd_d5 : begin //Receive one 0xd5// if ((datain[7:0] == 8’hd5) && (e_rxdv == 1’b1)) rx_state <= rx_mac; else rx_state <= idle; end
rx_mac : begin //Receive target MAC address and source MAC address if (e_rxdv == 1’b1) begin if (state_counter < 5’d11) begin mymac <= {mymac[87:0], datain}; state_counter <= state_counter + 1’b1; end else begin board_mac <= mymac[87:40]; pc_mac <= {mymac[39:0], datain}; state_counter <= 5’d0; if ((mymac[87:72] == 16’h000a) && (mymac[71:56] == 16’h3501) && (mymac[55:40] == 16’hfec0)) //Determine if the target MAC Address is from the current FPGA rx_state <= rx_IP_Protocol; else rx_state <= idle; end end else rx_state <= idle; end
rx_IP_Protocol : begin //Receive 2 bytes of IP TYPE if (e_rxdv == 1’b1) begin if (state_counter < 5’d1) begin myIP_Prtcl <= {myIP_Prtcl[7:0], datain[7:0]}; state_counter <= state_counter+1’b1; end else begin IP_Prtcl <= {myIP_Prtcl[7:0],datain[7:0]}; valid_ip_P <= 1’b1; state_counter <= 5’d0; rx_state <= rx_IP_layer; end end else rx_state <= idle; end
rx_IP_layer : begin //Receive 20 bytes of udp virtual header, ip address valid_ip_P <= 1’b0; if (e_rxdv == 1’b1) begin if (state_counter < 5’d19) begin myIP_layer <= {myIP_layer[151:0], datain[7:0]}; state_counter <= state_counter + 1’b1; end else begin IP_layer <= {myIP_layer[151:0], datain[7:0]}; state_counter <= 5’d0; rx_state <= rx_UDP_layer; end end else rx_state <= idle; end
rx_UDP_layer : begin // Receive 8-byte UDP port number and UDP packet length rx_total_length <= IP_layer[143:128]; pc_IP <= IP_layer[63:32]; board_IP <= IP_layer[31:0]; if (e_rxdv == 1’b1) begin if (state_counter < 5’d7) begin myUDP_layer <= {myUDP_layer[55:0], datain[7:0]}; state_counter <= state_counter + 1’b1; end else begin UDP_layer <= {myUDP_layer[55:0], datain[7:0]}; rx_data_length <= myUDP_layer[23:8]; //length of UDP data package state_counter <= 5’d0; rx_state <= rx_data; end end else rx_state <= idle; end
rx_data : begin //Receive UDP data if (e_rxdv == 1’b1) begin if (data_counter == rx_data_length-9) begin //Save last data data_counter <= 0; rx_state <= rx_finish; ram_wr_addr <= ram_wr_addr + 1’b1; data_o_valid <= 1’b1; // Write RAM if (byte_counter == 3’d3) begin data_o <= {mydata[23:0], datain[7:0]}; byte_counter <= 0; end else if (byte_counter==3’d2) begin data_o <= {mydata[15:0], datain[7:0],8’h00}; //Less than 32-bit, //add ‘0’ byte_counter <= 0; end else if (byte_counter==3’d1) begin data_o <= {mydata[7:0], datain[7:0], 16’h0000}; //Less than //32-bit , add ‘0’ byte_counter <= 0; end else if (byte_counter==3’d0) begin data_o <= {datain[7:0], 24’h000000}; //Less than 32-bit, //add ‘0’ byte_counter <= 0; end end else begin data_counter <= data_counter + 1’b1; if (byte_counter < 3’d3) begin mydata <= {mydata[23:0], datain[7:0]}; byte_counter <= byte_counter + 1’b1; data_o_valid <= 1’b0; end else begin data_o <= {mydata[23:0], datain[7:0]}; byte_counter <= 3’d0; data_o_valid <= 1’b1; // Receive 4bytes of data, write //RAM request ram_wr_addr <= ram_wr_addr+1’b1; end end end else rx_state <= idle; end
rx_finish : begin data_o_valid <= 1’b0; //added for receive test// data_receive <= 1’b1; rx_state <= idle; end default : rx_state <= idle; endcase end |
The receiving module is to perform step by step analysis on the received data.
Idle state: If ‘55’ is received, jump to the six_55 state.
Six_55 state: If it continues to receive six consecutive 55s, it will jump to the spd_d5 state, otherwise it will return the idle state.
Spd_d5 state: If ‘d5’ continues received, it proves that the complete packet preamble “55_55_55_55_55_55_55_d5” has been received, and jumps to rx_mac, otherwise it returns the idle transition.
rx_mac state: This part is the judgment of the target MAC address and the source MAC address. If it matches, jump to the rx_IP_Protocol state, otherwise it will return the idle state and resend.
rx_IP_Protocol state: Determine the type and length of the packet and jump to the rx_IP_layer state.
rx_IP_layer state: Receive 20 bytes of UDP virtual header and IP address, jump to rx_UDP_layer state
rx_UDP_layer state: Receive 8-byte UDP port number and UDP packet length, jump to rx_data state
Rx_data state: Receive UDP data, jump to rx_finish state
Rx_finish state: A packet of data is received, and jump to the idle state to wait for the arrival of the next packet of data.
- Data sending module (ip_send)
The main content of this module is to read out the data in the RAM, package and transmit the data with the correct packet protocol type (UDP). Before transmitting, the data is also checked by CRC.
initial begin
tx_state <= idle; //Define IP header preamble[0] <= 8’h55; //7 preambles “55”, one frame start //character “d5” preamble[1] <= 8’h55; preamble[2] <= 8’h55; preamble[3] <= 8’h55; preamble[4] <= 8’h55; preamble[5] <= 8’h55; preamble[6] <= 8’h55; preamble[7] <= 8’hD5;
mac_addr[0] <= 8’hB4; //Target MAC address “ff-ff-ff-ff-ff-ff”, full ff is //broadcast package mac_addr[1] <= 8’h2E; //Target MAC address “B4-2E-99-20-C4-61”, // For the PC-side address used for this experiment, change the content according to the actual //PC in the debugging phase. mac_addr[2] <= 8’h99; mac_addr[3] <= 8’h20; mac_addr[4] <= 8’hC4; mac_addr[5] <= 8’h61;
mac_addr[6] <= 8’h00; //Source MAC address “00-0A-35-01-FE-C0” mac_addr[7] <= 8’h0A; //Modify it according to the actual needs mac_addr[8] <= 8’h35; mac_addr[9] <= 8’h01; mac_addr[10]<= 8’hFE; mac_addr[11]<= 8’hC0;
mac_addr[12]<= 8’h08; //0800: IP package type mac_addr[13]<= 8’h00;
i<=0; end |
This part defines the preamble of the data packet, the MAC address of the PC, the MAC address of the development board, and the IP packet type. It should be noted that in the actual experiment, the MAC address of the PC needs to be modified. Keep the MAC address consistent along the project, otherwise the subsequent experiments will not receive data.
always @ (posedge clk) begin
case (tx_state) idle : begin e_txen <= 1’b0; crcen <= 1’b0; crcre <= 1; j <= 0; dataout <= 0; ram_rd_addr <= 1; tx_data_counter <= 0; if (time_counter == 32’h04000000) begin //Wait for the delay, send a data //package regularly tx_state <= start; time_counter <= 0; end else time_counter <= time_counter + 1’b1; end
start : begin //IP header ip_header[0] <= {16’h4500, tx_total_length}; //Version: 4; IP header length: 20; //IP total length ip_header[1][31:16] <= ip_header[1][31:16]+1’b1; // Package serial number ip_header[1][15:0] <= 16’h4000; //Fragment offset ip_header[2] <= 32’h80110000; //mema[2][15:0] protocol: 17(UDP) ip_header[3] <= 32’hc0a80002; //Source MAC address ip_header[4] <= 32’hc0a80003; //Target MAC address ip_header[5] <= 32’h1f901f90; // 2-byte source port number and //2-byte target port number ip_header[6] <= {tx_data_length, 16’h0000}; //2 bytes of data length and 2 //bytes of checksum (none) tx_state <= make; end
make : begin // Generate a checksum of the header if (i == 0) begin check_buffer <= ip_header[0][15:0] + ip_header[0][31:16] + ip_header[1][15:0] + ip_header[1][31:16] + ip_header[2][15:0] + ip_header[2][31:16] + ip_header[3][15:0] + ip_header[3][31:16] + ip_header[4][15:0] + ip_header[4][31:16]; i <= i + 1’b1; end else if(i == 1) begin check_buffer[15:0] <= check_buffer[31:16] + check_buffer[15:0]; i <= i+1’b1; end else begin ip_header[2][15:0] <= ~check_buffer[15:0]; //header checksum i <= 0; tx_state <= send55; end end
send55 : begin // Send 8 IP preambles: 7 “55”, 1 “d5” e_txen <= 1’b1; //GMII transmitted valid data crcre <= 1’b1; //reset crc if(i == 7) begin dataout[7:0] <= preamble[i][7:0]; i <= 0; tx_state <= sendmac; end else begin dataout[7:0] <= preamble[i][7:0]; i <= i + 1’b1; end end
sendmac : begin // Send target MAC address, source MAC address and IP packet type crcen <= 1’b1; // CRC check enable, crc32 data check starts from the target MAC crcre <= 1’b0; if (i == 13) begin dataout[7:0] <= mac_addr[i][7:0]; i <= 0; tx_state <= sendheader; end else begin dataout[7:0] <= mac_addr[i][7:0]; i <= i + 1’b1; end end
sendheader : begin // Send 7 32-bit IP headers datain_reg <= datain; //Prepare the data to be transmitted if(j == 6) begin if(i == 0) begin dataout[7:0] <= ip_header[j][31:24]; i <= i + 1’b1; end else if(i == 1) begin dataout[7:0] <= ip_header[j][23:16]; i <= i + 1’b1; end else if(i == 2) begin dataout[7:0] <= ip_header[j][15:8]; i <= i + 1’b1; end else if(i == 3) begin dataout[7:0] <= ip_header[j][7:0]; i <= 0; j <= 0; tx_state <= senddata; end end else begin if(i == 0) begin dataout[7:0] <= ip_header[j][31:24]; i <= i + 1’b1; end else if(i == 1) begin dataout[7:0] <= ip_header[j][23:16]; i <= i + 1’b1; end else if(i == 2) begin dataout[7:0] <= ip_header[j][15:8]; i <= i + 1’b1; end else if(i == 3) begin dataout[7:0] <= ip_header[j][7:0]; i <= 0; j <= j + 1’b1; end end end
senddata : begin //Transmit UDP packets if(tx_data_counter == tx_data_length – 9) begin //Transmit last data tx_state <= sendcrc; if (i == 0) begin dataout[7:0] <= datain_reg[31:24]; i <= 0; end else if (i == 1) begin dataout[7:0] <= datain_reg[23:16]; i <= 0; end else if (i == 2) begin dataout[7:0] <= datain_reg[15:8]; i <= 0; end else if (i == 3) begin dataout[7:0] <= datain_reg[7:0]; datain_reg <= datain; //Prepare the data i <= 0; end end else begin //Send other data package tx_data_counter <= tx_data_counter+1’b1; if (i == 0) begin dataout[7:0] <= datain_reg[31:24]; i <= i + 1’b1; ram_rd_addr <= ram_rd_addr + 1’b1; // Add 1 to the RAM address, //let the RAM output data in advance. end else if (i == 1) begin dataout[7:0] <= datain_reg[23:16]; i <= i + 1’b1; end else if (i == 2) begin dataout[7:0] <= datain_reg[15:8]; i <= i + 1’b1; end else if (i == 3) begin dataout[7:0] <= datain_reg[7:0]; datain_reg <= datain; //Prepare data i <= 0; end end end
sendcrc : begin //Send 32-bit CRC checksum crcen <= 1’b0; if (i == 0) begin dataout[7:0] <= {~crc[24], ~crc[25], ~crc[26], ~crc[27], ~crc[28], ~crc[29], ~crc[30], ~crc[31]}; i <= i + 1’b1; end else begin if (i == 1) begin dataout[7:0] <= {~crc[16], ~crc[17], ~crc[18], ~crc[19], ~crc[20], ~crc[21], ~crc[22], ~crc[23]}; i <= i + 1’b1; end else if (i == 2) begin dataout[7:0] <= {~crc[8], ~crc[9], ~crc[10], ~crc[11], ~crc[12], ~crc[13], ~crc[14], ~crc[15]}; i <= i + 1’b1; end else if (i == 3) begin dataout[7:0] <= {~crc[0], ~crc[1], ~crc[2], ~crc[3], ~crc[4], ~crc[5], ~crc[6], ~crc[7]}; i <= 0; tx_state <= idle; end end end
default : tx_state <= idle; endcase end |
Idle state: waiting for delay, sending a packet at regular intervals and jumping to the start state.
Start state: send the packet header and jump to the make state.
make state: generates the checksum of the header and jumps to the send55 state.
Send55 status: send 8 preambles and jump to the sendmac state.
sendmac state: send the target MAC address, source MAC address and IP packet type, and jump to the sendheader state.
sendheader state: sends 7 32-bit IP headers and jumps to the senddata state.
senddata state: send UDP packets and jump to the sendcrc state.
sendcrc state: sends 32-bit CRC check and returns the idle state.
Following the above procedure, the entire packet of data is transmitted, and the idle state is returned to wait for the transmission of the next packet of data.
- CRC check module (crc)
The CRC32 check of an IP packet is calculated at the destination MAC Address and until the last data of a packet. The CRC32 verilog algorithm and polynomial of Ethernet can be generated directly at the following website: http://www.easics.com/webtools/crctool
- UDP data test module (UDP)
This module only needs to instantiate the first three sub-modules together. Check the correctness of each connection.
- Top level module settings (ethernet)
The PLL, ddio_in, ddio_out, ram, and UDP modules are instantiated to the top level entity, and specific information is stored in advance in the RAM (Welcome To ZGZNXP World!). When there is no data input, the FPGA always sends this information. With data input, the received data is sent. Refer to the project files for more information.
13.4 Experiment Verification
The pin assignment of this test procedure is identical to that in loopback test.
Before programming the development board, it is necessary to note that the IP address of the PC and the MAC address of the development board must be determined and matched, otherwise the data will not be received.
Download the compiled project to the development board. As shown in Figure 13.14, the FPGA is keeping sending information to the PC. The entire transmitted packet can also be seen in Wireshark, as shown in Figure 13.15.
Figure 13.14 Send specific information
Figure 13.15 Specific information package
When the PC sends data to the FPGA, as shown in Figure 13.16, the entire packet arrives at the FPGA, and then the FPGA repackages the received data and sends it to the PC. See Figure 13.17, the network assistant also receives the transmitted data information accurately, as shown in Figure 13.18.
Figure 13.16 PC send data package
Figure 13.17 The FPGA repackages the received data and sends it to the PC
Figure 13.18 Information received by PC from FPGA
It should be noted that Ethernet II specifies the Ethernet frame data field is a minimum of 46 bytes, that is, the minimum Ethernet frame is 6+6+2+46+4=64. The 4-byte FCS is removed, so the packet capture is 60 bytes. When the length of the data field is less than 46 bytes, the MAC sublayer is padded after the data field to satisfy the data frame length of not less than 64 bytes. When communicating over a UDP LAN, “Hello World” often occurs for testing, but “Hello World” does not meet the minimum valid data (64-46) requirements. It is less than 18 bytes but the other party is still available for receiving, because data is complemented in the MAC sublayer of the link layer, less than 18 bytes are padded with ‘0’s. However, when the server is on the public network and the client is on the internal network, if less than 18 bytes of data is transmitted, the receiving end cannot receive the data. Therefore, if there is no data received, the information to be sent should be increased to more than 18 bytes.