blob: f5991732293b2d107bee2658db07c71754330c96 [file] [log] [blame]
module wb_arbiter #(
parameter AW = 32,
parameter DW = 32,
parameter NM = 2
)(
input wb_clk_i,
input wb_rst_i,
// Masters Interface
input [NM-1:0] wbm_stb_i,
input [NM-1:0] wbm_cyc_i,
input [NM-1:0] wbm_we_i,
input [NM*(DW/8)-1:0] wbm_sel_i,
input [NM*DW-1:0] wbm_dat_i,
input [NM*AW-1:0] wbm_adr_i,
output [NM-1:0] wbm_ack_o,
output [NM-1:0] wbm_err_o,
output [NM*DW-1:0] wbm_dat_o,
// Slave Interface
input wbs_ack_i,
input wbs_err_i,
input [DW-1:0] wbs_dat_i,
output reg wbs_stb_o,
output reg wbs_cyc_o,
output wbs_we_o,
output reg [(DW/8)-1:0] wbs_sel_o,
output reg [AW-1:0] wbs_adr_o,
output reg [DW-1:0] wbs_dat_o
);
localparam SEL = DW / 8;
// Current elected master (one hot)
reg [NM-1:0] cur_master;
reg capture_req;
wire [NM-1:0] master_sel;
wire [NM-1:0] requests;
wire any_req;
wire any_acks;
assign requests = wbm_cyc_i & wbm_stb_i;
assign any_req = |requests;
assign any_ack = |{wbs_ack_i, wbs_err_i};
genvar iM;
generate
assign master_sel[0] = requests[0];
for (iM=1; iM<NM; iM=iM+1) begin
assign master_sel[iM] = requests[iM] & (~master_sel[iM-1]);
end
endgenerate
// Current-elected master
always @(posedge wb_clk_i)
if(wb_rst_i) begin
cur_master <= {NM{1'b0}};
end else if (capture_req) begin
cur_master <= master_sel;
end
// Finite State Machine
localparam IDLE = 1'b0;
localparam BUSY = 1'b1;
reg state = IDLE;
reg next_state;
always @(*)
begin: FSM_COMB
case (state)
IDLE: if (any_req) begin
wbs_stb_o = 1'b1;
wbs_cyc_o = 1'b1;
capture_req = 1'b1;
next_state = BUSY;
end else begin
wbs_stb_o = 1'b0;
wbs_cyc_o = 1'b0;
capture_req = 1'b0;
next_state = IDLE;
end
BUSY: begin
if (any_ack & !any_req) begin
next_state = IDLE;
end if (any_ack & any_req) begin
capture_req = 1'b1;
end
end
default: next_state = IDLE;
endcase
end
always @(posedge wb_clk_i)
if (wb_rst_i)
state <= IDLE;
else
state <= next_state;
// Masters Output Assignment
assign wbm_dat_o = {NM{wbs_dat_i}};
assign wbm_ack_o = {NM{wbs_ack_i}} & cur_master;
assign wbm_err_o = {NM{wbs_err_i}} & cur_master;
// Multiplexed signal to the slave
assign wbs_we_o = |(cur_master & wbm_we_i);
integer k;
always @(*) begin
wbs_sel_o = {SEL{1'b0}};
for (k=0; k<(NM*SEL); k=k+1)
wbs_sel_o[k%SEL] = wbs_sel_o[k%SEL] | (cur_master[k/SEL] & wbm_sel_i[k]);
end
integer l;
always @(*) begin
wbs_adr_o = {AW{1'b0}};
for (l=0; l<(NM*AW); l=l+1)
wbs_adr_o[l%AW] = wbs_adr_o[l%AW] | (cur_master[l/AW] & wbm_adr_i[l]);
end
integer o;
always @(*) begin
wbs_dat_o = {DW{1'b0}};
for (o=0; o<(NM*DW); o=o+1)
wbs_dat_o[o%DW] = wbs_dat_o[o%DW] | (cur_master[o/DW] & wbm_dat_i[o]);
end
endmodule