📄 irqctrl.vhd
字号:
-----------------------------------------------------------------------------
-- This file is a part of the LEON VHDL model
-- Copyright (C) 1999 European Space Agency (ESA)
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- See the file COPYING for the full details of the license.
-----------------------------------------------------------------------------
-- Entity: irqctrl
-- File: irqctrl.vhd
-- Author: Jiri Gaisler - ESA/ESTEC
-- Description: Interrupt controller. Implements a two-level interrupt
-- controller for the 15 SPARC interrupts.
------------------------------------------------------------------------------
-- Version control:
-- 07-08-1998: First implemetation
-- 26-09-1999: Release 1.0
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use work.iface.all;
use work.macro.decode;
entity irqctrl is
port (
rst : in std_logic;
clk : in std_logic;
pbi : in pbus_in_type;
pbo : out pbus_out_type;
irqi : in irq_in_type;
irqo : out irq_out_type
);
end;
architecture rtl of irqctrl is
type irqregs is record
imask : std_logic_vector(15 downto 1);
ilevel : std_logic_vector(15 downto 1);
ipend : std_logic_vector(15 downto 1);
iforce : std_logic_vector(15 downto 1);
irl : std_logic_vector( 3 downto 0);
end record;
function priority(v : std_logic_vector(15 downto 1)) return std_logic_vector is
begin
if v(15) = '1' then return("1111");
elsif v(14) = '1' then return("1110");
elsif v(13) = '1' then return("1101");
elsif v(12) = '1' then return("1100");
elsif v(11) = '1' then return("1011");
elsif v(10) = '1' then return("1010");
elsif v( 9) = '1' then return("1001");
elsif v( 8) = '1' then return("1000");
elsif v( 7) = '1' then return("0111");
elsif v( 6) = '1' then return("0110");
elsif v( 5) = '1' then return("0101");
elsif v( 4) = '1' then return("0100");
elsif v( 3) = '1' then return("0011");
elsif v( 2) = '1' then return("0010");
elsif v( 1) = '1' then return("0001");
else return ("0000"); end if;
end;
signal ir, irin : irqregs;
begin
irqhandler : process(rst, ir, pbi, irqi)
variable irv : irqregs;
variable temp : std_logic_vector(15 downto 0);
variable rdata : std_logic_vector(31 downto 0);
begin
irv := ir;
irv.ipend := ir.ipend or irqi.irq; -- merge incoming interrupts
-- resolve interrupts
temp := ((ir.iforce or ir.ipend) and ir.imask) & '0';
irv.irl := priority(temp(15 downto 1) and ir.ilevel);
if irv.irl = "0000" then
irv.irl := priority(temp(15 downto 1) and not ir.ilevel);
end if;
-- register read/write
rdata := (others => '0');
if pbi.enable = '1' then
if pbi.read = '1' then
case pbi.address is
when "100100" => rdata(31 downto 17) := ir.ilevel;
rdata(15 downto 1) := ir.imask;
when "100101" => rdata(15 downto 1) := ir.ipend;
when "100110" => rdata(15 downto 1) := ir.iforce;
when others => null;
end case;
else
case pbi.address is
when "100100" => irv.ilevel := pbi.data(31 downto 17);
irv.imask := pbi.data(15 downto 1);
when "100101" => irv.ipend := pbi.data(15 downto 1);
when "100110" => irv.iforce := pbi.data(15 downto 1);
when "100111" => irv.ipend := ir.ipend and not pbi.data(15 downto 1);
when others => null;
end case;
end if;
end if;
-- clear irq pending/force on intack
if irqi.intack = '1' then
temp := decode(irqi.irl);
irv.iforce := ir.iforce and not temp(15 downto 1);
irv.ipend := ir.ipend and not ((not ir.iforce) and temp(15 downto 1));
end if;
-- clear irq mask and pending on reset
if rst = '0' then
irv.imask := (others => '0');
end if;
irin <= irv;
pbo.data <= rdata;
irqo.irl <= ir.irl;
end process;
regs : process(clk)
begin
if clk'event and clk = '1' then
ir <= irin;
end if;
end process;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -