10G MAC层设计系列-(2)MAC RX模块

一、概述

MAC RX模块的需要进行解码、对齐、CRC校验。

因为在空闲的时候10G PCS/PMA会一直向外吐空闲符(x07)所以需要根据开始符、结束符将有效数据从码流中截取,也就是解码。

因为开始字符的所在位置有两种形式,而结束字符的位置不确定,所以需要根据开始字符、结束字符的位置将数据进行对齐。

在将数据对齐的同时,还需要将获取到的有效数据进行CRC校验,这里就需要设计64bit CRC-32校验。

开始、结束、空闲、错误 控制字符

二、具体实现

 1、检测开始、结束字符的位置

assign w_sof = (ri_xgmii_rxc[7] && ri_xgmii_rxd[63:56] == 8'hFB) ||(ri_xgmii_rxc[3] && ri_xgmii_rxd[31:24] == 8'hFB) ;
assign w_sof_local = (ri_xgmii_rxc[7] && ri_xgmii_rxd[63:56] == 8'hFB) ? 0: 1;
assign w_eof = (ri_xgmii_rxc[0] && ri_xgmii_rxd[7:  0] == 8'hFE) ||(ri_xgmii_rxc[1] && ri_xgmii_rxd[15: 8] == 8'hFE) ||(ri_xgmii_rxc[2] && ri_xgmii_rxd[23:16] == 8'hFE) ||(ri_xgmii_rxc[3] && ri_xgmii_rxd[31:24] == 8'hFE) ||(ri_xgmii_rxc[4] && ri_xgmii_rxd[39:32] == 8'hFE) ||(ri_xgmii_rxc[5] && ri_xgmii_rxd[47:40] == 8'hFE) ||(ri_xgmii_rxc[6] && ri_xgmii_rxd[55:48] == 8'hFE) ||(ri_xgmii_rxc[7] && ri_xgmii_rxd[63:56] == 8'hFE) ;assign w_eof_local = (ri_xgmii_rxc[1] && ri_xgmii_rxd[15: 8] == 8'hFE) ? 6 :(ri_xgmii_rxc[2] && ri_xgmii_rxd[23:16] == 8'hFE) ? 5 :(ri_xgmii_rxc[3] && ri_xgmii_rxd[31:24] == 8'hFE) ? 4 :(ri_xgmii_rxc[4] && ri_xgmii_rxd[39:32] == 8'hFE) ? 3 :(ri_xgmii_rxc[5] && ri_xgmii_rxd[47:40] == 8'hFE) ? 2 :(ri_xgmii_rxc[6] && ri_xgmii_rxd[55:48] == 8'hFE) ? 1 :(ri_xgmii_rxc[7] && ri_xgmii_rxd[63:56] == 8'hFE) ? 0 :7;

2、获取目的MAC、源MAC、帧类型

//获取目的MAC
always@(posedge i_clk,posedge i_rst)beginif(i_rst)r_target_mac <= 'd0;  elseif(r_sof_local == 0 && r_cnt == 1)r_target_mac <= ri_xgmii_rxd_ff1[55:8];else if(r_sof_local == 1 && r_cnt == 1)r_target_mac <= {ri_xgmii_rxd_ff1[23:0],ri_xgmii_rxd[63:40]};elser_target_mac <= r_target_mac;
end
//获取源MAC
always@(posedge i_clk,posedge i_rst)beginif(i_rst)r_source_mac <= 'd0;elseif(r_sof_local == 0 && r_cnt == 1)r_source_mac <= {ri_xgmii_rxd_ff1[7:0],ri_xgmii_rxd[63:24]};else if(r_sof_local == 1 && r_cnt == 2)r_source_mac <= {ri_xgmii_rxd_ff1[39:0],ri_xgmii_rxd[63:56]};elser_source_mac <= r_source_mac;
end
//获取帧类型
always@(posedge i_clk,posedge i_rst)beginif(i_rst)r_type <= 'd0; elseif(r_sof_local == 0 && r_cnt == 2)r_type <= ri_xgmii_rxd_ff1[23:8];else if(r_sof_local == 1 && r_cnt == 3)r_type <= ri_xgmii_rxd_ff1[55:40];elser_type <= r_type;
end

这里需要了解一下标准以太网帧的帧格式

 在提取MAC字段之前需要去除前导码:56‘h55555555_555555,SFD:8‘hD5。

3、对齐数据

根据开始字符的位置对齐数据

always@(posedge i_clk,posedge i_rst)beginif(i_rst)rm_axis_data <= 'd0;elseif(r_sof_local == 0 && r_run)rm_axis_data <= {ri_xgmii_rxd_ff1[7:0],ri_xgmii_rxd[63:8]};else if(r_sof_local == 1 && r_run)rm_axis_data <= {ri_xgmii_rxd_ff1[39:0],ri_xgmii_rxd[63:40]};elserm_axis_data <= 'd0;
end

因为使用的AXI-Stream接口,所以需要根据结束字符的位置处理最后一次传输的KEEP信号、Valid信号、Last信号

//keep信号处理!!!!
always@(posedge i_clk,posedge i_rst)beginif(i_rst)rm_axis_keep <= 'd0;elseif(r_run && !r_run_ff1)rm_axis_keep <= 8'b1111_1111;else if(rm_axis_last)rm_axis_keep <= 'd0;else if(r_sof_local == 0 && w_eof)case(w_eof_local)0           : rm_axis_keep <= 8'b1000_0000;1           : rm_axis_keep <= 8'b1100_0000;2           : rm_axis_keep <= 8'b1110_0000;3           : rm_axis_keep <= 8'b1111_0000;4           : rm_axis_keep <= 8'b1111_1000;5           : rm_axis_keep <= 8'b1111_1100;6           : rm_axis_keep <= 8'b1111_1110;7           : rm_axis_keep <= 8'b1111_1111;default     : rm_axis_keep <= 8'b1111_1111;endcaseelse if(r_sof_local == 1 && w_eof && w_eof_local <= 3)case(w_eof_local)0           : rm_axis_keep <= 8'b1111_1000;1           : rm_axis_keep <= 8'b1111_1100;2           : rm_axis_keep <= 8'b1111_1110;3           : rm_axis_keep <= 8'b1111_1111;4           : rm_axis_keep <= 8'b1000_0000;5           : rm_axis_keep <= 8'b1100_0000;6           : rm_axis_keep <= 8'b1110_0000;7           : rm_axis_keep <= 8'b1111_0000;default     : rm_axis_keep <= 8'b1111_1111;endcase else if(r_sof_local == 1 && r_eof && r_eof_local >= 4)case(r_eof_local)0           : rm_axis_keep <= 8'b1111_1000;1           : rm_axis_keep <= 8'b1111_1100;2           : rm_axis_keep <= 8'b1111_1110;3           : rm_axis_keep <= 8'b1111_1111;4           : rm_axis_keep <= 8'b1000_0000;5           : rm_axis_keep <= 8'b1100_0000;6           : rm_axis_keep <= 8'b1110_0000;7           : rm_axis_keep <= 8'b1111_0000;default     : rm_axis_keep <= 8'b1111_1111;endcase         elserm_axis_keep <= rm_axis_keep;
endalways@(posedge i_clk,posedge i_rst)beginif(i_rst)rm_axis_last <= 1'b0;elseif(r_sof_local == 0 && w_eof)rm_axis_last <= 1'b1;else if(r_sof_local == 1 && w_eof && w_eof_local <= 3)rm_axis_last <= 1'b1;else if(r_sof_local == 1 && r_eof && r_eof_local >= 4)rm_axis_last <= 1'b1;else rm_axis_last <= 1'b0;end
///valid信号,用r_run的上升沿判断数据开始
always@(posedge i_clk,posedge i_rst)beginif(i_rst)rm_axis_valid <= 1'b0;else if(rm_axis_last)rm_axis_valid <= 1'b0;else if(r_run && !r_run_ff1)rm_axis_valid <= 1'b1;elserm_axis_valid <= rm_axis_valid;
end

4、CRC校验

在进行字节对齐的过程中,需要进行CRC校验,在此过程中使用的标准以太网的CRC-32校验。

因为校验开始的位置是从目的MAC开始的,因此需要从目的MAC字段对齐数据。

always@(posedge i_clk,posedge i_rst)beginif(i_rst)r_crc_data <= 'd0;elseif(r_sof_local == 0)if(r_sof_ff2)r_crc_data <= {ri_xgmii_rxd_ff2[55:0],ri_xgmii_rxd_ff1[63:56]};else if(r_eof || r_eof_ff1)r_crc_data <= {ri_xgmii_rxd_ff2[55:0],ri_xgmii_rxd_ff1[63:56]};else if(r_run_ff1)r_crc_data <= {ri_xgmii_rxd_ff2[55:0],ri_xgmii_rxd_ff1[63:56]};else r_crc_data <= 'd0; else if(r_sof_ff2)r_crc_data <= {ri_xgmii_rxd_ff2[23:0],ri_xgmii_rxd_ff1[63:24]};else if(r_eof || r_eof_ff1)r_crc_data <= {ri_xgmii_rxd_ff2[23:0],ri_xgmii_rxd_ff1[63:24]};else if(r_run)r_crc_data <= {ri_xgmii_rxd_ff2[23:0],ri_xgmii_rxd_ff1[63:24]};elser_crc_data <= 'd0;
end

在此过程中需要一个使能信号,指示需要对当前的数据进行CRC校验

//CRC_en控制
always@(posedge i_clk,posedge i_rst)beginif(i_rst)r_crc_en <= 'd0;elseif(r_sof_local == 0)if(r_sof_ff2)r_crc_en <= 1'b1;else if(r_eof)r_crc_en <= 1'b1;else if(r_eof_ff1)case(r_eof_local)0           :r_crc_en <= 1'b0;1           :r_crc_en <= 1'b0;2           :r_crc_en <= 1'b0;3           :r_crc_en <= 1'b0;4           :r_crc_en <= 1'b0;5           :r_crc_en <= 1'b0;6           :r_crc_en <= 1'b1;//剩余一个数据,需要再次拉高crc_en7           :r_crc_en <= 1'b1;//剩余两个数据,需要再次拉高crc_endefault     :r_crc_en <= 1'b0;endcase                else if(r_eof_ff2)r_crc_en <= 1'b0;else r_crc_en <= r_crc_en; else if(r_sof_ff2)r_crc_en <= 1'b1;else if(w_eof)r_crc_en <= 1'b1;               else if(r_eof)case(r_eof_local)0           :r_crc_en <= 1'b0;//1           :r_crc_en <= 1'b0;2           :r_crc_en <= 1'b1;3           :r_crc_en <= 1'b1;4           :r_crc_en <= 1'b1;5           :r_crc_en <= 1'b1;6           :r_crc_en <= 1'b1;7           :r_crc_en <= 1'b1;default     :r_crc_en <= 1'b0;endcaseelse if(r_eof_ff1)r_crc_en <= 1'b0;elser_crc_en <= r_crc_en;
end

最后也需要对CRC数据的最后一次传输的有效数据进行指示,这里加入一个CRC_KEEP信号,指示最后一次传输的有效数据。

//CRC_KEEP处理!!!!
always@(posedge i_clk,posedge i_rst)beginif(i_rst)r_crc_keep <= 'd0;elseif(r_sof_ff2)r_crc_keep <= 8'b1111_1111;// else if((!r_crc_en && r_crc_en_ff1) || r_eof_ff2)//     r_crc_keep <= 8'b0000_0000;else if(r_sof_local == 0 && r_eof)case(r_eof_local)0           : r_crc_keep <= 8'b1110_0000;1           : r_crc_keep <= 8'b1111_0000;2           : r_crc_keep <= 8'b1111_1000;3           : r_crc_keep <= 8'b1111_1100;4           : r_crc_keep <= 8'b1111_1110;5           : r_crc_keep <= 8'b1111_1111;default     : r_crc_keep <= 8'b1111_1111;endcaseelse if(r_sof_local == 0 && r_eof_ff1)case(r_eof_local)6           : r_crc_keep <= 8'b1000_0000;7           : r_crc_keep <= 8'b1100_0000;default     : r_crc_keep <= r_crc_keep;endcase   else if(r_sof_local == 1 && w_eof)case(w_eof_local)0           : r_crc_keep <= 8'b1111_1110;1           : r_crc_keep <= 8'b1111_1111;2           : r_crc_keep <= 8'b1111_1111;3           : r_crc_keep <= 8'b1111_1111;4           : r_crc_keep <= 8'b1111_1111;5           : r_crc_keep <= 8'b1111_1111;6           : r_crc_keep <= 8'b1111_1111;7           : r_crc_keep <= 8'b1111_1111;default     : r_crc_keep <= 8'b1111_1111;endcase else if(r_sof_local == 1 && r_eof)case(r_eof_local)// 0           : r_crc_keep <= 8'b1111_1000;// 1           : r_crc_keep <= 8'b1111_1100;2           : r_crc_keep <= 8'b1000_0000;3           : r_crc_keep <= 8'b1100_0000;4           : r_crc_keep <= 8'b1110_0000;5           : r_crc_keep <= 8'b1111_0000;6           : r_crc_keep <= 8'b1111_1000;7           : r_crc_keep <= 8'b1111_1100;default     : r_crc_keep <= r_crc_keep;endcase // else if(r_sof_local == 1 && r_eof && r_eof_local >= 4)//     case(r_eof_local)//         0           : r_crc_keep <= 8'b1111_1000;//         1           : r_crc_keep <= 8'b1111_1100;//         2           : r_crc_keep <= 8'b1111_1110;//         3           : r_crc_keep <= 8'b1111_1111;//         4           : r_crc_keep <= 8'b1000_0000;//         5           : r_crc_keep <= 8'b1100_0000;//         6           : r_crc_keep <= 8'b1110_0000;//         7           : r_crc_keep <= 8'b1111_0000;//         default     : r_crc_keep <= 8'b1111_1111;//     endcase         elser_crc_keep <= r_crc_keep;
end

 5、CRC模块

CRC的生成公式采用的标准以太网的CRC-32的公式,这里可以参考此篇文章。

三、总结

MAC RX模块主要的难点就在于数据KEEP信号的处理以及相应的64bit的 CRC-32模块的实现。KEEP信号要考虑到开始、结束字符的位置,因此需要处理多种情况。而CEC模块的那点主要在于对于多Bytw数据,一次输入的数据可能不是全部有效的,所以也是需要考虑多种情况。

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

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

相关文章

白盒测试与黑盒测试区别和联系

一、概念辨析 白盒测试 黑盒测试 二、其他测试方法 三、相关练习

算法训练营第十三天 | LeetCode 239 滑动窗口最大值、LeetCode 347 前K个高频元素

LeetCode 239 滑动窗口最大值 本体初始思路是这样的&#xff0c;首先看下给定数组长度和维持一个滑动窗口所需要花费的时间复杂度之间的关系。初步判断是还行的&#xff0c;当然后面被样例打脸了。需要更新成优先队列的解法。原本的解法能通过37/51和46/51的测试用例。但这还不…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.5--I.MX6U启动方式

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

VS Code工具将json数据格式化

诉求&#xff1a;json数据格式化应该在工作中用到的地方特别多&#xff0c;为了更方便、更仔细的对json数据查看&#xff0c;将json数据格式化是非常有必要的。 VS Code中如何将json数据快速格式化 1、在VS Code中安装Beautify JSON插件 2、安装完后在需要格式化的文件中按住…

Web APIs 学习归纳6--- BOM浏览器对象

前面几节主要针对DOM进行了学习&#xff0c;现在开始新的内容的学习---DOM浏览器对象。 DOM是更注重页面&#xff08;document&#xff09;内容的设计&#xff0c;但是BOM不仅限于页面&#xff08;document&#xff09;的设计&#xff0c;而是更加全面包括页面的刷新&#xff0…

【linux学习指南】linux指令与实践文件编写

文章目录 &#x1f4dd;前言&#x1f320; linux目录结构&#x1f309;linux命令介绍 &#x1f320;pwd命令&#x1f309;mkdir指令&#xff08;重要&#xff09; &#x1f320;cd 指令&#x1f309;touch指令 &#x1f320;rmdir指令 && rm 指令&#xff08;重要&…

抖音评论区精准获客自动化获客释放双手

挺好用的&#xff0c;评论区自动化快速获客&#xff0c;如果手动点引流涨&#xff0c;那就很耗费时间了&#xff0c;不是吗&#xff1f; 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x 提取码&#xff1a;0b8x

Dashboard 安装部署

Dashboard 安装部署 Dashboard 安装部署 一&#xff1a;下载 二&#xff1a;部署步骤 1.镜像下载及导入 国内直接拉外网镜像会失败&#xff0c;可在境外下载镜像 查看 deployment 里的镜像版本 Dashboard Deploymentcontainers:- name: kubernetes-dashboardimage: k8s.g…

Unity Audio Filter 入门

概述&#xff1a; 如果你在你项目中需要一些特殊的声音效果&#xff0c;那这部分声音过滤器的部分一定不要错过喔&#xff0c;让我们来学习这部分的内容吧&#xff01; 这部分理论性比较强&#xff0c;认真看我的注解哈&#xff0c;我尽量解释的易懂一点。 Audio Chorus Filter…

Intelij Idea Push失败,出现git Authentication failed(验证失败)

目录 1、出现问题的原因 2、解决之法 1、出现问题的原因 能出现这种问题&#xff0c;最主要的原因是链接对上了&#xff0c;但用户验证失败了&#xff0c;即登录失败。 因为服务器转移或者换了git项目链接&#xff0c;导致你忘记了用户名密码&#xff0c;随意输入之后&…

持续更新|UNIAPP适配APP遇到的问题以及解决方案

在使用UNIAPP开发APP的时候遇到的一些奇奇怪怪问题记录 组件样式丢失 问题&#xff1a;组件引入界面中&#xff0c;在小程序和H5环境下样式正常&#xff0c;而在APP中却出现高度异常问题 解决&#xff1a;增加view标签将组件包裹起来即可正常显示 解决前&#xff1a; 解决后…

数据结构:实验七:数据查找

一、 实验目的 &#xff08;1&#xff09;领会各种查找算法的过程和算法设计。 &#xff08;2&#xff09;掌握查找算法解决实际问题。 二、 实验要求 &#xff08;1&#xff09;编写一个程序exp8-1.cpp, 按提示输入10个任意的整形数据&#xff08;无序&#xff09;&…

Mysql_数据库事务

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a; MySQL__事务&#xff09; ⏱️ 创作时间&#xff1a;2024年04月26日 ———————————————— 这里写目…

服务端不 listen 可以创建 tcp 连接吗

这个问题有三类答案。 上来就撸 linux kernel 源码&#xff0c;折腾半天&#xff0c;哦&#xff0c;终于在 tcp_rcv_state_process 里找到了 tcp_rcv_synsent_state_process 调用&#xff0c;后者包含&#xff1a; if (th->syn) {/* We see SYN without ACK. It is attemp…

【golang-ent】go-zero框架 整合 ent orm框架实现一对一 一对多 多种姿势查询方式

一、ent的 O2O 问题 官方文档如下: https://entgo.io/zh/docs/schema-edges#o2o-same-type 1、ent O2O问题 官方提供了三种 one2one的方式,可以看到他全部使用了 mysql的 foregionKey 的方式进行关联,虽然举例了单表和双表的不同使用方式,但是我们实际使用mysql中是不创建…

【R语言数据分析】函数

目录 自定义函数 apply函数 分类汇总函数aggregate 自定义函数 R语言中的自定义函数更像是在自定义一种运算规则。 自定义函数的语法是 函数名 函数体 } 比如 表示定义了一个名为BMI_function的函数&#xff0c;这个函数代表了一种运算规则&#xff0c;就是把传入的x和…

目标检测算法YOLOv3简介

YOLOv3由Joseph Redmon等人于2018年提出&#xff0c;论文名为&#xff1a;《YOLOv3: An Incremental Improvement》&#xff0c;论文见&#xff1a;https://arxiv.org/pdf/1804.02767.pdf &#xff0c;项目网页&#xff1a;https://pjreddie.com/darknet/yolo/ 。YOLOv3是对YOL…

Node.js -- express 框架

文章目录 1. express 使用2. 路由2.1 路由的使用2.2 获取请求报文参数2.3 获取路由参数2.4 路由参数练习 3. express 响应设置4. 中间件4.1 全局中间件4.2 路由中间件4.3 静态资源中间件 5. 获取请求体数据 body-parser6. 防盗链7. 路由模块化8. 模板引擎8.1 了解EJS8.2 列表渲…

【C++】深入理解string类

一、熟悉string类 1.1 string类的由来&#xff1a; C语音中的字符串需要我们自己管理底层空间&#xff0c;容易内存泄露。而C是面向对象语音&#xff0c;所以它把字符串封装成一个string类。 C中对于string的定义为&#xff1a;typedef basic_string string; 也就是说C中的str…

java面试(微服务)

SpringCloud五大组件 Nacos&#xff1a;注册中心Ribbon&#xff1a;负载均衡Feign&#xff1a;远程调用sentinel&#xff1a;服务熔断Gateway&#xff1a;网关 注册中心 Eureka Nacos 负载均衡 Ribbon负载均衡流程 Ribbon的负载均衡策略 RoundRobinRule&#xff1a;简单的…