0


数字IC前端学习笔记:仲裁轮询(三)

相关文章

数字IC前端学习笔记:LSFR(线性反馈移位寄存器)

数字IC前端学习笔记:跨时钟域信号同步

数字IC前端学习笔记:信号同步和边沿检测

数字IC前端学习笔记:锁存器Latch的综合

数字IC前端学习笔记:格雷码(含Verilog实现的二进制格雷码转换器)

数字IC前端学习笔记:FIFO的Verilog实现(一)

数字IC前端学习笔记:FIFO的Verilog实现(二)

数字IC前端学习笔记:仲裁轮询(一)

数字IC前端学习笔记:仲裁轮询(二)

数字IC前端学习笔记:仲裁轮询(四)

数字IC前端学习笔记:仲裁轮询(五)

数字IC前端学习笔记:仲裁轮询(六)

数字IC前端学习笔记:近期最少使用(LRU)算法


5.无死周期的公平轮询

  1. 在前面公平轮询仲裁器的Verilog RTL代码中,每个用户有三个信号:request(请求)、grant(授权)、end_access(结束访问)。在总线使用时,我们能观察到总线上存在不能进行数据传输的死周期。当传输的数据包较长或每个突发较长时,其对传输效率影响不大。然而,当数据包很短时,死周期会影响到总线的使用效率。如下图所示为没有间隔的公平轮询仲裁波形。下面给出了一些方法,用于减少甚至消除死周期。

  • 第一种方案是当grant信号有效时,该用户的第一个数据已经准备好并且有效输出。原来的方案中,在用户的grant有效后,它在下一个周期输出数据,现在改为当grant采样为高时,在同一个周期就开始输出数据。此时需要用户提前从内部电路中读出第一个数据。采用这种方案时,仲裁器的设计不变,用户部分需要进行修改。

  • 第二种方法是增加额外的信号start_access,它和end_access一起使用。一个用户获得总线使用权并开始操作后,仲裁器通过将start_access置为有效表示开始新的仲裁过程,而不是等待end_access信号变高来开始新的仲裁过程,这样就减少了转换期间的死周期。当下一个用户被授权时,当前用户仍在使用总线,此时新的用户不能立即使用总线。仲裁器在当前用户完成操作时会给出end_access_out信号,新的授权用户此后就可以开始操作了。仲裁器在没有用户使用公共资源时,将resource_idle置为1。当resource_idle为1时,获得授权的用户不需要查看end_access_out信号就可以开始数据操作。

    1. 没有死周期的公平轮询代码及仿真结果如下。
  1. module arbiter_roundrobin(
  2. clk,resetb,
  3. req_vec,
  4. end_access_vec,
  5. gnt_vec,
  6. end_access_out);
  7. input clk, resetb;
  8. input [2:0] req_vec, end_access_vec;
  9. output [2:0] gnt_vec;
  10. output end_access_out;
  11. reg [1:0] arbiter_state, arbiter_state_nxt;
  12. reg [2:0] gnt_vec, gnt_vec_nxt;
  13. reg [2:0] relative_req_vec;
  14. wire any_req_asserted;
  15. reg [1:0] grant_posn, grant_posn_nxt;
  16. reg resource_idle_nxt, resource_idle;
  17. reg [2:0] start_access_vec, start_access_vec_nxt;
  18. parameter IDLE = 2'b00;
  19. parameter END_ACCESS = 2'b01;
  20. assign any_req_asserted = (req_vec != 0);
  21. assign end_access_out = |end_access_vec;
  22. always@(*) begin
  23. relative_req_vec = req_vec;
  24. case(grant_posn)
  25. 2'd0: relative_req_vec = {req_vec[0], req_vec[2:1]};
  26. 2'd1: relative_req_vec = {req_vec[1:0], req_vec[2]};
  27. 2'd2: relative_req_vec = {req_vec[2:0]};
  28. endcase
  29. end
  30. always@(*) begin
  31. arbiter_state_nxt = arbiter_state;
  32. grant_posn_nxt = grant_posn;
  33. gnt_vec_nxt = gnt_vec;
  34. resource_idle_nxt = 1'b0;
  35. start_access_vec_nxt = 3'b0;
  36. case(arbiter_state)
  37. IDLE:begin
  38. if(any_req_asserted)
  39. arbiter_state_nxt = END_ACCESS;
  40. resource_idle_nxt = 1'b1;
  41. if(relative_req_vec[0])
  42. case(grant_posn)
  43. 2'd0: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
  44. 2'd1: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
  45. 2'd2: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
  46. endcase
  47. else if(relative_req_vec[1])
  48. case(grant_posn)
  49. 2'd0: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
  50. 2'd1: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
  51. 2'd2: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
  52. endcase
  53. else if(relative_req_vec[2])
  54. case(grant_posn)
  55. 2'd0: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
  56. 2'd1: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
  57. 2'd2: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
  58. endcase
  59. else
  60. gnt_vec_nxt = 3'b000;
  61. end
  62. END_ACCESS:begin
  63. if((resource_idle == 1'b1) || (end_access_out == 1'b1))
  64. start_access_vec_nxt = gnt_vec;
  65. if(start_access_vec != 0)begin
  66. if(relative_req_vec[0])
  67. case(grant_posn)
  68. 2'd0: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
  69. 2'd1: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
  70. 2'd2: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
  71. endcase
  72. else if(relative_req_vec[1])
  73. case(grant_posn)
  74. 2'd0: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
  75. 2'd1: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
  76. 2'd2: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
  77. endcase
  78. else if(relative_req_vec[2])
  79. case(grant_posn)
  80. 2'd0: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
  81. 2'd1: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
  82. 2'd2: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
  83. endcase
  84. else begin
  85. gnt_vec_nxt = 3'b000;
  86. arbiter_state_nxt = IDLE;
  87. end
  88. end
  89. end
  90. endcase
  91. end
  92. always@(posedge clk or negedge resetb)begin
  93. if(!resetb) begin
  94. arbiter_state <= IDLE;
  95. gnt_vec <= 0;
  96. grant_posn <= 0;
  97. resource_idle <= 0;
  98. start_access_vec <= 0;
  99. end
  100. else begin
  101. arbiter_state <= arbiter_state_nxt;
  102. gnt_vec <= gnt_vec_nxt;
  103. grant_posn <= grant_posn_nxt;
  104. resource_idle <= resource_idle_nxt;
  105. start_access_vec <= start_access_vec_nxt;
  106. end
  107. end
  108. endmodule
  1. Verilog实现过程中,使用了两个状态IDLEEND_ACCESS,分别表示仲裁器处于无请求和仲裁器授权的状态。在IDLE状态时,任何请求信号能使状态转移至END_ACCESS状态,并将resource_idle信号置1(这是为了IDLE状态下start_access的置位而设计的信号),并根据请求信号给出相应授权。在END_ACCESS状态,会根据resource_idleend_access_out信号使用gnt_vecstart_access置位。当start_access信号有效时,根据请求信号进行下一次授权。若此时没有请求信号,则状态回到IDLE等待。

以上内容来源于《Verilog高级数字系统设计技术和实例分析》,有删改


本文转载自: https://blog.csdn.net/weixin_45791458/article/details/131339436
版权归原作者 日晨难再 所有, 如有侵权,请联系我们删除。

“数字IC前端学习笔记:仲裁轮询(三)”的评论:

还没有评论