------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------ ---- Project: NULL STAR (Devember 2021) ---- ---- Module: Interrupt Controller ---- ---- Drawing: (Not Assigned) ---- ---- ---- ---- Filename: interrupt_controller.vhd ---- ---- File Type: VHDL (93) ---- ---- Modified: 11/28/2021 ---- ---- Target: Universal ---- ---- Toolchain: Universal ---- ---- ---- ---- Dependencies: ---- ---- [ ] fifo_fwft.vhd ---- ---- ---- ---- Description: ---- ---- Encodes up to 65536 interrupt lines (INTERRUPT) into a single vector which is pushed into ---- ---- a FIFO of interrupt events. Interrupts latched on the rising edge of INTERRUPT. ---- ---- ---- ---- Revision History: ---- ---- 11/28/2021 - Initial release. ---- ------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; entity interrupt_controller is generic ( NUM_INTERRUPT_LINES : integer := 32 ); port ( -- System Clock, Reset MCLK : in std_ulogic; MRST : in std_ulogic; -- Interrupt Inputs INTERRUPT : in std_ulogic_vector(NUM_INTERRUPT_LINES - 1 downto 0); -- Interrupt Vector FIFO Interface IREQ : out std_ulogic; IREQ_FIFO_READ : in std_ulogic; IREQ_IDENT : out std_ulogic_vector(15 downto 0) ); end entity interrupt_controller; architecture Dataflow of interrupt_controller is -- Constants constant INTERRUPT_ENCODED_WIDTH : integer := integer(ceil(log2(real(NUM_INTERRUPT_LINES)))); constant ZERO_NUM_INTERRUPT_LINES : std_ulogic_vector(NUM_INTERRUPT_LINES - 1 downto 0) := (others => '0'); constant FIFO_DATA_ZERO_PAD : std_ulogic_vector(15 - INTERRUPT_ENCODED_WIDTH downto 0) := (others => '0'); -- Interrupt Synchronization/Rising Edge Detect type INTERRUPT_sync_array_type is array (0 to NUM_INTERRUPT_LINES - 1) of std_ulogic_vector(3 downto 0); signal INTERRUPT_sync_array : INTERRUPT_sync_array_type; signal INTERRUPT_pulse : std_ulogic_vector(NUM_INTERRUPT_LINES - 1 downto 0); -- Interrupt Encoding signal interrupt_or_collapse : std_ulogic; signal interrupt_waiting : std_ulogic_vector(NUM_INTERRUPT_LINES - 1 downto 0); signal interrupt_clear : std_ulogic_vector(NUM_INTERRUPT_LINES - 1 downto 0); signal interrupt_encoded : unsigned(INTERRUPT_ENCODED_WIDTH - 1 downto 0); -- FIFO Control Signals signal interrupt_fifo_wr_en : std_ulogic; signal interrupt_fifo_wr_data : std_ulogic_vector(INTERRUPT_ENCODED_WIDTH - 1 downto 0); signal interrupt_fifo_rd_data : std_ulogic_vector(INTERRUPT_ENCODED_WIDTH - 1 downto 0); signal interrupt_fifo_empty : std_ulogic; begin -- Ungrouped Assignments ----------------------------------------------------------------------------------------------- interrupt_or_collapse <= '1' when (interrupt_waiting /= ZERO_NUM_INTERRUPT_LINES) else '0'; IREQ_IDENT <= FIFO_DATA_ZERO_PAD & interrupt_fifo_rd_data; IREQ <= not interrupt_fifo_empty; interrupt_fifo_wr_data <= std_ulogic_vector(interrupt_encoded); interrupt_fifo_wr_en <= interrupt_or_collapse; ------------------------------------------------------------------------------------------------------------------------ -- INTERRUPT Input Synchronization, Edge Detect ------------------------------------------------------------------------ INTERRUPT_Input_Register_Generate : for I in 0 to NUM_INTERRUPT_LINES - 1 generate begin -- Synchronization INTERRUPT_Input_Register_Process : process (MCLK) begin if rising_edge(MCLK) then if (MRST = '1') then INTERRUPT_sync_array(I) <= "0000"; else INTERRUPT_sync_array(I) <= INTERRUPT(I) & INTERRUPT_sync_array(I)(3 downto 1); end if; end if; end process INTERRUPT_Input_Register_Process; -- Edge Detect INTERRUPT_pulse(I) <= INTERRUPT_sync_array(I)(1) and not INTERRUPT_sync_array(I)(0); end generate INTERRUPT_Input_Register_Generate; ------------------------------------------------------------------------------------------------------------------------- -- Interrupt Waiting Latch ---------------------------------------------------------------------------------------------- Interrupt_Waiting_Register_Generate : for I in 0 to NUM_INTERRUPT_LINES - 1 generate begin Interrupt_Waiting_Register_Process : process (MCLK) begin if rising_edge(MCLK) then if (MRST = '1' or interrupt_clear(I) = '1') then interrupt_waiting(I) <= '0'; elsif (INTERRUPT_pulse(I) = '1') then interrupt_waiting(I) <= '1'; end if; end if; end process Interrupt_Waiting_Register_Process; end generate Interrupt_Waiting_Register_Generate; ------------------------------------------------------------------------------------------------------------------------- -- Interrupt Priority Encoder ------------------------------------------------------------------------------------------- Interrupt_Priority_Encoder_Process : process (interrupt_waiting) begin interrupt_encoded <= (others => '0'); for I in 0 to NUM_INTERRUPT_LINES - 1 loop if (interrupt_waiting(I) = '1') then interrupt_encoded <= to_unsigned(I,INTERRUPT_ENCODED_WIDTH); end if; end loop; end process Interrupt_Priority_Encoder_Process; -- Interrupt Clear Bit Interrupt_Clear_Bit_Generate : for I in 0 to NUM_INTERRUPT_LINES - 1 generate begin interrupt_clear(I) <= '1' when (interrupt_or_collapse = '1' and interrupt_encoded = I) else '0'; end generate Interrupt_Clear_Bit_Generate; ------------------------------------------------------------------------------------------------------------------------- -- Interrupt Identifier FIFO -------------------------------------------------------------------------------------------- Interrupt_ID_FIFO_Instance : entity work.fifo_fwft generic map ( ADDR_WIDTH => INTERRUPT_ENCODED_WIDTH, DATA_WIDTH => INTERRUPT_ENCODED_WIDTH ) port map ( MCLK => MCLK, MRST => MRST, WR_EN => interrupt_fifo_wr_en, WR_DATA => interrupt_fifo_wr_data, RD_EN => IREQ_FIFO_READ, RD_DATA => interrupt_fifo_rd_data, STATUS_EMPTY => interrupt_fifo_empty, STATUS_FULL => open ); ------------------------------------------------------------------------------------------------------------------------- end architecture Dataflow;