千兆以太网传输层 UDP 协议原理与 FPGA 实现(UDP接收)

news2025/1/13 7:24:45

文章目录

  • 前言
  • 心得体会
  • 一、 UDP 协议简单回顾
  • 二、UDP接收实现
  • 三、完整代码展示
  • 四、仿真测试
    • (1)模拟电脑数据发送,
    • (2)测试顶层文件编写
    • (3)仿真文件
    • (4)仿真波形


前言

在前面我们对以太网 UDP 帧格式做了讲解,UDP 帧格式包括前导码+帧界定符、以太网头部数据、IP 头部数据、UDP 头部数据、UDP 数据、FCS 数据,以太网接收模块同样是按照该格式接收数据。

提示:任何文章不要过度深思!万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案」 ;不要急着评判文章列出的观点,只需代入其中,适度审视一番自己即可,能「跳脱出来从外人的角度看看现在的自己处在什么样的阶段」才不为俗人 。怎么想、怎么做,全在乎自己「不断实践中寻找适合自己的大道」

心得体会

(1)UDP接收数据,无论是MAC地址,还是IP地址,或者UDP端口,其源端口都为计算机;
(2)在接收数据时不关心源端口(计算机)的MAC地址,还是IP地址,或者UDP端口,只关心目的地址,也就是说接收数据时可以将源端口MAC地址,IP地址,UDP端口全部置 0;
(3)验证时一定要弄清目的地址(开发板)的MAC和P地址,这里与UDP发送中目的MAC、IP(计算机)是相反的,此处需要注意;
(4)本实验针对千兆网,注意查看电脑是否支持。

一、 UDP 协议简单回顾

以太网 UDP 帧的用户数据是打包在 UDP 协议中,而 UDP 协议又是基于 IP 协议之上的,IP 协议又是走 MAC 层发送的,即从包含关系来说:MAC 帧中的数据段为 IP 数据报文,IP 报文中的数据段为 UDP 报文,UDP 报文中的数据段为用户希望传输的数据内容下图为使用 UDP 协议发送数据的层层打包示意图。
在这里插入图片描述
其中,和以太网帧、IP 报文具有帧头一样,UDP 数据报也包含了一个 UDP 报头部分,与 UDP 协议相关的一些信息如端口号,数据包长度等会被打包进 UDP 报头中,然后再与需要传输的 UDP 报文数据一起,作为 IP 报文的数据段送往 IP 层发送。

二、UDP接收实现

GMII 接口信号连接关系及各信号的介绍如下。
1
(注:表格中的方向是站在 MAC 侧角度看的)

在这里插入图片描述
此处给出GMII 接口信号连接关系及各信号的介绍,是为了明确UDP发送与接收需要什么输入与输出。

下面将对各个状态的实现及功能进行简要介绍。

  1. IDLE
    空闲状态,当产生接收数据有效信号时,进入PREAMBLE_CODE状态,否则处于 IDLE 状态,代码如下所示:
 IDLE:     begin
							    GMII_RX_DONE <= 0;
								if(GMII_DV_reg1 && !GMII_DV_reg2)
									begin
										  curr_state <= PREAMBLE_CODE;
										  crc_init <= 1;
									end
								else
								  curr_state <= curr_state;
							end

上述代码中的GMII_DV_reg1 信号是将接收数据有效信号GMII_DV寄存之后打一拍得到的,GMII_DV_reg2 信号是将GMII_DV_reg1信号打一拍得到的,将GMII_DV_reg2 信号取反与
GMII_DV_reg1 相与得到接收数据有效脉冲,得到该信号之后,进入到PREAMBLE_CODE 状态,
在这里插入图片描述

GMII_DV_reg1 信号和GMII_DV_reg2 信号的实现代码如下所示,代码中对GMII_TXD 信号也进
行了寄存和打拍操作,得到crc_data用于计算crc校验判断与接收到的CRC值是否一致,后续有关crc_xx名称均为计算crc校验所需输入。

//输入数据寄存
	always @ (posedge clk125m_o  or  negedge reset_n)
		if(!reset_n)
			begin
				GMII_ER_reg <= 0;
				GMII_DV_reg <= 0;
				GMII_TXD_reg<= 0;
			end
		else begin
		        GMII_ER_reg <= GMII_ER;
				GMII_DV_reg <= GMII_DV;
				GMII_TXD_reg<= GMII_TXD;
		     end
			
	
	
	
	//数据打两拍判断接收起始
	always @ (posedge clk125m_o  or negedge reset_n)
	    if(!reset_n)
			begin
			
				GMII_DV_reg1 <= 0;
				GMII_DV_reg2 <= 0;
				
				GMII_TXD_reg1<= 0;
				GMII_TXD_reg2<= 0;
				crc_data        <= 0;
			
			end
		else
			begin
					GMII_DV_reg1 <= GMII_DV_reg;
					GMII_DV_reg2 <= GMII_DV_reg1;
					
					GMII_TXD_reg1<= GMII_TXD_reg;
					GMII_TXD_reg2<= GMII_TXD_reg1;
					crc_data     <= GMII_TXD_reg2;   
					
			end
	
  1. PREAMBLE_CODE 状态
    处于 PREAMBLE_CODE状态的时候,当以太网接收到帧界定符(D5)和 7 个的前导码(55)
    时,进入到ETH_HEADER 状态,代码如下所示:
PREAMBLE_CODE:
								begin
									crc_init <= 0;
									if(cnt_preamble == 4'd7)
									  begin
										  curr_state <= ETH_HEADER;
										  cnt_preamble <= 0;
									  end
									  
									
									else
										begin
											cnt_preamble <= cnt_preamble + 1'b1;
											curr_state <= curr_state;
										end
                                end
  1. ETH_HEADER
    处于 ETH_HEADER 状态时,接收以太网头部数据,当接收完 14 个以太网头部数据之后,进入到 IP_HEADER 状态,如果接收不是7个55和一个D5,则表明此时数据接收错误,进入 IDLE 状态,然后当处于该状态的时候,根据 cnt_eth_header 的值,依次得到 14 个字节的以太网头部数据,分别是 MAC 目的地址(6 个字节)、MAC 源地址(6 个字节)和以太网类型(2 个字节),代码如下所示:
 ETH_HEADER:begin
								crc_en <= 1;
								if(cnt_eth_header == 4'd13)
									begin
										curr_state <= IP_HEADER;
										cnt_eth_header <= 0;
									end
								else if((cnt_eth_header == 4'd0) && (preamble_code_check_ok == 1'b0))
									begin
										curr_state <= IDLE;
										cnt_eth_header <= 0;
									end	
								else
									begin
										cnt_eth_header <= cnt_eth_header + 1'b1;
										curr_state <= curr_state;
									end
								
								case(cnt_eth_header)
									 
									  4'd0 :dst_mac_reg[47:40] <= GMII_TXD_reg2;   
									  4'd1 :dst_mac_reg[39:32] <= GMII_TXD_reg2;
									  4'd2 :dst_mac_reg[31:24] <= GMII_TXD_reg2;
									  4'd3 :dst_mac_reg[23:16] <= GMII_TXD_reg2;
									  4'd4 :dst_mac_reg[15:8]  <= GMII_TXD_reg2;
									  4'd5 :dst_mac_reg[7:0]   <= GMII_TXD_reg2;

									  4'd6 :src_mac_reg[47:40] <= GMII_TXD_reg2;
									  4'd7 :src_mac_reg[39:32] <= GMII_TXD_reg2;
									  4'd8 :src_mac_reg[31:24] <= GMII_TXD_reg2;
									  4'd9 :src_mac_reg[23:16] <= GMII_TXD_reg2;
									  4'd10:src_mac_reg[15:8]  <= GMII_TXD_reg2;
									  4'd11:src_mac_reg[7:0]   <= GMII_TXD_reg2;

									  4'd12:eth_type[15:8] <= GMII_TXD_reg2;
									  4'd13:eth_type[7:0]  <= GMII_TXD_reg2;
									  default: ;	
									
								endcase
						    end

其中preamble_code_check_ok为:

always @ (posedge clk125m_o  or negedge reset_n)
		if(!reset_n)
			preamble_code_check_ok <= 1'b0;
		else if((GMII_TXD_reg2 == 8'hd5) && (cnt_preamble == 4'd7))
			preamble_code_check_ok <= 1'b1;
		else
			preamble_code_check_ok <= 1'b0;
  1. IP_HEADER
    (1)接收以太网 IP 头部数据状态IP_HEADER,首先得对接收的以太网 IP 头部数据进行计数,定义一个计数器 cnt_ip_header,当处于该状态的时候进行计数,否则清零,
    (2)然后当处于 IP_HEADER 状态时,获取以太网 IP 头部数据,根据 cnt_ip_header 的值,一共需要获取 20 个字节的数据,分别为 IP 版本(ip_ver)、首部长度(ip_hdr_len)、服务类型(ip_tos)、数据报总长度(total_len)、标识主机发送的每一份数据报(ip_id)、标志位(ip_rsv、ip_df、ip_mf)、段偏移量(ip_frag_offset)、生存期(ip_ttl)、IP 的协议封装类型(ip_protocol)、头部校验和(ip_check_sum)、源 IP 地址(src_ip)和目的 IP 地址(dst_ip),代码如下所示:
IP_HEADER:begin
									if(cnt_ip_header == 5'd19)
									    begin
										    curr_state <= UDP_HEADER;
											udp_data_length_reg <= ip_total_len - 16'd20 - 16'd8;
											cnt_ip_header <= 5'd0;
											ip_cal_en     <= 1;
											
										end
									else if(cnt_ip_header >= 5'd1 && eth_header_check_ok == 1'b0)
									    begin
											curr_state <= IDLE;
											cnt_ip_header <= 0;
											
										end
									else
										begin
											cnt_ip_header <= cnt_ip_header + 1'b1;
											curr_state <= curr_state;
										end
									case (cnt_ip_header)
										          5'd0:   {
   ip_ver,ip_hdr_len}                       <= GMII_TXD_reg2;
												  5'd1:   ip_tos                                    <= GMII_TXD_reg2;
												  5'd2:   ip_total_len[15:8]                        <= GMII_TXD_reg2;
												  5'd3:   ip_total_len[7:0]                         <= GMII_TXD_reg2;
												  5'd4:   ip_id[15:8]                               <= GMII_TXD_reg2;
												  5'd5:   ip_id[7:0]                                <= GMII_TXD_reg2;
												  5'd6:   {
   ip_rsv,ip_df,ip_mf,ip_frag_offset[12:8]} <= GMII_TXD_reg2;
												  5'd7:   ip_frag_offset[7:0]                       <= GMII_TXD_reg2;
												  5'd8:   ip_ttl                                    <= GMII_TXD_reg2;
												  5'd9:   ip_protocol                               <= GMII_TXD_reg2;
												  5'd10:  ip_check_sum[15:8]                        <= GMII_TXD_reg2;
												  5'd11:  ip_check_sum[7:0]                         <= GMII_TXD_reg2;
												  5'd12:  src_ip_reg[31:24]                         <= GMII_TXD_reg2;
												  5'd13:  src_ip_reg[23:16]                         <= GMII_TXD_reg2;
												  5'd14:  src_ip_reg[15:8]                          <= GMII_TXD_reg2;
												  5'd15:  src_ip_reg[7:0]                           <= GMII_TXD_reg2;
												  5'd16:  dst_ip_reg[31:24]                         <= GMII_TXD_reg2;
												  5'd17:  dst_ip_reg[23:16]                         <= GMII_TXD_reg2;
												  5'd18:  dst_ip_reg[15:8]                          <= GMII_TXD_reg2;
												  5'd19:  dst_ip_reg[7:0]                           <= GMII_TXD_reg2;      
												  default: ;
										
					                endcase
					        end

(3)在 ETH_HEADER 状态时,我们获取了以太网头部数据,进入本状态 IP_HEADER 之后,需要判断之前获取的以太网头部数据是否正确,当获取的数据类型等于 ETH_type(0x0800),得到的 MAC 地址等于代码中设定的值Local_mac 时,则代表以太网头部数据接收成功将eth_header_check_ok 信号拉高,否则为低,

always @ (posedge clk125m_o  or negedge reset_n)
		if(!reset_n)
			eth_header_check_ok <= 1'b0;
		
		else if((eth_type == ETH_type) && (dst_mac_reg == Local_mac) )
		
			eth_header_check_ok <= 1'b1;
		else
			eth_header_check_ok <= 1'b0;
  1. UDP_HEADER
    (1)接收 UDP 头部数据状态 UDP_HEADER,进入该状态之后,首先设置一个计数cnt_udp_header 用来计数得到的 UDP 头部数据的个数,
    (2)在 UDP_HEADER 状态时,需要判断前一个状态获取的以太网 IP 头部数据是否正确,当获取的数据正确时,将 ip_header_check_ok 信号拉高,否则为低,
always @ (posedge clk125m_o  or negedge reset_n)
		if(!reset_n)
			ip_header_check_ok <= 1'b0;
		else if({IP_ver,IP_hdr_len,IP_protocol,Check_sum,Local_ip} == 
          {ip_ver,ip_hdr_len,ip_protocol,ip_check_sum,dst_ip_reg})
			ip_header_check_ok <= 1'b1;
		else
			ip_header_check_ok <= 1'b0;

(3)当 cnt_udp_header 计数到 1并且 ip_header_check_ok 信号为 0 时,则代表接收数据出
错,返回 IDLE 状态;当 cnt_udp_header

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

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

相关文章

Ride基本使用

基本使用步骤&#xff1a; 创建项目(New Project)创建模块(New Directory)创建测试套件(New Suite)创建测试用例(New Test Case)创建资源文件(New Resource)创建业务关键字(New User Keyword)常用关键字用例编写robot报告显示 创建项目(New Project) File --> New Project…

程序无法启动,提示“找不到msvcp140.dll”或“msvcp140.dll缺失报错”解决方法

大家好&#xff01;今天我来给大家分享一下msvcp140.dll丢失的解决方法。我们都知道&#xff0c;在运行一些软件或游戏时&#xff0c;经常会遇到“找不到msvcp140.dll”的错误提示&#xff0c;这会让我们非常苦恼。那么&#xff0c;这个问题该怎么解决呢&#xff1f;下面我将为…

如何理解分布式锁?

分布式锁的实现有哪些&#xff1f; 1.Memcached分布式锁 利用Memcached的add命令。此命令是原子操作&#xff0c;只有在key不存在的情况下&#xff0c;才能add成功&#xff0c;也就意味着线程得到了锁。 2.Reids分布式锁 和Memcached的方式类似&#xff0c;利用Redis的setn…

“益路同行”栏目专访第12期——泰格智能AI英语·李勤骞老师

中国善网在本届&#xff08;第十届&#xff09;慈展会上特别推出了《益路同行》采访栏目&#xff0c;《益路同行》栏目旨在寻觅公益之路上同行者的故事&#xff0c;挖掘公益更深层次的内涵&#xff0c;探索新时代公益发展道路。希望公益企业、人物、故事被更多人看到&#xff0…

HEC-RAS 1D/2D水动力与水环境模拟技术案例实践及拓展应用

水动力与水环境模型的数值模拟是实现水资源规划、环境影响分析、防洪规划以及未来气候变化下预测和分析的主要手段。然而&#xff0c;一方面水动力和水环境模型的使用非常复杂&#xff0c;理论繁复&#xff1b;另一方面&#xff0c;免费的水动力和水环境软件往往缺少重要功能&a…

蓝桥杯 字符串和日期

有一个类型的题目是找到输出图形的规律&#xff0c;然后将其实现。观察下面的图形。你想想你该怎么输出这个图形呢? ABBB#include<stdio.h> int main(){printf(" A\n");printf("BBB\n");return 0; }那么&#xff0c;对于如下的图形&#xff1a; ABB…

9 家用热水器用户行为分析与事件识别

第9章 家用热水器用户行为分析与事件识别 9.1 了解家用热水器用户行为分析的背景与步骤9.1.1 热水器采集数据基本情况9.1.2 熟悉家用热水器用户行为分析的步骤与流程 9.2 预处理热水器用户用水数据9.2.1 删除冗余特征9.2.2 划分用水事件9.2.3 确定单次用水事件时长阈值9.2.4 代…

C++并发与多线程(4) | 传递临时对象作为线程参数的一些问题Ⅰ

一、陷阱1 写一个传递临时对象作为线程参数的示例: #include <iostream> #include <vector> #include <thread> using namespace std;void myprint(const int& i, char* pmybuf) {cout << i << endl;cout << pmybuf << endl;r…

Python 无废话-基础知识列表list详讲

本文详细的介绍了在Python中如何处理list数据类型&#xff0c;涉及了Python 基础知识列表list 详讲&#xff0c;包含list 定义、遍历循环、元素获取、切片、添加、删除、查找元素&#xff0c;以后列表在函数、copy中使用。 列表List数据类型 列表特征 1) 列表中的各个元素&…

06. 机器学习入门2 - 理解特征和向量

文章目录 机器学习初探特征和向量机器学习的通用框架梯度下降 Hi, 你好。我是茶桁。 上一节课&#xff0c;咱们用一个案例引入了机器学习的话题&#xff0c;并跟大家讲了一下「动态规划」。 那这节课&#xff0c;我们要真正进入机器学习。 机器学习初探 在正式开始之前&…

什么是CAS机制?

CAS和Synchronized的区别是什么&#xff1f;适合什么样的场景&#xff1f;有什么样的优点和缺点&#xff1f; 示例程序&#xff1a;启动两个线程&#xff0c;每个线程中让静态变量count循环累加100次。 public class ThreadTest {private static int count 0;public static …

数据统计--图形报表--ApacheEcharts技术 --苍穹外卖day10

Apache Echarts 营业额统计 重点:已完成订单金额要排除其他状态的金额 根据时间选择区间 设计vo用于后端向前端传输数据,dto用于后端接收前端发送的数据 GetMapping("/turnoverStatistics")ApiOperation("营业额统计")public Result<TurnoverReportVO…

CamoDroid 与 Frida Android动态分析工具搭建流程(linux)

CamoDroid 与 Frida Android动态分析工具搭建流程&#xff08;linux&#xff09; 写在前面 这个东西配置起来比较复杂&#xff0c;其实最主要就是配置frida&#xff0c;如果你之前就使用过frida框架的话问题就不是很大 介绍camodroid CamoDroid 是一个开源和开放架构的 And…

图片素材免费下载,高清无水印,无需担心版权问题。

找图片素材就上这8个网站&#xff0c;免费可商用&#xff0c;建议收藏起来~ 1、菜鸟图库 https://www.sucai999.com/pic.html?vNTYwNDUx 网站主要为新手设计师提供免费素材&#xff0c;这些素材的质量都很高&#xff0c;类别也很多&#xff0c;像平面、UI、电商、视频、图片…

JVM命令行监控工具

JVM命令行监控工具 概述 性能诊断是软件工程师在日常工作中需要经常面对和解决的问题&#xff0c;在用户体验至上的今天&#xff0c;解决好应用的性能问题能带来非常大的收益。 Java作为最流行的编程语言之一&#xff0c;其应用性能诊断一直受到业界广泛关注&#xff0c;可能…

【Spring MVC研究】MVC如何浏览器请求(service方法)

文章目录 1. DispatcherServlet 的 service 方法1.1. processRequest 方法1.2. doService 方法 背景&#xff1a;平时我们学习 MVC 重点关注的时DispatcherServlet 的 doDispatcher 方法&#xff0c;但是在 doDispatcher 方法之前 还有请求处理的前置过程&#xff0c;这个过程…

B站涨粉,UP主涨粉技巧有哪些?

B 站作为深受年轻人喜爱的社交媒体平台&#xff0c;是一个不断生产优质内容的多元化文化社区&#xff0c;有不少视频出圈。随着视频行业的成熟发展&#xff0c;视频创作者们的竞争愈发激烈&#xff0c;不少创作者有涨粉难&#xff0c;曝光差的困扰。而UP主连续不断的涨粉不仅取…

CS5210芯片设计|CS5210设计方案|HDMI转VGA方案|

CS5210方案应用&#xff0c;CS5210方案设计&#xff0c;HDMI转VGA方案&#xff0c;国产集睿致远研发CS5210 HDMI到VGA转换器结合了HDMI输入接口和模拟RGB DAC输出。支持内部LDO&#xff0c;节省成本&#xff0c;优化电路板空间。CS5210适用于各种市场和显示应用程序&#xff0c…

ToBeWritten之车联网安全中常见的TOP 10漏洞

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

MySql 终端常用指令

一、开发背景 利用数据库实现数据的增删改查 二、开发环境 Window10 mysql-8.0.33-win64 三、实现步骤 1、管理员模式打开终端 2、登录数据库&#xff08;停止 开启 登录&#xff09; 具体指令参考 MySql 安装篇 ​​​​​​​ ​​…