`include "defs.svh" module mem_arbiter ( input bit clock , input bit reset , output bit command_ready , input bit command_valid , input arb_to_ram_t command_data , output bit [`NUM_PDPS-1:0] pdp_ready , input bit [`NUM_PDPS-1:0] pdp_valid , input core_to_mem_t [`NUM_PDPS-1:0] pdp_data , input bit ram_ready , output bit ram_valid , output arb_to_ram_t ram_data ); bit [`NUM_PDPS:0] hold_valid; arb_to_ram_t [`NUM_PDPS:0] hold_data; bit [$clog2(`NUM_PDPS+1):0] selector; always @(posedge clock) begin if (reset) begin command_ready = 0; for (int i = 0; i < `NUM_PDPS; ++i) pdp_ready[i] = 0; ram_valid = 0; for (int i = 0; i < `NUM_PDPS+1; ++i) hold_valid[i] = 0; selector = 0; end else begin automatic bit selector_stale = 0; if (ram_ready) ram_valid = 0; if (!ram_valid && hold_valid[selector]) begin ram_valid = 1; ram_data = hold_data[selector]; hold_valid[selector] = 0; selector_stale = 1; end if (hold_valid == 0) begin if (command_ready && command_valid) begin hold_valid[0] = 1; hold_data[0] = command_data; hold_data[0].tag = 0; end for (int i = 0; i < `NUM_PDPS; ++i) begin if (pdp_ready[i] && pdp_valid[i]) begin hold_valid[i+1] = 1; hold_data[i+1].address[`RAM_ADDRESS_BITS-1:`PDP_ADDRESS_BITS] = i; hold_data[i+1].address[`PDP_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] = pdp_data[i].address; hold_data[i+1].write = pdp_data[i].write; hold_data[i+1].data = pdp_data[i].data; hold_data[i+1].mask = pdp_data[i].mask; hold_data[i+1].tag = i+1; end end end if (hold_valid != 0 && !ram_valid) begin for (int i = 0; i < `NUM_PDPS+1; ++i) begin if (hold_valid == 1 << i) begin ram_valid = 1; ram_data = hold_data[i]; hold_valid[i] = 0; break; end end end if (hold_valid != 0 && (selector_stale || !ram_valid)) begin for (int i = 0; i < `NUM_PDPS+1; ++i) begin automatic int j = selector + i; if (j > `NUM_PDPS) j -= `NUM_PDPS+1; if (hold_valid[j]) begin selector = j; break; end end end command_ready = hold_valid == 0; for (int i = 0; i < `NUM_PDPS; ++i) pdp_ready[i] = hold_valid == 0; end end endmodule