mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-03 20:12:55 +00:00
wb_arbiter: Avoid IDLE cycle when not changing master
Consecutive accesses from the same master shouldn't need an IDLE cycle. Completely remove the IDLE state and switch master when the bus is idle, but stay on the last selected one between cycles. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
@@ -24,58 +24,53 @@ entity wishbone_arbiter is
|
||||
end wishbone_arbiter;
|
||||
|
||||
architecture behave of wishbone_arbiter is
|
||||
type wishbone_arbiter_state_t is (IDLE, WB1_BUSY, WB2_BUSY, WB3_BUSY);
|
||||
signal state : wishbone_arbiter_state_t := IDLE;
|
||||
type wb_arb_master_t is (WB1, WB2, WB3);
|
||||
signal candidate, selected : wb_arb_master_t;
|
||||
begin
|
||||
|
||||
wishbone_muxes: process(state, wb_in, wb1_in, wb2_in, wb3_in)
|
||||
wishbone_muxes: process(selected, wb_in, wb1_in, wb2_in, wb3_in)
|
||||
begin
|
||||
-- Requests from masters are fully muxed
|
||||
wb_out <= wb1_in when state = WB1_BUSY else
|
||||
wb2_in when state = WB2_BUSY else
|
||||
wb3_in when state = WB3_BUSY else
|
||||
wishbone_master_out_init;
|
||||
wb_out <= wb1_in when selected = WB1 else
|
||||
wb2_in when selected = WB2 else
|
||||
wb3_in when selected = WB3;
|
||||
|
||||
-- Responses from slave don't need to mux the data bus
|
||||
wb1_out.dat <= wb_in.dat;
|
||||
wb2_out.dat <= wb_in.dat;
|
||||
wb3_out.dat <= wb_in.dat;
|
||||
wb1_out.ack <= wb_in.ack when state = WB1_BUSY else '0';
|
||||
wb2_out.ack <= wb_in.ack when state = WB2_BUSY else '0';
|
||||
wb3_out.ack <= wb_in.ack when state = WB3_BUSY else '0';
|
||||
wb1_out.stall <= wb_in.stall when state = WB1_BUSY else '1';
|
||||
wb2_out.stall <= wb_in.stall when state = WB2_BUSY else '1';
|
||||
wb3_out.stall <= wb_in.stall when state = WB3_BUSY else '1';
|
||||
wb1_out.ack <= wb_in.ack when selected = WB1 else '0';
|
||||
wb2_out.ack <= wb_in.ack when selected = WB2 else '0';
|
||||
wb3_out.ack <= wb_in.ack when selected = WB3 else '0';
|
||||
wb1_out.stall <= wb_in.stall when selected = WB1 else '1';
|
||||
wb2_out.stall <= wb_in.stall when selected = WB2 else '1';
|
||||
wb3_out.stall <= wb_in.stall when selected = WB3 else '1';
|
||||
end process;
|
||||
|
||||
-- Candidate selection is dumb, priority order... we could
|
||||
-- instead consider some form of fairness but it's not really
|
||||
-- an issue at the moment.
|
||||
--
|
||||
wishbone_candidate: process(wb1_in.cyc, wb2_in.cyc, wb3_in.cyc)
|
||||
begin
|
||||
if wb1_in.cyc = '1' then
|
||||
candidate <= WB1;
|
||||
elsif wb2_in.cyc = '1' then
|
||||
candidate <= WB2;
|
||||
elsif wb3_in.cyc = '1' then
|
||||
candidate <= WB3;
|
||||
else
|
||||
candidate <= selected;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
wishbone_arbiter_process: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
state <= IDLE;
|
||||
else
|
||||
case state is
|
||||
when IDLE =>
|
||||
if wb1_in.cyc = '1' then
|
||||
state <= WB1_BUSY;
|
||||
elsif wb2_in.cyc = '1' then
|
||||
state <= WB2_BUSY;
|
||||
elsif wb3_in.cyc = '1' then
|
||||
state <= WB3_BUSY;
|
||||
end if;
|
||||
when WB1_BUSY =>
|
||||
if wb1_in.cyc = '0' then
|
||||
state <= IDLE;
|
||||
end if;
|
||||
when WB2_BUSY =>
|
||||
if wb2_in.cyc = '0' then
|
||||
state <= IDLE;
|
||||
end if;
|
||||
when WB3_BUSY =>
|
||||
if wb3_in.cyc = '0' then
|
||||
state <= IDLE;
|
||||
end if;
|
||||
end case;
|
||||
selected <= WB1;
|
||||
elsif wb_out.cyc = '0' then
|
||||
selected <= candidate;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
Reference in New Issue
Block a user