| 软件版本: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
 |