stack-machine/arbiter.v

80 lines
2.4 KiB
Verilog

// Simple 2:1 alternating (round-robin) arbiter.
// Switches master on ACK from slave unless selected master asserts LOCK.
// Data from slave is sent to both masters. Address and data bus widths
// are configurable, as is granularity. Default is 32-bit addresses and
// data with byte granularity.
module WB_ARB_2M (CLK_I, RST_I, SELECT_O,
M0_ADR_I, M0_DAT_I, M0_DAT_O, M0_LOCK_I, M0_CYC_I, M0_STB_I,
M0_WE_I, M0_SEL_I, M0_ACK_O, M0_ERR_O, M0_RTY_O,
M1_ADR_I, M1_DAT_I, M1_DAT_O, M1_LOCK_I, M1_CYC_I, M1_STB_I,
M1_WE_I, M1_SEL_I, M1_ACK_O, M1_ERR_O, M1_RTY_O,
S_ADR_O, S_DAT_O, S_DAT_I, S_LOCK_O, S_CYC_O, S_STB_O,
S_WE_O, S_SEL_O, S_ACK_I, S_ERR_I, S_RTY_I);
parameter ADDR_WIDTH = 30;
parameter DATA_WIDTH = 32;
parameter SEL_WIDTH = 4;
input CLK_I, RST_I;
output SELECT_O;
input [ADDR_WIDTH-1:0] M0_ADR_I, M1_ADR_I;
input [DATA_WIDTH-1:0] M0_DAT_I, M1_DAT_I;
output [DATA_WIDTH-1:0] M0_DAT_O, M1_DAT_O;
input M0_LOCK_I, M1_LOCK_I;
input M0_CYC_I, M1_CYC_I;
input M0_STB_I, M1_STB_I;
input M0_WE_I, M1_WE_I;
input [SEL_WIDTH-1:0] M0_SEL_I, M1_SEL_I;
output M0_ACK_O, M1_ACK_O;
output M0_ERR_O, M1_ERR_O;
output M0_RTY_O, M1_RTY_O;
output [ADDR_WIDTH-1:0] S_ADR_O;
output [DATA_WIDTH-1:0] S_DAT_O;
input [DATA_WIDTH-1:0] S_DAT_I;
output S_LOCK_O, S_CYC_O;
output S_STB_O, S_WE_O;
output [SEL_WIDTH-1:0] S_SEL_O;
input S_ACK_I, S_ERR_I, S_RTY_I;
reg SELECT_O = 1'bX;
assign M0_DAT_O = ~SELECT_O ? S_DAT_I : 256'dX;
assign M1_DAT_O = SELECT_O ? S_DAT_I : 256'dX;
assign M0_ACK_O = S_ACK_I & ~SELECT_O;
assign M1_ACK_O = S_ACK_I & SELECT_O;
assign M0_ERR_O = S_ERR_I & ~SELECT_O;
assign M1_ERR_O = S_ERR_I & SELECT_O;
assign M0_RTY_O = S_RTY_I & ~SELECT_O;
assign M1_RTY_O = S_RTY_I & SELECT_O;
assign S_ADR_O = SELECT_O ? M1_ADR_I : M0_ADR_I;
assign S_DAT_O = SELECT_O ? M1_DAT_I : M0_DAT_I;
assign S_LOCK_O = SELECT_O ? M1_LOCK_I : M0_LOCK_I;
assign S_CYC_O = SELECT_O ? M1_CYC_I : M0_CYC_I;
assign S_STB_O = SELECT_O ? M1_STB_I : M0_STB_I;
assign S_WE_O = SELECT_O ? M1_WE_I : M0_WE_I;
assign S_SEL_O = SELECT_O ? M1_SEL_I : M0_SEL_I;
wire CYC_END = (S_ACK_I | S_ERR_I | S_RTY_I);
always @(posedge CLK_I)
begin
casex ({S_LOCK_O, CYC_END, M1_CYC_I, M0_CYC_I})
4'b1XXX: SELECT_O <= SELECT_O;
4'b0111: SELECT_O <= ~SELECT_O;
4'b0X10: SELECT_O <= 1'b1;
4'b0X01: SELECT_O <= 1'b0;
4'b0XXX: SELECT_O <= SELECT_O;
endcase
end
endmodule