| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -1,11 +1,13 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				--
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- This is a simple XICS compliant interrupt controller.  This is a
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- Presenter (ICP) and Source (ICS) in a single unit with no routing
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- layer.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- Presenter (ICP) and Source (ICS) in two small units directly
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- connected to each other with no routing layer.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				--
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- The sources have a fixed IRQ priority set by HW_PRIORITY. The
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- source id starts at 16 for int_level_in(0) and go up from
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- there (ie int_level_in(1) is source id 17).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- The sources have a configurable IRQ priority set a set of ICS
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- registers in the source units.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				--
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- 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
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- favourable than the current CPPR and present it via the XISR and
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -22,38 +24,31 @@ library work;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				use work.common.all;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				use work.wishbone_types.all;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				entity xics is
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    generic (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        LEVEL_NUM : positive := 16
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				entity xics_icp is
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    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(LEVEL_NUM - 1 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        wb_in        : in wb_io_master_out;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        wb_out       : out wb_io_slave_out;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ics_in       : in ics_to_icp_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					xisr : std_ulogic_vector(23 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_pending : std_ulogic;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					irq : std_ulogic;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wb_rd_data : std_ulogic_vector(31 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wb_ack : std_ulogic;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    end record;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    constant reg_internal_init : reg_internal_t :=
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(wb_ack => '0',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 mfrr_pending => '0',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 mfrr => x"00", -- mask everything on reset
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 mfrr => x"ff", -- mask everything on reset
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 irq => '0',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 others => (others => '0'));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -74,25 +69,43 @@ begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if rising_edge(clk) then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    r <= r_next;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            -- We delay core_irq_out by a cycle to help with timing
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            core_irq_out <= r.irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    end process;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    wb_out.dat <= r.wb_rd_data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    wb_out.ack <= r.wb_ack;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    wb_out.stall <= '0'; -- never stall wishbone
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    core_irq_out <= r.irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    comb : process(all)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					variable v : reg_internal_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        variable be_in  : 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
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					v := r;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					v.wb_ack := '0';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					xirr_accept_rd := '0';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					irq_eoi := '0';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        be_in := bswap(wb_in.dat);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        be_out := (others => '0');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if wb_in.cyc = '1' and wb_in.stb = '1' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    v.wb_ack := '1'; -- always ack
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -100,112 +113,83 @@ begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						-- writes to both XIRR are the same
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case wb_in.adr(7 downto 0) is
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                when XIRR_POLL =>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    report "XICS XIRR_POLL write";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    if wb_in.sel = x"f" then -- 4 bytes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.cppr := wb_in.dat(31 downto 24);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    elsif wb_in.sel = x"1"  then -- 1 byte
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.cppr := wb_in.dat(7 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    report "ICP XIRR_POLL write";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    v.cppr := be_in(31 downto 24);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                when XIRR =>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    v.cppr := be_in(31 downto 24);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    if wb_in.sel = x"f"  then -- 4 byte
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "XICS XIRR write word:" & to_hstring(wb_in.dat);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.cppr := wb_in.dat(31 downto 24);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq_eoi := '1';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "ICP XIRR write word (EOI) :" & to_hstring(be_in);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    elsif wb_in.sel = x"1"  then -- 1 byte
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "XICS XIRR write byte:" & to_hstring(wb_in.dat(7 downto 0));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.cppr := wb_in.dat(7 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "ICP XIRR write byte (CPPR):" & to_hstring(be_in(31 downto 24));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "XICS XIRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "ICP XIRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						when MFRR =>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    v.mfrr := be_in(31 downto 24);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    if wb_in.sel = x"f" then -- 4 bytes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "XICS MFRR write word:" & to_hstring(wb_in.dat);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.mfrr_pending := '1';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.mfrr := wb_in.dat(31 downto 24);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "ICP MFRR write word:" & to_hstring(be_in);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    elsif wb_in.sel = x"1" then -- 1 byte
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "XICS MFRR write byte:" & to_hstring(wb_in.dat(7 downto 0));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.mfrr_pending := '1';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.mfrr := wb_in.dat(7 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "ICP MFRR write byte:" & to_hstring(be_in(31 downto 24));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "XICS MFRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        report "ICP MFRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                when others =>                        
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						end case;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    else -- read
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						v.wb_rd_data := (others => '0');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case wb_in.adr(7 downto 0) is
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                when XIRR_POLL =>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    report "XICS XIRR_POLL read";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    if wb_in.sel = x"f" then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data(23 downto  0) := r.xisr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data(31 downto 24) := r.cppr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    elsif wb_in.sel = x"1" then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data(7 downto  0) := r.cppr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    report "ICP XIRR_POLL read";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    be_out := r.cppr & r.xisr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                when XIRR =>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    report "XICS XIRR read";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    report "ICP XIRR read";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    be_out := r.cppr & r.xisr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    if wb_in.sel = x"f" then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data(23 downto 0) := r.xisr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data(31 downto 24) := r.cppr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							xirr_accept_rd := '1';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    elsif wb_in.sel = x"1" then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data(7 downto 0) := r.cppr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						when MFRR =>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    report "XICS MFRR read";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    if wb_in.sel = x"f" then -- 4 bytes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data(31 downto 24) := r.mfrr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    elsif wb_in.sel = x"1" then -- 1 byte
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							v.wb_rd_data( 7 downto  0) := r.mfrr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    report "ICP MFRR read";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    be_out(31 downto 24) := r.mfrr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                when others =>                        
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						end case;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					-- generate interrupt
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if r.irq = '0' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    -- Here we just present any interrupt that's valid and
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    -- 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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        pending_priority := x"ff";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        v.xisr := x"000000";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        v.irq := '0';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    -- Do mfrr as a higher priority so mfrr_pending is cleared
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    if unsigned(r.mfrr) < unsigned(r.cppr) then --
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						report "XICS: MFRR INTERRUPT";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						-- IPI
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if r.mfrr_pending = '1' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    v.irq := '1';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    v.xisr := x"000002"; -- special XICS MFRR IRQ source number
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    v.pending_priority := r.mfrr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    v.mfrr_pending := '0';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if ics_in.pri /= x"ff" then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            v.xisr := x"00001" & ics_in.src;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            pending_priority := ics_in.pri;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        -- Check MFRR
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if unsigned(r.mfrr) < unsigned(pending_priority) then --
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            v.xisr := x"000002"; -- special XICS MFRR IRQ source number
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            pending_priority := r.mfrr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					-- Accept the interrupt
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if xirr_accept_rd = '1' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    report "XICS: ACCEPT" &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						" cppr:" &  to_hstring(r.cppr) &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						" xisr:" & to_hstring(r.xisr) &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						" mfrr:" & to_hstring(r.mfrr);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    v.cppr := r.pending_priority;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            report "XICS: ICP ACCEPT" &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                " cppr:" &  to_hstring(r.cppr) &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                " xisr:" & to_hstring(r.xisr) &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                " mfrr:" & to_hstring(r.mfrr);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    v.cppr := pending_priority;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if irq_eoi = '1' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    v.irq := '0';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        v.wb_rd_data := bswap(be_out);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if unsigned(pending_priority) < unsigned(v.cppr) then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if r.irq = '0' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                report "IRQ set";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            v.irq := '1';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        elsif r.irq = '1' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            report "IRQ clr";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if rst = '1' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    v := reg_internal_init;
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -216,3 +200,227 @@ begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    end process;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				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    : integer range 1 to 256  := 16;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        PRIO_BITS  : integer range 1 to 8    := 8
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    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(PRIO_BITS-1 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    type xive_t is record
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        pri : pri_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    end record;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    constant pri_masked : pri_t := (others => '1');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    function get_config return std_ulogic_vector is
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        variable r: std_ulogic_vector(31 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        r := (others => '0');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        r(23 downto  0) := std_ulogic_vector(to_unsigned(SRC_NUM, 24));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        r(27 downto 24) := std_ulogic_vector(to_unsigned(PRIO_BITS, 4));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return r;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    end function;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    function prio_pack(pri8: std_ulogic_vector(7 downto 0)) return pri_t is
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return pri8(PRIO_BITS-1 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    end function;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    function prio_unpack(pri: pri_t) return std_ulogic_vector is
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        variable r : std_ulogic_vector(7 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if pri = pri_masked then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            r := x"ff";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            r := (others => '0');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            r(PRIO_BITS-1 downto 0) := pri;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return r;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				   end function;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				-- Register map
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --     0  : Config
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --     4  : Debug/diagnostics
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --   800  : XIVE0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --   804  : XIVE1 ...
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    -- Config register format:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --  23..  0 : Interrupt base (hard wired to 16)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --  27.. 24 : #prio bits (1..8)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    --
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    -- 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" &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                          prio_unpack(xives(reg_idx).pri);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elsif reg_is_config = '1' then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                be_out := get_config;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            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 => pri_masked);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                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 <= prio_pack(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 wasteful 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 : unsigned(PRIO_BITS-1 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            variable b_i : unsigned(PRIO_BITS-1 downto 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            a_i := unsigned(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            b_i := unsigned(b);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            report "a_mf_b a=" & to_hstring(a) &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                " b=" & to_hstring(b) &
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                " r=" & boolean'image(a < b);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return a_i < b_i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        end function;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    begin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        -- XXX FIXME: Use a tree
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        max_pri := pri_masked;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        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 /= pri_masked then
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            report "MFI: " & integer'image(max_idx) & " pri=" & to_hstring(prio_unpack(max_pri));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        end if;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        icp_out_next.src <= std_ulogic_vector(to_unsigned(max_idx, 4));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        icp_out_next.pri <= prio_unpack(max_pri);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    end process;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				end architecture rtl;
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |