IC设计----仲裁器

这篇具有很好参考价值的文章主要介绍了IC设计----仲裁器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

#为了方便以后自己查询和复习,写了一个简短的总结;代码部分是参考其他博主

1. 固定优先级

假设request低bit优先级更高,那么低位到高位,最先出现1的那一位被对应的request被grant,那问题就变成了如何从一个01串中寻找最先出现bit 为1的那一位,这里最经典的方法就是:equest和它的2的补码按位与。可以用增值表举例子看看

代码如下:


module prior_arb #(
 parameter REQ_WIDTH = 16
   ) (
 
   input  [REQ_WIDTH-1:0]     req,
   output [REQ_WIDTH-1:0]     gnt
 
   );
   
   assign gnt = req & (~(req-1));
endmodule

 

2. 轮询仲裁器

先考虑固定优先级的仲裁器,基于以下结论:A & ~(A- base) 的结果就是保留base对应位的A的左边的第一个1,其他的设为0,例如A= 0100100 , base= 0001000,结果为010000,base为onehot,base的[3] bit为1,那么结果就是找到A的第3 bit的左边的第一个1 ;

在没有仲裁前,base对应的位的权重最高,左边位权重次之,右边位权重最低,仲裁后,base对应的权重最低,左边位权重最高,右边为权重倒数第二低,也就是权重最高位左移,所以每次仲裁后我们需要左移一位。

代码如下:

wire[2*NUM_REQ-1:0] double_req = {req,req};
wire[2*NUM_REQ-1:0]double_gnt = double_req & ~(double_req - base);  
assign gnt = double_gnt[NUM_REQ-1:0] | double_gnt[2*NUM_REQ-1:NUM_REQ];

logic [NUM_REQ-1:0]          hist_q, hist_d;
assign base = hist_q ;

always_ff@(posedge clk) begin
  if(!rstn) 
    hist_q <= {{NUM_REQ-1{1'b0}}, 1'b1};
  else
    if(|req)
      hist_q <= {gnt[NUM_REQ-2:0, gnt[NUM_REQ-1]}; 

 上述实现方式很容易理解,但是在硬件实现上减法器,如果request位宽比较大,整体的时序和面积不是很理想。

另外一种算法就是:如果某一路request被grant,那我们就把该路mask掉,再仲裁剩下的路,剩下路的权重不变;如果所有的request都被仲裁完了,那我们重新做载入新的mask。根据request,从最低位开始判断,如果第i 位为1,那么mask的第i+1位到最高位都是1,第0位到第i位为0, mask and request的结果作为简单优先级仲裁器的输入请求。然后再找到为1的最低位。

原理图如下:

IC设计----仲裁器,# 通用数字IP设计,数字IC设计,fpga开发,算法

这里转载下代码:

module round_robin_arbiter #(
 parameter N = 16
)(
 
input         clk,
input         rst,
input [N-1:0] req,
output[N-1:0] grant
 
);
 
 
logic [N-1:0] req_masked;
logic [N-1:0] mask_higher_pri_reqs;
logic [N-1:0] grant_masked;
logic [N-1:0] unmask_higher_pri_reqs;
logic [N-1:0] grant_unmasked;
logic no_req_masked;
logic [N-1:0] pointer_reg;
 
 
// Simple priority arbitration for masked portion
 
assign req_masked = req & pointer_reg;
assign mask_higher_pri_reqs[N-1:1] = mask_higher_pri_reqs[N-2: 0] | req_masked[N-2:0];
assign mask_higher_pri_reqs[0] = 1'b0;
assign grant_masked[N-1:0] = req_masked[N-1:0] & ~mask_higher_pri_reqs[N-1:0];
 
 
// Simple priority arbitration for unmasked portion
assign unmask_higher_pri_reqs[N-1:1] = unmask_higher_pri_reqs[N-2:0] | req[N-2:0];
assign unmask_higher_pri_reqs[0] = 1'b0;
assign grant_unmasked[N-1:0] = req[N-1:0] & ~unmask_higher_pri_reqs[N-1:0];
 
 
// Use grant_masked if there is any there, otherwise use grant_unmasked. 
assign no_req_masked = ~(|req_masked);
assign grant = ({N{no_req_masked}} & grant_unmasked) | grant_masked;
 
// Pointer update
always @ (posedge clk) begin
  if (rst) begin
    pointer_reg <= {N{1'b1}};
  end else begin
    if (|req_masked) begin // Which arbiter was used?
      pointer_reg <= mask_higher_pri_reqs;
    end else begin
      if (|req) begin // Only update if there's a req 
        pointer_reg <= unmask_higher_pri_reqs;
      end else begin
        pointer_reg <= pointer_reg ;
      end
    end
  end
end
 
endmodule

3 权重循环仲裁器

所谓的权重,就是当某个请求过来,能够累计grant的过程,这样能够轮询的同时,又能可以设定公平系数。

“ 和Round robin不同的是对于mask的调整。回想一下,round robin里的mask是,只要第i路被许可,那么从0到第i路的req都会被mask掉,只允许更高位的request 通过,去往上面的那个Masked Priority Arbiter。但是对于Weighted Round Robin,一次grant不足以立刻让这一路request被mask掉,而是要看这一路的counter值,如果counter值还没有减为0,那么就认为这一路依然有credit,mask值就和之前保持不变,下次仲裁的时候依然可以选择这一路grant。”

由于基于request的时序和面积更加友好,所以这里只转载request代码文章来源地址https://www.toymoban.com/news/detail-850750.html

module weight_rr_arbiter(

clk,
rst_n,
req,
weight,
grant,
grant_vld,
grant_ff,
grant_ff_vld,
switch_to_next
);

parameter   REQ_CNT         = 4;
parameter   GRANT_WIDTH     = 5;
parameter   INIT_GRANT      = {{REQ_CNT-1{1'b0}}, 1'b1};
parameter   WEIGHT_WIDTH    = GRANT_WIDTH * REQ_CNT;

input                       clk;
input                       rst_n;
input   [REQ_CNT-1:0]       req;
input   [WEIGHT_WIDTH-1:0]  weight;
input                       switch_to_next;
output  [REQ_CNT-1:0]       grant;
output                      grant_vld;
output  [REQ_CNT-1:0]       grant_ff;
output                      grant_ff_vld;

wire    [REQ_CNT-1:0]       grant;
wire                        grant_vld;
reg     [REQ_CNT-1:0]       grant_ff;
reg                         grant_ff_vld;

wire                        no_req;
wire                        no_grant;
wire                        first_grant;
wire                        arb_trig;

reg     [GRANT_WIDTH-1:0]   priority_cnt    [REQ_CNT-1:0];
wire    [REQ_CNT-1:0]       cnt_over;
wire                        round_en;

assign no_req       = ~(|req);
assign no_grant     = ~(|grant_ff);
assign first_grant  = ~no_req && no_grant;
assign arb_trig     = first_grant || switch_to_next;
assign round_en     = |cnt_over[REQ_CNT-1:0];


wire    [REQ_CNT-1:0]   req_masked;
wire    [REQ_CNT-1:0]   mask_higher_pri_reqs;
wire    [REQ_CNT-1:0]   grant_masked;
wire    [REQ_CNT-1:0]   unmask_higher_pri_reqs;
wire    [REQ_CNT-1:0]   grant_unmasked;
wire                    no_req_masked;
reg     [REQ_CNT-1:0]   mask_next;

//Simple priority arbitration for masked portion
assign req_masked[REQ_CNT-1:0] = req & mask_next;
assign mask_higher_pri_reqs[0] = 1'b0;
assign mask_higher_pri_reqs[REQ_CNT-1:1] = req_masked[REQ_CNT-2:0] | mask_higher_pri_reqs[REQ_CNT-2:0];
assign grant_masked[REQ_CNT-1:0] = req_masked[REQ_CNT-1:0] & ~mask_higher_pri_reqs[REQ_CNT-1:0];

//Simple priority arbitration for unmasked portion
assign unmask_higher_pri_reqs[0] = 1'b0;
assign unmask_higher_pri_reqs[REQ_CNT-1:1] = req[REQ_CNT-2:0] | unmask_higher_pri_reqs[REQ_CNT-2:0];
assign grant_unmasked[REQ_CNT-1:0] = req[REQ_CNT-1:0] & ~unmask_higher_pri_reqs[REQ_CNT-1:0];

//Use grant_masked if there is any there, otherwise use grant_unmasked
assign no_req_masked = ~(|req_masked);
assign grant = ({REQ_CNT{no_req_masked}} & grant_unmasked) | grant_masked;
assign grant_vld = (arb_trig && |req)? 1'b1 : 1'b0;

//round cnt 
generate 
genvar i;
for(i=0;i<REQ_CNT;i=i+1)begin
    
assign  cnt_over[i] = (priority_cnt[i] == weight[GRANT_WIDTH*(i+1)-1-:GRANT_WIDTH]-1'b1);

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        priority_cnt[i] <= {GRANT_WIDTH{1'b0}};
    else if(cnt_over[i])
        priority_cnt[i] <= {GRANT_WIDTH{1'b0}};
    else if(grant[i] && grant_vld)
        priority_cnt[i] <= priority_cnt[i] + 1'b1;
end
end
endgenerate

//pointer update
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        mask_next <= {REQ_CNT{1'b1}};
    else begin
        case({first_grant,round_en})
            2'b10:begin
                if(|req_masked)
                    mask_next <= req_masked | mask_higher_pri_reqs;
                else 
                    mask_next <= req | unmask_higher_pri_reqs;
            end
            2'b01,2'b11:begin
                if(|req_masked)
                    mask_next <= mask_higher_pri_reqs;
                else begin
                    if(|req)
                        mask_next <= unmask_higher_pri_reqs;
                    else 
                        mask_next <= mask_next;
                end
            end
            default:mask_next <= mask_next;
        endcase
    end
end


always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin 
        grant_ff <= {REQ_CNT{1'b0}};  
        grant_ff_vld <= 1'b0;
    end 
    else if(arb_trig)begin
        grant_ff <= grant;
        grant_ff_vld <= no_req? 1'b0 : 1'b1;
    end 
    else begin 
        grant_ff <= grant_ff;
        grant_ff_vld <= grant_ff_vld;
    end
end

endmodule


到了这里,关于IC设计----仲裁器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数字IC设计】VCS仿真DesignWare IP

    DesignWare是SoC/ASIC设计者最钟爱的设计IP库和验证IP库。它包括一个独立于工艺的、经验证的、可综合的虚拟微架构的元件集合,包括逻辑、算术、存储和专用元件系列,超过140个模块。DesignWare和 Design Compiler的结合可以极大地改进综合的结果,并缩短设计周期。Synopsys在DesignW

    2024年02月14日
    浏览(39)
  • 「数字IC设计项目」 —— AHB SRAM控制器设计 & March C-算法内建自测试的实现

    本项目用Verilog HDL语言设计了AHB总线上的SRAM控制器,SRAM存储器在AHB总线上作为AHB slave存在,该SRAM控制器具有以下特性: 支持单周期的SRAM读写操作 支持低功耗工作 SRAM存储体由两个Bank组成,系统根据地址选中一块/多块Bank,未被选中的Bank将处于low-power standby模式以降低功耗

    2024年02月01日
    浏览(26)
  • 【数字IC精品文章收录】近500篇文章|学习路线|基础知识|接口|总线|脚本语言|芯片求职|安全|EDA|工具|低功耗设计|Verilog|低功耗|STA|设计|验证|FPGA|架构|AMBA|书籍|

    1.1 索引目的 本篇索引旨在 收藏CSDN全站中有关数字IC领域高价值文章 ,在数字芯片领域中,就算将架构,设计,验证,DFT,后端诸多岗位加在一起的数量,都不及软件类一个细分方向的岗位数量多,反映在社区氛围或是开源资料的丰富度而言,数字IC领域相较于软件/互联网领

    2024年02月03日
    浏览(108)
  • 数字IC/FPGA面试题目合集解析(一)

    1,计算题:计算该触发器等效的建立保持时间(西安某Fabless面试笔试题) 2,计算题:计算组合逻辑的延时时间范围 3,选择题:Which of following ways cannot be used to improve timing of a hold violation path 问题:原触发器,即对于D点的建立时间,保持时间均为2ns,先由于存在线延时,对

    2024年02月06日
    浏览(34)
  • 【数字 IC / FPGA】 有关建立/保持时间计算的思考

    最近准备一些数字IC的机试,刷到了一些有关静态时序分析的题目。有一些比较经典的题目,在这里整理分享一下。 有什么疑问可以在评论区交流~互相进步 假设时钟周期为Tcycle,Tsetup,Thold分别为触发器建立保持时间,为保证时需满足要求,需要满足什么样的时序关系?(T1~

    2024年02月06日
    浏览(34)
  • 数字IC/FPGA面试宝典--经典60道例题详解

    1.关于亚稳态的描述错误的是(A) A、多用几级寄存器打拍可以消除亚稳态。 B、亚稳态是极不稳定的,理论上来讲处在亚稳态的时间可以无限长。 C、亚稳态稳定到0或者1,是随机的,与输入没有必然的关系。 D、如果数据传输中不满足触发器的建文时间Tsu和保持时间Th,可能

    2024年01月16日
    浏览(39)
  • 【数字IC/FPGA】Verilog中的force和release

    在Verilog中,将 force 用于variable会覆盖掉 过程赋值 ,或者assign引导的 连续(procedural assign)赋值 ,直到 release 。 下面通过一个简单的例子展示其用法: 加法器代码 测试平台代码(主要用于产生激励) 如上所示,正常情况下,u_adder模块的a和b端口由testbench中的a和b信号驱动,

    2024年02月09日
    浏览(34)
  • 数字IC所用软件及IP分类

       先来回答一个在国内经常被问到的问题:为何大部分EDA工具都是使用Linux平台而不是普通的Windows平台?这其实很好理解,因为多数工程及科技软件原先都是在UNIX平台上首先开发和使用的。这些工具出现的时候还没有微软的Windows呢。一些工程和科技软件被移植到Windows.上

    2023年04月08日
    浏览(17)
  • 【数字IC/FPGA】百度昆仑芯手撕代码--累加器

    已知一个加法器IP,其功能是计算两个数的和,但这个和延迟两个周期才会输出。现在有一串连续的数据输入,每个周期都不间断,试问最少需要例化几个上述的加法器IP,才可以实现累加的功能。 由于加法器两个周期后才能得到结果(再将该结果作为加法器的输入进行累加

    2024年02月09日
    浏览(29)
  • 关键元器件选型设计指引--通用逻辑器件(逻辑IC)

    标准数字逻辑IC集成电路可以从工艺、功能和电平三个方面划分,列表所示。 注:常见的逻辑电路有54军用系列和74商用系列,两者电路功能一致,本文仅讨论74系列。 按照制造工艺特点分类: 工艺 逻辑器件产品族 优点 不足 Bipolar TTL 、S、LS、AS、F、ALS、ECL 速度快,强电流驱

    2024年02月20日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包