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

news/2024/5/18 14:41:24 标签: fpga开发, udp, 网络协议, 网络

文章目录

  • UDP层报文解析
  • 一、UDP_TX模块
  • 二、UDP_RX模块

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

http://www.niftyadmin.cn/n/5447087.html

相关文章

Debezium日常分享系列之:Debezium2.5稳定版本之处理常见问题

Debezium日常分享系列之&#xff1a;Debezium2.5稳定版本之处理常见问题 一、配置和启动错误二、MySQL 不可用三、Kafka Connect stops gracefully四、Kafka Connect 进程崩溃五、Kafka变得不可用六、MySQL 清除 binlog 文件七、Debezium技术总结 下面描述 Debezium 如何处理各…

rider下ef core迁移

新建数据库 create database mockstu新建web项目 安装Microsoft.EntityFrameworkCore.SqlServer包 设置连接字符串 新建model using MockStuWeb.Models.EnumTypes; using System.ComponentModel.DataAnnotations;namespace MockStuWeb.Models {/// <summary>/// 学生…

ubuntu arm qt 读取execl xls表格数据

一&#xff0c;ubuntu linux pc编译读取xls的库 1&#xff0c;安装libxls(读取xls文件 电脑版) 确保你已经安装了基本的编译工具&#xff0c;如gcc和make。如果没有安装&#xff0c;可以使用以下命令安装&#xff1a; sudo apt-update sudo apt-get install build-essentia…

LEETCODE-DAY30

title: LEETCODE-DAY30 date: 2024-03-22 16:28:30 tags: 今日内容&#xff1a;332.重新安排行程 、51. N皇后 、37. 解数独 、总结 今日三题都是hard&#xff0c;了解思路即可 回溯总结篇 T1 class Solution:def findItinerary(self, tickets: List[List[str]]) -> Li…

Day45:WEB攻防-PHP应用SQL二次注入堆叠执行DNS带外功能点黑白盒条件

目录 PHP-MYSQL-二次注入-DEMO&74CMS DEMO-用户注册登录修改密码 CMS-74CMS个人中心简历功能 PHP-MYSQL-堆叠注入-DEMO&CTF强网 Demo 2019强网杯-随便注&#xff08;CTF题型&#xff09; PHP-MYSQL-带外注入-DEMO&DNSLOG(让服务器主动把数据交出去) 知识点&…

idea使用token方式登录GitHub

总体上分为两大步&#xff1a;1.GitHub生成token。2.idea配置token登录GitHub。 注&#xff1a;idea配置GitHub的前提是本地已经安装了git程序。 一、GitHub生成token 1.登录GitHub 2.进入token创建页面&#xff08;右上角点击头像–>settings–>页面向下滚动左侧菜单栏…

一文详解Rust中的字符串

有人可能会说&#xff0c;字符串这么简单还用介绍&#xff1f;但是很多人学习rust受到的第一个暴击就来自这浓眉大眼、看似毫无难度的字符串。 请看下面的例子。 fn main() {let my_name "World!";greet(my_name); }fn greet(name: String) {println!("Hello…

5.7、【AI技术新纪元:Spring AI解码】Prompts

翻译: Spring AI 中的 Prompts 处理 Prompts 是指导 AI 模型生成特定输出的输入。这些 Prompts 的设计和措辞显著影响模型的响应。 在与 Spring AI 模型交互的最基础层面上,处理 Prompts 有点类似于在 Spring MVC 中管理“视图”。这涉及创建带有动态内容占位符的大量文本。…