Line 23... |
Line 23... |
interrupt_valid_o: out std_logic;
|
interrupt_valid_o: out std_logic;
|
interrupt_vector_o: out std_logic_vector(2 downto 0);
|
interrupt_vector_o: out std_logic_vector(2 downto 0);
|
interrupt_ready_i: in std_logic;
|
interrupt_ready_i: in std_logic;
|
interrupt_return_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_waddr_i: in std_logic_vector(7 downto 0);
|
sp_we_i: in std_logic;
|
sp_we_i: in std_logic;
|
sp_wdata_i: in std_logic_vector(31 downto 0)
|
sp_wdata_i: in std_logic_vector(31 downto 0)
|
);
|
);
|
end entity;
|
end entity;
|
Line 41... |
Line 43... |
signal pending_interrupts: std_logic_vector(irq_i'range):=(others=>'0');
|
signal pending_interrupts: std_logic_vector(irq_i'range):=(others=>'0');
|
|
|
signal interrupt_valid: std_logic:='0';
|
signal interrupt_valid: std_logic:='0';
|
|
|
signal interrupts_enabled: std_logic_vector(7 downto 0):=(others=>'0');
|
signal interrupts_enabled: std_logic_vector(7 downto 0):=(others=>'0');
|
signal interrupts_blocked: std_logic_vector(7 downto 0):=(others=>'0');
|
signal interrupts_wakeup: std_logic_vector(7 downto 0):=(others=>'0');
|
|
|
begin
|
begin
|
|
|
-- Note: "disabled" interrupts (i.e. for which interrupts_enabled_i(i)='0')
|
-- Note: "disabled" interrupts (i.e. for which interrupts_enabled_i(i)='0')
|
-- are ignored completely, meaning that the interrupt handler won't be
|
-- are ignored completely, meaning that the interrupt handler won't be
|
-- called even if the interrupt is enabled later. Conversely, "blocked"
|
-- called even if the interrupt is enabled later.
|
-- interrupts are registered, but their handlers are not called until they
|
|
-- are unblocked.
|
|
|
|
process (clk_i) is
|
process (clk_i) is
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if rst_i='1' then
|
if rst_i='1' then
|
irq_reg<=(others=>'0');
|
irq_reg<=(others=>'0');
|
pending_interrupts<=(others=>'0');
|
pending_interrupts<=(others=>'0');
|
state<=Ready;
|
state<=Ready;
|
interrupt_valid<='0';
|
interrupt_valid<='0';
|
interrupt_vector_o<=(others=>'-');
|
interrupt_vector_o<=(others=>'-');
|
|
wakeup_o<='0';
|
else
|
else
|
irq_reg<=irq_i;
|
irq_reg<=irq_i;
|
|
|
pending_interrupts<=(pending_interrupts or
|
pending_interrupts<=(pending_interrupts or
|
(irq_i and not irq_reg)) and
|
(irq_i and not irq_reg)) and
|
interrupts_enabled;
|
interrupts_enabled and not interrupts_wakeup;
|
|
|
case state is
|
case state is
|
when Ready =>
|
when Ready =>
|
for i in pending_interrupts'reverse_range loop -- lower interrupts have priority
|
for i in pending_interrupts'reverse_range loop -- lower interrupts have priority
|
if pending_interrupts(i)='1' and interrupts_blocked(i)='0' then
|
if pending_interrupts(i)='1' then
|
pending_interrupts(i)<='0';
|
pending_interrupts(i)<='0';
|
interrupt_valid<='1';
|
interrupt_valid<='1';
|
interrupt_vector_o<=std_logic_vector(to_unsigned(i,3));
|
interrupt_vector_o<=std_logic_vector(to_unsigned(i,3));
|
state<=Requested;
|
state<=Requested;
|
exit;
|
exit;
|
Line 88... |
Line 89... |
when WaitForExit =>
|
when WaitForExit =>
|
if interrupt_return_i='1' then
|
if interrupt_return_i='1' then
|
state<=Ready;
|
state<=Ready;
|
end if;
|
end if;
|
end case;
|
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 if;
|
end if;
|
end process;
|
end process;
|
|
|
interrupt_valid_o<=interrupt_valid;
|
interrupt_valid_o<=interrupt_valid;
|
Line 99... |
Line 106... |
process (clk_i) is
|
process (clk_i) is
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if rst_i='1' then
|
if rst_i='1' then
|
interrupts_enabled<=(others=>'0');
|
interrupts_enabled<=(others=>'0');
|
interrupts_blocked<=(others=>'0');
|
interrupts_wakeup<=(others=>'0');
|
elsif sp_we_i='1' and sp_waddr_i=X"FC" then
|
elsif sp_we_i='1' and sp_waddr_i=X"FC" then
|
interrupts_enabled<=sp_wdata_i(7 downto 0);
|
interrupts_enabled<=sp_wdata_i(7 downto 0);
|
interrupts_blocked<=sp_wdata_i(15 downto 8);
|
interrupts_wakeup<=sp_wdata_i(15 downto 8);
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
end architecture;
|
end architecture;
|