Files
TSConf_MiST/rtl/T80/T80pa.vhd
2020-05-11 23:17:53 +08:00

213 lines
6.4 KiB
VHDL

--
-- Z80 compatible microprocessor core, preudo-asynchronous top level (by Sorgelig)
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized 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.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- 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 AUTHOR 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.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- File history :
--
-- v1.0: convert to preudo-asynchronous model with original Z80 timings.
--
-- v2.0: rewritten for more precise timings.
-- support for both CEN_n and CEN_p set to 1. Effective clock will be CLK/2.
--
-- v2.1: Output Address 0 during non-bus MCycle (fix ZX contention)
--
-- v2.2: Interrupt acknowledge cycle has been corrected
-- WAIT_n is broken in T80.vhd. Simulate correct WAIT_n locally.
--
-- v2.3: Output last used Address during non-bus MCycle seems more correct.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity T80pa is
generic(
Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
);
port(
RESET_n : in std_logic;
CLK : in std_logic;
CEN_p : in std_logic := '1';
CEN_n : in std_logic := '1';
WAIT_n : in std_logic := '1';
INT_n : in std_logic := '1';
NMI_n : in std_logic := '1';
BUSRQ_n : in std_logic := '1';
M1_n : out std_logic;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : out std_logic;
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
OUT0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255
A : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
REG : out std_logic_vector(207 downto 0) -- IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A
);
end T80pa;
architecture rtl of T80pa is
signal IntCycle_n : std_logic;
signal IntCycleD_n : std_logic_vector(1 downto 0);
signal IORQ : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal BUSAK : std_logic;
signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
signal CEN_pol : std_logic;
signal A_int : std_logic_vector(15 downto 0);
signal A_last : std_logic_vector(15 downto 0);
begin
A <= A_int when NoRead = '0' or Write = '1' else A_last;
BUSAK_n <= BUSAK;
u0 : work.T80
generic map(
Mode => Mode,
IOWait => 1
)
port map(
CEN => CEN_p and not CEN_pol,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => '1',
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK,
CLK_n => CLK,
A => A_int,
DInst => DI, -- valid at beginning of T3
DI => DI_Reg, -- latched at middle of T3
DO => DO,
REG => REG,
MC => MCycle,
TS => TState,
OUT0 => OUT0,
IntCycle_n => IntCycle_n
);
process(CLK)
begin
if rising_edge(CLK) then
if RESET_n = '0' then
WR_n <= '1';
RD_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
DI_Reg <= "00000000";
CEN_pol <= '0';
elsif CEN_p = '1' and CEN_pol = '0' then
CEN_pol <= '1';
if MCycle = "001" then
if TState = "010" then
IORQ_n <= '1';
MREQ_n <= '1';
RD_n <= '1';
end if;
else
if TState = "001" and IORQ = '1' then
WR_n <= not Write;
RD_n <= Write;
IORQ_n <= '0';
end if;
end if;
elsif CEN_n = '1' and CEN_pol = '1' then
if TState = "010" then
CEN_pol <= not WAIT_n;
else
CEN_pol <= '0';
end if;
if TState = "011" and BUSAK = '1' then
DI_Reg <= DI;
end if;
if MCycle = "001" then
if TState = "001" then
IntCycleD_n <= IntCycleD_n(0) & IntCycle_n;
RD_n <= not IntCycle_n;
MREQ_n <= not IntCycle_n;
IORQ_n <= IntCycleD_n(1);
A_last <= A_int;
end if;
if TState = "011" then
IntCycleD_n <= "11";
RD_n <= '1';
MREQ_n <= '0';
end if;
if TState = "100" then
MREQ_n <= '1';
end if;
else
if NoRead = '0' and IORQ = '0' then
if TState = "001" then
RD_n <= Write;
MREQ_n <= '0';
A_last <= A_int;
end if;
end if;
if TState = "010" then
WR_n <= not Write;
end if;
if TState = "011" then
WR_n <= '1';
RD_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
end if;
end if;
end if;
end if;
end process;
end;