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数据,一次输入的数据可能不是全部有效的,所以也是需要考虑多种情况。
相关文章:
10G MAC层设计系列-(2)MAC RX模块
一、概述 MAC RX模块的需要进行解码、对齐、CRC校验。 因为在空闲的时候10G PCS/PMA会一直向外吐空闲符(x07)所以需要根据开始符、结束符将有效数据从码流中截取,也就是解码。 因为开始字符的所在位置有两种形式,而结束字符的位…...
解码Starknet Verifier:深入逆向工程之旅
1. 引言 Sandstorm为: 能提交独立proof给StarkWare的Ethereum Verifier,的首个开源的STARK prover。 开源代码见: https://github.com/andrewmilson/sandstorm(Rust) L2Beat 提供了以太坊上Starknet的合约架构图&…...
【C++语言】类和对象--默认成员函数 (中)
文章目录 前言类的六个默认成员函数:1. 构造函数概念特性做了什么?易错注意:显式定义和默认构造函数 2. 析构函数概念特征做了什么?注意事项: 3.拷贝构造函数概念特征做了什么?注意事项: 4.赋值运算符重载…...
前端递归常见应用
概览 在 JavaScript 中,递归是一种编程技术,指的是函数直接或间接调用自身的过程。 递归通常用于解决可以分解为相同子问题的问题。通过不断地将问题分解成更小的、相似的子问题,直到达到某种基本情况(不再需要进一步递归的简单情…...
AI工具如何改变我们的工作与生活
AI工具在当今社会中扮演着越来越重要的角色,它们已经开始改变着我们的工作方式和生活方式。在接下来的2000字篇幅中,我将详细探讨AI工具如何影响我们的工作和生活。 AI工具在工作中的影响: 自动化和智能化生产流程: AI工具可以通…...
深入了解C/C++的内存区域划分
🔥个人主页:北辰水墨 🔥专栏:C学习仓 本节我们来讲解C/C的内存区域划分,文末会附加一道题目来检验成果(有参考答案) 一、大体有哪些区域?分别存放什么变量开辟的空间? …...
C++构造函数和析构函数的调用顺序
一般情况下,调用析构函数的次序正好与调用构造函数的次序相反,也就是最先被调用的构造函数,其对应的析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。 当然对象的构造函数和析构函数调用时机和…...
智能家居1 -- 实现语音模块
项目整体框架: 监听线程4: 1. 语音监听线程:用于监听语音指令, 当有语音指令过来后, 通过消息队列的方式给消息处理线程发送指令 2. 网络监听线程:用于监听网络指令,当有网络指令过来后, 通过消息队列的方…...
Leetcode 3139. Minimum Cost to Equalize Array
Leetcode 3139. Minimum Cost to Equalize Array 1. 解题思路2. 代码实现 题目链接:3139. Minimum Cost to Equalize Array 1. 解题思路 这一题是一道hard的题目,而且看了一下答出率低的离谱,就一开始被吓到了,不过实际做了一下…...
【element-ui】el-table横向滚动后,通过is-scrolling-left获取滚动高度失效的问题
el-table横向滚动后,通过is-scrolling-left获取滚动高度失效的问题 需求 现在有一个需求,需要监听el-table的纵向滚动,当滚动高度达到特定值时进行一些操作。 代码如下: methods:{throttledHandleScroll() {// 如果已经有定时器…...
JAVA中的日期
获取当前的日期 LocalDate LocalDate today LocalDate.now();System.out.println("今天是:"today);//今天是:2024-05-06String format today.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));System.out.println("今天是:"…...
一起了解开源自定义表单的优势表现
随着社会的进步和科技的发展,越来越多的中小企业希望采用更为先进的软件平台,助力企业实现高效率的流程化管理。低代码技术平台、开源自定义表单已经慢慢走入大众视野,成为一款灵活、高效的数字化转型工具。流辰信息专注于低代码技术平台的研…...
体育老师工资高吗,奖金有吗
教师的薪资水平与多种因素相关,包括教育经验、工作地点、学校类型以及个人的教学成果等。在讨论体育教师的工资问题时,不能仅仅关注数字,更应了解教育价值和个人发展。 初中体育教师的工资水平受多种因素影响。根据网络统计的数据,…...
Linux驱动开发——(十一)INPUT子系统
目录 一、input子系统简介 二、input驱动API 2.1 input字符设备 2.2 input_dev结构体 2.3 上报输入事件 2.4 input_event结构体 三、代码 3.1 驱动代码 3.2 测试代码 四、平台测试 一、input子系统简介 input子系统是管理输入的子系统,和pinctrl、gpio子…...
大数据毕业设计Python+Django旅游景点评论数据采集分析可视化系统 NLP情感分析 LDA主题分析 bayes分类 旅游爬虫 旅游景点评论爬虫 机器学习 深度学习 人工智能 计算机毕业设计
毕业论文(设计)开题报告 学生姓名 学 号 所在学院 信息工程学院 专 业 指导教师姓名 指导教师职称 工程师 助教 指导教师单位 论文(设计)题目 基于朴素贝叶斯算法旅游景点线上评价情感分析 开 题 报 告…...
FSNotes for Mac v6.7.1中文激活版:强大的笔记管理工具
FSNotes for Mac是一款功能强大的文本处理与笔记管理工具,为Mac用户提供了一个直观、高效的笔记记录和整理平台。 FSNotes for Mac v6.7.1中文激活版下载 FSNotes支持Markdown语法,使用户能够轻松设置笔记格式并添加链接、图像等元素,实现笔记…...
课程34:Windows Docker部署.Net Core项目
这里写目录标题 🚀前言一、安装Docker Desktop1.1 官网下载Docker1.2 安装Docker1.2.1 选择配置,默认都勾选1.2.2 安装中1.2.3 安装成功1.2.4 启动1.2.5 启动成功二、.Net Core 项目发布与部署2.1 修改Dockerfile文件2.2 Web项目发布2.3 修改配置2.3.1 修改dockerfile<...
分布式与一致性协议之ZAB协议(四)
ZAB协议 ZooKeeper是如何选举领导者的。 首先我们来看看ZooKeeper是如何实现成员身份的? 在ZooKeeper中,成员状态是在QuorumPeer.java中实现的,为枚举型变量 public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING }其实&…...
在M1芯片安装鸿蒙闪退解决方法
在M1芯片安装鸿蒙闪退解决方法 前言下载鸿蒙系统安装完成后,在M1 Macos14上打开闪退解决办法接下来就是按照提示一步一步安装。 前言 重新安装macos系统后,再次下载鸿蒙开发软件,竟然发现打不开。 下载鸿蒙系统 下载地址:http…...
Linux基础-socket详解、TCP/UDP
文章目录 一、Socket 介绍二、Socket 通信模型三、Socket 常用函数1 创建套接字2 绑定套接字3、监听连接4、接受连接5、接收和发送数据接收数据发送数据 6、关闭套接字 四、Socket编程试验1、源码server.cclient.c 2、编译:3、执行结果 五、补充TCP和UDP协议的Socke…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
