当前位置:   article > 正文

IC设计----仲裁器_权重轮询仲裁器

权重轮询仲裁器

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

1. 固定优先级

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

代码如下:

  1. module prior_arb #(
  2. parameter REQ_WIDTH = 16
  3. ) (
  4. input [REQ_WIDTH-1:0] req,
  5. output [REQ_WIDTH-1:0] gnt
  6. );
  7. assign gnt = req & (~(req-1));
  8. 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对应的权重最低,左边位权重最高,右边为权重倒数第二低,也就是权重最高位左移,所以每次仲裁后我们需要左移一位。

代码如下:

  1. wire[2*NUM_REQ-1:0] double_req = {req,req};
  2. wire[2*NUM_REQ-1:0]double_gnt = double_req & ~(double_req - base);
  3. assign gnt = double_gnt[NUM_REQ-1:0] | double_gnt[2*NUM_REQ-1:NUM_REQ];
  4. logic [NUM_REQ-1:0] hist_q, hist_d;
  5. assign base = hist_q ;
  6. always_ff@(posedge clk) begin
  7. if(!rstn)
  8. hist_q <= {{NUM_REQ-1{1'b0}}, 1'b1};
  9. else
  10. if(|req)
  11. 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的最低位。

原理图如下:

这里转载下代码:

  1. module round_robin_arbiter #(
  2. parameter N = 16
  3. )(
  4. input clk,
  5. input rst,
  6. input [N-1:0] req,
  7. output[N-1:0] grant
  8. );
  9. logic [N-1:0] req_masked;
  10. logic [N-1:0] mask_higher_pri_reqs;
  11. logic [N-1:0] grant_masked;
  12. logic [N-1:0] unmask_higher_pri_reqs;
  13. logic [N-1:0] grant_unmasked;
  14. logic no_req_masked;
  15. logic [N-1:0] pointer_reg;
  16. // Simple priority arbitration for masked portion
  17. assign req_masked = req & pointer_reg;
  18. assign mask_higher_pri_reqs[N-1:1] = mask_higher_pri_reqs[N-2: 0] | req_masked[N-2:0];
  19. assign mask_higher_pri_reqs[0] = 1'b0;
  20. assign grant_masked[N-1:0] = req_masked[N-1:0] & ~mask_higher_pri_reqs[N-1:0];
  21. // Simple priority arbitration for unmasked portion
  22. assign unmask_higher_pri_reqs[N-1:1] = unmask_higher_pri_reqs[N-2:0] | req[N-2:0];
  23. assign unmask_higher_pri_reqs[0] = 1'b0;
  24. assign grant_unmasked[N-1:0] = req[N-1:0] & ~unmask_higher_pri_reqs[N-1:0];
  25. // Use grant_masked if there is any there, otherwise use grant_unmasked.
  26. assign no_req_masked = ~(|req_masked);
  27. assign grant = ({N{no_req_masked}} & grant_unmasked) | grant_masked;
  28. // Pointer update
  29. always @ (posedge clk) begin
  30. if (rst) begin
  31. pointer_reg <= {N{1'b1}};
  32. end else begin
  33. if (|req_masked) begin // Which arbiter was used?
  34. pointer_reg <= mask_higher_pri_reqs;
  35. end else begin
  36. if (|req) begin // Only update if there's a req
  37. pointer_reg <= unmask_higher_pri_reqs;
  38. end else begin
  39. pointer_reg <= pointer_reg ;
  40. end
  41. end
  42. end
  43. end
  44. 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代码

  1. module weight_rr_arbiter(
  2. clk,
  3. rst_n,
  4. req,
  5. weight,
  6. grant,
  7. grant_vld,
  8. grant_ff,
  9. grant_ff_vld,
  10. switch_to_next
  11. );
  12. parameter REQ_CNT = 4;
  13. parameter GRANT_WIDTH = 5;
  14. parameter INIT_GRANT = {{REQ_CNT-1{1'b0}}, 1'b1};
  15. parameter WEIGHT_WIDTH = GRANT_WIDTH * REQ_CNT;
  16. input clk;
  17. input rst_n;
  18. input [REQ_CNT-1:0] req;
  19. input [WEIGHT_WIDTH-1:0] weight;
  20. input switch_to_next;
  21. output [REQ_CNT-1:0] grant;
  22. output grant_vld;
  23. output [REQ_CNT-1:0] grant_ff;
  24. output grant_ff_vld;
  25. wire [REQ_CNT-1:0] grant;
  26. wire grant_vld;
  27. reg [REQ_CNT-1:0] grant_ff;
  28. reg grant_ff_vld;
  29. wire no_req;
  30. wire no_grant;
  31. wire first_grant;
  32. wire arb_trig;
  33. reg [GRANT_WIDTH-1:0] priority_cnt [REQ_CNT-1:0];
  34. wire [REQ_CNT-1:0] cnt_over;
  35. wire round_en;
  36. assign no_req = ~(|req);
  37. assign no_grant = ~(|grant_ff);
  38. assign first_grant = ~no_req && no_grant;
  39. assign arb_trig = first_grant || switch_to_next;
  40. assign round_en = |cnt_over[REQ_CNT-1:0];
  41. wire [REQ_CNT-1:0] req_masked;
  42. wire [REQ_CNT-1:0] mask_higher_pri_reqs;
  43. wire [REQ_CNT-1:0] grant_masked;
  44. wire [REQ_CNT-1:0] unmask_higher_pri_reqs;
  45. wire [REQ_CNT-1:0] grant_unmasked;
  46. wire no_req_masked;
  47. reg [REQ_CNT-1:0] mask_next;
  48. //Simple priority arbitration for masked portion
  49. assign req_masked[REQ_CNT-1:0] = req & mask_next;
  50. assign mask_higher_pri_reqs[0] = 1'b0;
  51. assign mask_higher_pri_reqs[REQ_CNT-1:1] = req_masked[REQ_CNT-2:0] | mask_higher_pri_reqs[REQ_CNT-2:0];
  52. assign grant_masked[REQ_CNT-1:0] = req_masked[REQ_CNT-1:0] & ~mask_higher_pri_reqs[REQ_CNT-1:0];
  53. //Simple priority arbitration for unmasked portion
  54. assign unmask_higher_pri_reqs[0] = 1'b0;
  55. assign unmask_higher_pri_reqs[REQ_CNT-1:1] = req[REQ_CNT-2:0] | unmask_higher_pri_reqs[REQ_CNT-2:0];
  56. assign grant_unmasked[REQ_CNT-1:0] = req[REQ_CNT-1:0] & ~unmask_higher_pri_reqs[REQ_CNT-1:0];
  57. //Use grant_masked if there is any there, otherwise use grant_unmasked
  58. assign no_req_masked = ~(|req_masked);
  59. assign grant = ({REQ_CNT{no_req_masked}} & grant_unmasked) | grant_masked;
  60. assign grant_vld = (arb_trig && |req)? 1'b1 : 1'b0;
  61. //round cnt
  62. generate
  63. genvar i;
  64. for(i=0;i<REQ_CNT;i=i+1)begin
  65. assign cnt_over[i] = (priority_cnt[i] == weight[GRANT_WIDTH*(i+1)-1-:GRANT_WIDTH]-1'b1);
  66. always @(posedge clk or negedge rst_n)begin
  67. if(!rst_n)
  68. priority_cnt[i] <= {GRANT_WIDTH{1'b0}};
  69. else if(cnt_over[i])
  70. priority_cnt[i] <= {GRANT_WIDTH{1'b0}};
  71. else if(grant[i] && grant_vld)
  72. priority_cnt[i] <= priority_cnt[i] + 1'b1;
  73. end
  74. end
  75. endgenerate
  76. //pointer update
  77. always @(posedge clk or negedge rst_n)begin
  78. if(!rst_n)
  79. mask_next <= {REQ_CNT{1'b1}};
  80. else begin
  81. case({first_grant,round_en})
  82. 2'b10:begin
  83. if(|req_masked)
  84. mask_next <= req_masked | mask_higher_pri_reqs;
  85. else
  86. mask_next <= req | unmask_higher_pri_reqs;
  87. end
  88. 2'b01,2'b11:begin
  89. if(|req_masked)
  90. mask_next <= mask_higher_pri_reqs;
  91. else begin
  92. if(|req)
  93. mask_next <= unmask_higher_pri_reqs;
  94. else
  95. mask_next <= mask_next;
  96. end
  97. end
  98. default:mask_next <= mask_next;
  99. endcase
  100. end
  101. end
  102. always @(posedge clk or negedge rst_n)begin
  103. if(!rst_n)begin
  104. grant_ff <= {REQ_CNT{1'b0}};
  105. grant_ff_vld <= 1'b0;
  106. end
  107. else if(arb_trig)begin
  108. grant_ff <= grant;
  109. grant_ff_vld <= no_req? 1'b0 : 1'b1;
  110. end
  111. else begin
  112. grant_ff <= grant_ff;
  113. grant_ff_vld <= grant_ff_vld;
  114. end
  115. end
  116. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/802646
推荐阅读
相关标签
  

闽ICP备14008679号