nios2_uc_mm_interconnect_0_rsp_mux.sv 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  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-2014 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/rel/18.1std/ip/merlin/altera_merlin_multiplexer/altera_merlin_multiplexer.sv.terp#1 $
  24. // $Revision: #1 $
  25. // $Date: 2018/07/18 $
  26. // $Author: psgswbuild $
  27. // ------------------------------------------
  28. // Merlin Multiplexer
  29. // ------------------------------------------
  30. `timescale 1 ns / 1 ns
  31. // ------------------------------------------
  32. // Generation parameters:
  33. // output_name: nios2_uc_mm_interconnect_0_rsp_mux
  34. // NUM_INPUTS: 7
  35. // ARBITRATION_SHARES: 1 1 1 1 1 1 1
  36. // ARBITRATION_SCHEME "no-arb"
  37. // PIPELINE_ARB: 0
  38. // PKT_TRANS_LOCK: 60 (arbitration locking enabled)
  39. // ST_DATA_W: 96
  40. // ST_CHANNEL_W: 7
  41. // ------------------------------------------
  42. module nios2_uc_mm_interconnect_0_rsp_mux
  43. (
  44. // ----------------------
  45. // Sinks
  46. // ----------------------
  47. input sink0_valid,
  48. input [96-1 : 0] sink0_data,
  49. input [7-1: 0] sink0_channel,
  50. input sink0_startofpacket,
  51. input sink0_endofpacket,
  52. output sink0_ready,
  53. input sink1_valid,
  54. input [96-1 : 0] sink1_data,
  55. input [7-1: 0] sink1_channel,
  56. input sink1_startofpacket,
  57. input sink1_endofpacket,
  58. output sink1_ready,
  59. input sink2_valid,
  60. input [96-1 : 0] sink2_data,
  61. input [7-1: 0] sink2_channel,
  62. input sink2_startofpacket,
  63. input sink2_endofpacket,
  64. output sink2_ready,
  65. input sink3_valid,
  66. input [96-1 : 0] sink3_data,
  67. input [7-1: 0] sink3_channel,
  68. input sink3_startofpacket,
  69. input sink3_endofpacket,
  70. output sink3_ready,
  71. input sink4_valid,
  72. input [96-1 : 0] sink4_data,
  73. input [7-1: 0] sink4_channel,
  74. input sink4_startofpacket,
  75. input sink4_endofpacket,
  76. output sink4_ready,
  77. input sink5_valid,
  78. input [96-1 : 0] sink5_data,
  79. input [7-1: 0] sink5_channel,
  80. input sink5_startofpacket,
  81. input sink5_endofpacket,
  82. output sink5_ready,
  83. input sink6_valid,
  84. input [96-1 : 0] sink6_data,
  85. input [7-1: 0] sink6_channel,
  86. input sink6_startofpacket,
  87. input sink6_endofpacket,
  88. output sink6_ready,
  89. // ----------------------
  90. // Source
  91. // ----------------------
  92. output src_valid,
  93. output [96-1 : 0] src_data,
  94. output [7-1 : 0] src_channel,
  95. output src_startofpacket,
  96. output src_endofpacket,
  97. input src_ready,
  98. // ----------------------
  99. // Clock & Reset
  100. // ----------------------
  101. input clk,
  102. input reset
  103. );
  104. localparam PAYLOAD_W = 96 + 7 + 2;
  105. localparam NUM_INPUTS = 7;
  106. localparam SHARE_COUNTER_W = 1;
  107. localparam PIPELINE_ARB = 0;
  108. localparam ST_DATA_W = 96;
  109. localparam ST_CHANNEL_W = 7;
  110. localparam PKT_TRANS_LOCK = 60;
  111. // ------------------------------------------
  112. // Signals
  113. // ------------------------------------------
  114. wire [NUM_INPUTS - 1 : 0] request;
  115. wire [NUM_INPUTS - 1 : 0] valid;
  116. wire [NUM_INPUTS - 1 : 0] grant;
  117. wire [NUM_INPUTS - 1 : 0] next_grant;
  118. reg [NUM_INPUTS - 1 : 0] saved_grant;
  119. reg [PAYLOAD_W - 1 : 0] src_payload;
  120. wire last_cycle;
  121. reg packet_in_progress;
  122. reg update_grant;
  123. wire [PAYLOAD_W - 1 : 0] sink0_payload;
  124. wire [PAYLOAD_W - 1 : 0] sink1_payload;
  125. wire [PAYLOAD_W - 1 : 0] sink2_payload;
  126. wire [PAYLOAD_W - 1 : 0] sink3_payload;
  127. wire [PAYLOAD_W - 1 : 0] sink4_payload;
  128. wire [PAYLOAD_W - 1 : 0] sink5_payload;
  129. wire [PAYLOAD_W - 1 : 0] sink6_payload;
  130. assign valid[0] = sink0_valid;
  131. assign valid[1] = sink1_valid;
  132. assign valid[2] = sink2_valid;
  133. assign valid[3] = sink3_valid;
  134. assign valid[4] = sink4_valid;
  135. assign valid[5] = sink5_valid;
  136. assign valid[6] = sink6_valid;
  137. // ------------------------------------------
  138. // ------------------------------------------
  139. // Grant Logic & Updates
  140. // ------------------------------------------
  141. // ------------------------------------------
  142. reg [NUM_INPUTS - 1 : 0] lock;
  143. always @* begin
  144. lock[0] = sink0_data[60];
  145. lock[1] = sink1_data[60];
  146. lock[2] = sink2_data[60];
  147. lock[3] = sink3_data[60];
  148. lock[4] = sink4_data[60];
  149. lock[5] = sink5_data[60];
  150. lock[6] = sink6_data[60];
  151. end
  152. assign last_cycle = src_valid & src_ready & src_endofpacket & ~(|(lock & grant));
  153. // ------------------------------------------
  154. // We're working on a packet at any time valid is high, except
  155. // when this is the endofpacket.
  156. // ------------------------------------------
  157. always @(posedge clk or posedge reset) begin
  158. if (reset) begin
  159. packet_in_progress <= 1'b0;
  160. end
  161. else begin
  162. if (last_cycle)
  163. packet_in_progress <= 1'b0;
  164. else if (src_valid)
  165. packet_in_progress <= 1'b1;
  166. end
  167. end
  168. // ------------------------------------------
  169. // Shares
  170. //
  171. // Special case: all-equal shares _should_ be optimized into assigning a
  172. // constant to next_grant_share.
  173. // Special case: all-1's shares _should_ result in the share counter
  174. // being optimized away.
  175. // ------------------------------------------
  176. // Input | arb shares | counter load value
  177. // 0 | 1 | 0
  178. // 1 | 1 | 0
  179. // 2 | 1 | 0
  180. // 3 | 1 | 0
  181. // 4 | 1 | 0
  182. // 5 | 1 | 0
  183. // 6 | 1 | 0
  184. wire [SHARE_COUNTER_W - 1 : 0] share_0 = 1'd0;
  185. wire [SHARE_COUNTER_W - 1 : 0] share_1 = 1'd0;
  186. wire [SHARE_COUNTER_W - 1 : 0] share_2 = 1'd0;
  187. wire [SHARE_COUNTER_W - 1 : 0] share_3 = 1'd0;
  188. wire [SHARE_COUNTER_W - 1 : 0] share_4 = 1'd0;
  189. wire [SHARE_COUNTER_W - 1 : 0] share_5 = 1'd0;
  190. wire [SHARE_COUNTER_W - 1 : 0] share_6 = 1'd0;
  191. // ------------------------------------------
  192. // Choose the share value corresponding to the grant.
  193. // ------------------------------------------
  194. reg [SHARE_COUNTER_W - 1 : 0] next_grant_share;
  195. always @* begin
  196. next_grant_share =
  197. share_0 & { SHARE_COUNTER_W {next_grant[0]} } |
  198. share_1 & { SHARE_COUNTER_W {next_grant[1]} } |
  199. share_2 & { SHARE_COUNTER_W {next_grant[2]} } |
  200. share_3 & { SHARE_COUNTER_W {next_grant[3]} } |
  201. share_4 & { SHARE_COUNTER_W {next_grant[4]} } |
  202. share_5 & { SHARE_COUNTER_W {next_grant[5]} } |
  203. share_6 & { SHARE_COUNTER_W {next_grant[6]} };
  204. end
  205. // ------------------------------------------
  206. // Flag to indicate first packet of an arb sequence.
  207. // ------------------------------------------
  208. wire grant_changed = ~packet_in_progress && ~(|(saved_grant & valid));
  209. reg first_packet_r;
  210. wire first_packet = grant_changed | first_packet_r;
  211. always @(posedge clk or posedge reset) begin
  212. if (reset) begin
  213. first_packet_r <= 1'b0;
  214. end
  215. else begin
  216. if (update_grant)
  217. first_packet_r <= 1'b1;
  218. else if (last_cycle)
  219. first_packet_r <= 1'b0;
  220. else if (grant_changed)
  221. first_packet_r <= 1'b1;
  222. end
  223. end
  224. // ------------------------------------------
  225. // Compute the next share-count value.
  226. // ------------------------------------------
  227. reg [SHARE_COUNTER_W - 1 : 0] p1_share_count;
  228. reg [SHARE_COUNTER_W - 1 : 0] share_count;
  229. reg share_count_zero_flag;
  230. always @* begin
  231. if (first_packet) begin
  232. p1_share_count = next_grant_share;
  233. end
  234. else begin
  235. // Update the counter, but don't decrement below 0.
  236. p1_share_count = share_count_zero_flag ? '0 : share_count - 1'b1;
  237. end
  238. end
  239. // ------------------------------------------
  240. // Update the share counter and share-counter=zero flag.
  241. // ------------------------------------------
  242. always @(posedge clk or posedge reset) begin
  243. if (reset) begin
  244. share_count <= '0;
  245. share_count_zero_flag <= 1'b1;
  246. end
  247. else begin
  248. if (last_cycle) begin
  249. share_count <= p1_share_count;
  250. share_count_zero_flag <= (p1_share_count == '0);
  251. end
  252. end
  253. end
  254. // ------------------------------------------
  255. // For each input, maintain a final_packet signal which goes active for the
  256. // last packet of a full-share packet sequence. Example: if I have 4
  257. // shares and I'm continuously requesting, final_packet is active in the
  258. // 4th packet.
  259. // ------------------------------------------
  260. wire final_packet_0 = 1'b1;
  261. wire final_packet_1 = 1'b1;
  262. wire final_packet_2 = 1'b1;
  263. wire final_packet_3 = 1'b1;
  264. wire final_packet_4 = 1'b1;
  265. wire final_packet_5 = 1'b1;
  266. wire final_packet_6 = 1'b1;
  267. // ------------------------------------------
  268. // Concatenate all final_packet signals (wire or reg) into a handy vector.
  269. // ------------------------------------------
  270. wire [NUM_INPUTS - 1 : 0] final_packet = {
  271. final_packet_6,
  272. final_packet_5,
  273. final_packet_4,
  274. final_packet_3,
  275. final_packet_2,
  276. final_packet_1,
  277. final_packet_0
  278. };
  279. // ------------------------------------------
  280. // ------------------------------------------
  281. wire p1_done = |(final_packet & grant);
  282. // ------------------------------------------
  283. // Flag for the first cycle of packets within an
  284. // arb sequence
  285. // ------------------------------------------
  286. reg first_cycle;
  287. always @(posedge clk, posedge reset) begin
  288. if (reset)
  289. first_cycle <= 0;
  290. else
  291. first_cycle <= last_cycle && ~p1_done;
  292. end
  293. always @* begin
  294. update_grant = 0;
  295. // ------------------------------------------
  296. // No arbitration pipeline, update grant whenever
  297. // the current arb winner has consumed all shares,
  298. // or all requests are low
  299. // ------------------------------------------
  300. update_grant = (last_cycle && p1_done) || (first_cycle && ~(|valid));
  301. update_grant = last_cycle;
  302. end
  303. wire save_grant;
  304. assign save_grant = 1;
  305. assign grant = next_grant;
  306. always @(posedge clk, posedge reset) begin
  307. if (reset)
  308. saved_grant <= '0;
  309. else if (save_grant)
  310. saved_grant <= next_grant;
  311. end
  312. // ------------------------------------------
  313. // ------------------------------------------
  314. // Arbitrator
  315. // ------------------------------------------
  316. // ------------------------------------------
  317. // ------------------------------------------
  318. // Create a request vector that stays high during
  319. // the packet for unpipelined arbitration.
  320. //
  321. // The pipelined arbitration scheme does not require
  322. // request to be held high during the packet.
  323. // ------------------------------------------
  324. assign request = valid;
  325. wire [NUM_INPUTS - 1 : 0] next_grant_from_arb;
  326. altera_merlin_arbitrator
  327. #(
  328. .NUM_REQUESTERS(NUM_INPUTS),
  329. .SCHEME ("no-arb"),
  330. .PIPELINE (0)
  331. ) arb (
  332. .clk (clk),
  333. .reset (reset),
  334. .request (request),
  335. .grant (next_grant_from_arb),
  336. .save_top_priority (src_valid),
  337. .increment_top_priority (update_grant)
  338. );
  339. assign next_grant = next_grant_from_arb;
  340. // ------------------------------------------
  341. // ------------------------------------------
  342. // Mux
  343. //
  344. // Implemented as a sum of products.
  345. // ------------------------------------------
  346. // ------------------------------------------
  347. assign sink0_ready = src_ready && grant[0];
  348. assign sink1_ready = src_ready && grant[1];
  349. assign sink2_ready = src_ready && grant[2];
  350. assign sink3_ready = src_ready && grant[3];
  351. assign sink4_ready = src_ready && grant[4];
  352. assign sink5_ready = src_ready && grant[5];
  353. assign sink6_ready = src_ready && grant[6];
  354. assign src_valid = |(grant & valid);
  355. always @* begin
  356. src_payload =
  357. sink0_payload & {PAYLOAD_W {grant[0]} } |
  358. sink1_payload & {PAYLOAD_W {grant[1]} } |
  359. sink2_payload & {PAYLOAD_W {grant[2]} } |
  360. sink3_payload & {PAYLOAD_W {grant[3]} } |
  361. sink4_payload & {PAYLOAD_W {grant[4]} } |
  362. sink5_payload & {PAYLOAD_W {grant[5]} } |
  363. sink6_payload & {PAYLOAD_W {grant[6]} };
  364. end
  365. // ------------------------------------------
  366. // Mux Payload Mapping
  367. // ------------------------------------------
  368. assign sink0_payload = {sink0_channel,sink0_data,
  369. sink0_startofpacket,sink0_endofpacket};
  370. assign sink1_payload = {sink1_channel,sink1_data,
  371. sink1_startofpacket,sink1_endofpacket};
  372. assign sink2_payload = {sink2_channel,sink2_data,
  373. sink2_startofpacket,sink2_endofpacket};
  374. assign sink3_payload = {sink3_channel,sink3_data,
  375. sink3_startofpacket,sink3_endofpacket};
  376. assign sink4_payload = {sink4_channel,sink4_data,
  377. sink4_startofpacket,sink4_endofpacket};
  378. assign sink5_payload = {sink5_channel,sink5_data,
  379. sink5_startofpacket,sink5_endofpacket};
  380. assign sink6_payload = {sink6_channel,sink6_data,
  381. sink6_startofpacket,sink6_endofpacket};
  382. assign {src_channel,src_data,src_startofpacket,src_endofpacket} = src_payload;
  383. endmodule