10G UDP协议栈 (9)UDP模块

目录

一、UDP协议简单介绍

二、UDP功能实现

三、仿真

一、UDP协议简单介绍

UDP协议和TCP协议同位于传输层,介于网络层(IP)和应用层之间:UDP数据部分为应用层报文,而UDP报文在IP中承载。

UDP 报文格式相对于简单,如下图:


源端口:端口号0-65535,1-1024保留端口号,为标准的服务端口
目的端口:无须多解释
UDP长度:header+data 总长度
UDP校验和:伪头部,头部,data 三部分校验和。
数据:上层应用层的数据。

 UDP校验和计算:UDP校验和计算-CSDN博客

二、UDP功能实现

UDP_RX模块功能:接收IP层传递过来的数据,判断数据中的目的端口号是否与本节点的源端口号相同,同时执行UDP校验和计算。(由于此时的校验是对整个UDP首部+UDP伪首部+UDP数据进行校验,所以可以参考IP校验的方式,将数据暂存在一个RAM中,根据校验和的正确性控制地址的分配)。

UDP_TX模块功能:将上层传递过来的数据封装上UDP头,并进行UDP校验和计算。(此时的校验和计算可以先将封装完毕的UDP帧存储在一个RAM中,并在一帧的结尾单独对UDP校验和所在的地址进行操作)。

UDP_TX模块:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/22 10:38:55
// Design Name: 
// Module Name: UDP_TX
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module UDP_TX#(parameter           P_SOURCE_PORT = 16'd8080    ,parameter           P_TARGET_PORT = 16'd8080    
)(input               i_clk                       ,input               i_rst                       ,input  [15:0]       i_set_source_port           ,input               i_set_source_valid          ,input  [15:0]       i_set_target_port           ,input               i_set_target_valid          ,input  [63:0]       s_axis_user_data            ,input  [31:0]       s_axis_user_user            ,//16'dByteLen,16'dBrustinput  [7 :0]       s_axis_user_keep            ,input               s_axis_user_last            ,input               s_axis_user_valid           ,output              s_axis_user_ready           ,output [63:0]       m_axis_ip_data              ,output [70:0]       m_axis_ip_user              ,//16'dByteLen,1'bMF,16'dlen,1'bsplit,8'dtype,13'doffset,16'dIDoutput [7 :0]       m_axis_ip_keep              ,output              m_axis_ip_last              ,output              m_axis_ip_valid             ,input               m_axis_ip_ready             
);reg  [15:0]             ri_set_source_port          ;
reg  [15:0]             ri_set_target_port          ;
reg  [63:0]             rs_axis_user_data           ;
reg  [31:0]             rs_axis_user_user           ;
reg  [7 :0]             rs_axis_user_keep           ;
reg                     rs_axis_user_last           ;
reg                     rs_axis_user_valid          ;
reg                     rs_axis_user_ready          ;
reg  [63:0]             rm_axis_ip_data             ;
reg  [70:0]             rm_axis_ip_user             ;
reg  [7 :0]             rm_axis_ip_keep             ;
reg                     rm_axis_ip_last             ;
reg                     rm_axis_ip_valid            ;
reg                     r_fifo_data_rden            ;
reg  [15:0]             r_cnt                       ;
reg  [7 :0]             r_last_keep                 ;
reg                     r_fifo_data_empty           ;
reg                     r_fifo_data_empty_1d        ;wire [63:0]             w_fifo_data_dout            ;
wire                    w_fifo_data_full            ;
wire                    w_fifo_data_empty           ;assign s_axis_user_ready = rs_axis_user_ready       ;
assign m_axis_ip_data  = rm_axis_ip_data            ;
assign m_axis_ip_user  = rm_axis_ip_user            ;
assign m_axis_ip_keep  = rm_axis_ip_keep            ;
assign m_axis_ip_last  = rm_axis_ip_last            ;
assign m_axis_ip_valid = rm_axis_ip_valid           ;
//将用户传输的数据缓存
FIFO_DATA_64X256 FIFO_DATA_64X256_u0 (.clk                  (i_clk                      ), .srst                 (i_rst                      ),.din                  (rs_axis_user_data          ), .wr_en                (rs_axis_user_valid         ),.rd_en                (r_fifo_data_rden           ),.dout                 (w_fifo_data_dout           ),.full                 (w_fifo_data_full           ),.empty                (w_fifo_data_empty          )
);always@(posedge i_clk,posedge i_rst)
beginif(i_rst) beginr_fifo_data_empty <= 'd0;r_fifo_data_empty_1d <= 'd0;end else beginr_fifo_data_empty <= w_fifo_data_empty;r_fifo_data_empty_1d <= r_fifo_data_empty;end
end
//动态配置源端口、目的端口
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)ri_set_source_port <= P_SOURCE_PORT;else if(i_set_source_valid)ri_set_source_port <= i_set_source_port;else ri_set_source_port <= ri_set_source_port;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)ri_set_target_port <= P_TARGET_PORT;else if(i_set_target_valid)ri_set_target_port <= i_set_target_port;else ri_set_target_port <= ri_set_target_port;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst) beginrs_axis_user_data  <= 'd0;rs_axis_user_keep  <= 'd0;rs_axis_user_last  <= 'd0;rs_axis_user_valid <= 'd0;end else beginrs_axis_user_data  <= s_axis_user_data ;rs_axis_user_keep  <= s_axis_user_keep ;rs_axis_user_last  <= s_axis_user_last ;rs_axis_user_valid <= s_axis_user_valid;end
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst) rs_axis_user_user <= 'd0;else if(s_axis_user_valid)rs_axis_user_user  <= s_axis_user_user ;else rs_axis_user_user <= rs_axis_user_user;
end
//控制ready信号,当一帧输入时将ready信号拉低
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rs_axis_user_ready <= 'd1;else if(s_axis_user_last)rs_axis_user_ready <= 'd0;else if(r_fifo_data_empty_1d)rs_axis_user_ready <= 'd1;else rs_axis_user_ready <= rs_axis_user_ready;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_last_keep <= 'd0;else if(s_axis_user_last)r_last_keep <= s_axis_user_keep;else r_last_keep <= r_last_keep;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_cnt <= 'd0;else if(r_cnt == rs_axis_user_user[15:0])r_cnt <= 'd0;else if(r_fifo_data_rden || r_cnt)r_cnt <= r_cnt + + 1;else r_cnt <= r_cnt;
end
//控制fifo读使能,当FIFO不为空的时候开始读
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_fifo_data_rden <= 'd0;else if(r_cnt == rs_axis_user_user[15:0] - 1)r_fifo_data_rden <= 'd0;else if(!w_fifo_data_empty)r_fifo_data_rden <= 'd1;else         r_fifo_data_rden <= r_fifo_data_rden;
end 
//组UDP帧
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_ip_data <= 'd0;else case(r_cnt)0           :rm_axis_ip_data <= {ri_set_source_port,ri_set_target_port,rs_axis_user_user[31:16] + 16'd8,16'd0};//源端口号、目的端口号、UDP长度、UDP校验和(暂时为0)default     :rm_axis_ip_data <= w_fifo_data_dout;endcase
end
//控制Keep信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_ip_keep <= 'd0;else if(r_cnt && r_cnt == rs_axis_user_user[15:0] - 0)rm_axis_ip_keep <= r_last_keep;else rm_axis_ip_keep <= 8'b1111_1111;
end
//控制Last信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_ip_last <= 'd0;else if(r_cnt && r_cnt == rs_axis_user_user[15:0] - 0)rm_axis_ip_last <= 'd1;else rm_axis_ip_last <= 'd0;
end
//控制Valid信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_ip_valid <= 'd0;else if(rm_axis_ip_last)rm_axis_ip_valid <= 'd0;else if(r_fifo_data_rden)rm_axis_ip_valid <= 'd1;else        rm_axis_ip_valid <= rm_axis_ip_valid;
end//16'dByteLen,1'bMF,16'dlen,1'bsplit,8'dtype,13'doffset,16'dID
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_ip_user <= 'd0;else rm_axis_ip_user <= {rs_axis_user_user[31:16] + 16'd8,1'b0,rs_axis_user_user[15:0] + 16'd1,1'b0,8'd17,13'd0,16'd0};
endendmodule

UDP_RX模块:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/22 10:38:55
// Design Name: 
// Module Name: UDP_RX
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module UDP_RX#(parameter           P_SOURCE_PORT = 16'd8080    ,parameter           P_TARGET_PORT = 16'd8080    
)(input               i_clk                       ,input               i_rst                       ,input  [15:0]       i_set_source_port           ,input               i_set_source_valid          ,input  [15:0]       i_set_target_port           ,input               i_set_target_valid          ,input  [63:0]       s_axis_ip_data              ,input  [54:0]       s_axis_ip_user              ,//1'bMF,16'dlen,1'bsplit,8'dtype,13'doffset,16'dIDinput  [7 :0]       s_axis_ip_keep              ,input               s_axis_ip_last              ,input               s_axis_ip_valid             ,
//上层数据output [63:0]       m_axis_user_data            ,output [31:0]       m_axis_user_user            ,output [7 :0]       m_axis_user_keep            ,output              m_axis_user_last            ,output              m_axis_user_valid           
);reg  [15:0]             ri_set_source_port          ;
reg  [15:0]             ri_set_target_port          ;
reg  [63:0]             rs_axis_ip_data             ;
reg  [54:0]             rs_axis_ip_user             ;
reg  [7 :0]             rs_axis_ip_keep             ;
reg                     rs_axis_ip_last             ;
reg                     rs_axis_ip_valid            ;
reg  [63:0]             rm_axis_user_data           ;
reg  [31:0]             rm_axis_user_user           ;
reg  [7 :0]             rm_axis_user_keep           ;
reg                     rm_axis_user_last           ;
reg                     rm_axis_user_valid          ;
reg  [15:0]             r_cnt                       ;
reg  [15:0]             r_source_port               ;
reg  [15:0]             r_target_port               ;
reg  [15:0]             r_len                       ;
reg  [7 :0]             r_last_keep                 ;   
reg                     r_udp_flag                  ;
reg                     r_port_check                ;assign m_axis_user_data  = rm_axis_user_data        ;
assign m_axis_user_user  = rm_axis_user_user        ;
assign m_axis_user_keep  = rm_axis_user_keep        ;
assign m_axis_user_last  = rm_axis_user_last        ;
assign m_axis_user_valid = rm_axis_user_valid       ;always@(posedge i_clk,posedge i_rst)
beginif(i_rst) beginrs_axis_ip_data  <= 'd0;rs_axis_ip_user  <= 'd0;rs_axis_ip_keep  <= 'd0;rs_axis_ip_last  <= 'd0;rs_axis_ip_valid <= 'd0;end else beginrs_axis_ip_data  <= s_axis_ip_data ;rs_axis_ip_user  <= s_axis_ip_user ;rs_axis_ip_keep  <= s_axis_ip_keep ;rs_axis_ip_last  <= s_axis_ip_last ;rs_axis_ip_valid <= s_axis_ip_valid;end    
end
//动态配置端口号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)ri_set_source_port <= P_SOURCE_PORT;else if(i_set_source_valid)ri_set_source_port <= i_set_source_port;else ri_set_source_port <= ri_set_source_port;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)ri_set_target_port <= 'd0;else if(i_set_target_valid)ri_set_target_port <= i_set_target_port;else ri_set_target_port <= ri_set_target_port;
end
//保存最后一次的Keep信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_last_keep <= 'd0;else if(s_axis_ip_last)r_last_keep <= s_axis_ip_keep;else r_last_keep <= 8'b1111_1111;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_cnt <= 'd0;else if(rs_axis_ip_valid)r_cnt <= r_cnt + 1;else r_cnt <= 'd0;
end
//获取IP层传递过来的数据的源端口号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_source_port <= 'd0;else if(rs_axis_ip_valid && r_cnt == 0)r_source_port <= rs_axis_ip_data[63:48];else r_source_port <= r_source_port;
end
//获取IP层传递过来的数据的目的端口号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_target_port <= 'd0;else if(rs_axis_ip_valid && r_cnt == 0)r_target_port <= rs_axis_ip_data[47:32];else r_target_port <= r_target_port;
end
//检测获取的源端口号是否等于本节点的目的端口号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_port_check <= 'd0;else if(r_cnt == 1 && r_target_port != ri_set_source_port)       r_port_check <= 'd0;else if(r_cnt == 1 && r_target_port == ri_set_source_port)r_port_check <= 'd1;else r_port_check <= r_port_check;
end
//获取数据净荷的长度
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_len <= 'd0;else if(rs_axis_ip_valid && r_cnt == 0)r_len <= rs_axis_ip_data[31:16] - 16'd8;else r_len <= r_len;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_user_data <= 'd0;elserm_axis_user_data <= rs_axis_ip_data;
end
//控制向上传递的USER信号,其中r_len代表字节长度,(r_len - 16'd1) >> 16'd3代表以8字节为单位的传输次数
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_user_user <= 'd0;else rm_axis_user_user <= {r_len,((r_len - 16'd1) >> 16'd3) + 16'd1};
end 
//控制keep信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)rm_axis_user_keep <= 'd0;else if(rs_axis_ip_last)rm_axis_user_keep <= r_last_keep;else rm_axis_user_keep <= 8'b1111_1111;
end
//控制Last信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)   rm_axis_user_last <= 'd0;else if(rs_axis_ip_last && rm_axis_user_valid)rm_axis_user_last <= 'd1;else rm_axis_user_last <= 'd0;
end
//控制Valid信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)  rm_axis_user_valid <= 'd0;else if(rm_axis_user_last)rm_axis_user_valid <= 'd0;else if(rs_axis_ip_valid && r_cnt == 1 && r_port_check && r_udp_flag)rm_axis_user_valid <= 'd1;else rm_axis_user_valid <= rm_axis_user_valid;
end
//检查本次从IP层获取的信号是否为UDP数据
always@(posedge i_clk,posedge i_rst)
beginif(i_rst)  r_udp_flag <= 'd0;else if(s_axis_ip_valid && !rs_axis_ip_valid && s_axis_ip_user[36:29] != 17)r_udp_flag <= 'd0;else if(s_axis_ip_valid && !rs_axis_ip_valid && s_axis_ip_user[36:29] == 17)r_udp_flag <= 'd1;else r_udp_flag <= r_udp_flag;
endendmodule

三、仿真

UDP_TX模块:

UDP_RX模块:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/18695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑出现:excel词典(xllex.dll)文件丢失或损坏的错误提示怎么办?有效的将丢失的xllex.dll修复

当遇到 Excel 提示“词典 (xllex.dll) 文件丢失或损坏”的问题时&#xff0c;通常意味着该动态链接库文件&#xff08;Dynamic Link Library&#xff0c;DLL&#xff09;&#xff0c;它与拼写检查功能相关联的&#xff0c;无法被正确找到或者合适地使用。那么有什么办法可以解决…

LLVM技术在GaussDB等数据库中的应用

目录 LLVM和数据库 LLVM适用场景 LLVM对所有类型的SQL都会有收益吗&#xff1f; LLVM在OLTP中就一定没有收益吗&#xff1f; GaussDB中的LLVM 1. LLVM在华为应用于数据库的时间线 2. GaussDB LLVM实现简析 3. GaussDB LLVM支持加速的场景 支持LLVM的表达式&#xff1a…

vue项目出现多次ElMessage

问题&#xff1a; 解决方法&#xff1a; let message null if (message null) { message ElMessage.error(“登录过期,请重新登录”); } 最终效果&#xff1a;只出现一个弹框

Orange AIpro Color triangle帧率测试

OpenGL概述 OpenGL ES是KHRNOS Group推出的嵌入式加速3D图像标准&#xff0c;它是嵌入式平台上的专业图形程序接口&#xff0c;它是OpenGL的一个子集&#xff0c;旨在提供高效、轻量级的图形渲染功能。现推出的最新版本是OpenGL ES 3.2。OpenGL和OpenCV OpenCL不同&#xff0c;…

实操专区-第15周-课堂练习专区-漏斗图与金字塔图

实操专区-第15周-课堂练习专区-漏斗图 下载安装ECharts&#xff0c;完成如下样式图形。 代码和截图上传 基本要求&#xff1a;下图3选1&#xff0c;完成代码和截图 完成 3.1.3.16 漏斗图中的任务点 基本要求&#xff1a;2个选一个完成&#xff0c;多做1个加2分。 请用班级学号姓…

银行对公贷款软件业务流程详解

对公贷款业务是指商业银行向企事业单位提供资金支持&#xff0c;用于资本扩充、生产经营、项目建设等方面的融资。其目的在于支持企事业单位的发展&#xff0c;推动经济增长。通过提供资金支持&#xff0c;企事业单位可以获得必要的资金来扩大生产规模、提高生产能力、研发新产…

第8周 分布式事务与数据一致性主流解决方案落地

第8周 分布式事务与数据一致性主流解决方案落地 1. 最终一致性原理与解析2. 微服务的解耦3. 本地消息存储4. 自定义事务管理器5. 本地消息删除********************************************************************************** 本周拓展数据的一致性落地&#xff0c;采用弱…

【Java EE】网络原理——HTTP请求

目录 1.认识URL 2.认识“方法&#xff08;method&#xff09;” 2.1GET方法 2.1.1使用Fiddler观察GET请求 2.1.2 GET请求的特点 2.2 POST方法 2.2.1 使用FIddler观察POST方法 2.2.2 POST请求的特点 3.认识请求“报头”&#xff08;header&#xff09; 3.1 Host 3.2 C…

Spring MVC 工作流程源码分析

前言&#xff1a; 我们知道 Spring MVC 的核心是前端控制器 DispatcherServlet&#xff0c;客户端所有的请求都会交给 DispatcherServlet 来处理&#xff0c;本篇我我们来分析 Spring MVC 处理客户端请求的流程&#xff0c;也就是工作流程。 Sping MVC 只是储备传送门&#x…

Java整合EasyExcel实战——3(上下列相同合并单元格策略)

参考&#xff1a;https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06 准备条件 依赖 <dependency><groupId>com.alibaba</gr…

邻接矩阵广度优先遍历

关于图的遍历实际上就两种 广度优先和深度优先&#xff0c;一般关于图的遍历都是基于邻接矩阵的&#xff0c;考试这些&#xff0c;用的也是邻接矩阵。 本篇文章先介绍广度优先遍历的原理&#xff0c;和代码实现 什么是图的广度优先遍历&#xff1f; 这其实和二叉树的层序遍…

新人学习笔记之(数组1)

一、数组的概念 1.数组&#xff08;Array&#xff09;可以把一组相关的数据一起存放&#xff0c;并提供方便的访问&#xff08;获取&#xff09;方式 2.数组是指一组数据的集合&#xff0c;其中的每个数据被称作元素&#xff0c;在数组中可以存放任意类型的元素&#xff0c;数组…

数据结构——二叉树的基本应用

在此之前我们已经初步了解了二叉树&#xff0c;在介绍堆的基本应用时&#xff0c;我们已经具体介绍了完全二叉树的基本应用&#xff0c;本章我们介绍二叉树的基本应用&#xff0c;这个不止指的是完全二叉树&#xff0c;而是指泛型的二叉树。 二叉树的基本应用&#xff0c;由于…

代码随想录算法训练营第54天|● 392.判断子序列 ● 115.不同的子序列

392. 判断子序列 这个微软面试的时候考过 双指针就行 编辑距离入门题&#xff1a; 思路是一样的 相同字符1 否则从前面顺下来 class Solution:def isSubsequence(self, s: str, t: str) -> bool:dp[[0]*(len(t)1) for _ in range(len(s)1)]for i in range(1,len(s)1):f…

aspose-*的使用

文章目录 aspose-*一、依赖--maven二、需求1、word------>pdf2、doc------>docx2、xls------>xlsx aspose-* 一、依赖–maven 备注&#xff1a;第三方的jar包可以从资源中下载&#xff0c;有上传的 <!--aspose依赖--><dependency><groupId>aspose…

刷代码随想录有感(81):贪心算法——分发饼干

题干&#xff1a; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int index s.size() - 1;int res 0;for(int i g.size() - 1; i > 0; i--){if(index >…

GitLab项目中添加用户,并设置其角色权限等

注意&#xff1a;创建用户(new user)&#xff0c;创建完用户然后再项目邀请用户&#xff0c;选择创建过的用户 一、以管理员身份登录GitLab的WebUI并创建用户 1>.使用管理员登录GitLab 使用管理员(root)用户登录成功后&#xff0c;点击如下图所示的小扳手&#xff0c;点击…

java 反射的用法

下面是一个简单的Java反射示例&#xff0c;演示了如何使用反射机制获取类的信息并调用其方法&#xff1a; import java.lang.reflect.Method;class MyClass {private String name;public void setName(String name) {this.name name;}public String getName() {return name;}…

C++数据结构之:链List

摘要&#xff1a; it人员无论是使用哪种高级语言开发东东&#xff0c;想要更高效有层次的开发程序的话都躲不开三件套&#xff1a;数据结构&#xff0c;算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合&#xff0c;即带“结构”的数据元素的集合&am…

在HTML和CSS当中运用显示隐藏

1.显示与隐藏 盒子显示:display:block;盒子隐藏: display:none:隐藏该元素并且该元素所占的空间也不存在了。 visibility:hidden:隐藏该元素但是该元素所占的内存空间还存在&#xff0c;即“隐身效果”。 2.圆角边框 在CSS2中添加圆角&#xff0c;我们不得不使用背景图像&am…