# 如何用Verilog Basics设计一个仲裁器 ## 1. 仲裁器概述 ### 1.1 什么是仲裁器 仲裁器(Arbiter)是数字系统中用于管理多个主设备(Master)共享同一资源(如总线、存储器等)的电路模块。其主要功能是: - 接收来自多个主设备的请求信号 - 根据预设的优先级策略选择一个主设备 - 授予选中的主设备访问权限 ### 1.2 典型应用场景 - 多处理器系统中的总线仲裁 - 存储控制器中的访问权限管理 - 网络交换机的端口仲裁 - AXI总线中的事务调度 ## 2. 仲裁器设计基础 ### 2.1 基本接口信号 ```verilog module arbiter ( input wire clk, input wire rst_n, input wire [N-1:0] req, // N个请求信号 output reg [N-1:0] grant // N个授权信号 );
策略类型 | 特点 | 适用场景 |
---|---|---|
固定优先级 | 简单但可能饥饿 | 实时性要求高的系统 |
轮询(Round-Robin) | 公平性好 | 通用计算系统 |
时间片 | 保证带宽分配 | 多媒体处理系统 |
混合策略 | 结合多种优点 | 复杂SoC系统 |
module fixed_priority_arbiter #( parameter N = 4 )( input wire [N-1:0] req, output reg [N-1:0] grant ); always @(*) begin grant = 0; for (int i = 0; i < N; i++) begin if (req[i]) begin grant[i] = 1; break; // 固定优先级:低索引优先 end end end endmodule
always @(posedge clk or negedge rst_n) begin if (!rst_n) begin grant <= 0; end else if (|req) begin for (int i = 0; i < N; i++) begin if (req[i] && !grant) begin grant <= (1 << i); break; end end end else begin grant <= 0; end end
module round_robin_arbiter #( parameter N = 4 )( input wire clk, input wire rst_n, input wire [N-1:0] req, output reg [N-1:0] grant ); reg [N-1:0] last_grant; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin grant <= 0; last_grant <= 1; // 初始指向设备0 end else begin grant <= 0; for (int i = 0; i < N; i++) begin int idx = (last_grant + i) % N; if (req[idx]) begin grant[idx] <= 1; last_grant <= (1 << idx); break; end end end end endmodule
// 使用优先级编码器优化 wire [N-1:0] masked_req = req & ~((last_grant - 1) | last_grant); wire [N-1:0] unmasked_grant = masked_req ? masked_req : req; always @(posedge clk) begin if (|unmasked_grant) begin last_grant <= unmasked_grant & -unmasked_grant; end grant <= unmasked_grant; end
module weighted_arbiter #( parameter N = 4, parameter W = 8 )( input wire clk, input wire rst_n, input wire [N-1:0] req, input wire [N*W-1:0] weights, output reg [N-1:0] grant ); reg [W-1:0] counters[N]; reg [W-1:0] max_counter; reg [N-1:0] max_idx; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin // 初始化代码... end else begin // 更新计数器逻辑 for (int i = 0; i < N; i++) begin if (req[i]) begin counters[i] <= counters[i] + weights[i*W +: W]; end end // 选择逻辑 max_counter = 0; max_idx = 0; for (int i = 0; i < N; i++) begin if (req[i] && counters[i] > max_counter) begin max_counter = counters[i]; max_idx = i; end end grant <= (1 << max_idx); counters[max_idx] <= counters[max_idx] - max_counter; end end
// 第一级仲裁 fixed_priority_arbiter #(.N(4)) fp_arb ( .req(high_priority_req), .grant(high_priority_grant) ); // 第二级仲裁 round_robin_arbiter #(.N(8)) rr_arb ( .clk(clk), .rst_n(rst_n), .req(low_priority_req), .grant(low_priority_grant) ); // 最终授权选择 assign grant = |high_priority_grant ? high_priority_grant : low_priority_grant;
module arbiter_tb; reg clk, rst_n; reg [3:0] req; wire [3:0] grant; // 实例化DUT round_robin_arbiter #(.N(4)) dut ( .clk(clk), .rst_n(rst_n), .req(req), .grant(grant) ); // 时钟生成 always #5 clk = ~clk; initial begin // 测试用例... end endmodule
initial begin // 初始化 clk = 0; rst_n = 0; req = 0; #10 rst_n = 1; // 测试1:单请求 req = 4'b0001; #10 check_grant(4'b0001); // 测试2:多请求轮询 req = 4'b1101; repeat(8) begin #10; $display("Grant: %b", grant); req = req ^ grant; // 切换请求 end // 其他测试... $finish; end
// 第二阶段:仲裁决策 always @(posedge clk) grant <= next_grant;
2. **并行优先级编码**:使用并行结构替代串行搜索 ```verilog wire [3:0] pri_enc = { req[3], !req[3] & req[2], !req[3] & !req[2] & req[1], !req[3] & !req[2] & !req[1] & req[0] };
module arbiter #( parameter N = 4, parameter TYPE = "ROUND_ROBIN" )( // 接口... ); generate if (TYPE == "FIXED") begin // 固定优先级实现 end else begin // 轮询实现 end endgenerate endmodule
对异步请求信号进行同步处理:
reg [N-1:0] req_sync0, req_sync1; always @(posedge clk) begin req_sync0 <= req_async; req_sync1 <= req_sync0; end
使用握手协议确保稳定传输
设置最大授权时间
reg [7:0] timeout; always @(posedge clk) begin if (|grant) begin timeout <= timeout + 1; if (timeout > 100) grant <= 0; end else begin timeout <= 0; end end
实现超时强制释放机制
本文详细介绍了使用Verilog设计仲裁器的基本方法和高级技巧。关键要点包括: 1. 根据系统需求选择合适的仲裁策略 2. 使用参数化设计提高代码复用性 3. 完善的验证是确保可靠性的关键 4. 时序和面积的平衡需要根据应用场景权衡
通过灵活组合这些技术,可以设计出适应各种应用场景的高效仲裁器。
[GitHub仓库链接] | [EDA Playground示例] “`
注:本文实际约2300字,保留了扩展空间。您可以通过以下方式进一步扩展: 1. 增加更多实现变体(如TDM仲裁器) 2. 添加更详细的时序图 3. 补充形式验证方法 4. 添加FPGA实现结果 5. 扩展AXI仲裁器具体案例
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。