@ -1,11 +1,13 @@
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					--
 
					 
					 
					 
					--
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					-- This is a simple XICS compliant interrupt controller.  This is a
 
					 
					 
					 
					-- This is a simple XICS compliant interrupt controller.  This is a
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					-- Presenter (ICP) and Source (ICS) in a single unit with no routing
 
					 
					 
					 
					-- Presenter (ICP) and Source (ICS) in two small units directly
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					-- layer.
 
					 
					 
					 
					-- connected to each other with no routing layer.
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					--
 
					 
					 
					 
					--
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					-- The sources have a fixed IRQ priority set by HW_PRIORITY. The
 
					 
					 
					 
					-- The sources have a configurable IRQ priority set a set of ICS
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					-- source id starts at 16 for int_level_in(0) and go up from
 
					 
					 
					 
					-- registers in the source units.
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					-- there (ie int_level_in(1) is source id 17).
 
					 
					 
					 
					--
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					-- The source ids start at 16 for int_level_in(0) and go up from
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					-- there (ie int_level_in(1) is source id 17). XXX Make a generic
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					--
 
					 
					 
					 
					--
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					-- The presentation layer will pick an interupt that is more
 
					 
					 
					 
					-- The presentation layer will pick an interupt that is more
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					-- favourable than the current CPPR and present it via the XISR and
 
					 
					 
					 
					-- favourable than the current CPPR and present it via the XISR and
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -22,38 +24,31 @@ library work;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					use work.common.all;
 
					 
					 
					 
					use work.common.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					use work.wishbone_types.all;
 
					 
					 
					 
					use work.wishbone_types.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					entity xics is
 
					 
					 
					 
					entity xics_icp is
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					    generic (
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        LEVEL_NUM : positive := 16
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        );
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    port (
 
					 
					 
					 
					    port (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        clk          : in std_logic;
 
					 
					 
					 
					        clk          : in std_logic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        rst          : in std_logic;
 
					 
					 
					 
					        rst          : in std_logic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        wb_in   : in wb_io_master_out;
 
					 
					 
					 
					        wb_in        : in wb_io_master_out;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					        wb_out  : out wb_io_slave_out;
 
					 
					 
					 
					        wb_out       : out wb_io_slave_out;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						int_level_in : in std_ulogic_vector(LEVEL_NUM - 1 downto 0);
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						ics_in       : in ics_to_icp_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						core_irq_out : out std_ulogic
 
					 
					 
					 
						core_irq_out : out std_ulogic
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        );
 
					 
					 
					 
					        );
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					end xics;
 
					 
					 
					 
					end xics_icp;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					architecture behaviour of xics is
 
					 
					 
					 
					architecture behaviour of xics_icp is
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    type reg_internal_t is record
 
					 
					 
					 
					    type reg_internal_t is record
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						xisr : std_ulogic_vector(23 downto 0);
 
					 
					 
					 
						xisr : std_ulogic_vector(23 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						cppr : std_ulogic_vector(7 downto 0);
 
					 
					 
					 
						cppr : std_ulogic_vector(7 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						pending_priority : std_ulogic_vector(7 downto 0);
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						mfrr : std_ulogic_vector(7 downto 0);
 
					 
					 
					 
						mfrr : std_ulogic_vector(7 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						mfrr_pending : std_ulogic;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						irq : std_ulogic;
 
					 
					 
					 
						irq : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						wb_rd_data : std_ulogic_vector(31 downto 0);
 
					 
					 
					 
						wb_rd_data : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						wb_ack : std_ulogic;
 
					 
					 
					 
						wb_ack : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end record;
 
					 
					 
					 
					    end record;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    constant reg_internal_init : reg_internal_t :=
 
					 
					 
					 
					    constant reg_internal_init : reg_internal_t :=
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						(wb_ack => '0',
 
					 
					 
					 
						(wb_ack => '0',
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						 mfrr_pending => '0',
 
					 
					 
					 
						 mfrr => x"ff", -- mask everything on reset
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						 mfrr => x"ff", -- no IPI on reset
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						 irq => '0',
 
					 
					 
					 
						 irq => '0',
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						 others => (others => '0'));
 
					 
					 
					 
						 others => (others => '0'));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -74,18 +69,19 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    begin
 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						if rising_edge(clk) then
 
					 
					 
					 
						if rising_edge(clk) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    r <= r_next;
 
					 
					 
					 
						    r <= r_next;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            -- We delay core_irq_out by a cycle to help with timing
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            core_irq_out <= r.irq;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						end if;
 
					 
					 
					 
						end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end process;
 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    wb_out.dat <= r.wb_rd_data;
 
					 
					 
					 
					    wb_out.dat <= r.wb_rd_data;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    wb_out.ack <= r.wb_ack;
 
					 
					 
					 
					    wb_out.ack <= r.wb_ack;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    wb_out.stall <= '0'; -- never stall wishbone
 
					 
					 
					 
					    wb_out.stall <= '0'; -- never stall wishbone
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    core_irq_out <= r.irq;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    comb : process(all)
 
					 
					 
					 
					    comb : process(all)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						variable v : reg_internal_t;
 
					 
					 
					 
						variable v : reg_internal_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						variable xirr_accept_rd : std_ulogic;
 
					 
					 
					 
						variable xirr_accept_rd : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						variable irq_eoi : std_ulogic;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        function  bswap(v : in std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
 
					 
					 
					 
					        function  bswap(v : in std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            variable r : std_ulogic_vector(31 downto 0);
 
					 
					 
					 
					            variable r : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -99,13 +95,14 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        variable be_in  : std_ulogic_vector(31 downto 0);
 
					 
					 
					 
					        variable be_in  : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        variable be_out : std_ulogic_vector(31 downto 0);
 
					 
					 
					 
					        variable be_out : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						variable pending_priority : std_ulogic_vector(7 downto 0);        
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    begin
 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						v := r;
 
					 
					 
					 
						v := r;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						v.wb_ack := '0';
 
					 
					 
					 
						v.wb_ack := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						xirr_accept_rd := '0';
 
					 
					 
					 
						xirr_accept_rd := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						irq_eoi := '0';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        be_in := bswap(wb_in.dat);
 
					 
					 
					 
					        be_in := bswap(wb_in.dat);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        be_out := (others => '0');
 
					 
					 
					 
					        be_out := (others => '0');
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -122,7 +119,6 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    v.cppr := be_in(31 downto 24);
 
					 
					 
					 
					                    v.cppr := be_in(31 downto 24);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    if wb_in.sel = x"f"  then -- 4 byte
 
					 
					 
					 
							    if wb_in.sel = x"f"  then -- 4 byte
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        report "ICP XIRR write word (EOI) :" & to_hstring(be_in);
 
					 
					 
					 
					                        report "ICP XIRR write word (EOI) :" & to_hstring(be_in);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								irq_eoi := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    elsif wb_in.sel = x"1"  then -- 1 byte
 
					 
					 
					 
							    elsif wb_in.sel = x"1"  then -- 1 byte
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        report "ICP XIRR write byte (CPPR):" & to_hstring(be_in(31 downto 24));
 
					 
					 
					 
					                        report "ICP XIRR write byte (CPPR):" & to_hstring(be_in(31 downto 24));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    else
 
					 
					 
					 
					                    else
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -130,7 +126,6 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    end if;
 
					 
					 
					 
							    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							when MFRR =>
 
					 
					 
					 
							when MFRR =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    v.mfrr := be_in(31 downto 24);
 
					 
					 
					 
					                    v.mfrr := be_in(31 downto 24);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    v.mfrr_pending := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    if wb_in.sel = x"f" then -- 4 bytes
 
					 
					 
					 
							    if wb_in.sel = x"f" then -- 4 bytes
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        report "ICP MFRR write word:" & to_hstring(be_in);
 
					 
					 
					 
					                        report "ICP MFRR write word:" & to_hstring(be_in);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    elsif wb_in.sel = x"1" then -- 1 byte
 
					 
					 
					 
							    elsif wb_in.sel = x"1" then -- 1 byte
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -161,49 +156,40 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    end if;
 
					 
					 
					 
						    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						end if;
 
					 
					 
					 
						end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						-- generate interrupt
 
					 
					 
					 
					        pending_priority := x"ff";
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						if r.irq = '0' then
 
					 
					 
					 
					        v.xisr := x"000000";
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    -- Here we just present any interrupt that's valid and
 
					 
					 
					 
					        v.irq := '0';
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    -- below cppr. For ordering, we ignore hardware
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    -- priorities.
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    if unsigned(HW_PRIORITY) < unsigned(r.cppr) then --
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							-- lower HW sources are higher priority
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							for i in LEVEL_NUM - 1 downto 0 loop
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    if int_level_in(i) = '1' then
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								v.irq := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								v.xisr := std_ulogic_vector(to_unsigned(16 + i, 24));
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								v.pending_priority := HW_PRIORITY; -- hardware HW IRQs
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    end if;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							end loop;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    end if;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    -- Do mfrr as a higher priority so mfrr_pending is cleared
 
					 
					 
					 
					        if ics_in.pri /= x"ff" then
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    if unsigned(r.mfrr) < unsigned(r.cppr) then --
 
					 
					 
					 
					            v.xisr := x"00001" & ics_in.src;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							report "XICS: MFRR INTERRUPT";
 
					 
					 
					 
					            pending_priority := ics_in.pri;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							-- IPI
 
					 
					 
					 
					        end if;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							if r.mfrr_pending = '1' then
 
					 
					 
					 
					
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							    v.irq := '1';
 
					 
					 
					 
					        -- Check MFRR
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							    v.xisr := x"000002"; -- special XICS MFRR IRQ source number
 
					 
					 
					 
					        if unsigned(r.mfrr) < unsigned(pending_priority) then --
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							    v.pending_priority := r.mfrr;
 
					 
					 
					 
					            v.xisr := x"000002"; -- special XICS MFRR IRQ source number
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							    v.mfrr_pending := '0';
 
					 
					 
					 
					            pending_priority := r.mfrr;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    end if;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						end if;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						-- Accept the interrupt
 
					 
					 
					 
						-- Accept the interrupt
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						if xirr_accept_rd = '1' then
 
					 
					 
					 
						if xirr_accept_rd = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    report "XICS: ACCEPT" &
 
					 
					 
					 
					            report "XICS: ICP ACCEPT" &
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							" cppr:" &  to_hstring(r.cppr) &
 
					 
					 
					 
					                " cppr:" &  to_hstring(r.cppr) &
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							" xisr:" & to_hstring(r.xisr) &
 
					 
					 
					 
					                " xisr:" & to_hstring(r.xisr) &
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							" mfrr:" & to_hstring(r.mfrr);
 
					 
					 
					 
					                " mfrr:" & to_hstring(r.mfrr);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    v.cppr := r.pending_priority;
 
					 
					 
					 
						    v.cppr := pending_priority;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						end if;
 
					 
					 
					 
						end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        v.wb_rd_data := bswap(be_out);
 
					 
					 
					 
					        v.wb_rd_data := bswap(be_out);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						if irq_eoi = '1' then
 
					 
					 
					 
					        if unsigned(pending_priority) < unsigned(v.cppr) then
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    v.irq := '0';
 
					 
					 
					 
					            if r.irq = '0' then
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						end if;
 
					 
					 
					 
					                report "IRQ set";
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            v.irq := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        elsif r.irq = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            report "IRQ clr";
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						if rst = '1' then
 
					 
					 
					 
						if rst = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    v := reg_internal_init;
 
					 
					 
					 
						    v := reg_internal_init;
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -214,3 +200,192 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end process;
 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					end architecture behaviour;
 
					 
					 
					 
					end architecture behaviour;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					library ieee;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					use ieee.std_logic_1164.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					use ieee.numeric_std.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					library work;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					use work.common.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					use work.wishbone_types.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					entity xics_ics is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    generic (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        SRC_NUM  : positive := 16
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        );
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    port (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        clk          : in std_logic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        rst          : in std_logic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        wb_in        : in wb_io_master_out;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        wb_out       : out wb_io_slave_out;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						int_level_in : in std_ulogic_vector(SRC_NUM - 1 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						icp_out      : out ics_to_icp_t
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        );
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					end xics_ics;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					architecture rtl of xics_ics is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    subtype pri_t is std_ulogic_vector(7 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    type xive_t is record
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        pri : pri_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end record;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    type xive_array_t is array(0 to SRC_NUM-1) of xive_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal xives : xive_array_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal wb_valid : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal reg_idx : integer range 0 to SRC_NUM - 1;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal icp_out_next : ics_to_icp_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal int_level_l : std_ulogic_vector(SRC_NUM - 1 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    function  bswap(v : in std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable r : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        r( 7 downto  0) := v(31 downto 24);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        r(15 downto  8) := v(23 downto 16);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        r(23 downto 16) := v(15 downto  8);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        r(31 downto 24) := v( 7 downto  0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        return r;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end function;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- Register map
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --     0  : Config (currently hard wired base irq#)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --     4  : Debug/diagnostics
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --   800  : XIVE0
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --   804  : XIVE1 ...
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- Config register format:
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --  23..  0 : Interrupt base (hard wired to 16)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- XIVE register format:
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --       31 : input bit (reflects interrupt input)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --       30 : reserved
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --       29 : P (mirrors input for now)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --       28 : Q (not implemented in this version)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- 30 ..    : reserved
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- 19 ..  8 : target (not implemented in this version)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --  7 ..  0 : prio/mask
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal reg_is_xive   : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal reg_is_config : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal reg_is_debug  : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    assert SRC_NUM = 16 report "Fixup address decode with log2";
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    reg_is_xive   <= wb_in.adr(11);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    reg_is_config <= '1' when wb_in.adr(11 downto 0) = x"000" else '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    reg_is_debug  <= '1' when wb_in.adr(11 downto 0) = x"004" else '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- Register index XX FIXME: figure out bits from SRC_NUM
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    reg_idx <= to_integer(unsigned(wb_in.adr(5 downto 2)));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- Latch interrupt inputs for timing
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    int_latch: process(clk)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        if rising_edge(clk) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            int_level_l <= int_level_in;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- We don't stall. Acks are sent by the read machine one cycle
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- after a request, but we can handle one access per cycle.
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    wb_out.stall <= '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    wb_valid <= wb_in.cyc and wb_in.stb;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- Big read mux. This could be replaced by a slower state
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- machine iterating registers instead if timing gets tight.
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    reg_read: process(clk)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable be_out : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        if rising_edge(clk) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            be_out := (others => '0');
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            if reg_is_xive = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                be_out := int_level_l(reg_idx) &
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                          '0' &
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                          int_level_l(reg_idx) &
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                          '0' &
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                          x"00000" &
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                          xives(reg_idx).pri;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            elsif reg_is_config = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                be_out := std_ulogic_vector(to_unsigned(SRC_NUM, 32));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            elsif reg_is_debug = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                be_out := x"00000" & icp_out_next.src & icp_out_next.pri;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            wb_out.dat <= bswap(be_out);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            wb_out.ack <= wb_valid;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- Register write machine
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    reg_write: process(clk)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable be_in  : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- Byteswapped input
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        be_in := bswap(wb_in.dat);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        if rising_edge(clk) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            if rst = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                for i in 0 to SRC_NUM - 1 loop
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    xives(i) <= (pri => x"ff");
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                end loop;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            elsif wb_valid = '1' and wb_in.we = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                if reg_is_xive then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    -- TODO: When adding support for other bits, make sure to
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    -- properly implement wb_in.sel to allow partial writes.
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    xives(reg_idx).pri <= be_in(7 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    report "ICS irq " & integer'image(reg_idx) & " set to:" & to_hstring(be_in(7 downto 0));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- generate interrupt. This is a simple combinational process,
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- potentially wasteul in HW for large number of interrupts.
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- could be replaced with iterative state machines and a message
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- system between ICSs' (plural) and ICP  incl. reject etc...
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    --
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    irq_gen_sync: process(clk)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        if rising_edge(clk) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            icp_out <= icp_out_next;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    irq_gen: process(all)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable max_idx : integer range 0 to SRC_NUM-1;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable max_pri : pri_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- A more favored than b ?
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        function a_mf_b(a: pri_t; b: pri_t) return boolean is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            variable a_i : integer range 0 to 255;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            variable b_i : integer range 0 to 255;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            a_i := to_integer(unsigned(a));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            b_i := to_integer(unsigned(b));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            return a < b;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end function;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- XXX FIXME: Use a tree
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        max_pri := x"ff";
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        max_idx := 0;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        for i in 0 to SRC_NUM - 1 loop
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            if int_level_l(i) = '1' and a_mf_b(xives(i).pri, max_pri) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                max_pri := xives(i).pri;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                max_idx := i;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end loop;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        if max_pri /= x"ff" then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            report "MFI: " & integer'image(max_idx) & " pri=" & to_hstring(max_pri);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        icp_out_next.src <= std_ulogic_vector(to_unsigned(max_idx, 4));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        icp_out_next.pri <= max_pri;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					end architecture rtl;