10G MAC层设计系列-(3)CRC Process 模块

一、前言

前面已经讲述了在Xilinx 10G PCS/PMA IP核的基础上设计的PHY层,已经xgmii接口的MAC_RX模块,本节主要描述MAC_RX之后的CRC_Process模块。

CRC_Prcess的主要作用就是利用RAM地址“返回初始状态”的方式将crc错误的帧丢掉,并将正确的传递到上级。

二、模块设计

首先,将数据帧、最后一次传输的KEEP信号存入RAM

BRAM_DATA_64X512 u_BRAM_DATA_64X512 (
  .clka     (i_clk                  ),    // input wire clka
  .wea      (rs_axis_valid          ),      // input wire [0 : 0] wea
  .addra    (r_bram_wdata_addr      ),  // input wire [8 : 0] addra
  .dina     (rs_axis_data           ),    // input wire [63 : 0] dina
  .clkb     (i_clk                  ),    // input wire clkb
  .enb      (r_bram_data_rden       ),      // input wire enb
  .addrb    (r_bram_rdata_addr      ),  // input wire [8 : 0] addrb
  .doutb    (w_bram_data_out        )  // output wire [63 : 0] doutb
);

//将每一帧的最后一次传输的KEEP信号存入到RAM
BRAM_KEEP_8X128 your_instance_name (
  .clka     (i_clk                  ),    // input wire clka
  .wea      (rs_axis_last           ),      // input wire [0 : 0] wea
  .addra    (r_bram_wkeep_addr      ),  // input wire [6 : 0] addra
  .dina     (rs_axis_keep           ),    // input wire [7 : 0] dina
  .clkb     (i_clk                  ),    // input wire clkb
  .enb      (r_bram_keep_rden       ),      // input wire enb
  .addrb    (r_bram_rkeep_addr      ),  // input wire [6 : 0] addrb
  .doutb    (w_bram_rkeep           )  // output wire [7 : 0] doutb
);

在此过程中存在一个初始化的地址信号,只有检测到CRC校验正确之后才会更新初始的地址信号。

//写数据初始化地址,当CRC校验正确的时候才会改变
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_init_wdata_addr <= 'd0;
    else 
        if(w_crc_correct)
            r_init_wdata_addr <= r_bram_wdata_addr + 1;
        else
            r_init_wdata_addr <= r_init_wdata_addr;
end
//写数据地址
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_bram_wdata_addr <= 'd0;
    else
        if(s_axis_valid && !rs_axis_valid)
            r_bram_wdata_addr <= r_init_wdata_addr;
        else if(rs_axis_valid && !rs_axis_last)
            r_bram_wdata_addr <= r_bram_wdata_addr + 1;
        else
            r_bram_wdata_addr <= r_bram_wdata_addr;
end
//写KEEP信号的初始化地址,当CRC校验正确的时候才会改变
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_init_wkeep_addr <= 'd0;
    else
        if(w_crc_correct)
            r_init_wkeep_addr <= r_bram_wkeep_addr + 1;
        else
            r_init_wkeep_addr <= r_init_wkeep_addr;        
end
//写KEEP信号地址
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_bram_wkeep_addr <= 'd0;
    else
        if(s_axis_last)
            r_bram_wkeep_addr <= r_init_wkeep_addr;
        else
            r_bram_wkeep_addr <= r_bram_wkeep_addr;
end

最后的帧长等信息只有在CRC校验正确之后存入FIFO,用FIFO的empty信号判断RAM中是否有正确的数据。

FIFO_USER_INFO_80X128 u_FIFO_USER_INFO_80X128 (
  .clk      (i_clk                  ),      // input wire clk
  .srst     (i_rst                  ),    // input wire srst
  .din      (r_user_info            ),      // input wire [79 : 0] din
  .wr_en    (w_crc_correct          ),  // input wire wr_en
  .rd_en    (r_fifo_user_info_rden  ),  // input wire rd_en
  .dout     (w_fifo_user_out        ),    // output wire [79 : 0] dout
  .full     (w_fifo_user_info_full  ),    // output wire full
  .empty    (w_fifo_user_info_empty )  // output wire empty
);

在读数据的过程中,便是根据FIFO是否为空判断是否有有效数据,之后读出FIFO帧长等信息,根据帧长去读取RAM中的数据。

//读取USER_INFO FIFO中的信息
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_fifo_user_info_rden <= 'd0;
    else
        if(!w_fifo_user_info_empty && !r_fifo_rden_lock)
            r_fifo_user_info_rden <= 1'b1;
        else
            r_fifo_user_info_rden <= 1'b0;
end
//锁存信号
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_fifo_rden_lock <= 'd0;
    else 
        if(!w_fifo_user_info_empty)
            r_fifo_rden_lock <= 1'b1;
        else if(rm_axis_last)
            r_fifo_rden_lock <= 1'b0;
        else
            r_fifo_rden_lock <= r_fifo_rden_lock; 
end
//读USER INFO
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_user <= 'd0;
    else
        rm_axis_user <= w_fifo_user_out;
end

//读数据的使能慢读USER INFO的使能一拍
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_bram_data_rden <= 'd0;
    else
        if(r_fifo_user_info_rden)
            r_bram_data_rden <= 1'b1;
        else if(r_data_cnt == w_fifo_user_out[79:64])
            r_bram_data_rden <= 'd0;
        else
            r_bram_data_rden <= r_bram_data_rden;
end
//读数据地址
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_bram_rdata_addr <= 'd0;
    else
        if(r_fifo_user_info_rden)
            r_bram_rdata_addr <= r_init_rdata_addr;
        else if((r_data_cnt < w_fifo_user_out[79:64]) && r_data_cnt)
            r_bram_rdata_addr <= r_bram_rdata_addr + 1;
        else
            r_bram_rdata_addr <= r_bram_rdata_addr ;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_init_rdata_addr <= 'd0;
    else    
        if((r_data_cnt == w_fifo_user_out[79:64]) && r_bram_data_rden)
            r_init_rdata_addr <= r_bram_rdata_addr + 1;
        else
            r_init_rdata_addr <= r_init_rdata_addr;
end


always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_bram_data_rden_ff1 <= 'd0; 
    else
        r_bram_data_rden_ff1 <= r_bram_data_rden;
end
//读keep使能
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_bram_keep_rden <= 1'b0;
    else
        if(r_data_cnt == w_fifo_user_out[79:64] -1)
            r_bram_keep_rden <= 1'b1;
        else 
            r_bram_keep_rden <= 1'b0;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_bram_rkeep_addr <= 'd0;
    else    
        if(r_data_cnt == w_fifo_user_out[79:64] -1)
            r_bram_rkeep_addr <= r_init_rkeep_addr;
        else 
            r_bram_rkeep_addr <= r_bram_rkeep_addr;        
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_init_rkeep_addr <= 'd0;
    else    
        if((r_data_cnt == w_fifo_user_out[79:64]) && r_data_cnt)
            r_init_rkeep_addr <= r_bram_rkeep_addr + 1;
        else 
            r_init_rkeep_addr <= r_init_rkeep_addr;        
end

//寻找上升沿
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_data_rden_pos <= 'd0; 
    else
        if(r_bram_data_rden && !r_bram_data_rden_ff1)
            r_data_rden_pos <= 1'b1;
        else
            r_data_rden_pos <= 1'b0;
end
//寻找下降沿
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_data_rden_nge <= 'd0; 
    else
        if(!r_bram_data_rden && r_bram_data_rden_ff1)
            r_data_rden_nge <= 1'b1;
        else
            r_data_rden_nge <= 1'b0;
end
//读数据计数
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_data_cnt <= 'd0;
    else
        if(r_fifo_user_info_rden || r_bram_data_rden)
            r_data_cnt <= r_data_cnt + 1;
        else
            r_data_cnt <= 'd0;
end
//数据转换成AXIS接口输出
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_data <= 'd0;
    else
        rm_axis_data <= w_bram_data_out;
end
//Valid信号
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_data_rden_pos)
            rm_axis_valid <= 1'b1;
        else
            rm_axis_valid <= rm_axis_valid;
end
//Last信号
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_last <= 'd0;
    else
        if(!r_bram_data_rden && r_bram_data_rden_ff1)
            rm_axis_last <= 1'b1;
        else
            rm_axis_last <= 1'b0;
end
//KEEP信号
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_keep <= 'd0;
    else
        if(w_fifo_user_out[79:64] == 1 && r_data_rden_pos)
            rm_axis_keep <= w_bram_rkeep;
        else if(w_fifo_user_out[79:64] > 1 && r_data_rden_pos)
            rm_axis_keep <= 8'hff;
        else if(!r_bram_data_rden && r_bram_data_rden_ff1)
            rm_axis_keep <= w_bram_rkeep;
        else
            rm_axis_keep <= rm_axis_keep;
end

三、总结

CRC Process模块比较简单,就是实现丢掉CRC错误帧的功能

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一、Mysql索引的底层数据结构与算法

Mysql索引的底层数据结构与算法 前言一、索引数据结构为什么 MySQL 的索引要使用 B 树而不是其他树形结构?比如 B 树?为什么InnoDB存储引擎选择使用Btree索引结构&#xff1f; 二、索引分类思考&#xff1a;以下SQL语句&#xff0c;那个执行效率高&#xff1f;为什么&#xf…

Stable Diffusion AI绘画

我们今天来了解一下最近很火的SD模型 ✨在人工智能领域&#xff0c;生成模型一直是研究的热点之一。随着深度学习技术的飞速发展&#xff0c;一种名为Stable Diffusion的新型生成模型引起了广泛关注。Stable Diffusion是一种基于概率的生成模型&#xff0c;它可以学习数据的潜…

数据仓库实验三:分类规则挖掘实验

目录 一、实验目的二、实验内容和要求三、实验步骤1、创建数据库和表2、决策树分类规则挖掘&#xff08;1&#xff09;新建一个 Analysis Services 项目 jueceshu&#xff08;2&#xff09;建立数据源视图&#xff08;3&#xff09;建立挖掘结构 DST.dmm&#xff08;4&#xff…

Qt模型视图代理之QTableView应用的简单介绍

往期回顾 Qt绘图与图形视图之绘制带三角形箭头的窗口的简单介绍-CSDN博客 Qt绘图与图形视图之Graphics View坐标系的简单介绍-CSDN博客 Qt模型视图代理之MVD(模型-视图-代理)概念的简单介绍-CSDN博客 Qt模型视图代理之QTableView应用的简单介绍 一、最终效果 二、设计思路 这里…

【Android学习】日期和时间选择对话框

实现功能 实现日期和时间选择的对话框&#xff0c;具体效果可看下图(以日期为例) 具体代码 1 日期对话框 1.1 xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android&quo…

EPAI手绘建模APP资源管理和模型编辑器2

g) 矩形 图 26模型编辑器-矩形 i. 修改矩形的中心位置。 ii. 修改矩形的长度和宽度。 h) 正多边形 图 27模型编辑器-内接正多边形 图 28模型编辑器-外切正多边形 i. 修改正多边形的中心位置。 ii. 修改正多边形中心距离端点的长度。 iii. 修改正多边形的阶数。阶数为3&…

排序算法之堆排序

首先在了解堆排序之前我们先来回顾一下什么叫做堆吧&#xff01; 基本概念 堆&#xff08;Heap&#xff09;&#xff1a;是一种特殊的完全二叉树&#xff0c;其中每个节点的值都大于或等于&#xff08;大顶堆&#xff09;或小于或等于&#xff08;小顶堆&#xff09;其子节点的…

活动图与状态图:UML中流程图的精细化表达——专业解析系统动态性与状态变迁

流程图是一种通用的图形表示法&#xff0c;用以展示步骤、决策和循环等流程控制结构。它通常用于描述算法、程序执行流程或业务过程&#xff0c;关注于任务的顺序执行。流程图强调顺序、分支和循环&#xff0c;适用于详细说明具体的处理步骤&#xff0c;图形符号相对基础和通用…

ubuntu搭建kms服务器

1.下载kms开源包(如果提示找不到wget命令的话:apt install wget): wget https://github.com/Wind4/vlmcsd/releases/download/svn1111/binaries.tar.gz2.解压: tar -xzvf binaries.tar.gz接着cd 进入 Linux/intel/static/ 文件夹下: 3.选择对应的文件&#xff0c;这里我们选…

onedrive下載zip檔案有20G限制,如何解決

一般來說&#xff0c;OneDrive網頁版對文件下載大小的限制如下圖所示&#xff0c;更多資訊&#xff0c;請您參考這篇文章&#xff1a;OneDrive 和 SharePoint 中的限制 - Microsoft Support 因此我們推薦您使用OneDrive同步用戶端來同步到本地電腦&#xff0c;您也可以選擇只同…

C语言——rand函数

一、rand函数 这是一个在 C 标准库 <stdlib.h> 中定义的函数&#xff0c;用于生成伪随机数&#xff0c;默认情况下&#xff0c;它生成从 0 到 RAND_MAX 的伪随机数&#xff0c;其中 RAND_MAX 是一个常数&#xff0c;通常是 32767。 1、函数原型&#xff1a; 2、函数返回…

C#中.net8WebApi加密解密

尤其在公网之中&#xff0c;数据的安全及其的重要&#xff0c;除过我们使用jwt之外&#xff0c;还可以对传送的数据进行加密&#xff0c;就算别人使用抓包工具&#xff0c;抓到数据&#xff0c;一时半会儿也解密不了数据&#xff0c;当然&#xff0c;加密也影响了效率&#xff…

【Qt问题】VS2019 Qt win32项目如何添加x64编译方式

解决办法&#xff1a; 注意改为x64版本以后&#xff0c;要记得在项目属性里&#xff0c;修改Qt Settings、对应的链接include、lib等 参考文章 VS2019 Qt win32项目如何添加x64编译方式_vs2019没有x64-CSDN博客 有用的知识又增加了~

www.fastssh.com SSH over WebSockets with CDNs

https://www.fastssh.com/page/create-ssh-cdn-websocket/server/这其实不是标准的websocket报文(服务器响应报文无Sec-Websocket-Accept字段)&#xff0c;所以无法使用github.com/gorilla/websocket包&#xff1a;GET / HTTP/1.1 Host: hostname:8080 User-Agent: Go-http-cli…

43 单例模式

目录 1.什么是单例模式 2.什么是设计模式 3.特点 4.饿汉和懒汉 5.峨汉实现单例 6.懒汉实现单例 7.懒汉实现单例&#xff08;线程安全&#xff09; 8.STL容器是否线程安全 9.智能指针是否线程安全 10.其他常见的锁 11.读者写者问题 1. 什么是单例模式 单例模式是一种经典的&a…

243 基于matlab的模糊C均值算法(FCM)及其改进算法将空间邻域项引入FCM的目标函数(FCM_S)

基于matlab的模糊C均值算法&#xff08;FCM&#xff09;及其改进算法将空间邻域项引入FCM的目标函数(FCM_S),广义的模糊C均值(GFCM)算法&#xff0c;基于核的改进的模糊c均值聚类算法&#xff08;KFCM&#xff09;,基于核的广义模糊c均值聚类算法KGFCM的图像分割方法。程序已调…

一文了解python机器学习Sklearn

1.3 安装和配置Sklearn 要使用Sklearn库&#xff0c;首先需要安装Python和相应的库。在本教程中&#xff0c;我们将使用Python 3.x版本。可以使用以下命令安装Sklearn库&#xff1a; pip install scikit-learn安装完成后&#xff0c;可以在Python代码中导入Sklearn库&#xf…

【Android学习】自定义文本框和输入监听

实现功能 以上代码可实现功能&#xff1a; 1 自定义文本框样式 2. 文本框触发形式转变 3. 文本框输入长度监听&#xff0c;达到最大长度关闭软键盘 4. password框触发检测phone框内容 1. drawable自定义形状 我创建了editor_focus.xml 和 editor_unfocus.xml&#xff0c;两者仅…

猿人学第七题-动态字体-随风漂移

前言&#xff1a;该题主要是考对fontTools.ttLib.TTFont的操作&#xff0c;另外就是对字典互相映射的操作 一、woff文件存储 from fontTools.ttLib import TTFont #pip install fontTools def save_woff(response):woff response[woff]woff_file base64.b64decode(woff.enc…

K8S 哲学 - 服务发现 services

apiVersion: v1 kind: Service metadata:name: deploy-servicelabels:app: deploy-service spec: ports: - port: 80targetPort: 80name: deploy-service-podselector: app: deploy-podtype: NodePort 主机端口分配方式 两个 name port 和 targetPort type 类型
最新文章