diff --git a/wishbone_arbiter.vhdl b/wishbone_arbiter.vhdl index 8e2358b..b206df1 100644 --- a/wishbone_arbiter.vhdl +++ b/wishbone_arbiter.vhdl @@ -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;