diff --git a/soc.vhdl b/soc.vhdl index 6ed6bf7..fb8a36d 100644 --- a/soc.vhdl +++ b/soc.vhdl @@ -43,6 +43,12 @@ architecture behaviour of soc is signal wishbone_debug_in : wishbone_slave_out; signal wishbone_debug_out : wishbone_master_out; + -- Arbiter array (ghdl doesnt' support assigning the array + -- elements in the entity instantiation) + constant NUM_WB_MASTERS : positive := 3; + signal wb_masters_out : wishbone_master_out_vector(0 to NUM_WB_MASTERS-1); + signal wb_masters_in : wishbone_slave_out_vector(0 to NUM_WB_MASTERS-1); + -- Wishbone master (output of arbiter): signal wb_master_in : wishbone_slave_out; signal wb_master_out : wishbone_master_out; @@ -96,13 +102,22 @@ begin ); -- Wishbone bus master arbiter & mux + wb_masters_out <= (0 => wishbone_dcore_out, + 1 => wishbone_icore_out, + 2 => wishbone_debug_out); + wishbone_dcore_in <= wb_masters_in(0); + wishbone_icore_in <= wb_masters_in(1); + wishbone_debug_in <= wb_masters_in(2); wishbone_arbiter_0: entity work.wishbone_arbiter + generic map( + NUM_MASTERS => NUM_WB_MASTERS + ) port map( clk => system_clk, rst => rst, - wb1_in => wishbone_dcore_out, wb1_out => wishbone_dcore_in, - wb2_in => wishbone_icore_out, wb2_out => wishbone_icore_in, - wb3_in => wishbone_debug_out, wb3_out => wishbone_debug_in, - wb_out => wb_master_out, wb_in => wb_master_in + wb_masters_in => wb_masters_out, + wb_masters_out => wb_masters_in, + wb_slave_out => wb_master_out, + wb_slave_in => wb_master_in ); -- Wishbone slaves address decoder & mux diff --git a/wishbone_arbiter.vhdl b/wishbone_arbiter.vhdl index b206df1..63b3c4a 100644 --- a/wishbone_arbiter.vhdl +++ b/wishbone_arbiter.vhdl @@ -6,70 +6,55 @@ use work.wishbone_types.all; -- TODO: Use an array of master/slaves with parametric size entity wishbone_arbiter is + generic( + NUM_MASTERS : positive := 3 + ); port (clk : in std_ulogic; rst : in std_ulogic; - wb1_in : in wishbone_master_out; - wb1_out : out wishbone_slave_out; + wb_masters_in : in wishbone_master_out_vector(0 to NUM_MASTERS-1); + wb_masters_out : out wishbone_slave_out_vector(0 to NUM_MASTERS-1); - wb2_in : in wishbone_master_out; - wb2_out : out wishbone_slave_out; - - wb3_in : in wishbone_master_out; - wb3_out : out wishbone_slave_out; - - wb_out : out wishbone_master_out; - wb_in : in wishbone_slave_out + wb_slave_out : out wishbone_master_out; + wb_slave_in : in wishbone_slave_out ); end wishbone_arbiter; architecture behave of wishbone_arbiter is - type wb_arb_master_t is (WB1, WB2, WB3); + subtype wb_arb_master_t is integer range 0 to NUM_MASTERS-1; signal candidate, selected : wb_arb_master_t; begin - wishbone_muxes: process(selected, wb_in, wb1_in, wb2_in, wb3_in) + wishbone_muxes: process(selected, wb_slave_in, wb_masters_in) begin - -- Requests from masters are fully muxed - 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 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'; + wb_slave_out <= wb_masters_in(selected); + for i in 0 to NUM_MASTERS-1 loop + wb_masters_out(i).dat <= wb_slave_in.dat; + wb_masters_out(i).ack <= wb_slave_in.ack when selected = i else '0'; + wb_masters_out(i).stall <= wb_slave_in.stall when selected = i else '1'; + end loop; 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) + wishbone_candidate: process(all) 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; + candidate <= selected; + for i in NUM_MASTERS-1 downto 0 loop + if wb_masters_in(i).cyc = '1' then + candidate <= i; + end if; + end loop; end process; wishbone_arbiter_process: process(clk) begin if rising_edge(clk) then if rst = '1' then - selected <= WB1; - elsif wb_out.cyc = '0' then + selected <= 0; + elsif wb_slave_out.cyc = '0' then selected <= candidate; end if; end if; diff --git a/wishbone_types.vhdl b/wishbone_types.vhdl index 1b8a28b..d1f2a45 100644 --- a/wishbone_types.vhdl +++ b/wishbone_types.vhdl @@ -27,4 +27,7 @@ package wishbone_types is end record; constant wishbone_slave_out_init : wishbone_slave_out := (ack => '0', stall => '0', others => (others => '0')); + type wishbone_master_out_vector is array (natural range <>) of wishbone_master_out; + type wishbone_slave_out_vector is array (natural range <>) of wishbone_slave_out; + end package wishbone_types;