altera_merlin_arbitrator.sv 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // (C) 2001-2018 Intel Corporation. All rights reserved.
  2. // Your use of Intel Corporation's design tools, logic functions and other
  3. // software and tools, and its AMPP partner logic functions, and any output
  4. // files from any of the foregoing (including device programming or simulation
  5. // files), and any associated documentation or information are expressly subject
  6. // to the terms and conditions of the Intel Program License Subscription
  7. // Agreement, Intel FPGA IP License Agreement, or other applicable
  8. // license agreement, including, without limitation, that your use is for the
  9. // sole purpose of programming logic devices manufactured by Intel and sold by
  10. // Intel or its authorized distributors. Please refer to the applicable
  11. // agreement for further details.
  12. // (C) 2001-2010 Altera Corporation. All rights reserved.
  13. // Your use of Altera Corporation's design tools, logic functions and other
  14. // software and tools, and its AMPP partner logic functions, and any output
  15. // files any of the foregoing (including device programming or simulation
  16. // files), and any associated documentation or information are expressly subject
  17. // to the terms and conditions of the Altera Program License Subscription
  18. // Agreement, Altera MegaCore Function License Agreement, or other applicable
  19. // license agreement, including, without limitation, that your use is for the
  20. // sole purpose of programming logic devices manufactured by Altera and sold by
  21. // Altera or its authorized distributors. Please refer to the applicable
  22. // agreement for further details.
  23. // $Id: //acds/main/ip/merlin/altera_merlin_std_arbitrator/altera_merlin_std_arbitrator_core.sv#3 $
  24. // $Revision: #3 $
  25. // $Date: 2010/07/07 $
  26. // $Author: jyeap $
  27. /* -----------------------------------------------------------------------
  28. Round-robin/fixed arbitration implementation.
  29. Q: how do you find the least-significant set-bit in an n-bit binary number, X?
  30. A: M = X & (~X + 1)
  31. Example: X = 101000100
  32. 101000100 &
  33. 010111011 + 1 =
  34. 101000100 &
  35. 010111100 =
  36. -----------
  37. 000000100
  38. The method can be generalized to find the first set-bit
  39. at a bit index no lower than bit-index N, simply by adding
  40. 2**N rather than 1.
  41. Q: how does this relate to round-robin arbitration?
  42. A:
  43. Let X be the concatenation of all request signals.
  44. Let the number to be added to X (hereafter called the
  45. top_priority) initialize to 1, and be assigned from the
  46. concatenation of the previous saved-grant, left-rotated
  47. by one position, each time arbitration occurs. The
  48. concatenation of grants is then M.
  49. Problem: consider this case:
  50. top_priority = 010000
  51. request = 001001
  52. ~request + top_priority = 000110
  53. next_grant = 000000 <- no one is granted!
  54. There was no "set bit at a bit index no lower than bit-index 4", so
  55. the result was 0.
  56. We need to propagate the carry out from (~request + top_priority) to the LSB, so
  57. that the sum becomes 000111, and next_grant is 000001. This operation could be
  58. called a "circular add".
  59. A bit of experimentation on the circular add reveals a significant amount of
  60. delay in exiting and re-entering the carry chain - this will vary with device
  61. family. Quartus also reports a combinational loop warning. Finally,
  62. Modelsim 6.3g has trouble with the expression, evaluating it to 'X'. But
  63. Modelsim _doesn't_ report a combinational loop!)
  64. An alternate solution: concatenate the request vector with itself, and OR
  65. corresponding bits from the top and bottom halves to determine next_grant.
  66. Example:
  67. top_priority = 010000
  68. {request, request} = 001001 001001
  69. {~request, ~request} + top_priority = 110111 000110
  70. result of & operation = 000001 000000
  71. next_grant = 000001
  72. Notice that if request = 0, the sum operation will overflow, but we can ignore
  73. this; the next_grant result is 0 (no one granted), as you might expect.
  74. In the implementation, the last-granted value must be maintained as
  75. a non-zero value - best probably simply not to update it when no requests
  76. occur.
  77. ----------------------------------------------------------------------- */
  78. `timescale 1 ns / 1 ns
  79. module altera_merlin_arbitrator
  80. #(
  81. parameter NUM_REQUESTERS = 8,
  82. // --------------------------------------
  83. // Implemented schemes
  84. // "round-robin"
  85. // "fixed-priority"
  86. // "no-arb"
  87. // --------------------------------------
  88. parameter SCHEME = "round-robin",
  89. parameter PIPELINE = 0
  90. )
  91. (
  92. input clk,
  93. input reset,
  94. // --------------------------------------
  95. // Requests
  96. // --------------------------------------
  97. input [NUM_REQUESTERS-1:0] request,
  98. // --------------------------------------
  99. // Grants
  100. // --------------------------------------
  101. output [NUM_REQUESTERS-1:0] grant,
  102. // --------------------------------------
  103. // Control Signals
  104. // --------------------------------------
  105. input increment_top_priority,
  106. input save_top_priority
  107. );
  108. // --------------------------------------
  109. // Signals
  110. // --------------------------------------
  111. wire [NUM_REQUESTERS-1:0] top_priority;
  112. reg [NUM_REQUESTERS-1:0] top_priority_reg;
  113. reg [NUM_REQUESTERS-1:0] last_grant;
  114. wire [2*NUM_REQUESTERS-1:0] result;
  115. // --------------------------------------
  116. // Scheme Selection
  117. // --------------------------------------
  118. generate
  119. if (SCHEME == "round-robin" && NUM_REQUESTERS > 1) begin
  120. assign top_priority = top_priority_reg;
  121. end
  122. else begin
  123. // Fixed arbitration (or single-requester corner case)
  124. assign top_priority = 1'b1;
  125. end
  126. endgenerate
  127. // --------------------------------------
  128. // Decision Logic
  129. // --------------------------------------
  130. altera_merlin_arb_adder
  131. #(
  132. .WIDTH (2 * NUM_REQUESTERS)
  133. )
  134. adder
  135. (
  136. .a ({ ~request, ~request }),
  137. .b ({{NUM_REQUESTERS{1'b0}}, top_priority}),
  138. .sum (result)
  139. );
  140. generate if (SCHEME == "no-arb") begin
  141. // --------------------------------------
  142. // No arbitration: just wire request directly to grant
  143. // --------------------------------------
  144. assign grant = request;
  145. end else begin
  146. // Do the math in double-vector domain
  147. wire [2*NUM_REQUESTERS-1:0] grant_double_vector;
  148. assign grant_double_vector = {request, request} & result;
  149. // --------------------------------------
  150. // Extract grant from the top and bottom halves
  151. // of the double vector.
  152. // --------------------------------------
  153. assign grant =
  154. grant_double_vector[NUM_REQUESTERS - 1 : 0] |
  155. grant_double_vector[2 * NUM_REQUESTERS - 1 : NUM_REQUESTERS];
  156. end
  157. endgenerate
  158. // --------------------------------------
  159. // Left-rotate the last grant vector to create top_priority.
  160. // --------------------------------------
  161. always @(posedge clk or posedge reset) begin
  162. if (reset) begin
  163. top_priority_reg <= 1'b1;
  164. end
  165. else begin
  166. if (PIPELINE) begin
  167. if (increment_top_priority) begin
  168. top_priority_reg <= (|request) ? {grant[NUM_REQUESTERS-2:0],
  169. grant[NUM_REQUESTERS-1]} : top_priority_reg;
  170. end
  171. end else begin
  172. if (increment_top_priority) begin
  173. if (|request)
  174. top_priority_reg <= { grant[NUM_REQUESTERS-2:0],
  175. grant[NUM_REQUESTERS-1] };
  176. else
  177. top_priority_reg <= { top_priority_reg[NUM_REQUESTERS-2:0], top_priority_reg[NUM_REQUESTERS-1] };
  178. end
  179. else if (save_top_priority) begin
  180. top_priority_reg <= grant;
  181. end
  182. end
  183. end
  184. end
  185. endmodule
  186. // ----------------------------------------------
  187. // Adder for the standard arbitrator
  188. // ----------------------------------------------
  189. module altera_merlin_arb_adder
  190. #(
  191. parameter WIDTH = 8
  192. )
  193. (
  194. input [WIDTH-1:0] a,
  195. input [WIDTH-1:0] b,
  196. output [WIDTH-1:0] sum
  197. );
  198. wire [WIDTH:0] sum_lint;
  199. // ----------------------------------------------
  200. // Benchmarks indicate that for small widths, the full
  201. // adder has higher fmax because synthesis can merge
  202. // it with the mux, allowing partial decisions to be
  203. // made early.
  204. //
  205. // The magic number is 4 requesters, which means an
  206. // 8 bit adder.
  207. // ----------------------------------------------
  208. genvar i;
  209. generate if (WIDTH <= 8) begin : full_adder
  210. wire cout[WIDTH-1:0];
  211. assign sum[0] = (a[0] ^ b[0]);
  212. assign cout[0] = (a[0] & b[0]);
  213. for (i = 1; i < WIDTH; i = i+1) begin : arb
  214. assign sum[i] = (a[i] ^ b[i]) ^ cout[i-1];
  215. assign cout[i] = (a[i] & b[i]) | (cout[i-1] & (a[i] ^ b[i]));
  216. end
  217. end else begin : carry_chain
  218. assign sum_lint = a + b;
  219. assign sum = sum_lint[WIDTH-1:0];
  220. end
  221. endgenerate
  222. endmodule