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

文章目录

  • 前言
  • 心得体会
  • 一、 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:     beginGMII_RX_DONE <= 0;if(GMII_DV_reg1 && !GMII_DV_reg2)begincurr_state <= PREAMBLE_CODE;crc_init <= 1;endelsecurr_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)beginGMII_ER_reg <= 0;GMII_DV_reg <= 0;GMII_TXD_reg<= 0;endelse beginGMII_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)beginGMII_DV_reg1 <= 0;GMII_DV_reg2 <= 0;GMII_TXD_reg1<= 0;GMII_TXD_reg2<= 0;crc_data        <= 0;endelsebeginGMII_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:begincrc_init <= 0;if(cnt_preamble == 4'd7)begincurr_state <= ETH_HEADER;cnt_preamble <= 0;endelsebegincnt_preamble <= cnt_preamble + 1'b1;curr_state <= curr_state;endend
  1. ETH_HEADER
    处于 ETH_HEADER 状态时,接收以太网头部数据,当接收完 14 个以太网头部数据之后,进入到 IP_HEADER 状态,如果接收不是7个55和一个D5,则表明此时数据接收错误,进入 IDLE 状态,然后当处于该状态的时候,根据 cnt_eth_header 的值,依次得到 14 个字节的以太网头部数据,分别是 MAC 目的地址(6 个字节)、MAC 源地址(6 个字节)和以太网类型(2 个字节),代码如下所示:
 ETH_HEADER:begincrc_en <= 1;if(cnt_eth_header == 4'd13)begincurr_state <= IP_HEADER;cnt_eth_header <= 0;endelse if((cnt_eth_header == 4'd0) && (preamble_code_check_ok == 1'b0))begincurr_state <= IDLE;cnt_eth_header <= 0;end	elsebegincnt_eth_header <= cnt_eth_header + 1'b1;curr_state <= curr_state;endcase(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: ;	endcaseend

其中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;elsepreamble_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:beginif(cnt_ip_header == 5'd19)begincurr_state <= UDP_HEADER;udp_data_length_reg <= ip_total_len - 16'd20 - 16'd8;cnt_ip_header <= 5'd0;ip_cal_en     <= 1;endelse if(cnt_ip_header >= 5'd1 && eth_header_check_ok == 1'b0)begincurr_state <= IDLE;cnt_ip_header <= 0;endelsebegincnt_ip_header <= cnt_ip_header + 1'b1;curr_state <= curr_state;endcase (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: ;endcaseend

(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;elseeth_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;elseip_header_check_ok <= 1'b0;

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

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

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

相关文章

光伏发电预测(LSTM、CNN_LSTM和XGBoost回归模型,Python代码)

运行效果&#xff1a;光伏发电预测&#xff08;LSTM、CNN_LSTM和XGBoost回归模型&#xff0c;Python代码&#xff09;_哔哩哔哩_bilibili 运行环境库的版本 光伏太阳能电池通过互连形成光伏模块&#xff0c;以捕捉太阳光并将太阳能转化为电能。因此&#xff0c;当光伏模块暴露…

windows 任务计划自动提交 笔记到github 、gitee

一、必须有个git仓库托管到git上。 这个就不用说了&#xff0c;自己在github或者码云上新建一个仓库就行了。 二、创建自动提交脚本 这个bat脚本是在windows环境下使用的。 注意&#xff1a;windows定时任务下 调用自动提交git前&#xff0c;必须先进入该git仓库目录&#x…

【Linux】线程控制

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️林 子       &#x1f6f0;️博客专栏&#xff1a;✈️ Linux       &#x1f6f0;️社区 :✈️ 进步学堂       &#x1f6f0…

DependsOn注解失效问题排查

文章目录 前言一、现象描述1.1.背景描述1.2.第一次修改&#xff0c;使用DependsOn注解1.3.第二次修改&#xff0c;设置方法入参 二、看看源码2.1.Spring实例化的源码2.2.调试2.3.验证 总结 前言 最近几天遇到一个比较有意思的问题&#xff0c;发现Spring的DependsOn注解失效&a…

CSS3与HTML5

box-sizing content-box&#xff1a;默认&#xff0c;宽高包不含边框和内边距 border-box&#xff1a;也叫怪异盒子&#xff0c;宽高包含边框和内边距 动画&#xff1a;移动translate&#xff0c;旋转、transform等等 走马灯&#xff1a;利用动画实现animation&#xff1a;from…

websocket拦截

python实现websocket拦截 前言一、拦截的优缺点优点缺点二、实现方法1.环境配置2.代码三、总结现在的直播间都是走的websocket通信,想要获取websocket通信的内容就需要使用websocket拦截,大多数是使用中间人代理进行拦截,这里将会使用更简单的方式进行拦截。 前言 开发者工…

【C++面向对象侯捷下】4. pointer-like classes,关于智能指针 | 5. function-like classes,所谓仿函数

文章目录 4. pointer-like classes,关于智能指针pointer-like classes,关于智能指针 shared_ptrpointer-like classes,关于迭代器5. function-like classes&#xff0c;所谓仿函数【不懂&#xff0c;跳过】 4. pointer-like classes,关于智能指针 pointer-like classes,关于智…

FFMPEG 视频类过滤器学习整理

针对FFMPEG提供视频过滤器进行了介绍,并提供使用实例 addroi 作用 在视频帧上标记一块感兴趣的区域。 帧数据被原封不动地传递,但元数据被附加到帧,指示可能影响后续编码行为的感兴趣区域。可以通过多次应用过滤器来标记多个区域。 参数 qoffset: 应用在此区域的量化偏…

C语言 - 数组

目录 1. 一维数组的创建和初始化 1.1 数组的创建 1.2 数组的初始化 1.3 一维数组的使用 1.4 一维数组在内存中的存储 2. 二维数组的创建和初始化 2.1 二维数组的创建 2.2 二维数组的初始化 2.3 二维数组的使用 2.4 二维数组在内存中的存储 3. 数组越界 4. 数组作为函数参数 4.1…

电脑上制定工作计划的软件有哪些?

在数字的时代&#xff0c;电脑成为了我们工作的得力助手&#xff0c;但在这个信息过载的年代&#xff0c;如何在电脑上制定高效的工作计划成了工作中必不可少的一项任务。我在工作中也曾经迷茫过&#xff0c;制定的各项计划不能按时完成&#xff0c;直到我找到一款可以辅助我办…

tomcat整体架构

Tomcat介绍 Tomcat是Apache Software Foundation&#xff08;Apache软件基金会&#xff09;开发的一款开源的Java Servlet 容器。它是一种Web服务器&#xff0c;用于在服务器端运行Java Servlet和JavaServer Pages (JSP)技术。它可 以为Java Web应用程序提供运行环境&#x…

Linux读写锁的容易犯的问题

Linux读写锁的容易犯的问题 读写锁是互斥锁之外的另一种用于多线程之间同步的一种方式。 多线程对于一个共享变量的读操作是安全的&#xff0c; 而写操作是不安全的。如果在一个读很多而写很少的场景之下&#xff0c;那么使用互斥锁将会阻碍大量的线程安全的读操作的进行。在…

腾讯云轻量和CVM有啥区别?怎么选择服务器配置?

腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器价格便宜&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境&#xff0c;云服务器CV…

关于Jupyter markdown的使用

一级标题 #空格 标题1 二级标题 ## 空格 标题2 三级标题 ###空格 标题3 无序&#xff1b; 有序&#xff1a; 数学符号&#xff1a;

记一次问题排查

1785年&#xff0c;卡文迪许在实验中发现&#xff0c;把不含水蒸气、二氧化碳的空气除去氧气和氮气后&#xff0c;仍有很少量的残余气体存在。这种现象在当时并没有引起化学家的重视。 一百多年后&#xff0c;英国物理学家瑞利测定氮气的密度时&#xff0c;发现从空气里分离出来…

Visual Studio 2019中的安全问题

最近&#xff0c;在使用Visual Studio 2019的时候遇到了一个很奇怪的问题&#xff0c;如下所示。 这里一直在说scanf函数不安全&#xff0c;导致报错&#xff0c;然后上网查了查相关资料&#xff0c;发现在代码中加那么一句就可以了&#xff0c;而且必须放在最前面。 #define …

网工内推 | IT高级运维工程师,周末双休,包吃包住,14-20k

01 深圳朗特智能控制股份有限公司 招聘岗位&#xff1a;IT高级运维工程师 职责描述&#xff1a; 1、对集团网络基础架构的建设、运维、安全制定相关标准和准则&#xff1b; 2、负责集团数据中心、核心设备、信息安全的管理和运维&#xff1b; 3、执行网络、服务器、核心交换机…

wpf中prism框架

安装prism包&#xff1a; 添加引用 using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows; using Prism.DryIoc; using Prism.Ioc;namespace PrismDemo …

A (1087) : DS单链表--类实现

Description 用C语言和类实现单链表&#xff0c;含头结点 属性包括&#xff1a;data数据域、next指针域 操作包括&#xff1a;插入、删除、查找 注意&#xff1a;单链表不是数组&#xff0c;所以位置从1开始对应首结点&#xff0c;头结点不放数据 类定义参考 #include<…

【考研复习】union有关的输出问题

文章目录 遇到的问题正确解答拓展参考文章 遇到的问题 首次遇到下面的代码时&#xff0c;感觉应该输出65,323。深入理解union的存储之后发现正确答案是&#xff1a;67,323. union {char c;int i; } u; int main(){u.c A;u.i 0x143;printf("%d,%d\n", u.c, u.i); …