module axis_interconnect #(
	parameter CHANNELS_IN = 4,
	parameter CHANNELS_OUT = 1,
	parameter DATA_WIDTH = 8,
	parameter USER_WIDTH = 2
)
(
	input wire aclk,
	input wire aresetn,
	input wire [CHANNELS_IN*DATA_WIDTH-1:0]s_axis_tdata,
	input wire [CHANNELS_IN*$clog2(CHANNELS_OUT)-1:0]s_axis_tdest,
	input wire [CHANNELS_IN*USER_WIDTH-1:0]s_axis_tuser,
	input wire [CHANNELS_IN-1:0]s_axis_tvalid,
	output wire [CHANNELS_IN-1:0]s_axis_tready,
	input wire [CHANNELS_IN-1:0]s_axis_tlast,
	output wire [CHANNELS_OUT*DATA_WIDTH-1:0]m_axis_tdata,
	output wire [CHANNELS_OUT*USER_WIDTH-1:0]m_axis_tuser,
	output wire [CHANNELS_OUT-1:0]m_axis_tvalid,
	input wire [CHANNELS_OUT-1:0]m_axis_tready,
	output wire [CHANNELS_OUT-1:0]m_axis_tlast	
);

genvar g, h;

generate 
	wire [CHANNELS_IN*CHANNELS_OUT-1:0]arb_tready;
	wire [CHANNELS_IN*CHANNELS_OUT-1:0]axis_tready;

	for (g = 0; g < CHANNELS_OUT; g = g + 1) begin : ARBITER
		for (h = 0; h < CHANNELS_IN; h = h + 1) begin
			assign axis_tready[CHANNELS_OUT*h+g+:1] = arb_tready[CHANNELS_IN*g+h+:1];
		end
	
		axis_arbiter #(
			.CHAN_NUM(CHANNELS_IN),
			.DATA_WIDTH(DATA_WIDTH),
			.DEST_INDEX(g),
			.DEST_WIDTH($clog2(CHANNELS_OUT)),
			.USER_WIDTH(USER_WIDTH)
		) axis_arbiter_inst (
			.aclk(aclk),
			.aresetn(aresetn),
			.s_axis_tdata(s_axis_tdata),
			.s_axis_tuser(s_axis_tuser),
			.s_axis_tdest(s_axis_tdest),
			.s_axis_tvalid(s_axis_tvalid),
			.s_axis_tready(arb_tready[CHANNELS_IN*(g+1)-1-:CHANNELS_IN]),
			.s_axis_tlast(s_axis_tlast),
			.m_axis_tdata(m_axis_tdata[DATA_WIDTH*(g+1)-1-:DATA_WIDTH]),
			.m_axis_tuser(m_axis_tuser[USER_WIDTH*(g+1)-1-:USER_WIDTH]),
			.m_axis_tvalid(m_axis_tvalid[g]),
			.m_axis_tready(m_axis_tready[g]),
			.m_axis_tlast(m_axis_tlast[g])
		);
	end 
	for (h = 0; h < CHANNELS_IN; h = h + 1) begin
		assign s_axis_tready[h] = (axis_tready[CHANNELS_OUT*(h+1)-1-:CHANNELS_OUT] != 0);
	end 
endgenerate

endmodule