从零开始 verilog 以太网交换机(五)帧合路单元的设计与实现

news2024/11/19 23:18:09

从零开始 verilog 以太网交换机(五)帧合路单元的设计与实现



🔈声明:
😃博主主页:王_嘻嘻的CSDN主页
🧨 从零开始 verilog 以太网交换机系列专栏:点击这里
🔑未经作者允许,禁止转载,侵权必删
🚩关注本专题的朋友们可以收获一个经典交换机设计的全流程,包括设计与验证(FPGA);以太网MAC的基础知识。新手朋友们还将获得一个具有竞争力的项目经历,后续整个工程和代码下载链接也都会放在csdn和公众号内

  本章将开始进行帧合路单元的设计,其负责将多个mac controller的帧合并为一路进行后续处理

  交换机完整的架构可以参考:从零开始 verilog 以太网交换机(一)架构分析。


1、以太网帧合路功能

  交换机的核心功能是 n端口⬅➡n端口的数据包传输,除了前一章谈到的帧转发表查询功能外,还会有其他的帧处理功能需要实现在交换机中。显然不可能每个端口都拥有一个独立的帧处理单元,通常只有一个帧处理单元通过帧合路将n个端口的数据帧合并为一路,再进入帧处理单元,最后根据目的端口号,进行分路,分发到对应端口上。

  所以帧合路单元的作用本质上就是一个arbiter + mux,但是需要规划好单元的主频,否则在最开始的合路阶段就可能来不及处理多路的数据帧。因为MII接口支持10Mbps和100Mbps两种速率,交换机支持4端口,所以,帧合路最低需要400Mbps的处理速度,为了便于后续升级,我们在此采用500MHz的时钟频率,最高能支持4Gbps的数据传输


2、帧合路单元接口

  帧合路单元接口较为简单,只有mac_r的4组fifo输入,以及帧合并后的一组fifo输出,由于mac_r的接口相同,这里直接采用二维数组的方式来进行接口的设计。

在这里插入图片描述


3、帧合路单元实现细节

3.1、功能细节分析

  帧合路单元整体实现比较简单,通过仲裁器选出一路mac_r,并对该mac的一帧数据进行检错,去除CRC-32的校验码,并填上交换机端口号,以便转发表进行后续处理;最后把处理合路后的数据帧存入sfifo中。

  综上,总体功能为以下两点:

  • 仲裁
  • 帧处理

  在第一版的交换机中,我们直接采用round robin arbiter作为仲裁器,帧处理操作也仅有检错、端口号、CRC的处理;
  之后的版本中,该模块会采用优先级可量化配置的仲裁期,帧处理操作也会更为丰富,复杂

①:轮询仲裁器:按照一定的顺序轮流分配资源,以保证公平性和效率。


3.2、核心电路设计

请添加图片描述

  帧合路单元架构如上图所示,理论上后级转发电路也能满足4Gbps的数据传输速率,所以frame mux只要能存储处理一次最大帧过程中,所可能来的数据帧即可。

  最大帧1518B处理过程中,最多可能来24个最小帧,我们以2^n计算,将state fifo设置成16 x 32;将data fifo设置成8 x 2048;

  此外,端口号将直接填在state fifo中的保留位,目前为3-bits,后续如果需要可以扩展。


3.3、帧合路单元代码

  Verilog代码将放在下面,Testbench就不展示了,有需要的可以等专题结束后在资源中下载,或者去我的公众号获得链接

  在实现上,我们直接调用了round robin arbiter的IP,就不展开介绍了,感兴趣的朋友可以自行搜索资料了解。


module frame_mux(
clk,rst_n,
mac_rx_state_fifo_empty,
mac_rx_state_fifo_rd,
mac_rx_state_fifo_dout,
mac_rx_data_fifo_rd,
mac_rx_data_fifo_dout,
frame_mux_state_fifo_empty,
frame_mux_state_fifo_rd,
frame_mux_state_fifo_dout,
frame_mux_data_fifo_rd,
frame_mux_data_fifo_dout
);

parameter       PORT_NUM    =   4;


`define         FRAME_LEN_RANGE     10:0
`define         FRAME_LEN_ERR_BIT   11
`define         FRAME_CRC_ERR_BIT   12
`define         FRAME_PORT_RANGE    15:13


input                           clk;
input                           rst_n;

input   [PORT_NUM-1:0]          mac_rx_state_fifo_empty;
output  [PORT_NUM-1:0]          mac_rx_state_fifo_rd;
input   [PORT_NUM-1:0] [15:0]   mac_rx_state_fifo_dout;
output  [PORT_NUM-1:0]          mac_rx_data_fifo_rd;
input   [PORT_NUM-1:0] [7:0]    mac_rx_data_fifo_dout;

output                          frame_mux_state_fifo_empty;
input                           frame_mux_state_fifo_rd;
output  [15:0]                  frame_mux_state_fifo_dout;
input                           frame_mux_data_fifo_rd;
output  [7:0]                   frame_mux_data_fifo_dout;



//rrarb
wire    [PORT_NUM-1:0]          mac_r_req;
wire                            mac_r_grant_vld;
wire    [PORT_NUM-1:0]          mac_r_grant;
wire                            mac_r_switch_to_next;

//demux
wire    [15:0]                  mux_state_dout;
wire    [7:0]                   mux_data_dout;

//frame field
wire                            err_frame;
wire    [10:0]                  frame_len;
wire    [2:0]                   frame_port_idx;
wire                            frame_vld;
//mar fifo operation
reg     [10:0]                  mac_data_fifo_pop_cnt; 
wire                            frame_mux_state_fifo_wr;
/*------------------------------------------------------------
rrarb choose one mac
------------------------------------------------------------*/
assign mac_r_req[PORT_NUM-1:0] = mac_rx_state_fifo_empty;


rrarb_ff x_rrarb_mac_r(
    .clk(clk),
    .rst_n(rst_n),
    .req(mac_r_req[PORT_NUM-1:0]),
    .grant(mac_r_grant_vld),
    .grant_ff(mac_r_grant[PORT_NUM-1:0]),
    .grant_vld(),
    .switch_to_next(mac_r_switch_to_next)
);


one_hot_mux_2d 
    x_one_hot_mux_mac_state(
    .din(mac_rx_state_fifo_dout),
    .sel(mac_r_grant[PORT_NUM-1:0]),
    .dout(mux_state_dout[15:0]),
    .err()
);

one_hot_mux_2d 
    x_one_hot_mux_mac_data(
    .din(mac_rx_data_fifo_dout),
    .sel(mac_r_grant[PORT_NUM-1:0]),
    .dout(mux_data_dout[7:0]),
    .err()
);



assign err_frame = mac_r_grant_vld ? mux_state_dout[`FRAME_LEN_ERR_BIT] | mux_state_dout[`FRAME_CRC_ERR_BIT]
                                   : 1'b0 ; 

assign frame_len[10:0] = mux_state_dout[`FRAME_LEN_RANGE]-11'd4;   //ignore crc 4B
assign frame_vld = mac_r_grant_vld & (~err_frame);

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        mac_data_fifo_pop_cnt[10:0] <= 11'b0;
    else if( (mac_data_fifo_pop_cnt[10:0]==frame_len[10:0]) | (~frame_vld) )
        mac_data_fifo_pop_cnt[10:0] <= 11'b0;
    else if(frame_vld)
        mac_data_fifo_pop_cnt[10:0] <= mac_data_fifo_pop_cnt[10:0] + 11'b1;
end

assign frame_mux_state_fifo_wr = (mac_data_fifo_pop_cnt[10:0]==frame_len[10:0]) & frame_vld;


assign frame_port_idx[2:0] = (mac_r_grant[PORT_NUM-1:0]=={{(PORT_NUM-1){1'b0}},1'b1})    ? 3'd0 :
                             (mac_r_grant[PORT_NUM-1:0]=={{(PORT_NUM-1){1'b0}},1'b1}<<1) ? 3'd1 :  
                             (mac_r_grant[PORT_NUM-1:0]=={{(PORT_NUM-1){1'b0}},1'b1}<<2) ? 3'd2 :
                             (mac_r_grant[PORT_NUM-1:0]=={{(PORT_NUM-1){1'b0}},1'b1}<<3) ? 3'd3 : 3'd0;

sfifo #(
    .DEPTH(32),
    .WIDTH(16)
    )x_state_fifo(
   .clk(clk),
   .data_in({frame_port_idx[2:0],mux_state_dout[12:0]}),
   .data_out(frame_mux_state_fifo_dout[15:0]),
   .empty_n(),
   .empty(frame_mux_state_fifo_empty),
   .full_n(),
   .full(),
   .rd_en(frame_mux_state_fifo_rd),
   .rst_n(rst_n),
   .wr_en(frame_mux_state_fifo_wr),
   .almost_full_n(),
   .almost_empty_n()
   );


sfifo #(
    .DEPTH(2048),
    .WIDTH(8)
    )x_data_fifo(
   .clk(clk),
   .data_in(mux_data_dout[7:0]),
   .data_out(frame_mux_data_fifo_dout[7:0]),
   .empty_n(),
   .empty(),
   .full_n(),
   .full(),
   .rd_en(frame_mux_data_fifo_rd),
   .rst_n(rst_n),
   .wr_en(mac_r_grant_vld),
   .almost_full_n(),
   .almost_empty_n()
   );



endmodule




搜索关注我的微信公众号【IC墨鱼仔】,获取我的更多IC干货分享!

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

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

相关文章

07-歌词滚动效果

现在学习的代码工作中不一定会需要&#xff0c;如果有&#xff0c;也已经做成了产品和库&#xff0c; 前端重点是创造&#xff0c;面试官考验你的能力是会提出最刁钻的问题给你的。 项目效果 原生JS效率是最高的&#xff0c;框架只是提高代码的可读性 favico图标添加 两种方…

一个工具类让你彻底解决bean深拷贝

深拷贝是我们在代码开发当中经常需要使用到的&#xff0c;但是市面上的对象拷贝方法&#xff0c;比如spring自带的&#xff0c;或者其他工具类带的对象拷贝&#xff0c;大部分都是浅拷贝&#xff0c;根本无法满足咱们的业务需求&#xff0c;我们就只能对里面的引用对象进行专门…

guacamole 纯web rdp预研:web应用程序部分

文章目录 web rdp预研 web应用程序部分预研目的相关基础Web应用结构&#xff08;框架&#xff09;配置tomcat运行web项目与前端交互原理问题整理Java web基础知识Java web调试预研结论 web rdp预研 web应用程序部分 ⭐️来自很多年前的笔记&#xff0c;只是一个归档&#xff0…

面向对象【成员变量与局部变量、方法声明与作用】

文章目录 成员变量局部变量成员变量与局部变量的区别 方法方法的作用方法的声明 成员变量 Java中的成员变量是指类中声明的变量&#xff0c;也称为实例变量或属性。它们与方法一样属于类的成员&#xff0c;不同之处在于&#xff0c;它们存储在对象(堆)中而不是栈中&#xff0c;…

基于灰色预测模型的负荷预测(matlab程序)

0.代码链接 基于灰色预测模型的负荷预测&#xff08;matlab程序&#xff09;资源-CSDN文库 1.简述 灰色预测是一种对含有不确定因素的系统进行预测的方法。灰色预测通过鉴别系统因素之间发展趋势的相异程度&#xff0c;即进行关联分析&#xff0c;并对原始数据进行生成处理来…

python:并发编程(二十六)

前言 本文将和大家一起探讨python并发编程的实际项目&#xff1a;win图形界面应用&#xff08;篇八&#xff0c;共八篇&#xff09;&#xff0c;系列文章将会从零开始构建项目&#xff0c;并逐渐完善项目&#xff0c;最终将项目打造成适用于高并发场景的应用。 本文为python并…

ADAS(高级驾驶员辅助系统)

什么是 ADAS ADAS —— 高级驾驶员辅助系统&#xff0c;包含一系列硬件和软件组件&#xff0c;自动起到驾驶员的多项作用。目前&#xff0c;常见的车辆 ADAS 功能包括自适应巡航控制、盲点检测、变道检测(车道偏离警告系统)、自动车道跟随和自动紧急制动、泊车。 L0到L2称为AD…

测试用例详解(强,硬,牛)

目录&#xff1a; 测试用例价值与体系黑盒测试方法论-等价类黑盒测试方法论-边界值黑盒测试方法论-因果图黑盒测试方法论-判定表黑盒测试方法论-场景法测试用例基础概念测试用例设计与评审面试测试测试用例设计搜索功能测试用例设计 1.测试用例价值与体系 测试用例概念测试…

【MQTT】| 搭建——在云服务器上搭建MQTT服务器

系列文章目录 【MQTT】| 搭建——在云服务器上搭建MQTT服务 失败了也挺可爱&#xff0c;成功了就超帅。 文章目录 前言1. EMQX简介2. EMQX部署3. EMQX一些操作指令3.1 启动EMQX3.2 停止EMQX3.3 检查EMQX运行状态3.4 卸载EMQX 4. EMQX设置4.1 进入EMQX控制面板 5. EMQX测试5.1…

模型评估 (Model Assessment)

1.模型评估 (Model Assessment) 笔记来源于《白话机器学习的数学》 我们训练好模型后&#xff0c;要对知道这个模型到底好不好&#xff0c;定量描述这个模型好坏就是模型评估 把获取的全部训练数据分成两份&#xff1a;一份用于测试&#xff0c;一份用于训练。然后用前者来评估…

数据库实训报告3000字

数据库实训报告1 一、实习目的 认识实习是本科教学计划中非常重要的实践性教学环节&#xff0c;其目的是使学生了解和掌握电力生产知识、印证、巩固和丰富已学过的计算机专业课程内容&#xff0c;培养学生理论联系实际&#xff0c;提高其在生产实践中调查研究、观察问题、分析问…

银行账户管理系统

1. 目的与要求 1、目的: (1)熟练掌握 C语言的基本知识和技能: (2)掌握面向对象程序设计的基本思想和方法;(3)能够利用所学的面向对象基本知识和技能&#xff0c;解决简单应用的程序设计 2、基本要求:(1)利用面向对象的方法以及 C的编程思想来完成系统的设计;(2)在设计的过程中…

抽象工厂模式(Abstract Factory)

定义 抽象工厂是一种创建型设计模式&#xff0c;它能创建一系列相关的对象&#xff0c;而无需指定其具体类。 前言 1. 问题 假设你正在开发一款家具商店模拟器。你的代码中包括一些类&#xff0c;用于表示&#xff1a; 一系列相关产品&#xff0c;例如椅子&#xff08;Chai…

091基于深度学习的手写汉字数字识别含10多种模型

emo仓库和视频演示找091期&#xff1a; 银色子弹zg的个人空间-银色子弹zg个人主页-哔哩哔哩视频 效果展示图如下&#xff1a; 代码文件展示如下&#xff1a; 运行01数据集文本生成制作.py可以读取图片路径保存再txt文本中&#xff0c; 运行02train.py可以对txt文本中的图片路…

同程数科基于 Apache Doris 构建统一实时数仓,查询提速数十倍!

本文导读&#xff1a; 同程数科是同程集团旗下的旅游产业金融科技服务平台&#xff0c;为上下游企业和个人消费者提供数字金融科技服务。近年来&#xff0c;随着同程数科业务的不断拓展和用户量的增加&#xff0c;高效可靠的一站式数据中心建设已成为必不可少的需求。为帮助业…

团体程序设计天梯赛-练习集L2篇④

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

WPF 零基础入门笔记(1):WPF静态页面,布局+样式+触发器

文章目录 官方文档往期回顾零基础笔记项目实战&#xff08;已完结&#xff09; WPF项目创建为什么选net core版本 WPF 静态页面WPF 页面布局WPF样式Style样式行内样式行外样式如果是简单样式&#xff0c;可以这么写如果是复杂样式 WPF样式继承WPF触发器单条件触发器多条件触发 …

LLDP(链路层发现协议)详解及C/C++代码实现

LLDP&#xff08;链路层发现协议&#xff09;是一种IEEE标准协议&#xff08;IEEE 802.1AB&#xff09;&#xff0c;它定义了封装在以太网帧中的消息&#xff0c;目的是通过默认情况下每30秒从每个端口定期重传一次&#xff0c;为设备提供一种向LAN&#xff08;局域网&#xff…

20个Java编程技巧

1. 把字符串常量放在前面 通过把字符串常量放在比较函数equals()比较项的左侧来防止偶然的 NullPointerException 从来都不是一个坏主意&#xff0c;就像这样&#xff1a; 这是毫无疑问的&#xff0c;把一种表达式转换成另一种更好的表达式&#xff0c;并不会失去什么。只要我…

mysql锁机制及MVCC底层原理

一、锁介绍 按性能可分为乐观锁&#xff08;适用于读多写少的情况下&#xff0c;如果是写多&#xff0c;导致过多cpu空转&#xff0c;影响性能&#xff09;和悲观锁&#xff08;适用于写多的情况&#xff09;按数据库操作粒度可分为表锁、页锁、行锁按数据库操作类型可分为读锁…