Files
SharpMZ_MiSTer/mz80c/mz80c.vhd
2018-09-28 17:04:36 +01:00

1074 lines
52 KiB
VHDL

---------------------------------------------------------------------------------------------------------
--
-- Name: mz80c.vhd
-- Created: July 2018
-- Author(s): Philip Smart
-- Description: Sharp MZ series Personal Computer:
-- Models MZ-80K, MZ-80C, MZ-1200, MZ-80A, MZ-700, MZ-800
--
-- This module is the main (top level) container for the Personal MZ Computer
-- Emulation.
--
-- The design tries to work from top-down, where components which are common
-- to the Business and Personal MZ series are at the top (ie. main memory,
-- ROM, CPU), drilling down two trees, MZ-80B (Business), MZ-80C (Personal)
-- to the machine specific modules and components. Some components are common
-- by their nature (ie. 8255 PIO) but these are instantiated within the lower
-- tree branch as their design use is less generic.
--
-- The tree is as follows;-
--
-- (emu) sharpmz.vhd (mz80c) -> mz80c.vhd
-- | -> mz80c_video.vhd
-- | -> pcg.vhd
-- | -> cmt.vhd (this may move to common and be shared with mz80b)
-- | -> keymatrix.vhd (common)
-- | -> pll.v (common)
-- | -> clkgen.vhd (common)
-- | -> T80 (common)
-- | -> i8255 (common)
-- | -> i8253 (common)
-- | -> dpram.vhd (common)
-- | -> dprom.vhd (common)
-- | -> mctrl.vhd (common)
-- sys_top.sv (emu) -> (emu) sharpmz.vhd (hps_io) -> hps_io.sv
-- |
-- (emu) sharpmz.vhd (mz80b) -> mz80b.vhd (under development)
--
--
--
-- Credits:
-- Copyright: (c) 2018 Philip Smart <philip.smart@net2net.org>
--
-- History: July 2018 - Initial module written.
--
---------------------------------------------------------------------------------------------------------
-- 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;
library pkgs;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use pkgs.clkgen_pkg.all;
use pkgs.mctrl_pkg.all;
entity mz80c is
PORT (
-- Clocks
CLKBUS : in std_logic_vector(CLKBUS_WIDTH); -- Clock signals created by clkgen module.
-- Resets.
SYSTEM_RESET : in std_logic;
-- Z80 CPU
T80_RST_n : in std_logic;
T80_CLK : in std_logic;
T80_CLKEN : out std_logic;
T80_WAIT_n : out std_logic;
T80_INT_n : out std_logic;
T80_NMI_n : out std_logic;
T80_BUSRQ_n : out std_logic;
T80_M1_n : in std_logic;
T80_MREQ_n : in std_logic;
T80_IORQ_n : in std_logic;
T80_RD_n : in std_logic;
T80_WR_n : in std_logic;
T80_RFSH_n : in std_logic;
T80_HALT_n : in std_logic;
T80_BUSAK_n : in std_logic;
T80_A16 : in std_logic_vector(15 downto 0);
T80_DI : out std_logic_vector(7 downto 0);
T80_DO : in std_logic_vector(7 downto 0);
-- Chip selects to common resources.
CS_ROM_n : out std_logic;
CS_RAM_n : out std_logic;
-- Audio.
AUDIO_L : out std_logic;
AUDIO_R : out std_logic;
-- Video signals.
R : out std_logic;
G : out std_logic;
B : out std_logic;
HSYNC_n : out std_logic;
VSYNC_n : out std_logic;
HBLANK : out std_logic;
VBLANK : out std_logic;
-- Different operations modes.
CONFIG : in std_logic_vector(CONFIG_WIDTH);
-- I/O -- I/O down to the core.
PS2_KEY : in std_logic_vector(10 downto 0);
-- Cassette magnetic tape signals.
CMTBUS : out std_logic_vector(CMTBUS_WIDTH);
-- HPS Interface
IOCTL_DOWNLOAD : in std_logic; -- HPS Downloading to FPGA.
IOCTL_UPLOAD : in std_logic; -- HPS Uploading from FPGA.
IOCTL_CLK : in std_logic; -- HPS I/O Clock.
IOCTL_WR : in std_logic; -- HPS Write Enable to FPGA.
IOCTL_RD : in std_logic; -- HPS Read Enable from FPGA.
IOCTL_ADDR : in std_logic_vector(24 downto 0); -- HPS Address in FPGA to write into.
IOCTL_DOUT : in std_logic_vector(15 downto 0); -- HPS Data to be written into FPGA.
IOCTL_DIN : out std_logic_vector(15 downto 0); -- HPS Data to be read into HPS.
-- Debug Status Leds
DEBUG_STATUS_LEDS : out std_logic_vector(111 downto 0) -- 112 leds to display status.
);
end mz80c;
architecture rtl of mz80c is
--
-- Buffered output signals.
--
signal HBLANKi : std_logic;
signal VBLANKi : std_logic;
signal BLNK_n : std_logic;
signal Ri : std_logic;
signal Gi : std_logic;
signal Bi : std_logic;
signal HSYNC_ni : std_logic;
signal VSYNC_ni : std_logic;
-- Parent signals.
--
signal MZ_RESET : std_logic;
signal MZ_MEMORY_SWAP : std_logic;
signal MZ_LOW_RAM_ENABLE : std_logic;
signal MZ_HIGH_RAM_ENABLE : std_logic;
signal MZ_HIGH_RAM_INHIBIT : std_logic;
signal MZ_INHIBIT_RESET : std_logic;
signal MZ_GRAM_ENABLE : std_logic;
signal i8255_PA_I : std_logic_vector(7 downto 0);
signal i8255_PA_O : std_logic_vector(7 downto 0);
signal i8255_PB_I : std_logic_vector(7 downto 0);
signal i8255_PB_O : std_logic_vector(7 downto 0);
signal i8255_PC_I : std_logic_vector(7 downto 0);
signal i8255_PC_O : std_logic_vector(7 downto 0);
--
-- System Clocks
--
signal MZ_RTC_CASCADE_CLK : std_logic; -- i8253 subdivision of the 31.250KHz clock creating 1s/1Hz timebase.
--
-- Decodes, misc
--
signal CMTBUSi : std_logic_vector(CMTBUS_WIDTH);
signal CMT_READBITi : std_logic;
signal CMT_MOTORi : std_logic;
signal CS_D_n : std_logic;
signal CS_E_n : std_logic;
signal CS_E0_n : std_logic;
signal CS_E1_n : std_logic;
signal CS_E2_n : std_logic;
signal CS_ESWP_n : std_logic;
signal CS_G_n : std_logic;
signal DO367 : std_logic_vector(7 downto 0);
signal CS_BANKSWITCH_n : std_logic;
signal CS_MZ700BS_n : std_logic;
signal CS_IO_E0_n : std_logic;
signal CS_IO_E1_n : std_logic;
signal CS_IO_E2_n : std_logic;
signal CS_IO_E3_n : std_logic;
signal CS_IO_E4_n : std_logic;
signal CS_IO_E5_n : std_logic;
signal CS_IO_E6_n : std_logic;
signal CS_IO_E8_n : std_logic;
signal CS_IO_E9_n : std_logic;
signal CS_IO_GRAM_n : std_logic;
signal CS_ROM_ni : std_logic;
signal CS_RAM_ni : std_logic;
signal VGATE_n : std_logic; -- Video Outpu Enable
signal VRAMDO : std_logic_vector(7 downto 0);
signal IOCTL_DIN_VIDEO : std_logic_vector(15 downto 0);
signal IOCTL_DIN_KEY : std_logic_vector(15 downto 0);
signal IOCTL_DIN_CMT : std_logic_vector(15 downto 0);
signal T80_IWR_n : std_logic;
signal T80_INT_ni : std_logic;
--
-- PPI
--
signal DOPPI : std_logic_vector(7 downto 0);
signal INTMSK : std_logic; -- EISUU/KANA LED
--
-- PIT
--
signal DOPIT : std_logic_vector(7 downto 0);
signal SOUND_ENABLE : std_logic;
signal SOUND_PULSE_X2 : std_logic;
signal SOUND : std_logic;
signal INTX : std_logic;
--
-- CURSOR blink
--
signal CURSOR_RESET : std_logic;
signal CURSOR_CLK : std_logic;
signal CURSOR_BLINK : std_logic;
signal CCOUNT : std_logic_vector(4 downto 0);
--
-- Remote
--
signal SNS : std_logic;
signal MTR : std_logic;
signal M_ON : std_logic;
signal SENSE0 : std_logic;
signal SWIN : std_logic_vector(3 downto 0);
--
-- Debug
--
signal PULSECPU : std_logic;
--
-- Components
--
component i8255
port (
RESET : in std_logic;
CLK : in std_logic;
ENA : in std_logic; -- (CPU) clk enable
ADDR : in std_logic_vector(1 downto 0); -- A1-A0
DI : in std_logic_vector(7 downto 0); -- D7-D0
DO : out std_logic_vector(7 downto 0);
CS_n : in std_logic;
RD_n : in std_logic;
WR_n : in std_logic;
PA_I : in std_logic_vector(7 downto 0);
PA_O : out std_logic_vector(7 downto 0);
PA_O_OE_n : out std_logic_vector(7 downto 0);
PB_I : in std_logic_vector(7 downto 0);
PB_O : out std_logic_vector(7 downto 0);
PB_O_OE_n : out std_logic_vector(7 downto 0);
PC_I : in std_logic_vector(7 downto 0);
PC_O : out std_logic_vector(7 downto 0);
PC_O_OE_n : out std_logic_vector(7 downto 0)
);
end component;
component i8253
Port (
RST : in std_logic;
CLK : in std_logic;
A : in std_logic_vector(1 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
CS_n : in std_logic;
WR_n : in std_logic;
RD_n : in std_logic;
CLK0 : in std_logic;
GATE0 : in std_logic;
OUT0 : out std_logic;
CLK1 : in std_logic;
GATE1 : in std_logic;
OUT1 : out std_logic;
CLK2 : in std_logic;
GATE2 : in std_logic;
OUT2 : out std_logic
);
end component;
component mz80c_video is
Port (
RST_n : in std_logic; -- Reset
-- Different operations modes.
CONFIG : in std_logic_vector(CONFIG_WIDTH);
-- Clocks
CLKBUS : in std_logic_vector(CLKBUS_WIDTH); -- Clock signals created by clkgen module.
-- CPU Signals
T80_A : in std_logic_vector(13 downto 0); -- CPU Address Bus
T80_RD_n : in std_logic; -- CPU Read Signal
T80_WR_n : in std_logic; -- CPU Write Signal
T80_MREQ_n : in std_logic; -- CPU Memory Request
T80_BUSACK_n : in std_logic; -- CPU Bus Acknowledge
T80_WAIT_n : out std_logic; -- CPU Wait Request
T80_DI : in std_logic_vector(7 downto 0); -- CPU Data Bus in
T80_DO : out std_logic_vector(7 downto 0); -- CPU Data Bus out
-- Selects.
CS_D_n : in std_logic; -- VRAM Select
CS_E_n : in std_logic; -- Peripherals Select
CS_G_n : in std_logic; -- GRAM Select
CS_IO_GRAM_n : in std_logic; -- GRAM IO Select range E8 - EF
-- Video Signals
VGATE_n : in std_logic; -- Video Output Control
HBLANK : out std_logic; -- Horizontal Blanking
VBLANK : out std_logic; -- Vertical Blanking
HSYNC_n : out std_logic; -- Horizontal Sync
VSYNC_n : out std_logic; -- Vertical Sync
ROUT : out std_logic; -- Red Output
GOUT : out std_logic; -- Green Output
BOUT : out std_logic; -- Green Output
-- HPS Interface
IOCTL_DOWNLOAD : in std_logic; -- HPS Downloading to FPGA.
IOCTL_UPLOAD : in std_logic; -- HPS Uploading from FPGA.
IOCTL_CLK : in std_logic; -- HPS I/O Clock.
IOCTL_WR : in std_logic; -- HPS Write Enable to FPGA.
IOCTL_RD : in std_logic; -- HPS Read Enable to FPGA.
IOCTL_ADDR : in std_logic_vector(24 downto 0); -- HPS Address in FPGA to write into.
IOCTL_DOUT : in std_logic_vector(15 downto 0); -- HPS Data to be written into FPGA.
IOCTL_DIN : out std_logic_vector(15 downto 0) -- HPS Data to be read into HPS.
);
end component;
component keymatrix
Port (
RST_n : in std_logic;
-- i8255
PA : in std_logic_vector(3 downto 0);
PB : out std_logic_vector(7 downto 0);
STALL : in std_logic;
-- PS/2 Keyboard Data
PS2_KEY : in std_logic_vector(10 downto 0); -- PS2 Key data.
-- Different operations modes.
CONFIG : in std_logic_vector(CONFIG_WIDTH);
-- Clock signals created by this module.
CLKBUS : in std_logic_vector(CLKBUS_WIDTH);
-- HPS Interface
IOCTL_DOWNLOAD : in std_logic; -- HPS Downloading to FPGA.
IOCTL_UPLOAD : in std_logic; -- HPS Uploading from FPGA.
IOCTL_CLK : in std_logic; -- HPS I/O Clock.
IOCTL_WR : in std_logic; -- HPS Write Enable to FPGA.
IOCTL_RD : in std_logic; -- HPS Read Enable to FPGA.
IOCTL_ADDR : in std_logic_vector(24 downto 0); -- HPS Address in FPGA to write into.
IOCTL_DOUT : in std_logic_vector(15 downto 0); -- HPS Data to be written into FPGA.
IOCTL_DIN : out std_logic_vector(15 downto 0) -- HPS Data to be read into HPS.
);
end component;
component cmt
Port (
-- HPS Bus
RST : in std_logic;
-- Clock signals created by this module.
CLKBUS : in std_logic_vector(CLKBUS_WIDTH);
-- Different operations modes.
CONFIG : in std_logic_vector(CONFIG_WIDTH);
-- Cassette magnetic tape signals.
CMTBUS : out std_logic_vector(CMTBUS_WIDTH);
CMT_READBIT : in std_logic;
CMT_MOTOR : in std_logic;
-- HPS Interface
IOCTL_DOWNLOAD : in std_logic; -- HPS Downloading to FPGA.
IOCTL_UPLOAD : in std_logic; -- HPS Uploading from FPGA.
IOCTL_CLK : in std_logic; -- HPS I/O Clock.
IOCTL_WR : in std_logic; -- HPS Write Enable to FPGA.
IOCTL_RD : in std_logic; -- HPS Read Enable from FPGA.
IOCTL_ADDR : in std_logic_vector(24 downto 0); -- HPS Address in FPGA to write into.
IOCTL_DOUT : in std_logic_vector(15 downto 0); -- HPS Data to be written into FPGA.
IOCTL_DIN : out std_logic_vector(15 downto 0); -- HPS Data to be read into HPS.
-- Debug Status Leds
DEBUG_STATUS_LEDS : out std_logic_vector(23 downto 0) -- 24 leds to display cmt internal status.
);
end component;
begin
--
-- Instantiation
--
PPI0 : i8255
port map (
RESET => MZ_RESET,
CLK => CLKBUS(CKCPU),
ENA => '1',
ADDR => T80_A16(1 downto 0),
DI => T80_DO,
DO => DOPPI,
CS_n => CS_E0_n,
RD_n => T80_RD_n,
WR_n => T80_WR_n,
PA_I => i8255_PA_O,
PA_O => i8255_PA_O,
PA_O_OE_n => open,
PB_I => i8255_PB_I,
PB_O => open,
PB_O_OE_n => open,
PC_I => i8255_PC_I,
PC_O => i8255_PC_O,
PC_O_OE_n => open
);
PIT0 : i8253
port map (
RST => MZ_RESET,
CLK => CLKBUS(CKCPU),
A => T80_A16(1 downto 0),
DI => T80_DO,
DO => DOPIT,
CS_n => CS_E1_n,
WR_n => T80_WR_n,
RD_n => T80_RD_n,
CLK0 => CLKBUS(CKSOUND),
GATE0 => SOUND_ENABLE,
OUT0 => SOUND_PULSE_X2,
CLK1 => CLKBUS(CKRTC),
GATE1 => '1',
OUT1 => MZ_RTC_CASCADE_CLK,
CLK2 => MZ_RTC_CASCADE_CLK,
GATE2 => '1',
OUT2 => INTX
);
VIDEO0 : mz80c_video
port map (
RST_n => T80_RST_n, -- Reset
-- Different operations modes.
CONFIG => CONFIG,
-- Clocks
CLKBUS => CLKBUS, -- Clock signals created by clkgen module.
-- CPU Signals
T80_A => T80_A16(13 downto 0), -- CPU Address Bus
T80_RD_n => T80_RD_n, -- CPU Read Signal
T80_WR_n => T80_WR_n, -- CPU Write Signal
T80_MREQ_n => T80_MREQ_n, -- CPU Memory Request
T80_BUSACK_n => T80_BUSAK_n, -- CPU Bus Acknowledge
T80_WAIT_n => T80_WAIT_n, -- CPU Wait Request
T80_DI => T80_DO, -- CPU Data Bus(in)
T80_DO => VRAMDO, -- CPU Data Bus(out)
-- Selects.
CS_D_n => CS_D_n, -- VRAM Select
CS_E_n => CS_E_n, -- Peripherals Select
CS_G_n => CS_G_n, -- GRAM Select
CS_IO_GRAM_n => CS_IO_GRAM_n, -- GRAM IO Select range E8 - EF
-- Video Signals
VGATE_n => VGATE_n, -- Video Output Control
HBLANK => HBLANKi, -- Horizontal Blanking
VBLANK => VBLANKi, -- Vertical Blanking
HSYNC_n => HSYNC_ni, -- Horizontal Sync
VSYNC_n => VSYNC_ni, -- Vertical Sync
ROUT => Ri, -- Red Output
GOUT => Gi, -- Green Output
BOUT => Bi, -- Blue Output
-- HPS Interface
IOCTL_DOWNLOAD => IOCTL_DOWNLOAD,
IOCTL_UPLOAD => IOCTL_UPLOAD,
IOCTL_CLK => IOCTL_CLK, -- HPS I/O Clock.
IOCTL_WR => IOCTL_WR, -- HPS Write Enable to FPGA.
IOCTL_RD => IOCTL_RD, -- HPS Read Enable to FPGA.
IOCTL_ADDR => IOCTL_ADDR, -- HPS Address in FPGA to write into.
IOCTL_DOUT => IOCTL_DOUT, -- HPS Data to be written into FPGA.
IOCTL_DIN => IOCTL_DIN_VIDEO -- HPS Data to be sent to HPS.
);
KEYS : keymatrix
port map (
RST_n => T80_RST_n,
-- i8255
PA => i8255_PA_O(3 downto 0),
PB => i8255_PB_I,
STALL => i8255_PA_O(4),
-- PS/2 Keyboard Data
PS2_KEY => PS2_KEY, -- PS2 Key data.
-- Different operations modes.
CONFIG => CONFIG,
-- Clock signals created by this module.
CLKBUS => CLKBUS,
-- HPS Interface
IOCTL_DOWNLOAD => IOCTL_DOWNLOAD, -- HPS Downloading to FPGA.
IOCTL_UPLOAD => IOCTL_UPLOAD, -- HPS Uploading from FPGA.
IOCTL_CLK => IOCTL_CLK, -- HPS I/O Clock.
IOCTL_WR => IOCTL_WR, -- HPS Write Enable to FPGA.
IOCTL_RD => IOCTL_RD, -- HPS Read Enable from FPGA.
IOCTL_ADDR => IOCTL_ADDR, -- HPS Address in FPGA to write into.
IOCTL_DOUT => IOCTL_DOUT, -- HPS Data to be written into FPGA.
IOCTL_DIN => IOCTL_DIN_KEY -- HPS Data to be sent to HPS.
);
TAPE0 : cmt
port map (
RST => MZ_RESET,
-- Clock signals needed by this module.
CLKBUS => CLKBUS,
-- Different operations modes.
CONFIG => CONFIG,
-- Cassette magnetic tape signals.
CMTBUS => CMTBUSi, -- Output is fed from CMT into MCTRL and MZ..
CMT_READBIT => CMT_READBITi,
CMT_MOTOR => CMT_MOTORi,
-- HPS Interface
IOCTL_DOWNLOAD => IOCTL_DOWNLOAD, -- HPS Downloading to FPGA.
IOCTL_UPLOAD => IOCTL_UPLOAD, -- HPS Uploading from FPGA.
IOCTL_CLK => IOCTL_CLK, -- HPS I/O Clock.
IOCTL_WR => IOCTL_WR, -- HPS Write Enable to FPGA.
IOCTL_RD => IOCTL_RD, -- HPS Read Enable from FPGA.
IOCTL_ADDR => IOCTL_ADDR, -- HPS Address in FPGA to write into.
IOCTL_DOUT => IOCTL_DOUT, -- HPS Data to be written into FPGA.
IOCTL_DIN => IOCTL_DIN_CMT, -- HPS Data to be sent to HPS.
-- Debug Status Leds
DEBUG_STATUS_LEDS=> DEBUG_STATUS_LEDS(63 downto 40) -- 24 leds to display cmt internal status.
);
-- Parent signals onto local wires.
--
T80_BUSRQ_n <= '1';
T80_NMI_n <= '1';
T80_CLKEN <= '1';
MZ_RESET <= SYSTEM_RESET;
--
-- MZ-80A - Mask interrupt from 8253 if INTMSK low.
-- MZ-80K - Interrupt is from 8253 direct.
T80_INT_ni <= '0' when ((CONFIG(MZ_A)='1' or CONFIG(MZ700) = '1') and INTX='1' and INTMSK='1') or ((CONFIG(MZ_KC)='1' and INTX='1'))
else '1';
T80_INT_n <= T80_INT_ni;
--
-- Control Signals
--
--T80_IWR_n <= T80_IORQ_n or T80_WR_n;
-- PIO and PIT signals.
--
i8255_PC_I(7) <= VBLANKi; -- V-BLANK signal
i8255_PC_I(6) <= CURSOR_BLINK; -- Cursor Blink
i8255_PC_I(5) <= CMTBUSi(WRITEBIT); -- MZ in from CMT out.
i8255_PC_I(4) <= CMTBUSi(SENSE); -- CMT Read/Write status.
i8255_PC_I(3) <= CMT_MOTORi; -- Motor active status.
i8255_PC_I(2) <= INTMSK; -- Red/Green LED MZ80K, Interrupt Mask MZ80A
i8255_PC_I(1) <= CMT_READBITi; -- MZ out to CMT in
i8255_PC_I(0) <= VGATE_n; -- Video Output Enable
CMT_MOTORi <= i8255_PC_O(3);
CMT_READBITi <= i8255_PC_O(1);
CURSOR_RESET <= i8255_PA_O(7);
INTMSK <= i8255_PC_O(2);
VGATE_n <= i8255_PC_O(0);
CMTBUS <= CMTBUSi;
--
-- Data Bus Multiplexing, plex all the output devices onto the Z80 Data Input according to the CS.
--
T80_DI <= DOPPI when CS_E0_n ='0' and T80_RD_n = '0' -- Read from 8255
else
DOPIT when CS_E1_n ='0' and T80_RD_n = '0' -- Read from 8253
else
DO367 when CS_E2_n ='0' and T80_RD_n = '0' -- Read from LS367
else
VRAMDO when CS_D_n ='0' and T80_RD_n = '0' -- Read from VRAM
else
VRAMDO when CS_G_n ='0' and T80_RD_n = '0' -- Read from GRAM
else
(others=>'1');
-- HPS Bus Multiplexing for reads.
IOCTL_DIN <= IOCTL_DIN_VIDEO when IOCTL_ADDR(24 downto 16)="000000100" -- Video RAM
else
IOCTL_DIN_VIDEO when IOCTL_ADDR(24 downto 16)="000001000" -- PCG
else
IOCTL_DIN_KEY when IOCTL_ADDR(24 downto 16)="000000011"
else
IOCTL_DIN_CMT when IOCTL_ADDR(24 downto 16)="000000101" or IOCTL_ADDR(24 downto 16)="000000110"
else
"1100110010101010"; -- Test pattern.
--
-- Chip Select map.
--
-- 0000 - 0FFF = CS_ROM_n : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
-- 1000 - CFFF = CS_RAM_n : MZ80K/A/700 = RAM
-- C000 - CFFF = CS_ROM_n : MZ80A = Monitor ROM (MZ80A rom swap)
-- D000 - D7FF = CS_D_n : MZ80K/A/700 = VRAM
-- D800 - DFFF = CS_D_n : MZ700 = Colour VRAM (MZ700)
-- E000 - E003 = CS_E0_n : MZ80K/A/700 = 8255
-- E004 - E007 = CS_E1_n : MZ80K/A/700 = 8253
-- E008 - E00B = CS_E2_n : MZ80K/A/700 = LS367
-- E00C - E00F = CS_ESWP_n : MZ80A = Memory Swap (MZ80A)
-- E010 - E013 = CS_ESWP_n : MZ80A = Reset Memory Swap (MZ80A)
-- E014 = CS_E5_n : MZ80A/700 = Normat CRT display
-- E015 = CS_E6_n : MZ80A/700 = Reverse CRT display
-- E200 - E2FF = : MZ80A/700 = VRAM roll up/roll down.
-- E800 - EFFF = : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
-- F000 - F7FF = : MZ80K/A/700 = Floppy Disk interface.
-- F800 - FFFF = : MZ80K/A/700 = Floppy Disk interface.
--
-- C000 - CFFF
--CS_C_n <= '0' when ( (T80_A16(15 downto 12)="1100" and T80_MREQ_n = '0' and MZ_GRAM_ENABLE = '0')
-- )
-- else '1';
-- D000 - DFFF
CS_D_n <= '0' when ( (T80_A16(15 downto 12)="1101" and T80_MREQ_n = '0' and MZ_GRAM_ENABLE = '0')
and
( (CONFIG(MZ_KC)='1' or CONFIG(MZ_A)='1')
or
(CONFIG(MZ700)='1' and MZ_HIGH_RAM_ENABLE='0' and MZ_HIGH_RAM_INHIBIT='0')
)
)
else '1';
-- E000 - EFFF
CS_E_n <= '0' when ( (T80_A16(15 downto 12)="1110" and T80_MREQ_n = '0' and MZ_GRAM_ENABLE = '0')
and
( (CONFIG(MZ_KC)='1' or CONFIG(MZ_A)='1')
or
(CONFIG(MZ700)='1' and MZ_HIGH_RAM_ENABLE='0' and MZ_HIGH_RAM_INHIBIT='0')
)
)
else '1';
-- Sub division E000 - E200
CS_E0_n <= '0' when CS_E_n='0' and T80_A16(11 downto 2)="0000000000" -- 8255
else '1';
CS_E1_n <= '0' when CS_E_n='0' and T80_A16(11 downto 2)="0000000001" -- 8253
else '1';
CS_E2_n <= '0' when CS_E_n='0' and T80_A16(11 downto 2)="0000000010" -- LS367
else '1';
CS_ESWP_n <= '0' when CONFIG(MZ_A)='1' and CS_E_n='0' and T80_RD_n='0' and T80_A16(11 downto 5)="0000000" -- ROM/RAM Swap
else '1';
-- F000 - FFFF
--CS_F_n <= '0' when ( (T80_A16(15 downto 12)="1111" and T80_MREQ_n = '0' and MZ_GRAM_ENABLE = '0')
-- and
-- ( (CONFIG(MZ_KC)='1' or CONFIG(MZ_A)='1')
-- or
-- (CONFIG(MZ700)='1' and MZ_HIGH_RAM_ENABLE='0' and MZ_HIGH_RAM_INHIBIT='0')
-- )
-- )
-- else '1';
-- C000 - FFFF
CS_G_n <= '0' when MZ_GRAM_ENABLE = '1' and T80_A16(15 downto 14) = "11" and T80_MREQ_n='0'
else '1';
--
CS_ROM_ni <= '0' when ( ( (T80_A16(15 downto 12)="0000")
and
( (CONFIG(MZ_A)='1' and MZ_MEMORY_SWAP='0') -- 0000 -> 0FFF MZ80A ROM
or
(CONFIG(MZ_KC)='1') -- 0000 -> 0FFF MZ80K ROM
or
(CONFIG(MZ700)='1' and MZ_LOW_RAM_ENABLE='0') -- 0000 -> 0FFF MZ700 ROM
)
)
or
( (T80_A16(15 downto 12)="1100")
and
( (CONFIG(MZ_A)='1' and MZ_GRAM_ENABLE='0' and MZ_MEMORY_SWAP='1') -- C000 -> CFFF MZ80A ROM memory swapped.
)
)
or
( T80_A16(15 downto 11) = "11101" -- E800 -> EFFF User ROM memory.
and
(CONFIG(USERROM) and CONFIG(CURRENTMACHINE)) /= "00000000" -- Active machine has the user rom enabled.
and
MZ_GRAM_ENABLE = '0' -- Graphics RAM is not enabled.
and
(MZ_HIGH_RAM_ENABLE = '0' or (MZ_HIGH_RAM_ENABLE = '1' and MZ_HIGH_RAM_INHIBIT = '1')) -- High RAM is not enabled.
)
or
( T80_A16(15 downto 12) = "1111"
and
(CONFIG(FDCROM) and CONFIG(CURRENTMACHINE)) /= "00000000" -- Active machine has the fdc rom enabled.
and
MZ_GRAM_ENABLE = '0' -- Graphics RAM is not enabled.
and
(MZ_HIGH_RAM_ENABLE = '0' or (MZ_HIGH_RAM_ENABLE = '1' and MZ_HIGH_RAM_INHIBIT = '1')) -- F000 -> FFFF FDC ROM memory.
)
) and T80_MREQ_n='0'
else '1';
CS_ROM_n <= CS_ROM_ni;
--
CS_RAM_ni <= '0' when ( ( (T80_A16(15 downto 12)="0000")
and
( (CONFIG(MZ_A)='1' and MZ_MEMORY_SWAP='1') -- 0000 -> 0FFF MZ80A memory swapped.
or
(CONFIG(MZ700)='1' and MZ_LOW_RAM_ENABLE='1') -- 0000 -> 0FFF MZ700 Low Ram Enabled.
)
)
or
(T80_A16(15 downto 12)="0001" or T80_A16(15 downto 12)="0010" or -- 1000 -> 2FFF
T80_A16(15 downto 12)="0011" or T80_A16(15 downto 12)="0100" or -- 3000 -> 4FFF
T80_A16(15 downto 12)="0101" or T80_A16(15 downto 12)="0110" or -- 5000 -> 6FFF
T80_A16(15 downto 12)="0111" or T80_A16(15 downto 12)="1000" or -- 7000 -> 8FFF
T80_A16(15 downto 12)="1001" or T80_A16(15 downto 12)="1010" or -- 9000 -> AFFF
T80_A16(15 downto 12)="1011") -- B000 -> BFFF
or
( (MZ_GRAM_ENABLE = '0')
and -- Higher memory only available when GRAM not active.
( ( (T80_A16(15 downto 12)="1100")
and
( (CONFIG(MZ_A)='1' and MZ_MEMORY_SWAP='0') -- C000 -> CFFF MZ80A memory not swapped.
or
(CONFIG(MZ_KC)='1') -- C000 -> CFFF MZ80K
or
(CONFIG(MZ700)='1') -- C000 -> CFFF MZ700
)
)
or
( (CONFIG(MZ700)='1' and MZ_HIGH_RAM_ENABLE='1' and MZ_HIGH_RAM_INHIBIT='0') -- D000 -> FFFF MZ700 Ram Enabled.
and
( (T80_A16(15 downto 12)="1101" or T80_A16(15 downto 12)="1110"
or
T80_A16(15 downto 12)="1111")
)
)
)
)
)
and T80_MREQ_n='0'
else '1';
CS_RAM_n <= CS_RAM_ni;
--
-- IO Select Map.
-- E0 - E6 are used by the MZ700 to perform memory bank switching.
-- E8 - EF are Graphics enhancements.
-- E8 switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. This overrides all MZ700 page switching functions.
-- E9 switches out the graphics ram and returns to previous state.
-- EA,<val> sets the graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
-- EB,<val> sets the Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
-- EC,<val> sets the Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
-- ED,<val> sets the Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
--
CS_BANKSWITCH_n <= '0' when T80_IORQ_n='0' and T80_WR_n = '0' and T80_A16(7 downto 4) = "1110"
else '1';
CS_MZ700BS_n <= '0' when CONFIG(MZ700)='1' and CS_BANKSWITCH_n = '0' and T80_A16(3) = '0'
else '1';
CS_IO_GRAM_n <= '0' when CS_BANKSWITCH_n = '0' and T80_A16(3) = '1' -- IO E8-EF Graphics framebuffer.
else '1';
CS_IO_E0_n <= '0' when CS_MZ700BS_n = '0' and T80_A16(2 downto 0) = "000" -- IO E0 = 0000 -> 0FFF RAM, D000 -> FFFF No Action
else '1';
CS_IO_E1_n <= '0' when CS_MZ700BS_n = '0' and T80_A16(2 downto 0) = "001" -- IO E1 = 0000 -> 0FFF No Action, D000 -> FFFF RAM
else '1';
CS_IO_E2_n <= '0' when CS_MZ700BS_n = '0' and T80_A16(2 downto 0) = "010" -- IO E2 = 0000 -> 0FFF ROM, D000 -> FFFF No Action
else '1';
CS_IO_E3_n <= '0' when CS_MZ700BS_n = '0' and T80_A16(2 downto 0) = "011" -- IO E3 = 0000 -> 0FFF No Action, D000 -> FFFF VRAM + IO Ports
else '1';
CS_IO_E4_n <= '0' when CS_MZ700BS_n = '0' and T80_A16(2 downto 0) = "100" -- IO E4 = 0000 -> 0FFF ROM, D000 -> FFFF VRAM + IO Ports
else '1';
CS_IO_E5_n <= '0' when CS_MZ700BS_n = '0' and T80_A16(2 downto 0) = "101" -- IO E5 = 0000 -> 0FFF No Action, D000 -> FFFF Inhibit
else '1';
CS_IO_E6_n <= '0' when CS_MZ700BS_n = '0' and T80_A16(2 downto 0) = "110" -- IO E6 = 0000 -> 0FFF No Action, D000 -> FFFF Unlock Inhibit
else '1';
CS_IO_E8_n <= '0' when CS_IO_GRAM_n = '0' and T80_A16(2 downto 0) = "000" -- IO E8 = C000 -> FFFF map to Graphics RAM.
else '1';
CS_IO_E9_n <= '0' when CS_IO_GRAM_n = '0' and T80_A16(2 downto 0) = "001" -- IO E9 = C000 -> FFFF revert to previous mode.
else '1';
-- MZ80A/1200 Memory Swap - swap rom out and ram in.
--
process( MZ_RESET, CS_ESWP_n ) begin
if(MZ_RESET = '1') then
MZ_MEMORY_SWAP <= '0';
elsif(CS_ESWP_n'event and CS_ESWP_n='0') then
if(T80_A16(4 downto 2) = "011") then
MZ_MEMORY_SWAP <= '1';
elsif(T80_A16(4 downto 2) = "100") then
MZ_MEMORY_SWAP <= '0';
end if;
end if;
end process;
-- MZ700 - Latch wether to enable RAM or ROM at 0000->0FFF.
--
process( MZ_RESET, CLKBUS(CKCPU), CS_IO_E0_n, CS_IO_E2_n, CS_IO_E4_n ) begin
if(MZ_RESET = '1') then
MZ_LOW_RAM_ENABLE <= '0';
elsif(CLKBUS(CKCPU)'event and CLKBUS(CKCPU)='1') then
if(CS_IO_E0_n = '0') then
MZ_LOW_RAM_ENABLE <= '1';
elsif(CS_IO_E2_n = '0') then
MZ_LOW_RAM_ENABLE <= '0';
elsif(CS_IO_E4_n = '0') then
MZ_LOW_RAM_ENABLE <= '0';
end if;
end if;
end process;
-- MZ700 - Latch wether to enable I/O or RAM at D000->FFFF.
--
process( MZ_RESET, CLKBUS(CKCPU), CS_IO_E1_n, CS_IO_E3_n, CS_IO_E4_n, MZ_HIGH_RAM_INHIBIT ) begin
if(MZ_RESET = '1') then
MZ_HIGH_RAM_ENABLE <= '0';
MZ_INHIBIT_RESET <= '0';
elsif(CLKBUS(CKCPU)'event and CLKBUS(CKCPU)='1') then
if(CS_IO_E1_n = '0' and MZ_HIGH_RAM_INHIBIT = '0') then
MZ_HIGH_RAM_ENABLE <= '1';
elsif(CS_IO_E3_n = '0' and MZ_HIGH_RAM_INHIBIT = '0') then
MZ_HIGH_RAM_ENABLE <= '0';
elsif(CS_IO_E4_n = '0') then
MZ_HIGH_RAM_ENABLE <= '0';
MZ_INHIBIT_RESET <= '1';
elsif(MZ_HIGH_RAM_INHIBIT = '0' and MZ_INHIBIT_RESET = '1') then
MZ_INHIBIT_RESET <= '0';
end if;
end if;
end process;
-- MZ700 - Latch wether to inhibit all functionality at D000->FFFF.
--
process( MZ_RESET, CLKBUS(CKCPU), CS_IO_E5_n, CS_IO_E6_n, MZ_INHIBIT_RESET ) begin
if(MZ_RESET = '1') then
MZ_HIGH_RAM_INHIBIT <= '0';
elsif(CLKBUS(CKCPU)'event and CLKBUS(CKCPU)='1') then
if(CS_IO_E5_n = '0') then
MZ_HIGH_RAM_INHIBIT <= '1';
elsif(CS_IO_E6_n = '0' or MZ_INHIBIT_RESET = '1') then
MZ_HIGH_RAM_INHIBIT <= '0';
end if;
end if;
end process;
-- Graphics Ram - Latch wether to enable Graphics RAM page from C000 - FFFF.
--
process( MZ_RESET, CLKBUS(CKCPU), CS_IO_E8_n, CS_IO_E9_n ) begin
if(MZ_RESET = '1') then
MZ_GRAM_ENABLE <= '0';
elsif(CLKBUS(CKCPU)'event and CLKBUS(CKCPU)='1') then
if(CS_IO_E8_n = '0') then
MZ_GRAM_ENABLE <= '1';
elsif(CS_IO_E9_n = '0') then
MZ_GRAM_ENABLE <= '0';
end if;
end if;
end process;
--
-- Cursor Base Clock
--
process( CLKBUS(CKPERIPH), T80_RST_n )
variable TCOUNT : std_logic_vector(15 downto 0);
begin
if T80_RST_n = '0' then
TCOUNT := (others=>'0');
elsif CLKBUS(CKPERIPH)'event and CLKBUS(CKPERIPH)='1' then
if( TCOUNT = 18371 ) then
TCOUNT := (others=>'0');
CURSOR_CLK <= not CURSOR_CLK;
else
TCOUNT := TCOUNT + '1';
end if;
end if;
end process;
--
-- Cursor blink Clock
--
process( CURSOR_CLK, CURSOR_RESET ) begin
if( CURSOR_RESET='0' ) then
CCOUNT <= (others => '0');
elsif( CURSOR_CLK'event and CURSOR_CLK = '1' ) then
if( CCOUNT = 18 ) then
CCOUNT <=(others=>'0');
CURSOR_BLINK <= not CURSOR_BLINK;
else
CCOUNT <= CCOUNT+'1';
end if;
end if;
end process;
--
-- Sound gate control
--
process( CLKBUS(CKPERIPH), T80_WR_n, CS_E2_n, T80_RST_n ) begin
if( T80_RST_n = '0' ) then
SOUND_ENABLE <= '0';
elsif( CLKBUS(CKPERIPH)'event and CLKBUS(CKPERIPH) = '1' and T80_WR_n = '0' and CS_E2_n = '0' ) then
SOUND_ENABLE <= T80_DO(0);
end if;
end process;
-- Audio output. Choose between generated sound and CMT pulse audio.
--
AUDIO_L <= SOUND when CONFIG(AUDIOSRC) = '0' -- Sound Output Left
else
CMTBUSi(WRITEBIT);
AUDIO_R <= SOUND when CONFIG(AUDIOSRC) = '0' -- Sound Output Right
else
CMTBUSi(READBIT);
-- The signal coming out of the 8253 is not a square wave and twice the frequency. The addition of a flip-flop to divide the
-- frequency by 2 results in a square wave of the correct audio frequency.
process( SOUND_PULSE_X2 ) begin
if( SOUND_PULSE_X2'event and SOUND_PULSE_X2 = '1' ) then
SOUND <= not SOUND;
end if;
end process;
-- MZ80 BLNK signal, enabled by VGATE being active and HBLANKi pulsing. If HBLANKi stops pulsing for more
-- than 32ms, then BLNK goes inactive.
--
process( CLKBUS(CKPERIPH), T80_RST_n )
variable TCOUNT : std_logic_vector(6 downto 0);
variable HBLANKLAST : std_logic;
begin
if T80_RST_n = '0' then
BLNK_n <= '1';
TCOUNT := (others=>'0');
elsif CLKBUS(CKPERIPH)'event and CLKBUS(CKPERIPH)='1' then
-- If HBLANKi goes active the first time or is retriggered, reset counter and set BLANKING active.
if (HBLANKi = '1' and TCOUNT = 0) or (HBLANKi = '1' and HBLANKLAST = '0') then
TCOUNT := "0000001";
BLNK_n <= '0';
-- If not retriggered and we get to the end of the count (32ms) then turn off the BLANKING signal.
elsif TCOUNT = 63 then
TCOUNT := (others=>'0');
BLNK_n <= '1';
else
TCOUNT := TCOUNT + '1';
end if;
-- Remember last state so we can retrigger.
HBLANKLAST := HBLANKi;
end if;
end process;
-- Try state register read, LS124 in MZ80A, LS367 in MZZ700. On MZ700 this register also inputs the
-- Joystick readings, yet to be implemented.
--
DO367(0) <= CURSOR_CLK;
DO367(7) <= not HBLANKi when CONFIG(MZ700) = '1'
else
'1' when CONFIG(MZ_A) = '1' and (BLNK_n = '0' and VGATE_n = '0')
else '1';
DO367(6 downto 1) <= (others=>'1');
-- Video Output.
--
HSYNC_n <= HSYNC_ni;
VSYNC_n <= VSYNC_ni;
R <= Ri;
G <= Gi;
B <= Bi;
VBLANK <= VBLANKi;
HBLANK <= HBLANKi;
-- A simple 1*cpufreq second pulse to indicate accuracy of CPU frequency for debug purposes..
--
process (SYSTEM_RESET, CLKBUS(CKCPU))
variable cnt : integer range 0 to 1999999 := 0;
begin
if SYSTEM_RESET = '1' then
PULSECPU <= '0';
cnt := 0;
elsif rising_edge(CLKBUS(CKCPU)) then
cnt := cnt + 1;
if cnt = 0 then
PULSECPU <= not PULSECPU;
end if;
end if;
end process;
-- Debug leds.
--
DEBUG_STATUS_LEDS(0) <= CS_D_n;
DEBUG_STATUS_LEDS(1) <= CS_E_n;
DEBUG_STATUS_LEDS(2) <= CS_E0_n;
DEBUG_STATUS_LEDS(3) <= CS_E1_n;
DEBUG_STATUS_LEDS(4) <= CS_E2_n;
DEBUG_STATUS_LEDS(5) <= CS_ESWP_n;
DEBUG_STATUS_LEDS(6) <= CS_ROM_ni;
DEBUG_STATUS_LEDS(7) <= CS_RAM_ni;
--
DEBUG_STATUS_LEDS(8) <= CS_BANKSWITCH_n;
DEBUG_STATUS_LEDS(9) <= CS_IO_E0_n;
DEBUG_STATUS_LEDS(10) <= CS_IO_E1_n;
DEBUG_STATUS_LEDS(11) <= CS_IO_E2_n;
DEBUG_STATUS_LEDS(12) <= CS_IO_E3_n;
DEBUG_STATUS_LEDS(13) <= CS_IO_E4_n;
DEBUG_STATUS_LEDS(14) <= CS_IO_E5_n;
DEBUG_STATUS_LEDS(15) <= CS_IO_E6_n;
--
DEBUG_STATUS_LEDS(16) <= CS_IO_E8_n;
DEBUG_STATUS_LEDS(17) <= CS_IO_E9_n;
DEBUG_STATUS_LEDS(18) <= CS_IO_GRAM_n;
DEBUG_STATUS_LEDS(19) <= CS_G_n;
DEBUG_STATUS_LEDS(20) <= MZ_GRAM_ENABLE;
DEBUG_STATUS_LEDS(21) <= '0';
DEBUG_STATUS_LEDS(22) <= '0';
DEBUG_STATUS_LEDS(23) <= '0';
--
DEBUG_STATUS_LEDS(24) <= PULSECPU;
DEBUG_STATUS_LEDS(25) <= T80_INT_ni;
DEBUG_STATUS_LEDS(26) <= INTMSK;
DEBUG_STATUS_LEDS(27) <= MZ_MEMORY_SWAP;
DEBUG_STATUS_LEDS(28) <= MZ_LOW_RAM_ENABLE;
DEBUG_STATUS_LEDS(29) <= MZ_HIGH_RAM_ENABLE;
DEBUG_STATUS_LEDS(30) <= MZ_HIGH_RAM_INHIBIT;
DEBUG_STATUS_LEDS(31) <= MZ_INHIBIT_RESET;
--
DEBUG_STATUS_LEDS(32) <= '0';
DEBUG_STATUS_LEDS(33) <= '0';
DEBUG_STATUS_LEDS(34) <= '0';
DEBUG_STATUS_LEDS(35) <= '0';
DEBUG_STATUS_LEDS(36) <= CURSOR_BLINK;
DEBUG_STATUS_LEDS(37) <= SOUND_ENABLE;
DEBUG_STATUS_LEDS(38) <= MZ_RTC_CASCADE_CLK;
DEBUG_STATUS_LEDS(39) <= PULSECPU;
--
-- LEDS 40 .. 63 are provided by the CMT unit.
--
-- LEDS 64 .. 112 are available.
DEBUG_STATUS_LEDS(111 downto 64) <= (others => '0');
end rtl;