软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 3.3 IP层ICMP层数据和UDP层数据都要经过IP层打包或者解包,IP层主要功能为判断数据报文类型,进行IP首部校验,添加包头或者过滤包头,处理ICMP请求。 3.3.1 IP接收模块该模块的主要功能是接收uiip_arp_rx传入的数据包,通过首部校验判断包头的正确性,对包头进行过滤,并且提取出UDP报文和ICMP报文。 该模块的状态机转换图如图所示。
WAIT_IP_PACKET:等待接收IP包,若I_ip_rvalid拉高,代表数据传入,进入RECORD_IP_HEADER状态。 RECORD_IP_HEADER:接收包头信息,20字节的包头数据全部接收完时,判断收到的IP地址和本地IP地址是否匹配,若不匹配,丢弃该帧,进入WAIT_PACKET_END状态;若匹配,则判断数据包类型。如果收到的数据报文为UDP数据报文,进入OUTPUT_UDP_PACKET状态。如果收到的数据报文为ICMP报文,则将数据传入ICMP子层模块,等待一包数据传输完成后,进入WAIT_PACKET_END状态。 OUTPUT_UDP_PACKET:将有效数据打拍后传输至UDP层,一包数据传输完成后,回到WAIT_IP_PACKET状态。 WAIT_PACKET_END:等待数据有效信号拉低,一帧数据传输完成,回到WAIT_IP_PACKET状态。 3.3.2 IP发送模块 该模块的主要功能有:接收uiudp_tx发送的UDP报文和uiip_rx发送的ICMP报文信息,将其封装成IP包并发送至下层uiip_arp_tx模块。 该模块的状态机转换图如图所示。 IDLE:uiip_tx模块处于发送空闲时,接收ICMP和UDP报文发送请求,优先响应ICMP请求。当收到请求时,向uiip_arp_tx模块发送请求信号,通过udp_pkg_en信号标记报文类型,进入WAIT_ACK状态,等待握手响应信号。 WAIT_ACK:接收到I_ip_tbusy信号,代表和IP_ARP层模块握手成功,可以发送数据,进入SEND_IP_HEADER状态。若要发送的是UDP报文,则会发送O_ip_udp_tbusy信号和UDP层进行握手。 SEND_IP_HEADER:在有效数据报文前添加对应的IP包头,发送包头完毕后,若报文类型为UDP报文,进入SEND_UDP_PACKET状态;若为ICMP报文,则进入SEND_ICMP_PACKET状态。 SEND_UDP_PACKET和SEND_ICMP_PACKET:发送完报文中的有效数据后,将标识加1,回到IDLE状态。 3.3.3 IP首部校验模块正常计算IP首部校验和时,将校验位置0。由于每两字节数据相加得到的不再产生进位结果,为最终校验和的取反,所以当计算过程中加入校验位时,相加得到的结果应当为全1。若结果不为全1,则数据校验错误,将O_check_rerror信号置为高。 - `timescale 1ns / 1ps
- module ip_header_checksum(
- input wire I_clk,
- input wire I_reset,
- input wire I_ip_rdata_valid,
- input wire [7:0] I_ip_rdata,
- output wire O_checksum_rerror
- );
- reg checksum_correct;
- assign O_checksum_rerror = ~checksum_correct;
- reg [1:0] state;
- reg [3:0] cnt;
- wire [16:0] tmp_accum1;
- reg [15:0] accum1, accum2;
- assign tmp_accum1 = accum1 + accum2;
- always @(posedge I_clk or posedge I_reset) begin
- if(I_reset) begin
- state <= 2'd0;
- cnt <= 4'd0;
- accum1 <= 16'd0;
- accum2 <= 16'd0;
- checksum_correct <= 1'b1;
- end
- else begin
- case(state)
- 0: begin
- if(I_ip_rdata_valid) begin
- accum1[15:8] <= I_ip_rdata;
- state <= 2'd1;
- end
- else begin
- accum1[15:8] <= 8'd0;
- state <= 2'd0;
- end
- end
- 1: begin accum1[7:0] <= I_ip_rdata; state <= 2'd2; end
- 2: begin
- if(cnt == 4'd9) begin
- if((tmp_accum1[15:0] + tmp_accum1[16]) != 16'hffff)
- checksum_correct <= 1'b0;
- cnt <= 4'd0;
- state <= 2'd3;
- end
- else begin
- accum2 <= tmp_accum1[15:0] + tmp_accum1[16];
- accum1[15:8] <= I_ip_rdata;
- cnt <= cnt + 1'b1;
- state <= 2'd1;
- end
- end
- 3: begin
- accum1 <= 16'd0;
- accum2 <= 16'd0;
- if(I_ip_rdata_valid)
- state <= state;
- else
- state <= 2'd0;
- end
- endcase
- end
- end
- endmodule
复制代码
|