仲裁器设计

发布时间:2026/7/30 1:59:53
仲裁器设计 一、固定优先级仲裁器仲裁器设计1固定优先级仲裁器-CSDN博客固定优先级的本质是找到一个多比特信号中,最开始出现的1,一般是从低位到高位的顺序. 约定好:低位代表高优先级,高位代表低优先级轮询的思想简单来说就是屏蔽已经授权的用户授权给还未仲裁的较高优先级用户因此核心问题在于如何找到那个还未仲裁的较高优先级用户。这让我们很容易联想到如何找到序列里第一个1位置由低到高的问题它是这样处理的。我们先以3个模块产生request为例大家一般在面试的时候都会碰到给定模块数目比如3让你设计。咱们就直接上code来表示一种写法modulefixed_prio_arb(input[2:0]req,output logic[2:0]grant);always_combbegincase(1b1)req[0]: grant 3b001;req[1]:grant3b010;req[2]: grant 3b100;default:grant3b000;endcaseendendmodule: fixed_prio_arb这里的技巧是利用verilog中的case语句可以比用if else简洁而且利用了case里的按顺序语法规则来实现了优先级。这里多说一句给verilog的初学者尽管verilog和C看起来很像很多关键字都是一样的比如case但是verilog的case和C的case是不一样的verilog的case自带break即当一个condition满足之后就只会执行这一条冒号之后的只有input 发生变化之后才会再次evaluate因为这是描述硬件电路。而C语言的case里如果一条满足之后会按照顺序继续往下执行如果下一个条件依然满足那么就会跳到下一个条件里所以C的case语句我们通常要加break。将序列减1这样序列中从低位开始为0的bit位就会因为不够减向高位借位当前位就变为1直到遇到序列中第一个为1的bit位其因为低位的借位变为0更高位则保持不变。再将得到的新seq进行按位~此时原seq中第一个1仍然为1再和原seq进行按位操作,即可得到由低到高的第一个1的位置。记住req和它的2的补码按位与req-1就是从低位找到高位找到最低位的1然后减掉之后变成0moduleprior_arb#(parameter REQ_WIDTH16)(input[REQ_WIDTH-1:0]req,output[REQ_WIDTH-1:0]grant);assign grant req (~(req-1));endmodule二、轮询仲裁器【数字IC设计】循环优先级仲裁器 的 verilog实现原理、源码、仿真_轮询仲裁器verilog代码-CSDN博客而轮询仲裁需要找到上一次授权后的最高优先级用户由于grant本身就是独热码所以只需要将上述中的1‘b1换成上一次仲裁结果即可这里就需要使用时序逻辑。考虑到grant的二进制数值可能比req大因此将位宽扩大一倍如下操作。将double_req减去上一次仲裁结果后再取反和原double_req按位此时就可找到当前可授权的用户再把grant位宽恢复成N位。最后需要把当前仲裁结果进行循环左移处理这是为了在下次仲裁时屏蔽当前已完成仲裁的用户。总之round-robin还是要体现round, 指的是某一位被选中时,它的优先级被降为最低,而他旁边的高一位的那个优先级变为最高。该算法每个req的优先级并不固定会根据前一次的仲裁结果动态调整各个req的优先级。具体描述如下同样假设有有四个reqDCBA规定四个req的初始优先级从左到右依次变高即A的优先级最高D的优先级最低。Round-Robin规定当前仲裁胜出的req的优先级在下一轮仲裁中变为最低胜出req相邻左边的优先级变为最高。即假设在第一次仲裁时req为4b0110那么B在该次仲裁中胜出那么下一轮仲裁时四个req的优先级顺序变为BADC注意这里是顺序轮转A的优先级会变得比D、C低。那如何将Round-Robin转换为相应的数学模型呢本着有轮子就不新造的理念可以试着将Fixed Priority Arbitrary升级为Round-Robin。观察可以发现第一次的仲裁其实是一次优先级顺序为DCBA的Fixed Priority Arbitrary第二次仲裁是将原本优先级顺序为DCBA的变为BADC的一次Fixed Priority Arbitrary。为了便于理解进一步将第二次仲裁拆分为DCBA和DC00两个同时执行的Fixed Priority Arbitrary如下图所示。两个仲裁分布得到了X和YX和Y之间谁最终胜出就很简单了因为在本轮仲裁中DC的优先级高于BA所以只要在DC中有相应的req则Y胜出反之则X胜出。这里提出pointer的概念pointer所指的位置表示优先级最高pointer的更新是基于上一次仲裁结果进行更新。以pointer为分界点做两个Fixed Priority Arbitrary再根据Pointer所指位置以及左边是否有req决定最终胜出的req。moduleround_robin_arb(inputclk ,inputrst_n ,input[3:0] req,output[3:0] grant);//生成上一次仲裁结果reg[3:0] last_state;always(posedgeclkornegedgerst_n)beginif(!rst_n)last_state 4b0001;//默认值表示最低位的优先级最高elseif(|req)last_state {grant[2:0],grant[3]};//有仲裁请求根据上一次的仲裁结果左移1bit后选择新的优先级最高的bitelselast_state last_state;//无仲裁请求时pre_state不更新end//如果最左侧几个高优先级主机都为发起仲裁请求需要从最低位开始轮询。//此处通过两个request拼接将右侧低位拼接到左侧即可实现对低位的判断。//相当于上面的例子的{DCBA,DC00}进行仲裁wire[7:0] grant_ext;assigngrant_ext {req,req} ~({req,req} - last_state);//得到的grant_ext必定为一个独热码但是置高位可能在代表低位的高4bit中因此进行求或运算assigngrant grant_ext[3:0] | grant_ext[7:4];endmodule三、权重轮询仲裁器我们在轮询的基础上加上一些权重仲裁器虽然轮询的去serve requestor的 请求但是完成一圈轮询后requestor被serve的次数并不完全相同。假设requestor有A、B、C、D三个权值分别为4、3、2、1假设它们的request一直为高且从A开始轮询。则A被serve 4 次后B 才能被serve依次类推。即weighted round robin则是要把weight计数器消耗光之后才轮换。如果A被serve的次数不够4次此时request被拉低了呢这个时候我们不能等待A而是要serve其他request为高的source不然如果A后面不再发出有request其他source的request就会永远不能被serve就会挂死。因此当source的counter与weight相同或者是正在被serve的source request被拉低则重新load权值。moduleweight_round_arb(input clk,input rst_n,input[3:0]req,output[3:0]grant);parameter integer WEIGHT[3:0] {1,2,3,4};reg [3:0] last_state;reg [3:0] count [3:0];wire [3:0] round_cell_en; //请求通道轮换触发信号wire round_en;genvar i;generatefor(i0; i4; ii1) begin: counteralways (posedge clk or negedge rst_n) beginif(!rst_n)count[i] 4b0;elseif(|grant)beginif(grant[i])count[i]count[i]1b1;elsecount[i] 4b0;endend// 1.当前节点连续占用总线的次数达到了设定的权重上限必须交出控制权。2.主动释放(count[i] ! 0 ~req[i])提前换人。当前节点的额度还没用完连庄进行中但突然撤销了请求比如数据发完了必须立刻交出总线避免浪费资源。assign round_cell_en[i](count[i]WEIGHT[i])|((count[i]!4d0) (~req[i]));endendgenerate//使用按位或归约运算符(|)简化你的写法assign round_en (|round_cell_en) (|req);always (posedge clk or negedge rst_n) beginif(!rst_n)last_state 4b0001;elseif(round_en)last_state{grant[2:0],grant[3]};endwire[7:0]grant_ext;assign grant_ext{req,req}~({req,req}-last_state);assign grantgrant_ext[3:0]|grant_ext[7:4];endmodule四、总结仲裁器用于管理多个主设备对同一共享资源如总线存储器的访问请求确保在任何时刻只有一个主设备可以获得访问权限避免资源冲突。如果请求信号是异步的怎么办呢就需要用同步器可以直接用打两拍的方式虽然是多bit信号但是每一个请求信号都来自不同的模块如何优化仲裁器的时序和面积呢时序例如对于轮询仲裁器可以用流水线的方式第一拍更新指针第二拍根据指针生成最终的grant。面积assign grant_ext{req,req}~({req,req}-last_state);在一个SoC系统中CPU,DMA和GPU都要访问DDR你会用哪个仲裁策略为什么呢1.流量识别与分类首先需要识别系统中所有可能产生数据流的主设备MasterCPU集群、GPU、NPU、DMA、视频编解码器、网络接口等。为这些数据流分类贴标签通常分为几大类延迟敏感型CPU取指、缓存维护、中断控制、触控反馈、音频回放。目标低延迟。带宽敏感型GPU纹理渲染、视频帧传输、内存拷贝DMA。目标高带宽。实时保证型显示控制器必须在下个帧扫描前送出新数据、汽车安全总线。目标确定性延迟和带宽绝不能有抖动。最佳effort型后台网络下载、磁盘碎片整理。目标有空闲资源则处理无任何保证。2.制定QoS策略根据分类将系统资源总线带宽、内存带宽按优先级进行分配。例如策略1CPU的实时请求Latency-Sensitive优先级最高可插队任何其他请求。策略2GPU的带宽请求Bandwidth-Sensitive享有最高权重保证其80%的可用带宽。策略3显示DMA控制器使用固定的时间片TDMA保证其每秒60帧数据必须按时送达。有哪些常见的仲裁策略呢