-------------------------------------------------------------------------------- -- CERN (BE-CO-HT) -- VME64x Core -- http://www.ohwr.org/projects/vme64x-core -------------------------------------------------------------------------------- -- -- unit name: VME_IRQ_Controller (VME_IRQ_Controller.vhd) -- -- author: Pablo Alvarez Sanchez -- Davide Pedretti -- -- description: -- -- This block acts as Interrupter. Phases of an interrupt cycle: -- -- 1) The Interrupt Controller receives an interrupt request by the WB bus; -- this request is a pulse on the INT_Req input -- 2) The Interrupt Controller asserts ('0') one of the 7 VME_IRQ lines; -- --> request of a service. -- The Interrupt priority is specificated by the Master writing the -- INT_Level register in the CR/CSR space -- 3) The Interrupter Controller wait for the falling edge on the VME_IACKIN -- line. -- 4) When detects VME_IACKIN_n_i = '0' and the Interrupt Handler initiates -- the Interrupt cycle by asserting AS,the Interrupt Controller check if it -- is the responding interrupter. Indeed before responding to an interrupt -- acknowledge cycle the interrupter shall have an interrupt request -- pending, shall check if the level of that request match the level -- indicated on the address lines A1, A2 and A3,the data transfer width -- during the interrupt acknowledge cycle should be equal or greater than -- the size the it can respond with, and it shall receive a falling edge on -- its IACKIN*. -- 5) If it is the responding interrupter should send the source/ID on the -- VME_DATA lines (in our case the source/ID is the INT_Vector that the -- Master can write in the corresponding register in the CR/CSR space) and -- it terminates the interrupt cycle with an acknowledge before releasing -- the IRQ lines. If it isn't the responding interrupter, it should pass a -- falling edge on down the daisy-chain so other interrupters can respond. -- -- All the output signals are registered -- -- To implement the 5 phases before mentioned the follow FSM has been -- implemented: -- __________ -- |--| IACKOUT2 |<-| -- | |__________| | -- | | -- | _________ | _________ _________ _________ -- |-->| IDLE |--->| IRQ |-->| WAIT_AS |-->| WAIT_DS |-------------->| -- |_________| |_________| |_________| |_________| | -- | | | -- | | _________ _________ | -- | |---------<------------| IACKOUT1| <--| CHECK |<--| -- | |_________| |_________| -- | __________ __________ | -- |--<-----------------| DTACK |<--| DATA_OUT |---<----| -- |__________| |__________| -- -- The interrupter wait the IACKIN falling edge in the IRQ state, so if the -- interrupter don't have interrupt pending for sure it will not respond -- because it is in IDLE. -- If the slave module does not have an interrupt pending (IDLE state) and it -- receives a falling edge on the IACKIN, it shall pass the falling edge -- through the daisy chain. -- To obtain this the IACKOUT2 state has been added. -- -- Time constraint: -- -- Time constraint n° 35: -- -- Clk ____ ____ ____ ____ ____ ____ -- _____| |____| |____| |____| |____| |____| |_____ -- -- VME_AS1_n_i __________________________________________________________ -- _______| -- -- VME_AS_n_i ______________________________ -- ___________________________________| -- -- s_AS_RisingEge _________ -- _____________________________________________| |__________ -- -- s_IACKOUT __________________________________________________________ -- _______| -- -- VME_IACKOUT_ __________________________________________________________ -- _______| -- -- _______________________________________________________ _________ -- IACKOUT 1/2 \/ IDLE/IRQ -- _______________________________________________________/\_________ -- -- To respect the time constraint indicated with the number 35 fig. 55 pag. 183 -- in the "VMEbus Specification" ANSI/IEEE STD1014-1987, is necessary to -- generate the VME_AS1_n_i signal which is the AS signal not sampled, and -- assign this signal to the s_IACKOUT signal when the fsm is in the IACKOUTx -- state. -- -- The LWORD* input is not used now, since this is a D08(O) Interrupter (see -- Table 31 page 157 VMEbus specification). -- -- Since this is a D08 interrupter we do not need to monitor the LWORD* and -- DS1* lines and the Vector (1 byte) is outputted in the D00-D07 data lines. -- -- dependencies: -- -------------------------------------------------------------------------------- -- GNU LESSER GENERAL PUBLIC LICENSE -------------------------------------------------------------------------------- -- This source file is free software; you can redistribute it and/or modify it -- under the terms of the GNU Lesser General Public License as published by the -- Free Software Foundation; either version 2.1 of the License, or (at your -- option) any later version. This source is distributed in the hope that it -- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- See the GNU Lesser General Public License for more details. You should have -- received a copy of the GNU Lesser General Public License along with this -- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html -------------------------------------------------------------------------------- -- last changes: see log. -------------------------------------------------------------------------------- -- TODO: - -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.vme64x_pack.all; entity VME_IRQ_Controller is generic ( g_RETRY_TIMEOUT : integer range 1024 to 16777215 ); port ( clk_i : in std_logic; reset_n_i : in std_logic; INT_Level_i : in std_logic_vector (2 downto 0); INT_Req_i : in std_logic; irq_pending_o : out std_logic; irq_ack_i : in std_logic; VME_IRQ_n_o : out std_logic_vector (7 downto 1) ); end VME_IRQ_Controller; architecture Behavioral of VME_IRQ_Controller is type t_retry_state is (WAIT_IRQ, WAIT_RETRY); signal retry_state : t_retry_state; signal retry_count : unsigned(23 downto 0); signal retry_mask : std_logic; signal s_irq_pending : std_logic; begin irq_pending_o <= s_irq_pending; -- Interrupts are automatically masked for g_RETRY_TIMEOUT (ie 1 ms) once -- they are acknowledge by the interrupt handler until they are deasserted -- by the interrupter. p_retry_fsm : process (clk_i) begin if rising_edge(clk_i) then if reset_n_i = '0' then retry_mask <= '1'; retry_state <= WAIT_IRQ; else case retry_state is when WAIT_IRQ => if s_irq_pending = '1' and INT_Req_i = '1' then retry_state <= WAIT_RETRY; retry_count <= (others => '0'); retry_mask <= '0'; else retry_mask <= '1'; end if; when WAIT_RETRY => if INT_Req_i = '0' then retry_state <= WAIT_IRQ; else retry_count <= retry_count + 1; if retry_count = g_RETRY_TIMEOUT then retry_state <= WAIT_IRQ; end if; end if; end case; end if; end if; end process; p_main_fsm : process (clk_i) begin if rising_edge(clk_i) then if reset_n_i = '0' then VME_IRQ_n_o <= (others => '1'); s_irq_pending <= '0'; else if s_irq_pending = '0' then VME_IRQ_n_o <= (others => '1'); if INT_Req_i = '1' and retry_mask = '1' then s_irq_pending <= '1'; -- Explicit decoding case INT_Level_i is when "001" => VME_IRQ_n_o <= "1111110"; when "010" => VME_IRQ_n_o <= "1111101"; when "011" => VME_IRQ_n_o <= "1111011"; when "100" => VME_IRQ_n_o <= "1110111"; when "101" => VME_IRQ_n_o <= "1101111"; when "110" => VME_IRQ_n_o <= "1011111"; when "111" => VME_IRQ_n_o <= "0111111"; when others => -- Incorrect value for INT_Level_i, ignore it. VME_IRQ_n_o <= "1111111"; s_irq_pending <= '0'; end case; end if; else if irq_ack_i = '1' then s_irq_pending <= '0'; end if; end if; end if; end if; end process; end Behavioral;