万兆以太网MAC设计(2)MAC_RX模块
文章目录
- 前言
- 一、模块功能
- 二、代码
- 三、仿真波形
前言
上文我们打通了了万兆以太网物理层和数据链路层,其实就是会使用IP核了,本文将正式开始MAC层设计第一篇,接收端设计。
一、模块功能
MAC_RX模块功能如下:
- 解析接收的报文:接受报文的目的MAC、源MAC、报文类型
- 将XGMII接口输入数据转化为AXIS的数据流形式传递给上层用户
难点在于数据格式的转化,最主要的是尾端KEEP信号该如何与有效数据进行对齐。
数据恢复的过程:
- 判断起始位SOF和起始位的位置:起始字节8‘hFB’位置存在俩种情况:第一种情况自然是在接收数据的第一个字节位置,但也存在在第五个字节位置的情况,所以需要分情况讨论。

- 关键字段信息提取:根据起始位置的不同,目的MAC以及源MAC和类型信息都要分情况进行讨论。
- 数据恢复:同理,恢复数据也需要讨论。
- 结束位EOF以及结束位的位置判断 :结束位有八种情况,一拍数据64bit,结束位可能存在在任何一个byte上。
- 尾端KEPP对齐,根据起始位位置以及结束位位置,尾端KEEP信号需要讨论各种情况。
- AXIS数据转换 :前面相当于把KEEP和DATA信号处理好了,然后还需要产生VALID、LAST、USER信号。
二、代码
设计思路参考了FPGA奇哥系列网课
注意一下几点:
- 老生常谈的大小端问题,进入该模块的数据全部应该是大端数据,我完全是按照大端进行处理的。
- LAST信号和KEEP信号分类讨论条件是一样的,俩者是在数据尾端同时进行变化的,根据最后一拍有效数据字节数的多少,LAST信号会在不同的时刻拉高(在r_eof拉高或w_eof拉高时刻)。
- USER信号是用户自定义的,我这里暂时定义为接收数据的源MAC的低16位加类型(16位)。
- 万兆以太网控制字符定义:

module TEN_GIG_MAC_RX(input i_clk ,input i_rst ,input [63:0] i_xgmii_rxd ,input [7 :0] i_xgmii_rxc ,output [63:0] m_axis_rdata ,output [31:0] m_axis_ruser ,//用户自定义{r_src_mac[15:0],r_type}output [7 :0] m_axis_rkeep ,output m_axis_rlast ,output m_axis_rvalid
);
/******************************function*****************************//******************************parameter****************************/
localparam P_FRAME_IDLE = 8'h07 ,P_FRAME_START = 8'hFB ,P_FRAME_END = 8'hFD ,P_FRAME_EEROR = 8'hFE ;
/******************************mechine******************************//******************************reg**********************************/
reg [63:0] ri_xgmii_rxd ;
reg [63:0] ri_xgmii_rxd_1d ;
reg [7 :0] ri_xgmii_rxc ;
reg [7 :0] ri_xgmii_rxc_1d ;
reg [63:0] rm_axis_rdata ;
//reg [63:0] rm_axis_rdata_1d ;
reg [31:0] rm_axis_ruser ;
reg [7 :0] rm_axis_rkeep ;
reg rm_axis_rlast ;
reg rm_axis_rvalid ;
//解析接收数据
reg [15:0] r_recv_cnt ;
reg r_comma ;
reg [47:0] r_dst_mac ;
reg [47:0] r_src_mac ;
reg [15:0] r_type ;
reg r_data_run ;//开始产生axis输出数据
reg r_data_run_1d ;
reg r_data_run_2d ;reg r_sof ;
reg r_eof ;
reg [2 :0] r_sof_location ;
reg [2 :0] r_eof_location ;
/******************************wire*********************************/
wire w_sof ;
wire w_eof ;
wire [2 :0] w_sof_location ;
wire [2 :0] w_eof_location ;
/******************************component****************************//******************************assign*******************************/
assign m_axis_rdata = rm_axis_rdata ;
assign m_axis_ruser = rm_axis_ruser ;
assign m_axis_rkeep = rm_axis_rkeep ;
assign m_axis_rlast = rm_axis_rlast ;
assign m_axis_rvalid = rm_axis_rvalid ;
//进入该模块的数据已经全部被转换为大端模式
//开始字符以及位置判断
assign w_sof = ((ri_xgmii_rxd[63:56] == P_FRAME_START) && (ri_xgmii_rxc[7] == 1)) || ((ri_xgmii_rxd[31:24] == P_FRAME_START) && (ri_xgmii_rxc[3] == 1));
assign w_sof_location = ((ri_xgmii_rxd[63:56] == P_FRAME_START) && (ri_xgmii_rxc[7] == 1)) ? 7 : ((ri_xgmii_rxd[31:24] == P_FRAME_START) && (ri_xgmii_rxc[3] == 1)) ? 3 :0;
//结束字符以及位置判断
assign w_eof = ((ri_xgmii_rxd[63:56] == P_FRAME_END) && (ri_xgmii_rxc[7] == 1)) || ((ri_xgmii_rxd[55:48] == P_FRAME_END) && (ri_xgmii_rxc[6] == 1)) ||((ri_xgmii_rxd[47:40] == P_FRAME_END) && (ri_xgmii_rxc[5] == 1)) ||((ri_xgmii_rxd[39:32] == P_FRAME_END) && (ri_xgmii_rxc[4] == 1)) ||((ri_xgmii_rxd[31:24] == P_FRAME_END) && (ri_xgmii_rxc[3] == 1)) ||((ri_xgmii_rxd[23:16] == P_FRAME_END) && (ri_xgmii_rxc[2] == 1)) ||((ri_xgmii_rxd[15: 8] == P_FRAME_END) && (ri_xgmii_rxc[1] == 1)) ||((ri_xgmii_rxd[7 : 0] == P_FRAME_END) && (ri_xgmii_rxc[0] == 1));assign w_eof_location = ((ri_xgmii_rxd[63:56] == P_FRAME_END) && (ri_xgmii_rxc[7] == 1)) ? 7 : ((ri_xgmii_rxd[55:48] == P_FRAME_END) && (ri_xgmii_rxc[6] == 1)) ? 6 :((ri_xgmii_rxd[47:40] == P_FRAME_END) && (ri_xgmii_rxc[5] == 1)) ? 5 :((ri_xgmii_rxd[39:32] == P_FRAME_END) && (ri_xgmii_rxc[4] == 1)) ? 4 :((ri_xgmii_rxd[31:24] == P_FRAME_END) && (ri_xgmii_rxc[3] == 1)) ? 3 :((ri_xgmii_rxd[23:16] == P_FRAME_END) && (ri_xgmii_rxc[2] == 1)) ? 2 :((ri_xgmii_rxd[15: 8] == P_FRAME_END) && (ri_xgmii_rxc[1] == 1)) ? 1 :((ri_xgmii_rxd[7 : 0] == P_FRAME_END) && (ri_xgmii_rxc[0] == 1)) ? 0 : 0;
/******************************always*******************************/
always @(posedge i_clk or posedge i_rst)beginif(i_rst)beginri_xgmii_rxd <= 'd0;ri_xgmii_rxc <= 'd0;ri_xgmii_rxd_1d <= 'd0;ri_xgmii_rxc_1d <= 'd0;endelse beginri_xgmii_rxd <= i_xgmii_rxd ;ri_xgmii_rxc <= i_xgmii_rxc ;ri_xgmii_rxd_1d <= ri_xgmii_rxd ;ri_xgmii_rxc_1d <= ri_xgmii_rxc ;end
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)beginr_sof <= 'd0;r_sof_location <= 'd0;endelse if(w_sof)beginr_sof <= w_sof ;r_sof_location <= w_sof_location ;endelse beginr_sof <= 'd0 ;r_sof_location <= r_sof_location ;end
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)beginr_eof <= 'd0;r_eof_location <= 'd0;endelse if(w_eof)beginr_eof <= w_eof ;r_eof_location <= w_eof_location ;endelse beginr_eof <= 'd0 ;r_eof_location <= r_eof_location ; end
end always @(posedge i_clk or posedge i_rst)beginif(i_rst)r_comma <= 'd0;else if(r_eof)r_comma <= 'd0;else if((r_sof_location == 7) && (ri_xgmii_rxd_1d[55:0] == 56'h55_5555_5555_5555) && (ri_xgmii_rxd[63:56] == 8'hd5))r_comma <= 'd1;else if((r_sof_location == 3) && (ri_xgmii_rxd_1d[23:0] == 24'h55_5555) && (ri_xgmii_rxd[63:24] == 40'h55_5555_55d5))r_comma <= 'd1;elser_comma <= r_comma;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_recv_cnt <= 'd0;else if(r_eof)r_recv_cnt <= 'd0;else if(r_sof | r_recv_cnt)r_recv_cnt <= r_recv_cnt + 'd1;elser_recv_cnt <= r_recv_cnt;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_dst_mac <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 1)r_dst_mac <= ri_xgmii_rxd_1d[55:8];else if(r_sof_location == 3 && r_recv_cnt == 1)r_dst_mac <= {ri_xgmii_rxd_1d[23:0],ri_xgmii_rxd[63:40]};elser_dst_mac <= r_dst_mac;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_src_mac <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 1)r_src_mac <= {ri_xgmii_rxd_1d[7:0],ri_xgmii_rxd[63:24]};else if(r_sof_location == 3 && r_recv_cnt == 2)r_src_mac <= {ri_xgmii_rxd_1d[39:0],ri_xgmii_rxd[63:56]};elser_src_mac <= r_src_mac;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_type <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 2)r_type <= ri_xgmii_rxd_1d[23:8];else if(r_sof_location == 3 && r_recv_cnt == 3)r_type <= ri_xgmii_rxd_1d[55:40];elser_type <= r_type;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_data_run <= 'd0;else if(rm_axis_rlast)r_data_run <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 1)r_data_run <= 'd1;else if(r_sof_location == 3 && r_recv_cnt == 2)r_data_run <= 'd1;elser_data_run <= r_data_run;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)beginr_data_run_1d <= 'd0;r_data_run_2d <= 'd0;endelse beginr_data_run_1d <= r_data_run;r_data_run_2d <= r_data_run_1d;end
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rdata <= 'd0;else if(rm_axis_rlast)rm_axis_rdata <= 'd0;else if(r_sof_location == 7 && r_data_run)rm_axis_rdata <= {ri_xgmii_rxd_1d[7:0],ri_xgmii_rxd[63:8]};else if(r_sof_location == 3 && r_data_run)rm_axis_rdata <= {ri_xgmii_rxd_1d[39:0],ri_xgmii_rxd[63:40]};elserm_axis_rdata <= 'd0;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_ruser <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 2)rm_axis_ruser <= {r_src_mac,ri_xgmii_rxd_1d[23:8]};else if(r_sof_location == 3 && r_recv_cnt == 3)rm_axis_ruser <= {r_src_mac,ri_xgmii_rxd_1d[55:40]};elserm_axis_ruser <= rm_axis_ruser;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rkeep <= 'd0;else if(r_sof_location == 7 && w_eof)case (w_eof_location)7 : rm_axis_rkeep <= 8'b1000_0000;6 : rm_axis_rkeep <= 8'b1100_0000;5 : rm_axis_rkeep <= 8'b1110_0000;4 : rm_axis_rkeep <= 8'b1111_0000;3 : rm_axis_rkeep <= 8'b1111_1000;2 : rm_axis_rkeep <= 8'b1111_1100;1 : rm_axis_rkeep <= 8'b1111_1110;0 : rm_axis_rkeep <= 8'b1111_1111;default : rm_axis_rkeep <= 8'b1111_1111;endcaseelse if(r_sof_location == 3 && (w_eof && w_eof_location >= 4))case (w_eof_location)7 : rm_axis_rkeep <= 8'b1111_1000;6 : rm_axis_rkeep <= 8'b1111_1100;5 : rm_axis_rkeep <= 8'b1111_1110;4 : rm_axis_rkeep <= 8'b1111_1111;3 : rm_axis_rkeep <= 8'b1000_0000;2 : rm_axis_rkeep <= 8'b1100_0000;1 : rm_axis_rkeep <= 8'b1110_0000;0 : rm_axis_rkeep <= 8'b1111_0000;default : rm_axis_rkeep <= 8'b1111_1111;endcaseelse if(r_sof_location == 3 && (r_eof && r_eof_location < 4))case (r_eof_location)7 : rm_axis_rkeep <= 8'b1111_1000;6 : rm_axis_rkeep <= 8'b1111_1100;5 : rm_axis_rkeep <= 8'b1111_1110;4 : rm_axis_rkeep <= 8'b1111_1111;3 : rm_axis_rkeep <= 8'b1000_0000;2 : rm_axis_rkeep <= 8'b1100_0000;1 : rm_axis_rkeep <= 8'b1110_0000;0 : rm_axis_rkeep <= 8'b1111_0000;default : rm_axis_rkeep <= 8'b1111_1111;endcaseelserm_axis_rkeep <= 8'b1111_1111;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rlast <= 'd0;else if(r_sof_location == 7 && w_eof)rm_axis_rlast <= 'd1;else if(r_sof_location == 3 && (w_eof && w_eof_location >= 4))rm_axis_rlast <= 'd1;else if(r_sof_location == 3 && (r_eof && r_eof_location < 4))rm_axis_rlast <= 'd1;elserm_axis_rlast <= 'd0;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rvalid <= 'd0;else if(rm_axis_rlast)rm_axis_rvalid <= 'd0;else if(r_data_run && !r_data_run_1d)rm_axis_rvalid <= 'd1;elserm_axis_rvalid <= rm_axis_rvalid;
endendmodule
三、仿真波形
仿真文件当中要遍历所有的起始位置与结束为止组合,一共16种。

以起始位在第五个byte,结束位在第一个byte为例,其波形如下,结果正确,对比其他16种情况,波形全部正确。

相关文章:
万兆以太网MAC设计(2)MAC_RX模块
文章目录 前言一、模块功能二、代码三、仿真波形 前言 上文我们打通了了万兆以太网物理层和数据链路层,其实就是会使用IP核了,本文将正式开始MAC层设计第一篇,接收端设计。 一、模块功能 MAC_RX模块功能如下: 解析接收的报文&…...
D. Solve The Maze Codeforces Round 648 (Div. 2)
题目链接: Problem - 1365D - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/problemset/problem/1365/D 题目大意: 有一张地图n行m列(地图外面全是墙),…...
CPU核心数、线程数都是什么意思?
最早,每个物理 cpu 上只有一个核心,对操作系统而言,也就是同一时刻只能运行一个进程/线程。 为了提高性能,cpu 厂商开始在单个物理 cpu 上增加核心(实实在在的硬件存在),也就出现了多核 cpu&…...
每日一篇 4.12
misstep:失误 epic proportions.:史无前例 arguably:按理来说 assembly:组装 performed :执行 underpins:支撑 holds a monopoly:垄断了 shipped:发货 a market capitalizati…...
鸿蒙南向开发:【智能烟感】
样例简介 智能烟感系统通过实时监测环境中烟雾浓度,当烟雾浓度超标时,及时向用户发出警报。在连接网络后,配合数字管家应用,用户可以远程配置智能烟感系统的报警阈值,远程接收智能烟感系统报警信息。实现对危险及时报…...
【主题广|检索稳定】2024年生态工程与农业科技国际会议 (EEAT 2024)
2024年生态工程与农业科技国际会议 (EEAT 2024) 2024 International Conference on Ecological Engineering and Agricultural Technology 【会议简介】 2024年生态工程与农业科技国际会议即将在贵阳召开。本次会议将汇集全球生态工程与农业科技领域的专家学者,共…...
代码随想录算法训练营第三十八天|509. 斐波那契数、 70. 爬楼梯、746. 使用最小花费爬楼梯
509 题目: 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n - 2),…...
07-app端文章搜索
app端文章搜索 1) 今日内容介绍 1.1)App端搜索-效果图 1.2)今日内容 文章搜索 ElasticSearch环境搭建 索引库创建 文章搜索多条件复合查询 索引数据同步 搜索历史记录 Mongodb环境搭建 异步保存搜索历史 查看搜索历史列表 删除搜索历史 联想词查询 联想词的来源 联…...
✔ ★Java项目——设计一个消息队列(二)
Java项目——设计一个消息队列 四. 项⽬创建五. 创建核⼼类创建 Exchange(名字、类型、持久化)创建 MSGQueue(名字、持久化、独占标识)创建 Binding(交换机名字、队列名字、bindingKey用于与routingKey匹配)…...
Java语言实现生产者/消费者问题
经典例题:生产者/消费者问题 生产者(Productor)将产品放在柜台(Counter),而消费者(Customer)从柜台 处取走产品,生产者一次只能生产固定数量的产品(比如:1), 这时柜台中不能 再放产品,此时生产者应停止生产等待消费者…...
bugku-web-file_get_contents
<?php extract($_GET); if (!empty($ac)){$f trim(file_get_contents($fn));if ($ac $f){echo "<p>This is flag:" ." $flag</p>";}else{echo "<p>sorry!</p>";} } ?> 这里涉及到几个不常用的函数 这里直接构…...
Python数据处理和常用库(如NumPy、Pandas)
Python是一种功能强大的编程语言,广泛应用于数据处理和分析领域。在Python中,有一些常用的库可以帮助我们进行数据处理和分析,其中包括NumPy和Pandas。下面是关于这两个库的简介和使用示例:NumPy(Numerical Python&…...
[SystemVerilog]Simulation and Test Benches
Simulation and Test Benches 测试语言中有很大一部分专门用于测试台和测试。在本章中,我们将介绍为硬件设计编写高效测试台的一些常用技术。 6.1 How SystemVerilog Simulator Works 在深入研究如何编写适当的测试台之前,我们需要深入了解模拟器的工作原…...
lightgbm-安装失败(解决方案)
1.pip install lightgbm 报错,出现长篇标黄和标红的,本人表示看不懂,直接忽略,如下所示: 2.尝试pip install lightgbm -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com,安装也报错&…...
halcon图像相减算子sub_image
1.图像相减算子 sub_image(ImageMinuend , ImageSubtrahend : ImageSub : Mult , Add :) (1)参数解释: ImageMinuend :输入参数需要被减的图片 ImageSubtrahend :输入参数拿来减的图片 ImageSub :输出…...
final、finally 和 finalize 有什么区别?
final 是一个关键字,用于声明一个类、方法或变量。当用 final 修饰一个类时,表示该类不能被继承;当用 final 修饰一个方法时,表示该方法不能被子类重写;当用 final 修饰一个变量时,表示该变量只能被赋值一次…...
智能运维场景 | 科技风险预警,能实现到什么程度?
[ 原作者:擎创夏洛克,本文略做了节选和改编 ] 每次一说到“风险预警”,就会有客户问我们能做怎样的风险预警。实际上在智能运维厂商来说,此风险非彼风险,不是能做银行的业务上的风险预警(比如贷款风险等&a…...
中颖51芯片学习3. 定时器
中颖51芯片学习3. 定时器 一、SH79F9476定时器简介1. 简介2. 定时器运行模式 二、定时器21. 说明(1)时钟(2)工作模式 2. 寄存器(1)控制寄存器 T2CON(2)定时器2模式控制寄存器 T2MOD …...
[python] Numpy库用法(持续更新)
先导入一下 import numpy as np 一、np.random用法 生成随机整数:np.random.randint(low, high, size) low: 最小值high: 最大值size: 生成的数组大小(可以是多维,下面同理) 生成随机浮点数:np.random.uniform(low, …...
vue快速入门(十七)v-model数据双向绑定修饰符
注释很详细,直接上代码 上一篇 新增内容 v-model.trim 自动去除首尾空格v-model.number 自动转换成数字类型 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" con…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
