--------------------------------------------------------------------------------------------------------------- -- RISA Project -- Author: A.Greensted -- Module: -- Description: -- History: --------------------------------------------------------------------------------------------------------------- -- Interrupt Fag Clearing & Setting -- -------------------------------- -- Normal operations will write to all flag locations at once. -- Due to pipeline delays it is possible for a flag to get -- set to a '1' between it being read as a '0' and then written to a '0'. -- For example: -- bc flagReg 0x0001 -- If flagReg(1) is set to one (by an interrupt occuting) in the execute -- pipeline stage, it will be forced back to a zero at the writeback stage, -- therefore the interrupt is lost, even though the desire was to only -- reset flagReg(0). -- Therefore the intSet and intClr locations are required to set or clear -- specific flags without risk of loosing interrupts. library ieee; use ieee.std_logic_1164.all; library SnapLib; use SnapLib.SnapPkg.all; entity InterruptController is port ( clk : in std_logic; enable : in std_logic; nReset : in std_logic; dIn : in std_logic_vector(15 downto 0); flagsReg0WEn : in std_logic; flagsReg0Out : out std_logic_vector(15 downto 0); flagsReg1WEn : in std_logic; flagsReg1Out : out std_logic_vector(15 downto 0); enableReg0WEn : in std_logic; enableReg0Out : out std_logic_vector(15 downto 0); enableReg1WEn : in std_logic; enableReg1Out : out std_logic_vector(15 downto 0); intClr0WEn : in std_logic; intClr1WEn : in std_logic; intSet0WEn : in std_logic; intSet1WEn : in std_logic; interruptsIn : in std_logic_vector(31 downto 0); interruptRequest : out std_logic); end InterruptController; architecture General of InterruptController is signal enableReg0 : std_logic_vector(15 downto 0); signal enableReg1 : std_logic_vector(15 downto 0); signal flagsReg0 : std_logic_vector(15 downto 0); signal flagsReg1 : std_logic_vector(15 downto 0); begin enableReg0Out <= enableReg0; enableReg1Out <= enableReg1; flagsReg0Out <= flagsReg0; flagsReg1Out <= flagsReg1; interruptRequest <= '0' when (flagsReg0=x"0000" and flagsReg1=x"0000") else '1'; EnableReg : process (clk) begin if (clk'event and clk='1') then if (nReset='0') then enableReg0 <= (others => '0'); enableReg1 <= (others => '0'); elsif (enable='1') then if (enableReg0WEn='1') then enableReg0 <= dIn; end if; if (enableReg1WEn='1') then enableReg1 <= dIn; end if; end if; end if; end process; FlagRegGen : for flagNum in 15 downto 0 generate begin FlagReg : process (clk) begin if (clk'event and clk='1') then if (nReset='0') then flagsReg0(flagNum) <= '0'; flagsReg1(flagNum) <= '0'; elsif (enable='1') then -- Flags Reg 0 if (enableReg0(flagNum)='1' and interruptsIn(flagNum)='1') then flagsReg0(flagNum) <= '1'; elsif (intClr0WEn='1' and dIn(flagNum)='1') then flagsReg0(flagNum) <= '0'; elsif (intSet0WEn='1' and dIn(flagNum)='1') then flagsReg0(flagNum) <= '1'; elsif (flagsReg0WEn='1') then flagsReg0(flagNum) <= dIn(flagNum); end if; -- Flags Reg 1 if (enableReg1(flagNum)='1' and interruptsIn(16 + flagNum)='1') then flagsReg1(flagNum) <= '1'; elsif (intClr1WEn='1' and dIn(flagNum)='1') then flagsReg1(flagNum) <= '0'; elsif (intSet1WEn='1' and dIn(flagNum)='1') then flagsReg1(flagNum) <= '1'; elsif (flagsReg1WEn='1') then flagsReg1(flagNum) <= dIn(flagNum); end if; end if; end if; end process; end generate; end General;