Add Tercel PHY reset synchronization
[microwatt.git] / wishbone_arbiter.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3
4 library work;
5 use work.wishbone_types.all;
6
7 -- TODO: Use an array of master/slaves with parametric size
8 entity wishbone_arbiter is
9 generic(
10 NUM_MASTERS : positive := 3
11 );
12 port (clk : in std_ulogic;
13 rst : in std_ulogic;
14
15 wb_masters_in : in wishbone_master_out_vector(0 to NUM_MASTERS-1);
16 wb_masters_out : out wishbone_slave_out_vector(0 to NUM_MASTERS-1);
17
18 wb_slave_out : out wishbone_master_out;
19 wb_slave_in : in wishbone_slave_out
20 );
21 end wishbone_arbiter;
22
23 architecture behave of wishbone_arbiter is
24 subtype wb_arb_master_t is integer range 0 to NUM_MASTERS-1;
25 signal candidate, selected : wb_arb_master_t;
26 signal busy : std_ulogic;
27 begin
28
29 busy <= wb_masters_in(selected).cyc;
30
31 wishbone_muxes: process(selected, candidate, busy, wb_slave_in, wb_masters_in)
32 variable early_sel : wb_arb_master_t;
33 begin
34 early_sel := selected;
35 if busy = '0' then
36 early_sel := candidate;
37 end if;
38 wb_slave_out <= wb_masters_in(early_sel);
39 for i in 0 to NUM_MASTERS-1 loop
40 wb_masters_out(i).dat <= wb_slave_in.dat;
41 wb_masters_out(i).ack <= wb_slave_in.ack when early_sel = i else '0';
42 wb_masters_out(i).stall <= wb_slave_in.stall when early_sel = i else '1';
43 end loop;
44 end process;
45
46 -- Candidate selection is dumb, priority order... we could
47 -- instead consider some form of fairness but it's not really
48 -- an issue at the moment.
49 --
50 wishbone_candidate: process(all)
51 begin
52 candidate <= selected;
53 for i in NUM_MASTERS-1 downto 0 loop
54 if wb_masters_in(i).cyc = '1' then
55 candidate <= i;
56 end if;
57 end loop;
58 end process;
59
60 wishbone_arbiter_process: process(clk)
61 begin
62 if rising_edge(clk) then
63 if rst = '1' then
64 selected <= 0;
65 elsif busy = '0' then
66 selected <= candidate;
67 end if;
68 end if;
69 end process;
70 end behave;