基于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
相关推荐
0zxm10 分钟前
06 - Django 视图view
网络·后端·python·django
stm 学习ing1 小时前
HDLBits训练5
c语言·fpga开发·fpga·eda·hdlbits·pld·hdl语言
超能力MAX1 小时前
IIC驱动EEPROM
单片机·嵌入式硬件·fpga开发
轩辰~1 小时前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
燕雀安知鸿鹄之志哉.1 小时前
攻防世界 web ics-06
网络·经验分享·安全·web安全·网络安全
ProcessOn官方账号2 小时前
如何绘制网络拓扑图?附详细分类解说和用户案例!
网络·职场和发展·流程图·拓扑学
Ven%2 小时前
如何在防火墙上指定ip访问服务器上任何端口呢
linux·服务器·网络·深度学习·tcp/ip
神的孩子都在歌唱3 小时前
TCP/IP 模型中,网络层对 IP 地址的分配与路由选择
网络·tcp/ip·智能路由器
阿雄不会写代码3 小时前
ubuntu安装nginx
linux·服务器·网络