Round-Robin仲裁器
Round-Robin仲裁器
概念:Round-Robin仲裁器是一种公平的仲裁方式,每个请求者按照固定的顺序轮流获得授权。当授权信号释放后,授权将传给下一个请求者(每次授权后,上一次被授权的请求者在下一轮优先级最低)。
Round-Robin仲裁器基本概念
-
功能:公平地在多个请求者之间轮流授权,避免低优先级请求者饥饿
-
机制:
- 记录上一次被授权的请求者(last_grant寄存器)
- 下一次仲裁从last_grant的下一位开始循环搜索
-
操作:
1.根据 last_grant 生成优先级屏蔽掩码
2.将请求分为高低优先级区域
3.优先处理高优先级区域的请求
先实现简单的固定优先级仲裁器,再改进为Round-Robin仲裁器。
代码实现
1.生成优先级屏蔽掩码
// 寄存器:记录上一次授权reg [3:0] last_grant;// 组合逻辑:生成优先级屏蔽掩码wire [3:0] mask = last_grant == 4\'b0000 ? 4\'b0000 : ~((last_grant - 1) | last_grant);
说明: 根据上一次的授权信号 last_grant 计算出一个掩码 mask 用于在下一轮仲裁中屏蔽优先级低于或等于 last_grant 的请求,确保高优先级的请求能够被优先处理。
结果如下:
last_grantmasklast_grant=0010, mask=1100 :屏蔽低两位,保留高两位
2.分割高低优先级请求区域
// 分割高低优先级请求区域wire [3:0] high_pri_req = req & mask;wire [3:0] low_pri_req = req & ~mask;
高优先级请求:仅保留比 last_grant 优先级高的请求
低优先级请求:保留优先级≤ last_grant 的请求
设计目的:避免低优先级请求“饿死”。每次授权后,下一轮会优先服务更高优先级的请求,若不存在则再处理低优先级请求。
3.仲裁逻辑
// 仲裁逻辑wire [3:0] high_pri_grant = high_pri_req & -high_pri_req;wire [3:0] low_pri_grant = low_pri_req & -low_pri_req;wire [3:0] grant_next = |high_pri_req ? high_pri_grant : low_pri_grant;
代码说明: -high_pri_req 表示 high_pri_req 的补码(取反+1)。
high_pri_grant = high_pri_req & -high_pri_req;
作用:在高优先级组内选择最低位的1。(表明该仲裁器是从最低位开始选择)
原理:X & -X 保留X中最低位的1。
grant_next = |high_pri_req ? high_pri_grant : low_pri_grant;
逻辑:若 |high_pri_req 为真(high_pri_req不为0,高优先级组存在请求),授权 high_pri_grant ;否则授权 low_pri_grant
意义:确保高优先级组绝对优先,避免低优先级请求饿死
最终程序:
module test ( input clk, input rst_n, input [3:0] req, // 4位请求信号 output [3:0] grant // 4位授权信号);// 寄存器:记录上一次授权reg [3:0] last_grant;// 组合逻辑:生成优先级屏蔽掩码wire [3:0] mask = last_grant == 4\'b0000 ? 4\'b0000 : ~((last_grant - 1) | last_grant);// 分割高低优先级请求区域wire [3:0] high_pri_req = req & mask;wire [3:0] low_pri_req = req & ~mask;// 仲裁逻辑wire [3:0] high_pri_grant = high_pri_req & -high_pri_req;wire [3:0] low_pri_grant = low_pri_req & -low_pri_req;wire [3:0] grant_next = |high_pri_req ? high_pri_grant : low_pri_grant;// 时序逻辑更新授权状态always @(posedge clk or negedge rst_n) begin if (!rst_n) last_grant <= 4\'b0000; // 复位清零 else if (req != 0) last_grant <= grant_next; // 有请求时更新endassign grant = grant_next;endmodule
测试
`timescale 1ns / 1psmodule sim();reg clk ; reg rst_n ; reg [3:0] req ;wire [3:0] grant;initial clk = 1;always #10 clk <= ~clk;test u_test ( .clk (clk ), .rst_n (rst_n ), .req (req ), .grant (grant ) );initial begin rst_n = 0; req = 4\'b0000; // 初始化 #50; rst_n = 1; // 持续请求测试 req = 4\'b1011; // A、B、D请求 #100; // 请求变化测试 req = 4\'b0100; // 仅C请求 #50; // 边界测试 req = 4\'b1000; // 仅最高位 #50;endendmodule



