基于FPGA的UDP协议栈设计第四章_UDP层设计

文章目录

UDP层报文解析

UDP层报文内容很简单:

源端口号:自身的端口号

目的端口号:接收方的端口号

UDP长度:UDP首部+数据的长度

UDP校验和:与IP校验合算法一致,不同的是UDP层对UDP头和数据部分都进行校验。

一、UDP_TX模块

发送模块的设计大同小异。

设计代码为本人参考FPGA奇哥系列网课自行编写

c 复制代码
module UDP_TX#(
    parameter       P_DST_UDP_PORT  =   16'h8080,
    parameter       P_SRC_UDP_PORT  =   16'h8080
)(
    input           i_clk           ,
    input           i_rst           ,
    /*----info port----*/
    input   [15:0]  i_dst_udp_port  ,
    input           i_dst_udp_valid ,
    input   [15:0]  i_src_udp_port  ,
    input           i_src_udp_valid ,
    /*----data port----*/
    input   [7 :0]  i_send_udp_data ,
    input   [15:0]  i_send_udp_len  ,
    input           i_send_udp_last ,
    input           i_send_udp_valid,
    /*----ip port----*/
    output  [7 :0]  o_ip_type       ,
    output  [7 :0]  o_ip_data       ,
    output  [15:0]  o_ip_len        ,
    output          o_ip_last       ,
    output          o_ip_valid      
);
/******************************function***************************/

/******************************parameter**************************/
localparam      P_UDP_MIN_LEN = 18  ;
/******************************port*******************************/

/******************************machine****************************/

/******************************reg********************************/
reg  [15:0]     r_dst_udp_port      ;
reg  [15:0]     r_src_udp_port      ;
reg  [7 :0]     ri_send_udp_data    ;
reg  [15:0]     ri_send_udp_len     ;
reg             ri_send_udp_last    ;
reg             ri_send_udp_valid   ;
reg             ri_send_udp_valid_1d;

reg  [7 :0]     ro_ip_data          ;
reg             ro_ip_last          ;
reg             ro_ip_valid         ;
reg  [15:0]     ro_ip_len           ;
//fifo
reg             r_fifo_rden         ;
reg             r_fifo_rden_1d      ; 
reg             r_fifo_empty        ;
//组帧
reg  [15:0]     r_udp_data_cnt      ;
/******************************wire*******************************/
wire [7 :0]     w_fifo_rdata        ;
wire            w_fifo_full         ;
wire            w_fifo_empty        ;
/******************************component**************************/
MAC_TX_FIFO_8x512 UDP_TX_FIFO_8x512_u0 (
  .clk              (i_clk              ), 
  .srst             (i_rst              ), 
  .din              (ri_send_udp_data   ), 
  .wr_en            (ri_send_udp_valid  ), 
  .rd_en            (r_fifo_rden        ), 
  .dout             (w_fifo_rdata       ), 
  .full             (w_fifo_full        ), 
  .empty            (w_fifo_empty       )
  //.wr_rst_busy      (), 
  //.rd_rst_busy      ()  
);
/******************************assign*****************************/
assign  o_ip_type   =   8'd17  ;
assign  o_ip_data   =   ro_ip_data  ;
assign  o_ip_len    =   ro_ip_len   ;
assign  o_ip_last   =   ro_ip_last  ;
assign  o_ip_valid  =   ro_ip_valid ;
/******************************always*****************************/
//源udp端口可设置?
always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_src_udp_port  <= P_SRC_UDP_PORT ;      
    else if(i_src_udp_valid)
        r_src_udp_port  <= i_src_udp_port; 
    else 
        r_src_udp_port  <= r_src_udp_port ;
end
//目的udp端口可设置?
always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_dst_udp_port <= P_DST_UDP_PORT;              
    else if(i_dst_udp_valid)
        r_dst_udp_port <= i_dst_udp_port;          
    else 
        r_dst_udp_port <= r_dst_udp_port;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst) begin
        ri_send_udp_data  <= 'd0;
        //ri_send_udp_len   <= 'd0;
        ri_send_udp_last  <= 'd0;
        ri_send_udp_valid <= 'd0;        
        ri_send_udp_valid_1d <= 'd0;
    end                    
    else begin 
        ri_send_udp_data  <= i_send_udp_data ;
        //ri_send_udp_len   <= i_send_udp_len + 8;
        ri_send_udp_last  <= i_send_udp_last ;
        ri_send_udp_valid <= i_send_udp_valid;  
        ri_send_udp_valid_1d <= ri_send_udp_valid;
    end
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ri_send_udp_len <= 'd0;             
    else if(i_send_udp_valid)
        ri_send_udp_len <= i_send_udp_len;         
    else 
        ri_send_udp_len <= ri_send_udp_len;
end

//组帧计数器 计数器与valid同步开始计数,因此发送38个数据计数器就要计数到38而不是37了
always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_udp_data_cnt <= 'd0;   
    else if((ri_send_udp_len < P_UDP_MIN_LEN) && (r_udp_data_cnt == P_UDP_MIN_LEN))
        r_udp_data_cnt <= 'd0;   
    else if((ri_send_udp_len >= P_UDP_MIN_LEN) && (r_udp_data_cnt == (ri_send_udp_len + 8)))
        r_udp_data_cnt <= 'd0;           
    else if(ri_send_udp_valid || r_udp_data_cnt)
        r_udp_data_cnt <= r_udp_data_cnt + 1;          
    else 
        r_udp_data_cnt <= r_udp_data_cnt;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_fifo_rden <= 'd0;    
    else if(r_udp_data_cnt == ri_send_udp_len + 8 - 2)//FIFO输出延迟1拍,应该在last拉高时同时拉高?
        r_fifo_rden <= 'd0;           
    else if(r_udp_data_cnt == 6)
        r_fifo_rden <= 'd1;          
    else 
        r_fifo_rden <= r_fifo_rden;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_fifo_empty <= 'd0;          
    else 
        r_fifo_empty <= w_fifo_empty;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ro_ip_data <= 'd0;        
    else case (r_udp_data_cnt)
        0       : ro_ip_data <= r_src_udp_port[15:8];     
        1       : ro_ip_data <= r_src_udp_port[7 :0];     
        2       : ro_ip_data <= r_dst_udp_port[15:8];     
        3       : ro_ip_data <= r_dst_udp_port[7 :0];     
        4       : ro_ip_data <= ro_ip_len[15:8];     
        5       : ro_ip_data <= ro_ip_len[7 :0];     
        6       : ro_ip_data <= 'd0;     
        7       : ro_ip_data <= 'd0;     
        default : ro_ip_data <= r_fifo_empty ? 'd0 : w_fifo_rdata;
    endcase
end
//计数器与valid同步开始计数,因此发送38个数据计数器就要计数到38而不是37,valid和last也不是-1和-2了,相应加1
always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ro_ip_valid <= 'd0;  
    else if((ri_send_udp_len < P_UDP_MIN_LEN) && (r_udp_data_cnt == P_UDP_MIN_LEN))
        ro_ip_valid <= 'd0;  
    else if((r_udp_data_cnt == ri_send_udp_len + 8) && (ri_send_udp_len >= P_UDP_MIN_LEN))
        ro_ip_valid <= 'd0;           
    else if(ri_send_udp_valid && !ri_send_udp_valid_1d)
        ro_ip_valid <= 'd1;          
    else 
        ro_ip_valid <= ro_ip_valid;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ro_ip_last <= 'd0;  
    else if((ri_send_udp_len < P_UDP_MIN_LEN) && (r_udp_data_cnt == P_UDP_MIN_LEN - 1))
        ro_ip_last <='d1;          
    else if((r_udp_data_cnt == ri_send_udp_len + 8 - 1) && (ri_send_udp_len >= P_UDP_MIN_LEN))
        ro_ip_last <='d1;          
    else 
        ro_ip_last <= 'd0;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ro_ip_len <= 'd0; 
    else if(ri_send_udp_valid && ri_send_udp_len < P_UDP_MIN_LEN)
        ro_ip_len <= 'd18 + 8;             
    else if(ri_send_udp_valid && ri_send_udp_len >= P_UDP_MIN_LEN)
        ro_ip_len <= ri_send_udp_len + 'd8;          
    else 
        ro_ip_len <= ro_ip_len;
end

endmodule

二、UDP_RX模块

c 复制代码
module UDP_RX#(
    parameter       P_DST_UDP_PORT  =   16'h8080,
    parameter       P_SRC_UDP_PORT  =   16'h8080
)(
    input           i_clk           ,
    input           i_rst           ,
    /*----info port----*/
    input   [15:0]  i_dst_udp_port  ,
    input           i_dst_udp_valid ,
    input   [15:0]  i_src_udp_port  ,
    input           i_src_udp_valid ,
    /*----data port----*/
    output  [7 :0]  o_udp_data      ,
    output  [15:0]  o_udp_len       ,
    output          o_udp_last      ,
    output          o_udp_valid     ,
    /*----ip port----*/
    input   [7 :0]  i_ip_data       ,
    input   [15:0]  i_ip_len        ,
    input           i_ip_last       ,
    input           i_ip_valid      
);
/******************************function***************************/

/******************************parameter**************************/

/******************************port*******************************/

/******************************machine****************************/

/******************************reg********************************/
reg  [15:0] r_dst_udp_port ;
reg  [15:0] r_src_udp_port ;
reg  [7 :0] ri_ip_data     ;
reg  [15:0] ri_ip_len      ;
reg         ri_ip_last     ;
reg         ri_ip_valid    ;
//reg  [7 :0] ro_udp_data    ;
reg  [15:0] ro_udp_len     ;
reg         ro_udp_last    ;
reg         ro_udp_valid   ;
reg  [15:0] r_udp_recv_cnt ;     
/******************************wire*******************************/

/******************************component**************************/

/******************************assign*****************************/
assign  o_udp_data  =   ri_ip_data      ;
assign  o_udp_len   =   ro_udp_len      ;
assign  o_udp_last  =   ro_udp_last     ;
assign  o_udp_valid =   ro_udp_valid    ;
/******************************always*****************************/
//源udp端口可设置
always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_src_udp_port  <= P_SRC_UDP_PORT ;      
    else if(i_src_udp_valid)
        r_src_udp_port  <= i_src_udp_port; 
    else 
        r_src_udp_port  <= r_src_udp_port ;
end
//目的udp端口可设置
always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_dst_udp_port <= P_DST_UDP_PORT;              
    else if(i_dst_udp_valid)
        r_dst_udp_port <= i_dst_udp_port;          
    else 
        r_dst_udp_port <= r_dst_udp_port;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst) begin
        ri_ip_data  <= 'd0;
        ri_ip_len   <= 'd0;
        ri_ip_last  <= 'd0;
        ri_ip_valid <= 'd0;        
    end                    
    else if(i_ip_valid)begin
        ri_ip_data  <= i_ip_data ;
        ri_ip_len   <= i_ip_len  ;
        ri_ip_last  <= i_ip_last ;
        ri_ip_valid <= i_ip_valid;         
    end
    else begin
        ri_ip_data  <= 'd0;
        ri_ip_len   <= ri_ip_len;
        ri_ip_last  <= 'd0;
        ri_ip_valid <= 'd0;         
    end
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        r_udp_recv_cnt <= 'd0;              
    else if(ri_ip_valid)
        r_udp_recv_cnt <= r_udp_recv_cnt + 1;          
    else 
        r_udp_recv_cnt <= 'd0;
end
//解析接收到的IP数据当中的udp数据内容
always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ro_udp_len <= 'd0;                       
    else 
        ro_udp_len <= ri_ip_len - 8;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ro_udp_last <= 'd0;              
    else if(r_udp_recv_cnt == ri_ip_len - 2)
        ro_udp_last <= 'd1;          
    else 
        ro_udp_last <= 'd0;
end

always @(posedge i_clk or posedge i_rst)begin
    if(i_rst)
        ro_udp_valid <= 'd0; 
    else if(r_udp_recv_cnt == ri_ip_len - 1)
        ro_udp_valid <= 'd0;             
    else if(r_udp_recv_cnt == 7)
        ro_udp_valid <= 'd1;          
    else 
        ro_udp_valid <= ro_udp_valid;
end

endmodule
相关推荐
阿尔帕兹3 分钟前
构建 HTTP 服务端与 Docker 镜像:从开发到测试
网络协议·http·docker
FeelTouch Labs25 分钟前
Netty实现WebSocket Server是否开启压缩深度分析
网络·websocket·网络协议
千天夜2 小时前
使用UDP协议传输视频流!(分片、缓存)
python·网络协议·udp·视频流
长弓三石3 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
xianwu5433 小时前
反向代理模块
linux·开发语言·网络·git
follycat3 小时前
[极客大挑战 2019]HTTP 1
网络·网络协议·http·网络安全
earthzhang20214 小时前
《深入浅出HTTPS》读书笔记(5):随机数
网络协议·http·https
xiaoxiongip6664 小时前
HTTP 和 HTTPS
网络·爬虫·网络协议·tcp/ip·http·https·ip
JaneJiazhao4 小时前
HTTPSOK:SSL/TLS证书自动续期工具
服务器·网络协议·ssl