FPGA - 仲裁器的设计实现

一,为什么做仲裁

在多主单从的设计中,当多个源端同时发起传输请求时,这个时候就需要仲裁器来根据优先级来判断响应哪一个源端,向其传输数据。比如:以太网仲裁,DDR仲裁,光纤传图仲裁.....

二,仲裁类别

仲裁器分为轮询仲裁(Round-Robiin)固定优先级仲裁(Fixed-Priority),轮询仲裁,各个源端优先级相同,当同时发起请求时,依次进行响应,而固定优先级仲裁就是根据优先级顺序依次进行响应。

轮询仲裁:每一路数据的优先级都是一样的

中断仲裁:有一路或者多路的优先级是最高的

用的比较多的方法就是轮询仲裁

三,轮询仲裁

在实际项目中,如果需要用到仲裁,可以以2路数据作为分析:

① :缓存每一路的数据

        使用两个FIFO

        数据FIFO缓存:data+last(last信号的作用指示每一帧数据的边界)

        控制FIFO缓存:缓存数据对应的信息:类型、地址、长度……

② :设计状态机(轮询跳变)

        复位状态机处于IDLE,复位结束调到发送通道0的状态

        发送通道0状态:开始判断通道0的数据有没有来(询问),如果通道0没有来数据,则调到通道1

        如果通道0有数据来,则把通道0的数据从FIFO里面读出来发送出去,然后跳到通道1。

        发送通道1状态:开始判断通道1的数据有没有来(询问),如果通道1没有来数据,则调到通道2

        如果通道1有数据来,则把通道1的数据从FIFO里面读出来发送出去,然后跳到通道2。

        …….

四,轮询仲裁逻辑设计

以2通道设计为例:

`timescale 1ns / 1psmodule mux2_arbit(input						   clk           ,input                          reset         ,input	      [15:0]           ch0_type      ,  //默认所有通道传来的信号都是reg型,所以进行无需打拍input	      [15:0]           ch0_length    ,input	                       ch0_data_vld  ,input	                       ch0_data_last ,input	      [7:0]            ch0_data      ,input	      [15:0]           ch1_type      ,input	      [15:0]           ch1_length    ,input	                       ch1_data_vld  ,input	                       ch1_data_last ,input	      [7:0]            ch1_data      ,output	reg   [15:0]           send_type      ,output	reg   [15:0]           send_length    ,output	reg                    send_data_vld  ,output	reg                    send_data_last ,output	reg   [7:0]            send_data      );
/*--------------------------------------------------*\状态机信号定义 
\*--------------------------------------------------*/
reg [2:0]  cur_status;
reg [2:0]  nxt_status;
localparam IDLE      = 2'b00;
localparam CH0_SEND  = 2'b01;
localparam CH1_SEND  = 2'b10;
/*--------------------------------------------------*\FIFO端口信号 
\*--------------------------------------------------*/
reg	 [31:0]  ch0_frame_din    ;
reg          ch0_frame_wren   ;
wire [31:0]  ch0_frame_dout   ;
reg 		 ch0_frame_rden   ;
wire		 ch0_frame_wrfull ;
wire		 ch0_frame_rdempty;
wire [4:0]   ch0_frame_count  ;reg	 [31:0]  ch1_frame_din    ;
reg          ch1_frame_wren   ;
wire [31:0]  ch1_frame_dout   ;
reg 		 ch1_frame_rden   ;
wire		 ch1_frame_wrfull ;
wire		 ch1_frame_rdempty;
wire [4:0]   ch1_frame_count  ;reg	 [8:0]   ch0_data_din    ;
reg          ch0_data_wren   ;
wire [8:0]   ch0_data_dout   ;
reg 		 ch0_data_rden   ;
wire		 ch0_data_wrfull ;
wire		 ch0_data_rdempty;
wire [11:0]  ch0_data_count  ;reg	 [8:0]   ch1_data_din    ;
reg          ch1_data_wren   ;
wire [8:0]   ch1_data_dout   ;
reg 		 ch1_data_rden   ;
wire		 ch1_data_wrfull ;
wire		 ch1_data_rdempty;
wire [11:0]  ch1_data_count  ;/*--------------------------------------------------*\其他端口信号 
\*--------------------------------------------------*/
reg           ch0_busy;
reg           ch1_busy;reg           ch0_frame_fifo_err;
reg           ch1_frame_fifo_err;
reg           ch0_data_fifo_err ;
reg           ch1_data_fifo_err ;/*--------------------------------------------------*\通道0、通道1的数据写入FIFO 
\*--------------------------------------------------*/
always @(posedge clk) beginch0_frame_wren <= ch0_data_last;ch0_frame_din  <= {ch0_type,ch0_length};ch1_frame_wren <= ch1_data_last;ch1_frame_din  <= {ch1_type,ch1_length};    
endalways @(posedge clk) beginch0_data_wren  <= ch0_data_vld;ch0_data_din   <= {ch0_data_last,ch0_data};	     ch1_data_wren  <= ch1_data_vld;ch1_data_din   <= {ch1_data_last,ch1_data};		  
end/*--------------------------------------------------*\busy信号
\*--------------------------------------------------*/
always @(posedge clk) beginif (reset) ch0_busy <= 0;else if (cur_status == CH0_SEND && send_data_last) ch0_busy <= 0;else if (cur_status == CH0_SEND && ~ch0_frame_rdempty)ch0_busy <= 1;
endalways @(posedge clk) beginif (reset) ch1_busy <= 0;else if (cur_status == CH1_SEND && send_data_last) ch1_busy <= 0;else if (cur_status == CH1_SEND && ~ch1_frame_rdempty)ch1_busy <= 1;
end/*--------------------------------------------------*\状态机设计
\*--------------------------------------------------*/
always @(posedge clk) beginif (reset) cur_status <= IDLE;else cur_status <= nxt_status;
endalways @(*) beginif (reset) beginnxt_status <= IDLE;		endelse begincase(cur_status)IDLE : beginnxt_status <= CH0_SEND;endCH0_SEND : beginif (~ch0_busy && ch0_frame_rdempty)nxt_status <= CH1_SEND;else if (send_data_last)nxt_status <= CH1_SEND;else nxt_status <= cur_status;endCH1_SEND : beginif (~ch1_busy && ch1_frame_rdempty)nxt_status <= CH0_SEND;else if (send_data_last)nxt_status <= CH0_SEND;else nxt_status <= cur_status;enddefault : nxt_status <= IDLE;endcase	end
endalways @(posedge clk) beginif (reset) beginsend_type      <= 0;send_length    <= 0;send_data_vld  <= 0;send_data_last <= 0;send_data      <= 0;endelse begincase(cur_status)IDLE : beginsend_type      <= 0;send_length    <= 0;send_data_vld  <= 0;send_data_last <= 0;send_data      <= 0;endCH0_SEND : beginif (ch0_frame_rden) beginsend_type   <= ch0_frame_dout[31:16];send_length <= ch0_frame_dout[15:0];endelse beginsend_type   <= send_type;send_length <= send_length;endif (ch0_data_rden) beginsend_data_vld  <= 1'b1;send_data_last <= ch0_data_dout[8];send_data      <= ch0_data_dout[7:0];endelse beginsend_data_vld  <= 0;send_data_last <= 0;send_data      <= 0;endendCH1_SEND : beginif (ch1_frame_rden) beginsend_type   <= ch1_frame_dout[31:16];send_length <= ch1_frame_dout[15:0];endelse beginsend_type   <= send_type;send_length <= send_length;endif (ch1_data_rden) beginsend_data_vld  <= 1'b1;send_data_last <= ch1_data_dout[8];send_data      <= ch1_data_dout[7:0];endelse beginsend_data_vld  <= 0;send_data_last <= 0;send_data      <= 0;end		enddefault : ;endcaseend
end/*--------------------------------------------------*\FIFO读使能设计
\*--------------------------------------------------*/
always @(posedge clk) beginif (reset) ch0_frame_rden <= 0;else if (cur_status == CH0_SEND && ~ch0_frame_rdempty && ~ch0_busy) ch0_frame_rden <= 1'b1;else ch0_frame_rden <= 0;
endalways @(posedge clk) beginif (reset) ch1_frame_rden <= 0;else if (cur_status == CH1_SEND && ~ch1_frame_rdempty && ~ch1_busy) ch1_frame_rden <= 1'b1;else ch1_frame_rden <= 0;
endalways @(posedge clk) beginif (reset) ch0_data_rden <= 0;else if (ch0_data_rden && ch0_data_dout[8]) ch0_data_rden <= 0;else if (ch0_frame_rden)ch0_data_rden <= 1'b1;else ch0_data_rden <= ch0_data_rden;
endalways @(posedge clk) beginif (reset) ch1_data_rden <= 0;else if (ch1_data_rden && ch1_data_dout[8]) ch1_data_rden <= 0;else if (ch1_frame_rden)ch1_data_rden <= 1'b1;else ch1_data_rden <= ch1_data_rden;
end/*--------------------------------------------------*\调试信号 
\*--------------------------------------------------*/
always @(posedge clk) beginif (reset) ch0_frame_fifo_err <= 0;else if (ch0_frame_wren && ch0_frame_wrfull) ch0_frame_fifo_err <= 1;else ch0_frame_fifo_err <= ch0_frame_fifo_err;
endalways @(posedge clk) beginif (reset) ch1_frame_fifo_err <= 0;else if (ch1_frame_wren && ch1_frame_wrfull) ch1_frame_fifo_err <= 1;else ch1_frame_fifo_err <= ch1_frame_fifo_err;
endalways @(posedge clk) beginif (reset) ch0_data_fifo_err <= 0;else if (ch0_data_wren && ch0_data_wrfull) ch0_data_fifo_err <= 1;else ch0_data_fifo_err <= ch0_data_fifo_err;
endalways @(posedge clk) beginif (reset) ch1_data_fifo_err <= 0;else if (ch1_data_wren && ch1_data_wrfull) ch1_data_fifo_err <= 1;else ch1_data_fifo_err <= ch1_data_fifo_err;
end/*--------------------------------------------------*\例化 
\*--------------------------------------------------*/
fifo_w9xd2048 ch0_data_fifo (.clk       (clk),                 // input wire clk.srst      (reset),               // input wire srst.din       (ch0_data_din),        // input wire [8 : 0] din.wr_en     (ch0_data_wren),       // input wire wr_en.rd_en     (ch0_data_rden),       // input wire rd_en.dout      (ch0_data_dout),       // output wire [8 : 0] dout.full      (ch0_data_wrfull),     // output wire full.empty     (ch0_data_rdempty),    // output wire empty.data_count(ch0_data_count)       // output wire [11 : 0] data_count
);fifo_w9xd2048 ch1_data_fifo (.clk       (clk),                 // input wire clk.srst      (reset),               // input wire srst.din       (ch1_data_din),        // input wire [8 : 0] din.wr_en     (ch1_data_wren),       // input wire wr_en.rd_en     (ch1_data_rden),       // input wire rd_en.dout      (ch1_data_dout),       // output wire [8 : 0] dout.full      (ch1_data_wrfull),     // output wire full.empty     (ch1_data_rdempty),    // output wire empty.data_count(ch1_data_count)       // output wire [11 : 0] data_count
);fifo_w32xd16 ch0_frame_fifo (.clk       (clk),                // input wire clk.srst      (reset),              // input wire srst.din       (ch0_frame_din),      // input wire [31 : 0] din.wr_en     (ch0_frame_wren),     // input wire wr_en.rd_en     (ch0_frame_rden),     // input wire rd_en.dout      (ch0_frame_dout),     // output wire [31 : 0] dout.full      (ch0_frame_wrfull),   // output wire full.empty     (ch0_frame_rdempty),  // output wire empty.data_count(ch0_frame_count)    // output wire [4 : 0] data_count
);fifo_w32xd16 ch1_frame_fifo (.clk       (clk),                // input wire clk.srst      (reset),              // input wire srst.din       (ch1_frame_din),      // input wire [31 : 0] din.wr_en     (ch1_frame_wren),     // input wire wr_en.rd_en     (ch1_frame_rden),     // input wire rd_en.dout      (ch1_frame_dout),     // output wire [31 : 0] dout.full      (ch1_frame_wrfull),   // output wire full.empty     (ch1_frame_rdempty),  // output wire empty.data_count(ch1_frame_count)    // output wire [4 : 0] data_count
);endmodule

编写测试:

`timescale 1ns / 1psmodule tb();parameter CH0_LENGTH = 256 ;parameter CH0_PERIOD = 300 ; parameter CH1_LENGTH = 256 ;parameter CH1_PERIOD = 300 ;reg          clk;reg          reset;wire         ch0_data_vld;wire         ch0_data_last;wire  [7:0]  ch0_data;wire         ch1_data_vld;wire         ch1_data_last;wire  [7:0]  ch1_data;wire  [15:0] send_type;wire  [15:0] send_length;wire         send_data_vld;wire         send_data_last;wire   [7:0] send_data	;initial beginclk = 0;forever #(10) clk = ~clk;endinitial beginreset = 1;#(2000) reset = 0;enddata_generate #(.LENGTH(CH0_LENGTH),.PERIOD(CH0_PERIOD)) data_generate_ch0 (.clk            (clk),.reset          (reset),.send_data_vld  (ch0_data_vld),.send_data_last (ch0_data_last),.send_data      (ch0_data));data_generate #(.LENGTH(CH1_LENGTH),.PERIOD(CH1_PERIOD)) data_generate_ch1 (.clk            (clk),.reset          (reset),.send_data_vld  (ch1_data_vld),.send_data_last (ch1_data_last),.send_data      (ch1_data));mux2_arbit mux2_arbit(.clk            (clk),.reset          (reset),.ch0_type       (16'h0001),.ch0_length     (CH0_LENGTH),.ch0_data_vld   (ch0_data_vld),.ch0_data_last  (ch0_data_last),.ch0_data       (ch0_data),.ch1_type       (16'h0002),.ch1_length     (CH1_LENGTH),.ch1_data_vld   (ch1_data_vld),.ch1_data_last  (ch1_data_last),.ch1_data       (ch1_data),.send_type      (send_type),.send_length    (send_length),.send_data_vld  (send_data_vld),.send_data_last (send_data_last),.send_data      (send_data));endmodule

仿真波形

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

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

相关文章

electron打包编译国产统信uos系统 arm架构 x86架构 linux mac等环境

electron v21版本以上统信UOS会提示gbm_bo_map错误&#xff0c;可使用v8~v21版本的electron 打包linux包需要再linux系统下运行编译&#xff0c;arch可以指定架构 如果要在统信uos上运行&#xff0c;需要打包成deb格式&#xff0c;在target中修改成deb 或者用第三方软件把app…

three.js捋文档的记录笔记(六):场景 几何体 材质 物体 相机 渲染器的简单理解

三维场景Scene const scene new THREE.Scene();物体形状&#xff1a;几何体 Geometry //创建一个长方体几何对象Geometry const geometry new THREE.BoxGeometry(100, 100, 100); 物体外观&#xff1a;材质Material //创建一个材质对象Material const material new THREE.M…

在Vue3中如何使用H.265视频流媒体播放器EasyPlayer.js?

H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;可支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff0c;能支持WebSocket-FLV、HTTP-FLV&#xff0c;HLS&#xff08;m3u8&#…

C语言面试题之奇偶链表

奇偶链表 实例要求 1、给定单链表的头节点 head &#xff0c;将所有索引为奇数的节点和索引为偶数的节点分别组合在一起&#xff0c;然后返回重新排序的列表&#xff1b;2、第一个节点的索引被认为是 奇数 &#xff0c; 第二个节点的索引为 偶数 &#xff0c;以此类推&#x…

Wpf 使用 Prism 实战开发Day20

备忘录功能页面完善以及优化 备忘录功能基本跟前一章节的待办事项差不多一至&#xff0c;就不再做过多的笔述了 一.备忘录功能完整页面源码 MemoView.xaml <UserControl x:Class"MyToDo.Views.MemoView"xmlns"http://schemas.microsoft.com/winfx/2006/xam…

33、链表-排序链表

思路&#xff1a; 首先排序可以使用集合将所有节点放入集合中&#xff0c;然后再根据每个节点值进行排序。这个可以很容易做到&#xff0c;不再赘述 其次就是直接在链表上排序&#xff0c;如何排序可以使用归并排序的方式&#xff0c;代码如下&#xff1a; class Solution {…

opencv | 编译缺失ippicv相关文件解决方案

1.执行cmake后&#xff0c;查看控制台输出信息 ~/VM_data/opencv-4.9.0$ cd buile_temp ~/VM_data/opencv-4.9.0/buile_temp$ cmake ..2.去浏览器打开链接&#xff0c;下载对应的压缩包&#xff0c;解压到 路径&#xff1a;/3rdparty/ippicv/

​LeetCode解法汇总2924. 找到冠军 II

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 一场比赛中共有 n 支队伍&#xff0c;按从…

【云计算】安全组和网络ACL的区别

安全组和网络ACL的区别 ACL&#xff08;Access Control List&#xff09;和 安全组&#xff08;Security Group&#xff09;是两种不同的网络安全控制机制&#xff0c;通常用于管理云计算平台中的网络访问权限。它们在功能和实现上有一些显著的区别&#xff1a; 辨析 范围不同&…

ASP.NET MVC企业级程序设计 (EF+三层架构+MVP实现查询数据)

目录 效果图 实现过程 1创建数据库 2创建项目文件 3创建控制器&#xff0c;右键添加&#xff0c;控制器 ​编辑 注意这里要写Home​编辑 创建成功 数据模型创建过程之前作品有具体过程​编辑 4创建DAL 5创建BLL 6创建视图&#xff0c;右键添加视图 ​编辑 7HomeContr…

【zookeeper】安装

第二次安装zookeeper了&#xff0c;蛮记录一下&#xff08;让blog丰富一点~&#xff09; 1. Apache Zookeeper官网下载 2. 解压后创建log和data文件夹 这个其实不一定要建在zookeeper文件夹下&#xff0c;建在任意一个文件夹里都行&#xff0c;只要配置文件中的路径配置能找到…

软件设计不是CRUD(18):像搭积木一样搭建应用系统(上)——单个应用系统的搭建过程

1、概述 之前的文章本专题花了大量文字篇幅,介绍如何基于业务抽象的设计方式完成应用系统各个功能模块的设计工作。而之所以进行这样的功能模块设计无非是希望这些功能模块在具体的项目实施过程中,能够按照当时的需求快速的、简易的、稳定的、最大可能节约开发成本的形成可用…

设计模式之观察者模式(上)

观察者模式 1&#xff09;概述 1.定义 定义对象之间的一种一对多依赖关系&#xff0c;使得每当一个对象状态发生改变时&#xff0c;其相关依赖对象皆得到通知并被自动更新。 观察者模式的别名包括发布-订阅&#xff08;Publish/Subscribe&#xff09;模式、模型-视图&#…

PCB整理

1.加工工艺流程&#xff1a; 开料磨边 、烘板、内光成像、内层腐刻、内层AOI、内层黑化、层压、钻孔、沉铜加厚、外光成像、外层腐刻、外层AOI、印阻焊、阻焊成像、丝印字符、涂覆保护层、二次钻孔、外形加工、电测试、烘板包装。 2.层叠结构&#xff1a; 3.基材&#xff1a;覆…

开源模型应用落地-chatglm3-6b-gradio-入门篇(七)

一、前言 早前的文章&#xff0c;我们都是通过输入命令的方式来使用Chatglm3-6b模型。现在&#xff0c;我们可以通过使用gradio&#xff0c;通过一个界面与模型进行交互。这样做可以减少重复加载模型和修改代码的麻烦&#xff0c; 让我们更方便地体验模型的效果。 二、术语 2.…

2024蓝桥A组E题

成绩统计 问题描述格式输入格式输出样例输入样例输出评测用例规模与约定解析参考程序难度等级 问题描述 题目有问题方差定义那加平方&#xff08;vi-v&#xff09; 格式输入 输入的第一行包含三个正整数n,k,T &#xff0c;相邻整数之间使用一个空格分隔。 第二行包含n个正整数…

Kubernetes(k8s)集群搭建部署,master节点配置

目录 1.切换为root用户 2.关闭防火墙&#xff0c;关闭swap分区和禁用SElinux 3.安装docker 4.更改daemon.json文件&#xff0c;指定 Docker 守护进程使用的 cgroup 驱动程序 5.重启docker服务 6.配置kubernetes.repo 7.安装Kubelet、Kubeadm、Kubectl 8.设置开机自启 …

【数据结构|C语言版】单链表应用

前言1. 基于单链表实现通讯录1.1 知识要求1.2 功能要求 2. 代码总结2.1 SeqList.h2.2 SeqList.c2.3 Contact.h2.4 Contact.c2.5 test.c 后言 上期回顾&#xff1a;【数据结构|C语言版】单链表 前言 各位小伙伴大家好&#xff01;上期小编讲解了单链表相关知识&#xff0c;在此…

【Go】原子并发操作

目录 一、基本概念 支持的数据类型 主要函数 使用场景 二、基础代码实例 开协程给原子变量做加法 统计多个变量 原子标志判断 三、并发日志记录器 四、并发计数器与性能监控 五、优雅的停止并发任务 worker函数 Main函数 应用价值 Go语言中&#xff0c;原子并发操…

【Linux】Linux基础与常用指令大全

文章目录 操作系统是什么&#xff1f;1. Linux家族介绍2. Linux的安装方式3. 常用指令3.1 ls [选项] [目录/文件]&#xff08;显示目录或文件信息&#xff09;3.2 pwd&#xff08;显示当前所在目录&#xff09;3.3 任意指令加上 --help&#xff08;查看指令的用法&#xff09;3…