2 -- This is a simple XICS compliant interrupt controller. This is a
3 -- Presenter (ICP) and Source (ICS) in a single unit with no routing
6 -- The sources have a fixed IRQ priority set by HW_PRIORITY. The
7 -- source id starts at 16 for int_level_in(0) and go up from
8 -- there (ie int_level_in(1) is source id 17).
10 -- The presentation layer will pick an interupt that is more
11 -- favourable than the current CPPR and present it via the XISR and
12 -- send an interrpt to the processor (via e_out). This may not be the
13 -- highest priority interrupt currently presented (which is allowed
18 use ieee.std_logic_1164.all;
19 use ieee.numeric_std.all;
23 use work.wishbone_types.all;
27 LEVEL_NUM : positive := 16
33 wb_in : in wishbone_master_out;
34 wb_out : out wishbone_slave_out;
36 int_level_in : in std_ulogic_vector(LEVEL_NUM - 1 downto 0);
38 e_out : out XicsToExecute1Type
42 architecture behaviour of xics is
43 type reg_internal_t is record
44 xisr : std_ulogic_vector(23 downto 0);
45 cppr : std_ulogic_vector(7 downto 0);
46 pending_priority : std_ulogic_vector(7 downto 0);
47 mfrr : std_ulogic_vector(7 downto 0);
48 mfrr_pending : std_ulogic;
50 wb_rd_data : wishbone_data_type;
53 constant reg_internal_init : reg_internal_t :=
56 mfrr => x"00", -- mask everything on reset
58 others => (others => '0'));
60 signal r, r_next : reg_internal_t;
62 -- hardwire the hardware IRQ priority
63 constant HW_PRIORITY : std_ulogic_vector(7 downto 0) := x"80";
65 -- 32 bit offsets for each presentation
66 constant XIRR_POLL : std_ulogic_vector(31 downto 0) := x"00000000";
67 constant XIRR : std_ulogic_vector(31 downto 0) := x"00000004";
68 constant RESV0 : std_ulogic_vector(31 downto 0) := x"00000008";
69 constant MFRR : std_ulogic_vector(31 downto 0) := x"0000000c";
75 if rising_edge(clk) then
80 wb_out.dat <= r.wb_rd_data;
81 wb_out.ack <= r.wb_ack;
82 wb_out.stall <= '0'; -- never stall wishbone
86 variable v : reg_internal_t;
87 variable xirr_accept_rd : std_ulogic;
88 variable irq_eoi : std_ulogic;
94 xirr_accept_rd := '0';
97 if wb_in.cyc = '1' and wb_in.stb = '1' then
98 -- wishbone addresses we get are 64 bit alligned, so we
99 -- need to use the sel bits to get 32 bit chunks.
100 v.wb_ack := '1'; -- always ack
101 if wb_in.we = '1' then -- write
102 -- writes to both XIRR are the same
103 if wb_in.adr = XIRR_POLL then
104 report "XICS XIRR_POLL/XIRR write";
105 if wb_in.sel = x"0f" then -- 4 bytes
106 v.cppr := wb_in.dat(31 downto 24);
107 elsif wb_in.sel = x"f0" then -- 4 byte
108 v.cppr := wb_in.dat(63 downto 56);
110 elsif wb_in.sel = x"01" then -- 1 byte
111 v.cppr := wb_in.dat(7 downto 0);
112 elsif wb_in.sel = x"10" then -- 1 byte
113 v.cppr := wb_in.dat(39 downto 32);
116 elsif wb_in.adr = RESV0 then
117 report "XICS MFRR write";
118 if wb_in.sel = x"f0" then -- 4 bytes
119 v.mfrr_pending := '1';
120 v.mfrr := wb_in.dat(63 downto 56);
121 elsif wb_in.sel = x"10" then -- 1 byte
122 v.mfrr_pending := '1';
123 v.mfrr := wb_in.dat(39 downto 32);
129 v.wb_rd_data := (others => '0');
131 if wb_in.adr = XIRR_POLL then
132 report "XICS XIRR_POLL/XIRR read";
133 if wb_in.sel = x"0f" then
134 v.wb_rd_data(23 downto 0) := r.xisr;
135 v.wb_rd_data(31 downto 24) := r.cppr;
136 elsif wb_in.sel = x"f0" then
137 v.wb_rd_data(55 downto 32) := r.xisr;
138 v.wb_rd_data(63 downto 56) := r.cppr;
139 xirr_accept_rd := '1';
140 elsif wb_in.sel = x"01" then
141 v.wb_rd_data(7 downto 0) := r.cppr;
142 elsif wb_in.sel = x"10" then
143 v.wb_rd_data(39 downto 32) := r.cppr;
146 elsif wb_in.adr = RESV0 then
147 report "XICS MFRR read";
148 if wb_in.sel = x"f0" then -- 4 bytes
149 v.wb_rd_data(63 downto 56) := r.mfrr;
150 elsif wb_in.sel = x"10" then -- 1 byte
151 v.wb_rd_data( 7 downto 0) := r.mfrr;
157 -- generate interrupt
159 -- Here we just present any interrupt that's valid and
160 -- below cppr. For ordering, we ignore hardware
162 if unsigned(HW_PRIORITY) < unsigned(r.cppr) then --
163 -- lower HW sources are higher priority
164 for i in LEVEL_NUM - 1 downto 0 loop
165 if int_level_in(i) = '1' then
167 v.xisr := std_ulogic_vector(to_unsigned(16 + i, 24));
168 v.pending_priority := HW_PRIORITY; -- hardware HW IRQs
173 -- Do mfrr as a higher priority so mfrr_pending is cleared
174 if unsigned(r.mfrr) < unsigned(r.cppr) then --
175 report "XICS: MFRR INTERRUPT";
177 if r.mfrr_pending = '1' then
179 v.xisr := x"000002"; -- special XICS MFRR IRQ source number
180 v.pending_priority := r.mfrr;
181 v.mfrr_pending := '0';
186 -- Accept the interrupt
187 if xirr_accept_rd = '1' then
188 report "XICS: ACCEPT" &
189 " cppr:" & to_hstring(r.cppr) &
190 " xisr:" & to_hstring(r.xisr) &
191 " mfrr:" & to_hstring(r.mfrr);
192 v.cppr := r.pending_priority;
195 if irq_eoi = '1' then
200 v := reg_internal_init;
207 end architecture behaviour;