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

UDP层报文解析

UDP层报文内容很简单:
在这里插入图片描述
源端口号:自身的端口号
目的端口号:接收方的端口号
UDP长度:UDP首部+数据的长度
UDP校验和:与IP校验合算法一致,不同的是UDP层对UDP头和数据部分都进行校验。

一、UDP_TX模块

发送模块的设计大同小异。
设计代码为本人参考FPGA奇哥系列网课自行编写

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模块

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
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顺子学不会FPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值