从课堂提问到芯片设计:用Verilog手把手教你实现一个带权重的公平仲裁器

张开发
2026/4/15 6:15:13 15 分钟阅读

分享文章

从课堂提问到芯片设计:用Verilog手把手教你实现一个带权重的公平仲裁器
从课堂提问到芯片设计用Verilog手把手教你实现一个带权重的公平仲裁器在数字电路设计中仲裁器Arbiter是一个至关重要的组件它负责在多个请求源之间公平合理地分配共享资源。想象一下教室里的场景老师需要公平地提问学生但又要考虑不同学生的学习能力差异——这正是带权重轮询仲裁器Weighted Round-Robin Arbiter的核心思想。1. 仲裁器的基本概念与应用场景1.1 为什么需要仲裁器在现代数字系统中多个主设备如CPU核心、DMA控制器等经常需要访问同一个从设备如内存控制器或外设。这就好比学校食堂的多个窗口同时开放时需要合理的排队机制来避免混乱。仲裁器就是这样的交通警察它确保资源公平分配防止某个设备长期霸占资源优先级管理处理不同紧急程度的请求效率优化最小化仲裁过程本身的开销1.2 常见仲裁策略对比仲裁类型工作原理优点缺点典型应用固定优先级始终优先服务高优先级请求实现简单延迟可预测低优先级可能饿死中断控制器轮询(RR)按固定顺序轮流服务保证基本公平性无法区分优先级简单总线仲裁权重轮询按预设比例分配服务机会兼顾公平与优先级实现较复杂QoS敏感系统课堂类比固定优先级就像老师只提问成绩最好的学生普通轮询是按学号依次提问而权重轮询则是给不同学生设置不同的提问频率比如成绩中等的学生获得更多锻炼机会。2. 权重轮询仲裁器的核心原理2.1 权重分配机制权重轮询仲裁器的核心在于为每个请求源分配一个权重值Weight这个值决定了该请求源在一个轮询周期内能获得的服务次数比例。例如权重配置 3:2:1 表示请求源A每轮可获得最多3次服务请求源B每轮可获得最多2次服务请求源C每轮可获得最多1次服务// 权重配置示例3位宽 parameter WEIGHT_A 3b011; // 3 parameter WEIGHT_B 3b010; // 2 parameter WEIGHT_C 3b001; // 12.2 仲裁状态机设计权重轮询仲裁器需要维护以下关键状态当前权重计数器记录每个请求源已使用的服务次数有效请求掩码标识当前可服务的请求轮询指针指示当前优先考虑的请求源注意当某个请求源的权重计数器达到设定值时需将其从当前轮询周期排除直到新一轮开始。3. 基于Verilog的硬件实现3.1 模块接口设计module weight_rr_arbiter #( parameter REQ_NUM 4, // 请求源数量 parameter WEIGHT_WIDTH 4 // 权重值位宽 )( input clk, input rst_n, input [REQ_NUM-1:0] req, // 请求信号 input [REQ_NUM*WEIGHT_WIDTH-1:0] weights, // 权重配置 output reg [REQ_NUM-1:0] grant, // 授权信号 output grant_valid // 授权有效 );3.2 核心算法实现3.2.1 权重计数器管理// 每个请求源的权重计数器 reg [WEIGHT_WIDTH-1:0] weight_cnt[REQ_NUM-1:0]; // 更新权重计数器 always (posedge clk or negedge rst_n) begin if (!rst_n) begin for (int i0; iREQ_NUM; i) weight_cnt[i] {WEIGHT_WIDTH{1b0}}; end else if (grant_valid) begin for (int i0; iREQ_NUM; i) begin if (grant[i]) begin // 被授权的请求源计数器递增 weight_cnt[i] weight_cnt[i] 1b1; end end end end3.2.2 轮询指针逻辑// 轮询指针寄存器 reg [REQ_NUM-1:0] rr_ptr; // 指针更新逻辑 always (posedge clk or negedge rst_n) begin if (!rst_n) begin rr_ptr {{REQ_NUM-1{1b0}}, 1b1}; // 初始指向请求源0 end else if (grant_valid) begin // 找到下一个有效的请求源 rr_ptr {rr_ptr[REQ_NUM-2:0], rr_ptr[REQ_NUM-1]}; end end3.3 仲裁决策逻辑// 生成授权信号 always (*) begin grant {REQ_NUM{1b0}}; // 检查每个请求源是否满足条件 // 1. 有请求(req[i]1) // 2. 未用完权重(weight_cnt[i] weights[i]) // 3. 是当前轮询指针指向的或更高优先级 for (int i0; iREQ_NUM; i) begin if (req[i] (weight_cnt[i] weights[i*WEIGHT_WIDTH : WEIGHT_WIDTH])) begin if (rr_ptr[i]) begin grant[i] 1b1; break; end end end // 如果当前轮询周期无有效请求开始新周期 if (grant 0) begin for (int i0; iREQ_NUM; i) begin if (req[i]) begin grant[i] 1b1; break; end end end end assign grant_valid |req; // 只要有请求就有效4. 实际应用与优化技巧4.1 性能优化策略流水线设计将仲裁决策分为多个周期完成周期1计算有效请求掩码周期2生成授权信号并行比较使用并行前缀网络加速优先级判断动态权重调整根据系统负载实时修改权重值4.2 常见问题排查权重计数器溢出确保权重值不超过计数器位宽死锁情况当所有请求源都用完权重时需自动重置时序违例在高速时钟下可能需要插入寄存器4.3 测试用例设计// 典型测试场景 initial begin // 初始化 req 4b0000; weights {4d3, 4d2, 4d1, 4d1}; // 权重3:2:1:1 // 测试用例1基础仲裁 #10 req 4b1111; #10 req 4b0111; // 测试用例2权重耗尽场景 #100 req 4b0011; end在真实的芯片设计项目中我们通常会遇到各种边界情况。比如当高优先级请求持续到来时如何确保低优先级请求不会被完全饿死这时可以在权重轮询的基础上加入紧急通道机制为特定请求保留最小带宽保障。

更多文章