OpenCores
URL https://opencores.org/ocsvn/lxp32/lxp32/trunk

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_interrupt_mux.vhd] - Rev 12

Compare with Previous | Blame | View Log

---------------------------------------------------------------------
-- Interrupt multiplexer
--
-- Part of the LXP32 CPU
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Manages LXP32 interrupts. Interrupts with lower numbers have
-- higher priority.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity lxp32_interrupt_mux is
	port(
		clk_i: in std_logic;
		rst_i: in std_logic;
 
		irq_i: in std_logic_vector(7 downto 0);
 
		interrupt_valid_o: out std_logic;
		interrupt_vector_o: out std_logic_vector(2 downto 0);
		interrupt_ready_i: in std_logic;
		interrupt_return_i: in std_logic;
 
		wakeup_o: out std_logic;
 
		sp_waddr_i: in std_logic_vector(7 downto 0);
		sp_we_i: in std_logic;
		sp_wdata_i: in std_logic_vector(31 downto 0)
	);
end entity;
 
architecture rtl of lxp32_interrupt_mux is
 
signal irq_reg: std_logic_vector(irq_i'range):=(others=>'0');
 
type state_type is (Ready,Requested,WaitForExit);
signal state: state_type:=Ready;
 
signal pending_interrupts: std_logic_vector(irq_i'range):=(others=>'0');
 
signal interrupt_valid: std_logic:='0';
 
signal interrupts_enabled: std_logic_vector(7 downto 0):=(others=>'0');
signal interrupts_wakeup: std_logic_vector(7 downto 0):=(others=>'0');
 
begin
 
-- Note: "disabled" interrupts (i.e. for which interrupts_enabled_i(i)='0')
-- are ignored completely, meaning that the interrupt handler won't be
-- called even if the interrupt is enabled later.
 
process (clk_i) is
begin
	if rising_edge(clk_i) then
		if rst_i='1' then
			irq_reg<=(others=>'0');
			pending_interrupts<=(others=>'0');
			state<=Ready;
			interrupt_valid<='0';
			interrupt_vector_o<=(others=>'-');
			wakeup_o<='0';
		else
			irq_reg<=irq_i;
 
			pending_interrupts<=(pending_interrupts or 
				(irq_i and not irq_reg)) and
				interrupts_enabled and not interrupts_wakeup;
 
			case state is
			when Ready =>
				for i in pending_interrupts'reverse_range loop -- lower interrupts have priority
					if pending_interrupts(i)='1' then
						pending_interrupts(i)<='0';
						interrupt_valid<='1';
						interrupt_vector_o<=std_logic_vector(to_unsigned(i,3));
						state<=Requested;
						exit;
					end if;
				end loop;
			when Requested =>
				if interrupt_ready_i='1' then
					interrupt_valid<='0';
					state<=WaitForExit;
				end if;
			when WaitForExit =>
				if interrupt_return_i='1' then
					state<=Ready;
				end if;
			end case;
 
			if (irq_i and (not irq_reg) and interrupts_enabled and interrupts_wakeup)/=X"00" then
				wakeup_o<='1';
			else
				wakeup_o<='0';
			end if;
		end if;
	end if;
end process;
 
interrupt_valid_o<=interrupt_valid;
 
process (clk_i) is
begin
	if rising_edge(clk_i) then
		if rst_i='1' then
			interrupts_enabled<=(others=>'0');
			interrupts_wakeup<=(others=>'0');
		elsif sp_we_i='1' and sp_waddr_i=X"FC" then
			interrupts_enabled<=sp_wdata_i(7 downto 0);
			interrupts_wakeup<=sp_wdata_i(15 downto 8);
		end if;
	end if;
end process;
 
end architecture;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.