mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-05-02 14:40:33 +00:00
417 lines
15 KiB
VHDL
417 lines
15 KiB
VHDL
------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------
|
|
-- --
|
|
-- Copyright (c) 2009-2011 Tobias Gubener --
|
|
-- Subdesign fAMpIGA by TobiFlex --
|
|
-- --
|
|
-- This is the TOP-Level for TG68KdotC_Kernel to generate 68K Bus signals --
|
|
-- --
|
|
-- This source file 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 3 of the License, or --
|
|
-- (at your option) any later version. --
|
|
-- --
|
|
-- This source file is distributed in the hope that it will be useful, --
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
|
|
-- GNU General Public License for more details. --
|
|
-- --
|
|
-- You should have received a copy of the GNU General Public License --
|
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
|
|
-- --
|
|
------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
entity TG68K is
|
|
port(
|
|
clk : in std_logic;
|
|
reset : in std_logic;
|
|
clkena_in : in std_logic:='1';
|
|
IPL : in std_logic_vector(2 downto 0):="111";
|
|
dtack : in std_logic;
|
|
vpa : in std_logic:='1';
|
|
ein : in std_logic:='1';
|
|
addr : buffer std_logic_vector(31 downto 0);
|
|
data_read : in std_logic_vector(15 downto 0);
|
|
data_write : out std_logic_vector(15 downto 0);
|
|
as : out std_logic;
|
|
uds : out std_logic;
|
|
lds : out std_logic;
|
|
rw : out std_logic;
|
|
e : out std_logic;
|
|
vma : buffer std_logic:='1';
|
|
wrd : out std_logic;
|
|
ena7RDreg : in std_logic:='1';
|
|
ena7WRreg : in std_logic:='1';
|
|
enaWRreg : in std_logic:='1';
|
|
|
|
fromram : in std_logic_vector(15 downto 0);
|
|
ramready : in std_logic:='0';
|
|
cpu : in std_logic_vector(1 downto 0);
|
|
memcfg : in std_logic_vector(5 downto 0);
|
|
ramaddr : out std_logic_vector(31 downto 0);
|
|
cpustate : out std_logic_vector(5 downto 0);
|
|
nResetOut : out std_logic;
|
|
skipFetch : buffer std_logic;
|
|
cpuDMA : buffer std_logic;
|
|
ramlds : out std_logic;
|
|
ramuds : out std_logic
|
|
);
|
|
end TG68K;
|
|
|
|
ARCHITECTURE logic OF TG68K IS
|
|
|
|
|
|
COMPONENT TG68KdotC_Kernel
|
|
generic(
|
|
SR_Read : integer:= 2; --0=>user, 1=>privileged, 2=>switchable with CPU(0)
|
|
VBR_Stackframe : integer:= 2; --0=>no, 1=>yes/extended, 2=>switchable with CPU(0)
|
|
extAddr_Mode : integer:= 2; --0=>no, 1=>yes, 2=>switchable with CPU(1)
|
|
MUL_Mode : integer := 2; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
|
|
DIV_Mode : integer := 2; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
|
|
BitField : integer := 2 --0=>no, 1=>yes, 2=>switchable with CPU(1)
|
|
);
|
|
port(clk : in std_logic;
|
|
nReset : in std_logic; --low active
|
|
clkena_in : in std_logic:='1';
|
|
data_in : in std_logic_vector(15 downto 0);
|
|
IPL : in std_logic_vector(2 downto 0):="111";
|
|
IPL_autovector : in std_logic:='0';
|
|
CPU : in std_logic_vector(1 downto 0):="00"; -- 00->68000 01->68010 11->68020(only same parts - yet)
|
|
addr : buffer std_logic_vector(31 downto 0);
|
|
data_write : out std_logic_vector(15 downto 0);
|
|
nWr : out std_logic;
|
|
nUDS, nLDS : out std_logic;
|
|
nResetOut : out std_logic;
|
|
FC : out std_logic_vector(2 downto 0);
|
|
-- for debug
|
|
busstate : out std_logic_vector(1 downto 0); -- 00-> fetch code 10->read data 11->write data 01->no memaccess
|
|
skipFetch : out std_logic;
|
|
regin : buffer std_logic_vector(31 downto 0)
|
|
);
|
|
END COMPONENT;
|
|
|
|
|
|
SIGNAL cpuaddr : std_logic_vector(31 downto 0);
|
|
SIGNAL t_addr : std_logic_vector(31 downto 0);
|
|
-- SIGNAL data_write : std_logic_vector(15 downto 0);
|
|
-- SIGNAL t_data : std_logic_vector(15 downto 0);
|
|
SIGNAL r_data : std_logic_vector(15 downto 0);
|
|
SIGNAL cpuIPL : std_logic_vector(2 downto 0);
|
|
SIGNAL addr_akt_s : std_logic;
|
|
SIGNAL addr_akt_e : std_logic;
|
|
SIGNAL data_akt_s : std_logic;
|
|
SIGNAL data_akt_e : std_logic;
|
|
SIGNAL as_s : std_logic;
|
|
SIGNAL as_e : std_logic;
|
|
SIGNAL uds_s : std_logic;
|
|
SIGNAL uds_e : std_logic;
|
|
SIGNAL lds_s : std_logic;
|
|
SIGNAL lds_e : std_logic;
|
|
SIGNAL rw_s : std_logic;
|
|
SIGNAL rw_e : std_logic;
|
|
SIGNAL vpad : std_logic;
|
|
SIGNAL waitm : std_logic;
|
|
SIGNAL clkena_e : std_logic;
|
|
SIGNAL S_state : std_logic_vector(1 downto 0);
|
|
SIGNAL S_stated : std_logic_vector(1 downto 0);
|
|
SIGNAL decode : std_logic;
|
|
SIGNAL wr : std_logic;
|
|
SIGNAL uds_in : std_logic;
|
|
SIGNAL lds_in : std_logic;
|
|
SIGNAL state : std_logic_vector(1 downto 0);
|
|
SIGNAL clkena : std_logic;
|
|
-- SIGNAL n_clk : std_logic;
|
|
SIGNAL vmaena : std_logic;
|
|
SIGNAL vmaenad : std_logic;
|
|
SIGNAL state_ena : std_logic;
|
|
SIGNAL sync_state3 : std_logic;
|
|
SIGNAL eind : std_logic;
|
|
SIGNAL eindd : std_logic;
|
|
SIGNAL sel_autoconfig: std_logic;
|
|
SIGNAL autoconfig_out: std_logic;
|
|
SIGNAL autoconfig_data: std_logic_vector(3 downto 0);
|
|
SIGNAL sel_fast: std_logic;
|
|
SIGNAL slower : std_logic_vector(3 downto 0);
|
|
|
|
|
|
type sync_states is (sync0, sync1, sync2, sync3, sync4, sync5, sync6, sync7, sync8, sync9);
|
|
signal sync_state : sync_states;
|
|
|
|
SIGNAL datatg68 : std_logic_vector(15 downto 0);
|
|
SIGNAL ramcs : std_logic;
|
|
|
|
BEGIN
|
|
-- n_clk <= NOT clk;
|
|
-- wrd <= data_akt_e OR data_akt_s;
|
|
wrd <= wr;
|
|
addr <= cpuaddr;-- WHEN addr_akt_e='1' ELSE t_addr WHEN addr_akt_s='1' ELSE "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
|
|
-- data <= data_write WHEN data_akt_e='1' ELSE t_data WHEN data_akt_s='1' ELSE "ZZZZZZZZZZZZZZZZ";
|
|
-- datatg68 <= fromram WHEN sel_fast='1' ELSE r_data;
|
|
datatg68 <= fromram WHEN sel_fast='1' ELSE r_data WHEN sel_autoconfig='0' ELSE autoconfig_data&r_data(11 downto 0);
|
|
-- toram <= data_write;
|
|
|
|
sel_autoconfig <= '1' when cpuaddr(23 downto 19)="11101" AND autoconfig_out='1' ELSE '0'; --$E80000 - $EFFFFF
|
|
sel_fast <= '1' when state/="01" AND (cpuaddr(23 downto 21)="001" OR cpuaddr(23 downto 21)="010" OR cpuaddr(23 downto 21)="011" OR cpuaddr(23 downto 21)="100") ELSE '0'; --$200000 - $9FFFFF
|
|
-- sel_fast <= '1' when cpuaddr(23 downto 21)="001" OR cpuaddr(23 downto 21)="010" ELSE '0'; --$200000 - $5FFFFF
|
|
-- sel_fast <= '1' when cpuaddr(23 downto 19)="11111" ELSE '0'; --$F800000;
|
|
-- sel_fast <= '0'; --$200000 - $9FFFFF
|
|
-- sel_fast <= '1' when cpuaddr(24)='1' AND state/="01" ELSE '0'; --$1000000 - $1FFFFFF
|
|
ramcs <= NOT sel_fast;-- OR (state(0) AND NOT state(1));
|
|
-- cpuDMA <= NOT ramcs;
|
|
cpuDMA <= sel_fast;
|
|
cpustate <= clkena&slower(1 downto 0)&ramcs&state;
|
|
ramlds <= lds_in;
|
|
ramuds <= uds_in;
|
|
ramaddr(23 downto 0) <= cpuaddr(23 downto 0);
|
|
ramaddr(24) <= sel_fast;
|
|
ramaddr(31 downto 25) <= cpuaddr(31 downto 25);
|
|
|
|
|
|
pf68K_Kernel_inst: TG68KdotC_Kernel
|
|
generic map(
|
|
SR_Read => 2, --0=>user, 1=>privileged, 2=>switchable with CPU(0)
|
|
VBR_Stackframe => 2, --0=>no, 1=>yes/extended, 2=>switchable with CPU(0)
|
|
extAddr_Mode => 2, --0=>no, 1=>yes, 2=>switchable with CPU(1)
|
|
MUL_Mode => 2, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
|
|
DIV_Mode => 2 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
|
|
)
|
|
PORT MAP(
|
|
clk => clk, -- : in std_logic;
|
|
nReset => reset, -- : in std_logic:='1'; --low active
|
|
clkena_in => clkena, -- : in std_logic:='1';
|
|
-- data_in => r_data, -- : in std_logic_vector(15 downto 0);
|
|
-- data_in => data_read, -- : in std_logic_vector(15 downto 0);
|
|
data_in => datatg68, -- : in std_logic_vector(15 downto 0);
|
|
IPL => cpuIPL, -- : in std_logic_vector(2 downto 0):="111";
|
|
IPL_autovector => '1', -- : in std_logic:='0';
|
|
addr => cpuaddr, -- : buffer std_logic_vector(31 downto 0);
|
|
data_write => data_write, -- : out std_logic_vector(15 downto 0);
|
|
busstate => state, -- : buffer std_logic_vector(1 downto 0);
|
|
regin => open, -- : out std_logic_vector(31 downto 0);
|
|
nWr => wr, -- : out std_logic;
|
|
nUDS => uds_in,
|
|
nLDS => lds_in, -- : out std_logic;
|
|
nResetOut => nResetOut,
|
|
CPU => cpu,
|
|
skipFetch => skipFetch -- : out std_logic
|
|
);
|
|
|
|
PROCESS (clk)
|
|
BEGIN
|
|
autoconfig_data <= "1111";
|
|
IF memcfg(5 downto 4)/="00" THEN
|
|
CASE cpuaddr(6 downto 1) IS
|
|
WHEN "000000" => autoconfig_data <= "1110"; --normal card, add mem, no ROM
|
|
WHEN "000001" =>
|
|
CASE memcfg(5 downto 4) IS
|
|
WHEN "01" => autoconfig_data <= "0110"; --2MB
|
|
WHEN "10" => autoconfig_data <= "0111"; --4MB
|
|
WHEN OTHERS => autoconfig_data <= "0000"; --8MB
|
|
END CASE;
|
|
WHEN "001000" => autoconfig_data <= "1110"; --4626=icomp
|
|
WHEN "001001" => autoconfig_data <= "1101";
|
|
WHEN "001010" => autoconfig_data <= "1110";
|
|
WHEN "001011" => autoconfig_data <= "1101";
|
|
WHEN "010011" => autoconfig_data <= "1110"; --serial=1
|
|
WHEN OTHERS => null;
|
|
END CASE;
|
|
END IF;
|
|
IF rising_edge(clk) THEN
|
|
IF reset='0' THEN
|
|
autoconfig_out <= '1'; --autoconfig on
|
|
ELSIF enaWRreg='1' THEN
|
|
IF sel_autoconfig='1' AND state="11"AND uds_in='0' AND cpuaddr(6 downto 1)="100100" THEN
|
|
autoconfig_out <= '0'; --autoconfig off
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
PROCESS (clk)
|
|
BEGIN
|
|
IF rising_edge(clk) THEN
|
|
IF reset='0' THEN
|
|
vmaena <= '0';
|
|
vmaenad <= '0';
|
|
sync_state3 <= '0';
|
|
ELSIF ena7RDreg='1' THEN
|
|
vmaena <= '0';
|
|
sync_state3 <= '0';
|
|
IF state/="01" OR state_ena='1' THEN
|
|
vmaenad <= vmaena;
|
|
END IF;
|
|
IF sync_state=sync5 THEN
|
|
e <= '1';
|
|
END IF;
|
|
IF sync_state=sync3 THEN
|
|
sync_state3 <= '1';
|
|
END IF;
|
|
IF sync_state=sync9 THEN
|
|
e <= '0';
|
|
vmaena <= NOT vma;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
IF rising_edge(clk) THEN
|
|
S_stated <= S_state;
|
|
IF ena7WRreg='1' THEN
|
|
eind <= ein;
|
|
eindd <= eind;
|
|
CASE sync_state IS
|
|
WHEN sync0 => sync_state <= sync1;
|
|
WHEN sync1 => sync_state <= sync2;
|
|
WHEN sync2 => sync_state <= sync3;
|
|
WHEN sync3 => sync_state <= sync4;
|
|
vma <= vpa;
|
|
WHEN sync4 => sync_state <= sync5;
|
|
WHEN sync5 => sync_state <= sync6;
|
|
WHEN sync6 => sync_state <= sync7;
|
|
WHEN sync7 => sync_state <= sync8;
|
|
WHEN sync8 => sync_state <= sync9;
|
|
WHEN OTHERS => sync_state <= sync0;
|
|
vma <= '1';
|
|
END CASE;
|
|
IF eind='1' AND eindd='0' THEN
|
|
sync_state <= sync7;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
|
|
PROCESS (clk)
|
|
BEGIN
|
|
state_ena <= '0';
|
|
IF clkena_in='1' AND enaWRreg='1' AND (state="01" OR (ena7RDreg='1' AND clkena_e='1') OR ramready='1') THEN
|
|
clkena <= '1';
|
|
ELSE
|
|
clkena <= '0';
|
|
END IF;
|
|
IF state="01" THEN
|
|
state_ena <= '1';
|
|
END IF;
|
|
IF rising_edge(clk) THEN
|
|
IF clkena='1' THEN
|
|
slower <= "1000";
|
|
ELSE
|
|
slower(3 downto 0) <= enaWRreg&slower(3 downto 1);
|
|
-- slower(0) <= NOT slower(3) AND NOT slower(2);
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
PROCESS (clk, reset, state, as_s, as_e, rw_s, rw_e, uds_s, uds_e, lds_s, lds_e)
|
|
BEGIN
|
|
IF state="01" THEN
|
|
as <= '1';
|
|
rw <= '1';
|
|
uds <= '1';
|
|
lds <= '1';
|
|
ELSE
|
|
as <= (as_s AND as_e) OR sel_fast;
|
|
rw <= rw_s AND rw_e;
|
|
uds <= uds_s AND uds_e;
|
|
lds <= lds_s AND lds_e;
|
|
END IF;
|
|
IF reset='0' THEN
|
|
S_state <= "00";
|
|
as_s <= '1';
|
|
rw_s <= '1';
|
|
uds_s <= '1';
|
|
lds_s <= '1';
|
|
addr_akt_s <= '0';
|
|
data_akt_s <= '0';
|
|
ELSIF rising_edge(clk) THEN
|
|
IF ena7WRreg='1' THEN
|
|
as_s <= '1';
|
|
rw_s <= '1';
|
|
uds_s <= '1';
|
|
lds_s <= '1';
|
|
addr_akt_s <= '0';
|
|
data_akt_s <= '0';
|
|
CASE S_state IS
|
|
WHEN "00" => IF state/="01" AND sel_fast='0' THEN
|
|
uds_s <= uds_in;
|
|
lds_s <= lds_in;
|
|
S_state <= "01";
|
|
END IF;
|
|
WHEN "01" => as_s <= '0';
|
|
rw_s <= wr;
|
|
uds_s <= uds_in;
|
|
lds_s <= lds_in;
|
|
S_state <= "10";
|
|
t_addr <= cpuaddr;
|
|
-- t_data <= data_write;
|
|
WHEN "10" =>
|
|
addr_akt_s <= '1';
|
|
data_akt_s <= NOT wr;
|
|
r_data <= data_read;
|
|
IF waitm='0' OR (vma='0' AND sync_state=sync9) THEN
|
|
S_state <= "11";
|
|
ELSE
|
|
as_s <= '0';
|
|
rw_s <= wr;
|
|
uds_s <= uds_in;
|
|
lds_s <= lds_in;
|
|
END IF;
|
|
WHEN "11" =>
|
|
S_state <= "00";
|
|
WHEN OTHERS => null;
|
|
END CASE;
|
|
END IF;
|
|
END IF;
|
|
IF reset='0' THEN
|
|
as_e <= '1';
|
|
rw_e <= '1';
|
|
uds_e <= '1';
|
|
lds_e <= '1';
|
|
clkena_e <= '0';
|
|
addr_akt_e <= '0';
|
|
data_akt_e <= '0';
|
|
ELSIF rising_edge(clk) THEN
|
|
IF ena7RDreg='1' THEN
|
|
as_e <= '1';
|
|
rw_e <= '1';
|
|
uds_e <= '1';
|
|
lds_e <= '1';
|
|
clkena_e <= '0';
|
|
addr_akt_e <= '0';
|
|
data_akt_e <= '0';
|
|
CASE S_state IS
|
|
WHEN "00" => addr_akt_e <= '1';
|
|
cpuIPL <= IPL;
|
|
IF sel_fast='0' THEN
|
|
IF state/="01" THEN
|
|
as_e <= '0';
|
|
END IF;
|
|
rw_e <= wr;
|
|
data_akt_e <= NOT wr;
|
|
IF wr='1' THEN
|
|
uds_e <= uds_in;
|
|
lds_e <= lds_in;
|
|
END IF;
|
|
END IF;
|
|
WHEN "01" => addr_akt_e <= '1';
|
|
data_akt_e <= NOT wr;
|
|
as_e <= '0';
|
|
rw_e <= wr;
|
|
uds_e <= uds_in;
|
|
lds_e <= lds_in;
|
|
WHEN "10" => rw_e <= wr;
|
|
addr_akt_e <= '1';
|
|
data_akt_e <= NOT wr;
|
|
cpuIPL <= IPL;
|
|
waitm <= dtack;
|
|
WHEN OTHERS => --null;
|
|
clkena_e <= '1';
|
|
END CASE;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
END; |