verilog代码实例-round robin arbiter

前言

Round Robin (RR) 仲裁器 是一种常见的硬件仲裁算法,广泛应用于多通道系统、总线仲裁和多处理器系统中,目的是在多个请求中公平地分配资源。Round Robin 算法的基本思想是,按照固定的顺序逐一服务每个请求,每次选择下一个请求,而不偏向任何特定请求。这种方法确保了所有请求获得均等的机会,从而避免了长时间的饥饿问题。

Round Robin 仲裁器的工作原理

  1. 请求队列:有多个请求线(Request Lines),每一条请求线表示一个模块或实体对资源的请求。例如,多个 CPU 核心请求访问共享的内存或总线。
  2. 轮转方式:当仲裁器选择一个请求时,它按照固定的顺序依次轮流选择请求信号。每次选择后,仲裁器会将选择的指针“轮换”到下一个请求信号。
  3. 优先级:Round Robin 仲裁器没有优先级偏向,它会按顺序选择一个请求,并在下次选择时轮流选择下一个请求。这意味着每个请求都有公平的机会。
  4. 请求和应答:在 Round Robin 仲裁器中,首先会有请求信号(Request)。如果请求被选择,仲裁器会通过分配信号(Grant)来通知相应模块资源已被分配。
  5. 轮转过程:例如,假设有三个请求 R1、R2 和 R3,在每个周期内,仲裁器会根据当前的指针依次选择这三个请求中的一个并分配资源。

Round Robin 仲裁器的基本结构

  1. 输入:多个请求信号,例如 R1, R2, R3, …
  2. 输出:一个选定的“授予”信号(G1, G2, G3…),表示哪个请求被选中并被授予资源。
  3. 内部状态:一个指示当前选择位置的计数器,通常是一个指针或循环计数器。
  4. 控制逻辑:用于判断哪个请求信号当前可用并分配相应的资源。它通过轮换顺序在请求之间切换。

Round Robin 仲裁器的工作流程

  1. 初始化:首先将指针指向第一个请求(例如 R1)。
  2. 轮询:在每个时钟周期,仲裁器检查当前的请求状态。它优先选择当前指针所指向的请求,并通过 Grant 信号通知资源分配。
  3. 轮换:当资源分配完后,指针会移到下一个请求信号。
  4. 重复:该过程会持续进行,直到所有的请求都得到服务。

代码示例

本实例代码,实现了一级优先级的round Robin的仲裁器。
仲裁器有两种工作模式,分别为periodic和valid,可通过参数ARB_MODE定义。
periodic的仲裁器为周期性 RR 仲裁器,每个valid为高的请求,周期性地按照固定的顺序轮流获得资源。
valid的仲裁器为有效请求 RR 仲裁器,当仲裁器选中当前通道后,会一直保持直到valid无效,然后按照固定的顺序选择下一个valid有效的通道。

// ######################################################################
// Filename        : prr_arbiter.v
// Description     : prior round robin arbiter
//                   There are two working modes, divided into:
//                   when the input parameter "ARB_MODE=periodic",the arbiter is periodic switching arbitration
//                   when the input parameter "ARB_MODE=valid",the arbiter is arbitration based on Valid signal
// Author          : 
// Created On      : 
// Last Modified By: 
// Last Modified On: 
// Update Count    : 
// Status          : Verified
// verilog-filelist: None
// verilog-file    : None
// ######################################################################
`timescale 1ns/1ps
module prr_arbiter#(
    parameter  ARB_MODE = "periodic"            ,//periodic , valid
    parameter  REQ_NUM = 8          
)(
    input  wire                     clk_in      ,
    input  wire                     rst_n       ,
    //----------------------------------------------------//
    input  wire     [REQ_NUM-1:0]   req         ,
    input  wire     [REQ_NUM-1:0]   prior       ,
    output wire     [REQ_NUM-1:0]   grant
);
//==============================================================================================//
//======                                 define signal                                  ========//
//==============================================================================================//
    wire    [REQ_NUM-1:0]   req_prior;
    wire    [REQ_NUM-1:0]   req_masked;
    wire    [REQ_NUM-1:0]   mask_higher_req;
    wire    [REQ_NUM-1:0]   grant_masked;
    wire    [REQ_NUM-1:0]   req_unmasked;
    wire    [REQ_NUM-1:0]   unmask_higher_req;
    wire    [REQ_NUM-1:0]   grant_unmask;

    reg     [REQ_NUM-1:0]   pointer_reg;
    wire    [REQ_NUM-1:0]   pointer;
    
    reg     [REQ_NUM-1:0]   grant_reg;
//==============================================================================================//
//======                                 behave of RTL                                  ========//
//==============================================================================================//
    assign req_prior  = req & prior;
    //--------------------------------------------------------------------
    //------simple priority arbitration for masked portion          ------
    //--------------------------------------------------------------------
    assign req_masked = (|req_prior) ? (req_prior & pointer) : (req & pointer);
    assign mask_higher_req = (mask_higher_req|req_masked)<<1;
    assign grant_masked = (~mask_higher_req)&req_masked;
    //--------------------------------------------------------------------
    //------simple priority arbitration for unmasked portion        ------
    //--------------------------------------------------------------------
    assign req_unmasked = (|req_prior) ? req_prior : req ;
    assign unmask_higher_req = (unmask_higher_req|req_unmasked)<<1;
    assign grant_unmask = (~unmask_higher_req)&req_unmasked;
    //--------------------------------------------------------------------
    //------                                                        ------
    //--------------------------------------------------------------------
    assign grant = (|req_masked) ? grant_masked : grant_unmask ;
    
    //******************************************************************//
    //------arbitration based on Valid signal                       ------
    //******************************************************************//
    generate if(ARB_MODE == "valid")begin:gen_valid_arbiter
        always@(posedge clk_in or negedge rst_n)begin
            if(!rst_n)begin
                grant_reg <= {REQ_NUM{1'b0}};
            end else begin
                grant_reg <= grant;
            end
        end
        //--------------------------------------------------------------------
        //------pointer update                                          ------
        //--------------------------------------------------------------------
        always@(posedge clk_in or negedge rst_n)begin
            if(!rst_n)begin
                pointer_reg <= {REQ_NUM{1'b1}};
            end else if((|req_masked == 1'b1) && (|(grant_reg&req) == 1'b0 ))begin
                pointer_reg <= mask_higher_req;
            end else if((|req == 1'b1) && (|(grant_reg&req) == 1'b0 ))begin
                pointer_reg <= unmask_higher_req;
            end else begin
                pointer_reg <= pointer_reg;
            end
        end
        assign pointer = |(grant_reg&req) ? pointer : pointer_reg ;

    //******************************************************************//
    //------periodic switching arbitration                          ------
    //******************************************************************//
    end else begin:gen_periodic_arbiter
        //--------------------------------------------------------------------
        //------pointer update                                          ------
        //--------------------------------------------------------------------
        always@(posedge clk_in or negedge rst_n)begin
            if(!rst_n)begin
                pointer_reg <= {REQ_NUM{1'b1}};
            end else if(|req_masked == 1'b1)begin
                pointer_reg <= mask_higher_req;
            end else if(|req == 1'b1)begin
                pointer_reg <= unmask_higher_req;
            end else begin
                pointer_reg <= pointer_reg;
            end
        end
        assign pointer = pointer_reg ;
    end endgenerate
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值