前面分别实现了ARP协议和ICMP协议,但这俩协议都不能进行数据的传输,如果想要用以太网传输数据的话还需要实现UDP协议或者TCP协议,关于二者的差别主要包括以下几点:
1.连接性
TCP是面向连接的协议,它在传输数据之前需要建立连接(三次握手),并在数据传输完成后关闭连接(四次挥手)。这种连接是全双工的,即数据可以在两个方向上同时传输。
UDP则是无连接的协议,它不需要建立或关闭连接,发送方可以直接发送数据报,接收方也可以随时接收数据报。
TCP提供可靠的传输服务。它使用确认和重传机制来确保数据正确、完整、有序地到达目的地。TCP还通过流量控制和拥塞控制机制来防止网络过载。
UDP则提供不可靠的传输服务。它不检查数据包的顺序、错误或重传。如果数据包在传输过程中丢失或损坏,UDP不会采取任何补救措施。因此,UDP通常用于对实时性要求较高、但对数据可靠性要求不高的应用(如视频流、音频流、实时游戏等)
TCP的头部开销相对较大,包含更多的控制信息,如序列号、确认号、窗口大小等。
UDP的头部开销较小,只包含必要的字段,如源端口、目的端口、长度和校验和。
由于TCP需要建立连接、确认数据、处理重传等,所以其传输效率相对较低。但这也使得TCP在需要可靠传输的场景下表现更好。
UDP则不需要这些额外的步骤,因为其传输效率更高。但这也意味着UDP在传输过程中可能会丢失数据。
TCP通常用于需要可靠传输的场景,如文件存储、电子邮件、远程登录等。
UDP则常用于对实时性要求较高、但对数据可靠性要求不高的场景,如视频流、音频流、DNS查询、VoIP(网络电话)等。
TCP具有流量控制和拥塞控制机制,可以根据网络状况动态调整发送速率,以防止网络拥塞和丢包。
UDP则没有这些机制,它只负责将数据报从源端发送到目的端,则不关心网络状况和数据传输质量。
TCP通常用于一对一的通信,即一个TCP连接只能有一个发送方和一个接收方。
UDP则支持一对多、多对一和多对多的通信模式,可以实现广播和组播功能。
总而言之,UDP的优点是协议简单,传输速度快,不用进行握手,一般用于进行视频数据的传输。
UDP协议结构图如下所示:
UDP首部组成如下:
UDP首部主要包括源端口号、目的端口号、UDP总长度和校验和。
源端口号:2个字节的发送端端口号,用于区分不同的发送端口。
目的端口号:2个字节的接收端端口号。
UDP长度:UDP首部和数据段的长度,单位字节,对于接收方来说该长度其实作用不大,因为UDP数据段的长度可以通过IP首部的总长度和IP首部长度计算出来。
UDP校验和:计算方式与IP首部校验和一致,需要对UDP伪首部、UDP首部、UDP数据进行校验。伪首部包括源IP地址、目的IP地址、协议类型、UDP长度。
UDP数据组成如下图所示:
代码实现如下所示:
发送部分:
`timescale 1ns / 1ps
module udp_tx(
input clk , //系统时钟
input rst_n , //系统复位
//input
input tx_start_en , //发送使能信号
input [15:0] tx_byte_num , //发送有效字节数
input [7:0] tx_data , //发送数据
input [47:0] des_mac , //源MAC地址
input [31:0] des_ip , //源ip地址
input [31:0] crc_data , //CRC校验数据
input [7:0] crc_next , //CRC下次校验数据
//ooutput
output reg tx_done , //发送结束信号
output reg tx_req , //发送请求信号
output reg gmii_tx_en , //GMII发送使能信号
output reg [7:0] gmii_txd , //GMII发送数据
output reg crc_en , //CRC校验使能
output reg crc_clr //CRC清零信号
);
//开发板MAC地址 00-11-22-33-44-55
parameter BOARD_MAC = 48'h00_11_22_33_44_55;
//开发板IP地址 192.168.1.123
parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd123};
//目的MAC地址 ff_ff_ff_ff_ff_ff
parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
//目的IP地址 192.168.1.102
parameter DES_IP = {8'd192,8'd168,8'd1,8'd102};
localparam IDLE = 7'b000_0001 ; //初始化状态
localparam CHECK_SUM = 7'b000_0010 ; //校验和
localparam PREAMBLE = 7'b000_0100 ; //发送前导码+SFD
localparam ETH_HEAD = 7'b000_1000 ; //发送以太网帧头
localparam IP_HEAD = 7'b001_0000 ; //发送ip首部
localparam TX_DATA = 7'b010_0000 ; //发送数据
localparam CRC = 7'b100_0000 ; //CRC校验
localparam ETH_TYPE = 16'h0800 ; //以太网协议类型 IP协议
localparam MIN_DATA_NUM= 16'd18 ; //以太网数据最小46个字节,IP首部20个字节+UDP首部8个字节,所以数据至少46-20-8=18个字节
reg [6:0] cur_state ; //现态
reg [6:0] next_state ; //次态
reg state_en ; //状态跳转使能
reg [7:0] preamble[7:0] ; //前导码+帧起始界定符
reg [7:0] eth_head[