mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-02-07 08:37:15 +00:00
145 lines
5.3 KiB
VHDL
145 lines
5.3 KiB
VHDL
-- Copyright (c) 2015, $ME
|
|
-- All rights reserved.
|
|
--
|
|
-- Redistribution and use in source and synthezised forms, with or without modification, are permitted
|
|
-- provided that the following conditions are met:
|
|
--
|
|
-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions
|
|
-- and the following disclaimer.
|
|
--
|
|
-- 2. Redistributions in synthezised form must reproduce the above copyright notice, this list of conditions
|
|
-- and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
--
|
|
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
-- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
-- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
-- POSSIBILITY OF SUCH DAMAGE.
|
|
--
|
|
--
|
|
-- more complete interrupt controller
|
|
-- - does not work atm
|
|
--
|
|
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
use IEEE.NUMERIC_STD.ALL;
|
|
|
|
entity intController is
|
|
generic (
|
|
numInts : integer := 8
|
|
);
|
|
port (
|
|
clk : in std_logic;
|
|
res : in std_logic;
|
|
int : out std_logic;
|
|
intPeriph : in std_logic_vector(numInts-1 downto 0);
|
|
intAck : out std_logic_vector(numInts-1 downto 0);
|
|
cpuDIn : in std_logic_vector(7 downto 0);
|
|
m1 : in std_logic;
|
|
iorq : in std_logic;
|
|
rd : in std_logic;
|
|
test : out std_logic_vector(numInts-1 downto 0);
|
|
RETI_n : in std_logic
|
|
);
|
|
end intController;
|
|
|
|
architecture rtl of intController is
|
|
constant zeroVect : std_logic_vector(numInts-1 downto 0) := (others => '0');
|
|
|
|
signal intInternal : std_logic_vector(numInts-1 downto 0);
|
|
signal intMask : std_logic_vector(numInts-1 downto 0);
|
|
signal currentInt : std_logic_vector(numInts-1 downto 0);
|
|
signal currentAck : std_logic_vector(numInts-1 downto 0);
|
|
|
|
signal intReti : std_logic_vector(numInts-1 downto 0);
|
|
signal intRetiMask : std_logic_vector(numInts-1 downto 0);
|
|
|
|
signal reti : integer range 0 to 2 := 0;
|
|
begin
|
|
intAck <= currentAck when m1='0' and iorq='0' else (others => '0');
|
|
|
|
test <= intReti;
|
|
|
|
int_mask : process(intInternal,intReti)
|
|
begin
|
|
intMask <= (others => '0');
|
|
for i in 0 to numInts-1 -- 0 is highest prio
|
|
loop
|
|
if intInternal(i)='1' and intReti(i)='0' then
|
|
intMask(i) <= '1';
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
end process;
|
|
|
|
ack_mask : process(intReti)
|
|
begin
|
|
intRetiMask <= (others => '0');
|
|
for i in 0 to numInts-1 -- 0 is highest prio
|
|
loop
|
|
if intReti(i)='1' then
|
|
intRetiMask(i) <= '1';
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
end process;
|
|
|
|
process
|
|
variable intResetMask : std_logic_vector(numInts-1 downto 0);
|
|
begin
|
|
wait until rising_edge(clk);
|
|
|
|
if (res='0') then
|
|
reti <= 0;
|
|
int <= '1';
|
|
currentInt <= (others => '0');
|
|
intInternal <= (others => '0');
|
|
intReti <= (others => '0');
|
|
else
|
|
intResetMask := (others => '1');
|
|
|
|
if (m1='1') then
|
|
currentAck <= (others => '0');
|
|
if intMask/=zeroVect then -- new int (with higher prio?)
|
|
int <= '0';
|
|
currentInt <= intMask;
|
|
currentAck <= intMask;
|
|
end if;
|
|
|
|
if RETI_n='0' and reti=0 then
|
|
reti <= 1;
|
|
elsif RETI_n='1' and reti=1 then
|
|
reti <= 2;
|
|
elsif reti=2 then
|
|
intReti <= intReti and not intRetiMask; -- reset highest reti-flag -> new int can be triggered
|
|
reti <= 0;
|
|
end if;
|
|
else
|
|
if iorq='0' then -- int ack
|
|
int <= '1';
|
|
intReti <= intReti or currentInt; -- update "wait for reti"-flags -> no more int for this until reti
|
|
intResetMask := not currentInt; -- reset current int
|
|
currentInt <= (others => '0');
|
|
elsif rd='0' then -- reti?
|
|
|
|
|
|
-- if cpuDIn=x"ED" and reti=0 then -- reti 1
|
|
-- reti <= 1;
|
|
-- elsif cpuDIn=x"4D" and reti=1 then -- reti 2
|
|
-- reti <= 2;
|
|
-- elsif reti /= 2 then
|
|
-- reti <= 0; -- something else -> reset statemachine
|
|
-- end if;
|
|
end if;
|
|
end if;
|
|
|
|
intInternal <= (intInternal and intResetMask) or intPeriph;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
end;
|