`include "VX_platform.vh" module VX_stream_arbiter #( parameter NUM_REQS = 1, parameter LANES = 1, parameter DATAW = 1, parameter TYPE = "P", parameter LOCK_ENABLE = 1, parameter BUFFERED = 0 ) ( input wire clk, input wire reset, input wire [NUM_REQS-1:0][LANES-1:0] valid_in, input wire [NUM_REQS-1:0][LANES-1:0][DATAW-1:0] data_in, output wire [NUM_REQS-1:0][LANES-1:0] ready_in, output wire [LANES-1:0] valid_out, output wire [LANES-1:0][DATAW-1:0] data_out, input wire [LANES-1:0] ready_out ); localparam LOG_NUM_REQS = `CLOG2(NUM_REQS); if (NUM_REQS > 1) begin wire sel_valid; wire sel_ready; wire [LOG_NUM_REQS-1:0] sel_index; wire [NUM_REQS-1:0] valid_in_any; wire [LANES-1:0] ready_in_sel; if (LANES > 1) begin for (genvar i = 0; i < NUM_REQS; i++) begin assign valid_in_any[i] = (| valid_in[i]); end assign sel_ready = (| ready_in_sel); end else begin for (genvar i = 0; i < NUM_REQS; i++) begin assign valid_in_any[i] = valid_in[i]; end assign sel_ready = ready_in_sel; end if (TYPE == "P") begin `UNUSED_VAR (sel_ready) VX_lzc #( .N (NUM_REQS) ) sel_arb ( .in_i (valid_in_any), .cnt_o (sel_index), .valid_o (sel_valid) ); end else if (TYPE == "R") begin VX_rr_arbiter #( .NUM_REQS (NUM_REQS), .LOCK_ENABLE (LOCK_ENABLE) ) sel_arb ( .clk (clk), .reset (reset), .requests (valid_in_any), .enable (sel_ready), .grant_valid (sel_valid), .grant_index (sel_index), `UNUSED_PIN (grant_onehot) ); end else if (TYPE == "F") begin VX_fair_arbiter #( .NUM_REQS (NUM_REQS), .LOCK_ENABLE (LOCK_ENABLE) ) sel_arb ( .clk (clk), .reset (reset), .requests (valid_in_any), .enable (sel_ready), .grant_valid (sel_valid), .grant_index (sel_index), `UNUSED_PIN (grant_onehot) ); end else if (TYPE == "M") begin VX_matrix_arbiter #( .NUM_REQS (NUM_REQS), .LOCK_ENABLE (LOCK_ENABLE) ) sel_arb ( .clk (clk), .reset (reset), .requests (valid_in_any), .enable (sel_ready), .grant_valid (sel_valid), .grant_index (sel_index), `UNUSED_PIN (grant_onehot) ); end else begin $error ("invalid parameter"); end wire [LANES-1:0] valid_in_sel; wire [LANES-1:0][DATAW-1:0] data_in_sel; if (LANES > 1) begin wire [NUM_REQS-1:0][(LANES * (1 + DATAW))-1:0] valid_data_in; for (genvar i = 0; i < NUM_REQS; i++) begin assign valid_data_in[i] = {valid_in[i], data_in[i]}; end VX_mux #( .DATAW (LANES * (1 + DATAW)), .N (NUM_REQS) ) data_in_mux ( .data_in (valid_data_in), .sel_in (sel_index), .data_out ({valid_in_sel, data_in_sel}) ); `UNUSED_VAR (sel_valid) end else begin VX_mux #( .DATAW (DATAW), .N (NUM_REQS) ) data_in_mux ( .data_in (data_in), .sel_in (sel_index), .data_out (data_in_sel) ); assign valid_in_sel = sel_valid; end for (genvar i = 0; i < NUM_REQS; i++) begin assign ready_in[i] = ready_in_sel & {LANES{(sel_index == LOG_NUM_REQS'(i))}}; end for (genvar i = 0; i < LANES; ++i) begin VX_skid_buffer #( .DATAW (DATAW), .PASSTHRU (0 == BUFFERED), .OUTPUT_REG (2 == BUFFERED) ) out_buffer ( .clk (clk), .reset (reset), .valid_in (valid_in_sel[i]), .data_in (data_in_sel[i]), .ready_in (ready_in_sel[i]), .valid_out (valid_out[i]), .data_out (data_out[i]), .ready_out (ready_out[i]) ); end end else begin `UNUSED_VAR (clk) `UNUSED_VAR (reset) assign valid_out = valid_in; assign data_out = data_in; assign ready_in = ready_out; end endmodule