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

news2024/11/24 1:18:46

一、概述

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)begin
    if(i_rst)
        r_target_mac <= 'd0;  
    else
        if(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]};
        else
            r_target_mac <= r_target_mac;
end
//获取源MAC
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_source_mac <= 'd0;
    else
        if(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]};
        else
            r_source_mac <= r_source_mac;
end
//获取帧类型
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_type <= 'd0; 
    else
        if(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];
        else
            r_type <= r_type;
end

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

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

3、对齐数据

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

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_data <= 'd0;
    else
        if(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]};
        else
            rm_axis_data <= 'd0;
end

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

//keep信号处理!!!!
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_keep <= 'd0;
    else
        if(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;
            endcase
        else 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         
        else
            rm_axis_keep <= rm_axis_keep;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_last <= 1'b0;
    else
        if(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)begin
    if(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;
        else
            rm_axis_valid <= rm_axis_valid;
end

4、CRC校验

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

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

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_crc_data <= 'd0;
    else
        if(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]};
            else
                r_crc_data <= 'd0;
end

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

//CRC_en控制
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_crc_en <= 'd0;
    else
        if(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_en
                    7           :r_crc_en <= 1'b1;//剩余两个数据,需要再次拉高crc_en
                    default     :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;
                endcase
            else if(r_eof_ff1)
                r_crc_en <= 1'b0;
            else
                r_crc_en <= r_crc_en;
end

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

//CRC_KEEP处理!!!!
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_crc_keep <= 'd0;
    else
        if(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;
            endcase
        else 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         
        else
            r_crc_keep <= r_crc_keep;
end

 5、CRC模块

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

三、总结

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

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

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

相关文章

C语言 | Leetcode C语言题解之第50题Pow(x,n)

题目&#xff1a; 题解&#xff1a; double myPow(double x, int n){if(n 0 || x 1){return 1;}if(n < 0){return 1/(x*myPow(x,-(n1)));}if(n % 2 0){return myPow(x*x,n/2);}else{return x*myPow(x*x,(n - 1)/2);} }

Node私库Verdaccio使用记录,包的构建,推送和拉取

Node私库Verdaccio使用记录&#xff0c;包的构建&#xff0c;推送和拉取 Verdaccio是一个轻量级的私有npm代理注册中心&#xff0c;它可以帮助你在本地搭建一个npm仓库&#xff0c;非常适合企业内部使用。通过使用Verdaccio&#xff0c;你可以控制和缓存依赖包&#xff0c;提高…

QT:信号和槽

文章目录 信号和槽connect函数槽自定义槽第一种第二种 信号和槽 这里的信号和Linux的信号一样吗&#xff1f; 答案是差不多&#xff0c;但是也有一定的区别&#xff0c;而且也是两个不同的概念 信号有三个概念&#xff0c;一个是信号源&#xff0c;这个信号是由谁发送的&…

基于Guava的异步线程结果监听:ListenableFuture

1.ListenableFuture概述&#xff1a; ListenableFuture是对原有Future的增强&#xff0c;它可以监听异步执行的过程&#xff0c;执行完了&#xff0c;自动触发回调操作。 除此之外&#xff0c;可以分别针对成功或者失败的情况做后续处理。 2.使用场景 你想拿到异步处理的结果…

vue2插件之@lucky-canvas/vue,大转盘、抽奖、老虎机

提示&#xff1a;vue2插件 文章目录 [TOC](文章目录) 前言一、查看nodejs版本二、创建项目三、大转盘四、抽奖五、老虎机六、官网总结 前言 lucky-canvas/vue 一、查看nodejs版本 node -v二、创建项目 1、安装插建 npm install lucky-canvas/vue --save2、目录结构 3、引用…

Stable Diffusion WebUI 中文提示词插件 sd-webui-prompt-all-in-one

本文收录于《AI绘画从入门到精通》专栏&#xff0c;订阅后可阅读专栏内所有文章&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 今天为大家介绍 Stable Diffusion WebUI 的一款中文提示词插件 sd-webui-prompt-all-in-one&#xff0c;就像它的名字一…

2024中国(江西)国际先进陶瓷材料及智能装备博览会

2024中国&#xff08;江西&#xff09;国际先进陶瓷材料及智能装备博览会 “中国&#xff08;江西&#xff09;国际先进陶瓷材料及智能装备博览会” 陶瓷三新展 &#xff08;新材料、新装备、新技术&#xff09; 绿色智能、引领未来 2024年11月1日-11月3日 中国江西 南昌…

网工内推 | 网络工程师,CCIE认证优先,最高10k*13薪

01 广东丰德科技有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、负责运营商机房的网络设备的运行维护、故障应急处理&#xff1b; 2、负责各类型网络设备或网络相关的故障的故障分析及诊断&#xff1b; 3、独立完成网络项目的方案设计编写并负责方案的验证…

Linux进程——进程的概念(PCB的理解)

前言&#xff1a;在了解完冯诺依曼体系结构和操作系统之后&#xff0c;我们进入了Linux的下一篇章Linux进程&#xff0c;但在学习Linux进程之前&#xff0c;一定要阅读理解上一篇内容&#xff0c;理解“先描述&#xff0c;再组织”才能更好的理解进程的含义。 Linux进程学习基…

关于配置nginx 代理去掉location 匹配的上下文规则

事情是这样的&#xff0c;有个需求&#xff0c;就是在本系统准备把所有的api 请求放到webman 框架 然后把后台的业务依然保留在fastadmin 框架&#xff0c; 打算加一个反向代理&#xff0c;用同一个域名的加上一个访问后缀&#xff0c;放到到webman 服务&#xff0c;也就是本…

mathtype中如何输入指示函数花体的 I

mathtype中如何输入花体的 I 问题描述解决办法 问题描述 写word文档时&#xff0c;借助mathtype敲公式&#xff0c;指示函数的花体I如何键入。 解决办法 1.编辑->插入符号 2.选择“Euclid Math Two”,里面有花体的各种字母。 3.成功。

新一代状态空间模型网络替代Transformer 综述

本文首先初步介绍了状态空间模型&#xff08;SSM&#xff09;的工作原理。然后&#xff0c;从多个方面回顾SSM的相关工作&#xff0c;包括SSM的起源和变化、自然语言处理、计算机视觉、图、多模态处理、多模态和多媒体、点云/事件流数据、时间序列数据等领域的相关工作。 此外…

vue3.0(三) Vite文件目录结构及SFC语法

文章目录 Vite介绍Vite文件目录结构SFC语法SFC 语法定义bug解决 Vite介绍 为什么使用Vite&#xff1f; 表现 与Vite的ESbuild预绑定使其比使用任何其他JS绑定器都快10到100倍。这是因为它有助于提高页面速度并将CommonJS/UMD模块转换为ESM。 基于Vite文件&#xff0c;“预绑定…

RabbitMQ中的交换机类型

交换机类型 可以看到&#xff0c;在订阅模型中&#xff0c;多了一个exchange角色&#xff0c;而且过程略有变化&#xff1a; Publisher&#xff1a;生产者&#xff0c;不再发送消息到队列中&#xff0c;而是发给交换机 Exchange&#xff1a;交换机&#xff0c;一方面&#xff…

【Linux】dlopen: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29‘ not found

[30116] Error loading Python lib /tmp/_MEIlvdUu6/libpython3.8.so.1.0: dlopen: /lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.29 not found (required by /tmp/_MEIlvdUu6/libpython3.8.so.1.0)1 cd到指定路径 cd /usr/local 2 下载 wget http://ftp.gnu.org/gnu/gl…

[NSSRound#23 misc] 前两题

这个周末NSS个人赛是个MISC&#xff0c;这个好久没怎么玩了&#xff0c;结果不会了。只作出一题来&#xff0c;不过参与的人比较少&#xff0c;每题解出数和也不到50。前50吧:) 画师 给了一个xml文件&#xff0c;看内容有 mxGraphModel 标签&#xff0c;应该是某个东西画的矢…

Qt Designer入门

安装 PyQt5提供了一个可视化图形工具Qt Designer&#xff0c;文件名为designer.exe。如果在电脑上找不到&#xff0c;可以用如下命令进行安装&#xff1a; pip install PyQt5-tools 安装完毕后&#xff0c;可在如下目录找到此工具软件&#xff1a; D:\Python3.9\Lib\site-pa…

【多态】有关多继承和菱形继承的多态

博主首页&#xff1a; 有趣的中国人 专栏首页&#xff1a; C进阶 其它专栏&#xff1a; C初阶 | 初阶数据结构 | Linux 博主会持续更新 本篇文章主要讲解 多继承和菱形继承的多态 的相关内容 文章目录 1. 回顾多态底层2. 抽象类2.1 概念2.2 接口继承和实现继承 3. 虚表所在…

运维的利器–监控–zabbix–第二步:建设–部署zabbix agent--windows server系统--agent客户端安装部署

第一步&#xff1a;下载windows agent软件 第一点&#xff1a;zabbix官网针对linux和window系统有两种不同的安装方式&#xff0c;其中&#xff1a;windows为tar压缩包&#xff0c;根据你zabbix server安装的版本&#xff0c;在官网下载同样版本的agent软件。 amd64&#xff…

Eclipse:-Dmaven.multiModuleProjectDirectory system propery is not set.

eclipse中使用maven插件的时候&#xff0c;运行run as maven build的时候报错 -Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME environment variable and mvn script match. 可以设一个环境变量M2_HOME指向你的maven安装目录 M2_HOMED:\Apps\…