---------------------------------------------------------------------------------------------------------
--
-- Name:            sharpmz.vhd
-- Created:         June 2018
-- Author(s):       Philip Smart
-- Description:     Sharp MZ series compatible logic.
--                                                     
--                  This module is the main (top level) container for the 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
--                                      |
--                                      |
--                                      |                                         -> cmt.vhd                   (common)
--                                      |                                         -> keymatrix.vhd             (common)
--                                      |                                         -> pll.v                     (common)
--                                      |                                         -> clkgen.vhd                (common)
--                                      |                                         -> T80                       (common)
--                                      |                                         -> i8255                     (common)
--                  sys_top.sv (emu) ->	(emu) sharpmz.vhd (hps_io) -> hps_io.sv
--                                      |                                         -> i8253                     (common)
--                                      |                                         -> dpram.vhd                 (common)
--                                      |                                         -> dprom.vhd                 (common)
--                                      |                                         -> mctrl.vhd                 (common)
--                                      |                                         -> video.vhd                 (common)
--                                      |
--                                      |
--                                      (emu) sharpmz.vhd (mz80b)	->	mz80b.vhd
--
--                  The idea of the design is to keep the emulation as independent of the HPS
--                  as possible (so it works standalone), only needing the HPS to set control registers,
--                  load tape ram and overlay the menu system. This in theory should allow easier
--                  porting if someone wants to port this emulator to another platform or even
--                  target an non-HPS Cyclone chip and instantiate another CPU as the menu control.
--
--                  As the Cyclone V SE on the Terasic DE10 has 5.5Mbits of memory, nearly all the RAM used
--                  by the emulation is on the FPGA. The Floppy Disk Controller may use HPS memory (or the
--                  external SDRAM) depending on wether I decide to cache entire Floppy Disks as per the CMT
--                  unit.
--
-- Credits:         Credit to Nibbles Lab. 2012-2016, as I was originally going to port his mz80c_de0 emulator
--                  based on a Terasic DE0 board. He used external memory and an instantiated NIOSII CPU
--                  to provide a menu/control system. Some snippets of his code, such as the keyboard matrix
--                  have been re-used in this emulation.
-- Copyright:       (c) 2018 Philip Smart <philip.smart@net2net.org>
--
-- History:         June 2018 - Initial creation.
--
---------------------------------------------------------------------------------------------------------
-- 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.config_pkg.all;
use pkgs.clkgen_pkg.all;
use pkgs.mctrl_pkg.all;

entity sharpmz is
  port(
        --------------------                Clock Input                         ----------------------------     
        CLKMASTER             : in     std_logic;                               -- Master Clock(50MHz)
        CLKSYS                : out    std_logic;                               -- System clock.
        CLKVID                : out    std_logic;                               -- Pixel base clock of video.
        --------------------                Reset                               ----------------------------
        COLD_RESET            : in     std_logic;
        WARM_RESET            : in     std_logic;
        --------------------                        main_leds                   ----------------------------
        MAIN_LEDS             : out    std_logic_vector(7 downto 0);            -- main_leds Green[7:0]
        --------------------                        PS2                         ----------------------------
        PS2_KEY               : in     std_logic_vector(10 downto 0);           -- PS2 Key data.
        --------------------                        VGA                         ----------------------------
        VGA_HB_O              : out    std_logic;                               -- VGA Horizontal Blank
        VGA_VB_O              : out    std_logic;                               -- VGA Vertical Blank
        VGA_HS_O              : out    std_logic;                               -- VGA H_SYNC
        VGA_VS_O              : out    std_logic;                               -- VGA V_SYNC
        VGA_R_O               : out    std_logic_vector(7 downto 0);            -- VGA Red[3:0], [7:4] = 0
        VGA_G_O               : out    std_logic_vector(7 downto 0);            -- VGA Green[3:0]
        VGA_B_O               : out    std_logic_vector(7 downto 0);            -- VGA Blue[3:0]
        --------------------                        AUDIO                       ------------------------------
        AUDIO_L_O             : out    std_logic;
        AUDIO_R_O             : out    std_logic;
        --------------------                      HPS Interface                 ------------------------------
        IOCTL_DOWNLOAD        : in     std_logic;                               -- Downloading to FPGA.
        IOCTL_UPLOAD          : in     std_logic;                               -- Uploading from FPGA.
        IOCTL_CLK             : in     std_logic;                               -- I/O Clock.
        IOCTL_WR              : in     std_logic;                               -- Write Enable to FPGA.
        IOCTL_RD              : in     std_logic;                               -- Read Enable from FPGA.
        IOCTL_ADDR            : in     std_logic_vector(24 downto 0);           -- Address in FPGA to write into.
        IOCTL_DOUT            : in     std_logic_vector(31 downto 0);           -- Data to be written into FPGA.
        IOCTL_DIN             : out    std_logic_vector(31 downto 0)            -- Data to be read into HPS.
);
end sharpmz;

architecture rtl of sharpmz is

-- Parent signals brought out onto wires.
--
signal MZ_PS2_KEY            :     std_logic_vector(10 downto 0);
--
-- Keyboard
--
signal MZ_KEYB_SCAN          :     std_logic_vector(3 downto 0);
signal MZ_KEYB_DATA          :     std_logic_vector(7 downto 0);
signal MZ_KEYB_STALL         :     std_logic;
signal MZ_KEYB_BREAKDETECT   :     std_logic;
--
-- Master Control signals and configuration.
--
signal MZ_SYSTEM_RESET       :     std_logic;
signal MZ_MEMWR              :     std_logic;
--
-- Signal BUS's
--
signal CLKBUS                :     std_logic_vector(CLKBUS_WIDTH);
signal CONFIG                :     std_logic_vector(CONFIG_WIDTH);
signal DEBUG                 :     std_logic_vector(DEBUG_WIDTH);
signal MZ_CMT_BUS_OUT        :     std_logic_vector(CMT_BUS_OUT_WIDTH);
--
-- HPS Control.
--
signal MZ_IOCTL_DOWNLOAD     :     std_logic;
signal MZ_IOCTL_UPLOAD       :     std_logic;
signal MZ_IOCTL_CLK          :     std_logic;
signal MZ_IOCTL_WR           :     std_logic;
signal MZ_IOCTL_RD           :     std_logic;
signal MZ_IOCTL_ADDR         :     std_logic_vector(24 downto 0);
signal MZ_IOCTL_DOUT         :     std_logic_vector(31 downto 0);
signal MZ_IOCTL_DIN_SYSROM   :     std_logic_vector(7 downto 0);
signal MZ_IOCTL_DIN_SYSRAM   :     std_logic_vector(7 downto 0);
signal MZ_IOCTL_DIN_VIDEO    :     std_logic_vector(31 downto 0);
signal MZ_IOCTL_DIN_MZ80C    :     std_logic_vector(31 downto 0);
signal MZ_IOCTL_DIN_MZ80B    :     std_logic_vector(31 downto 0);
signal MZ_IOCTL_DIN_MCTRL    :     std_logic_vector(31 downto 0);
signal MZ_IOCTL_DIN_CMT      :     std_logic_vector(31 downto 0);
signal MZ_IOCTL_DIN_KEY      :     std_logic_vector(31 downto 0);
signal MZ_IOCTL_WENROM       :     std_logic;
signal MZ_IOCTL_WENRAM       :     std_logic;
signal MZ_IOCTL_RENROM       :     std_logic;
signal MZ_IOCTL_RENRAM       :     std_logic;
--
-- T80 for MZ80C
--
signal MZ80C_BUSRQ_n         :     std_logic;
signal MZ80C_MWR_n           :     std_logic;
signal MZ80C_MRD_n           :     std_logic;
signal MZ80C_IWR_n           :     std_logic;
signal MZ80C_WAIT_n          :     std_logic;
signal MZ80C_INT_n           :     std_logic;
signal MZ80C_DI              :     std_logic_vector(7 downto 0);
signal MZ80C_NMI_n           :     std_logic;
--
-- Tape Control 
--
signal MZ80C_CMT_BUS_IN      :     std_logic_vector(CMT_BUS_IN_WIDTH);
--
-- Keyboard
--
signal MZ80C_KEYB_SCAN       :     std_logic_vector(3 downto 0);
signal MZ80C_KEYB_STALL      :     std_logic;
--
-- Video 
--
signal MZ_R                  :     std_logic_vector(7 downto 0);
signal MZ_B                  :     std_logic_vector(7 downto 0);
signal MZ_G                  :     std_logic_vector(7 downto 0);
signal MZ_VGATE_n            :     std_logic;
signal MZ_DISPLAY_INVERT_n   :     std_logic;
signal MZ_DISPLAY_CHAR80     :     std_logic;
signal MZ_HSYNC_n            :     std_logic;
signal MZ_VSYNC_n            :     std_logic;
signal MZ_HBLANK             :     std_logic;
signal MZ_VBLANK             :     std_logic;
--
-- Selects for MZ80C.
--
signal MZ80C_CS_ROM_n        :     std_logic;
signal MZ80C_CS_RAM_n        :     std_logic;
signal MZ80C_CS_VRAM_n       :     std_logic;
signal MZ80C_CS_MEM_G_n      :     std_logic;
signal MZ80C_CS_GRAM_n       :     std_logic;
signal MZ80C_CS_GRAM_80B_n   :     std_logic;
signal MZ80C_CS_IO_GFB_n     :     std_logic;
--
-- Audio for MZ80C
--
signal MZ80C_AUDIO_L         :     std_logic;
signal MZ80C_AUDIO_R         :     std_logic;
--
-- Video signals for MZ80C
--
signal MZ80C_VGATE_n         :     std_logic;
--
-- Debug for MZ80C
--
signal MZ80C_DEBUG_LEDS      :     std_logic_vector(111 downto 0);
--
-- T80 for MZ80B
--
signal MZ80B_BUSRQ_n         :     std_logic;
signal MZ80B_MWR_n           :     std_logic;
signal MZ80B_MRD_n           :     std_logic;
signal MZ80B_IWR_n           :     std_logic;
signal MZ80B_WAIT_n          :     std_logic;
signal MZ80B_INT_n           :     std_logic;
signal MZ80B_DI              :     std_logic_vector(7 downto 0);
signal MZ80B_NMI_n           :     std_logic;
--
-- Selects for MZ80B.
--
signal MZ80B_CS_ROM_n        :     std_logic;
signal MZ80B_CS_RAM_n        :     std_logic;
signal MZ80B_CS_VRAM_n       :     std_logic;
signal MZ80B_CS_GRAM_n       :     std_logic;
signal MZ80B_CS_IO_GFB_n     :     std_logic;
signal MZ80B_CS_IO_G_n       :     std_logic;
--
-- Audio for MZ80B
--
signal MZ80B_AUDIO_L         :     std_logic;
signal MZ80B_AUDIO_R         :     std_logic;
--
-- Video signals for MZ80B
--
signal MZ80B_VGATE_n         :     std_logic;
--
-- Tape Control 
--
signal MZ80B_CMT_BUS_IN      :     std_logic_vector(CMT_BUS_IN_WIDTH);
--
-- Keyboard
--
signal MZ80B_KEYB_SCAN       :     std_logic_vector(3 downto 0);
signal MZ80B_KEYB_STALL      :     std_logic;
--
-- Debug for MZ80B
--
signal MZ80B_DEBUG_LEDS      :     std_logic_vector(111 downto 0);
--
-- T80
--
signal T80_RST_n             :     std_logic;
signal T80_MREQ_n            :     std_logic;
signal T80_BUSRQ_n           :     std_logic;
signal T80_IORQ_n            :     std_logic;
signal T80_WR_n              :     std_logic;
signal T80_RD_n              :     std_logic;
signal T80_WAIT_n            :     std_logic;
signal T80_M1_n              :     std_logic;
signal T80_RFSH_n            :     std_logic;
signal T80_A16               :     std_logic_vector(15 downto 0);
signal T80_INT_n             :     std_logic;
signal T80_DO                :     std_logic_vector(7 downto 0);
signal T80_DI                :     std_logic_vector(7 downto 0);
signal T80_BUSAK_n           :     std_logic;
signal T80_NMI_n             :     std_logic;
signal T80_HALT_n            :     std_logic;
--
-- Decodes, control, misc
--
signal WENSYSRAM             :     std_logic;
--
-- Monitor ROM
--
signal SYSROM_DO             :     std_logic_vector(7 downto 0);
signal MZ_CS_ROM_n           :     std_logic;
signal MROM_BANK             :     std_logic_vector(5 downto 0);
--
-- Static RAM
--
signal SYSRAM_DO             :     std_logic_vector(7 downto 0);
signal MZ_CS_RAM_n           :     std_logic;
signal MZ_SYSMEM_A16         :     std_logic_vector(15 downto 0);
signal MZ_SWP_MEM_BANK_n     :     std_logic;
--
-- Graphics RAM control signals.
--
signal VRAM_DO               :     std_logic_vector(7 downto 0);
signal MZ_CS_VRAM_n          :     std_logic;
signal MZ_CS_MEM_G_n         :     std_logic;
signal MZ_CS_GRAM_n          :     std_logic;
signal MZ_CS_GRAM_80B_n      :     std_logic;
signal MZ_CS_IO_GFB_n        :     std_logic;
signal MZ_CS_IO_G_n          :     std_logic;
signal VIDEO_WAIT_n          :     std_logic;
--
-- Tape Control 
--
signal MZ_CMT_BUS_IN         :     std_logic_vector(CMT_BUS_IN_WIDTH);
signal MZ_CMT_DEBUG_LEDS     :     std_logic_vector(31 downto 0);
--
-- Debug and internal process signals.
--
signal debug_counter         :     integer range 0 to 13       := 0;
signal flip_counter          :     integer range 0 to 10000000 := 0;
signal block_flip            :     integer range 0 to 800000   := 0;
signal bank_flip             :     integer range 0 to 10000000 := 0;

--
-- Components
--
component clkgen
    Port (
          RST                : in  std_logic;                            -- Reset

          -- Clocks
          CKBASE             : in  std_logic;                            -- Base system main clock.
          CLKBUS             : out std_logic_vector(CLKBUS_WIDTH);       -- Clock signals created by this module.

          -- Different operations modes.
          CONFIG             : in  std_logic_vector(CONFIG_WIDTH);        

          -- Debug modes.
          DEBUG              : in  std_logic_vector(DEBUG_WIDTH) 
    );
end component;

component T80se
    generic (
          Mode               :     integer := 0;                         -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
          T2Write            :     integer := 1;                         -- 0 => WR_n active in T3, /=0 => WR_n active in T2
          IOWait             :     integer := 1                          -- 0 => Single cycle I/O, 1 => Std I/O cycle
    );
    Port (
          RESET_n            : in  std_logic;
          CLK_n              : in  std_logic;                            -- NB. Clock is high active.
          CLKEN              : in  std_logic;
          WAIT_n             : in  std_logic;
          INT_n              : in  std_logic;
          NMI_n              : in  std_logic;
          BUSRQ_n            : in  std_logic;
          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;
          A                  : out std_logic_vector(15 downto 0);
          DI                 : in  std_logic_vector(7 downto 0);
          DO                 : out std_logic_vector(7 downto 0)
    );
end component;

component dpram
    generic (
          init_file          : string;
          widthad_a          : natural;
          width_a            : natural;
          widthad_b          : natural;
          width_b            : natural;
          outdata_reg_a      : string := "UNREGISTERED";
          outdata_reg_b      : string := "UNREGISTERED"
    );
    Port (
          clock_a            : in  std_logic  := '1';
          clocken_a          : in  std_logic  := '1';
          address_a          : in  std_logic_vector (widthad_a-1 downto 0);
          data_a             : in  std_logic_vector (width_a-1 downto 0);
          wren_a             : in  std_logic  := '0';
          q_a                : out std_logic_vector (width_a-1 downto 0);

          clock_b            : in  std_logic;
          clocken_b          : in  std_logic  := '1';
          address_b          : in  std_logic_vector (widthad_b-1 downto 0);
          data_b             : in  std_logic_vector (width_b-1 downto 0);
          wren_b             : in  std_logic  := '0';
          q_b                : out std_logic_vector (width_b-1 downto 0)
      );
end component;

component mctrl
    Port (
          -- Clock signals used by this module.
          CLKBUS             : in  std_logic_vector(CLKBUS_WIDTH);

          -- Reset's
          COLD_RESET         : in  std_logic;
          WARM_RESET         : in  std_logic;
          SYSTEM_RESET       : out std_logic;

          -- HPS Interface
          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(31 downto 0);        -- HPS Data to be written into FPGA.
          IOCTL_DIN          : out std_logic_vector(31 downto 0);        -- HPS Data to be read into HPS.

          -- Different operations modes.
          CONFIG             : out std_logic_vector(CONFIG_WIDTH);

          -- Cassette magnetic tape signals.
          CMT_BUS_OUT        : in  std_logic_vector(CMT_BUS_OUT_WIDTH);
          CMT_BUS_IN         : in  std_logic_vector(CMT_BUS_IN_WIDTH);

          -- MZ80B series can dynamically change the video frequency to attain 40/80 character display.
          CONFIG_CHAR80      : in  std_logic;

          -- Debug modes.
          DEBUG              : out std_logic_vector(DEBUG_WIDTH) 
    );
end component;

component 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_VRAM_n            : in  std_logic;                            -- VRAM Select
        CS_MEM_G_n           : in  std_logic;                            -- Peripherals Select
        CS_GRAM_n            : in  std_logic;                            -- Colour GRAM Select
        CS_GRAM_80B_n        : in  std_logic;                            -- MZ80B GRAM Select
        CS_IO_GFB_n          : in  std_logic;                            -- Graphics FB IO Select range
        CS_IO_G_n            : in  std_logic;                            -- Graphics Options IO Select range

        -- Video Signals
        VGATE_n              : in  std_logic;                            -- Video Output Control
        INVERSE_n            : in  std_logic;                            -- Invert video display.
        CONFIG_CHAR80        : in  std_logic;                            -- 40 Char = 0, 80 Char = 1 select.
        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_vector(7 downto 0);         -- Red Output
        GOUT                 : out std_logic_vector(7 downto 0);         -- Green Output
        BOUT                 : out std_logic_vector(7 downto 0);         -- 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(31 downto 0);        -- HPS Data to be written into FPGA.
        IOCTL_DIN            : out std_logic_vector(31 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;
        BREAKDETECT          : out 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(31 downto 0);        -- HPS Data to be written into FPGA.
        IOCTL_DIN            : out std_logic_vector(31 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.
        CMT_BUS_OUT          : out std_logic_vector(CMT_BUS_OUT_WIDTH);
        CMT_BUS_IN           : in  std_logic_vector(CMT_BUS_IN_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(31 downto 0);        -- HPS Data to be written into FPGA.
        IOCTL_DIN            : out std_logic_vector(31 downto 0);        -- HPS Data to be read into HPS.

        -- Debug Status Leds
        DEBUG_STATUS_LEDS    : out std_logic_vector(31 downto 0)         -- 24 leds to display cmt internal status.
    );
end component;

component mz80c
    PORT (
          -- Clocks
          CLKBUS             : in  std_logic_vector(CLKBUS_WIDTH);    -- Clock signals created by this module.

          -- Resets.
          COLD_RESET         : in  std_logic;
          SYSTEM_RESET       : in  std_logic;
          
          -- Z80 CPU
          T80_RST_n          : in  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;
          CS_VRAM_n          : out std_logic;                            -- VRAM Select
          CS_MEM_G_n         : out std_logic;                            -- Memory mapped Peripherals Select
          CS_GRAM_n          : out std_logic;                            -- Colour GRAM Select
          CS_IO_GFB_n        : out std_logic;                            -- Graphics FB IO Select range

          -- Audio.
          AUDIO_L            : out std_logic;
          AUDIO_R            : out std_logic;

          -- Different operations modes.
          CONFIG             : in  std_logic_vector(CONFIG_WIDTH);

          -- I/O                                                         -- I/O down to the core.
          KEYB_SCAN          : out std_logic_vector(3 downto 0);         -- Keyboard scan lines out.
          KEYB_DATA          : in  std_logic_vector(7 downto 0);         -- Keyboard scan data in.
          KEYB_STALL         : out std_logic;                            -- Keyboard Stall out.

          -- Cassette magnetic tape signals.
          CMT_BUS_OUT        : in  std_logic_vector(CMT_BUS_OUT_WIDTH);
          CMT_BUS_IN         : out std_logic_vector(CMT_BUS_IN_WIDTH);

          -- Video
          VGATE_n            : out std_logic;
          HBLANK             : in  std_logic;                            -- Horizontal Blanking Signal
          VBLANK             : in  std_logic;                            -- Vertical Blanking Signal          

          -- 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(31 downto 0);        -- HPS Data to be written into FPGA.
          IOCTL_DIN          : out std_logic_vector(31 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 component;

component mz80b
    PORT (
          -- Clocks
          CLKBUS             : in  std_logic_vector(CLKBUS_WIDTH);    -- Clock signals created by this module.

          -- Resets.
          COLD_RESET         : in  std_logic;
          SYSTEM_RESET       : in  std_logic;
          
          -- Z80 CPU
          T80_RST_n          : in  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;
          CS_VRAM_n          : out std_logic;                            -- VRAM Select
          CS_GRAM_n          : out std_logic;                            -- Colour GRAM Select
          CS_GRAM_80B_n      : out std_logic;                            -- MZ80B GRAM Select
          CS_IO_GFB_n        : out std_logic;                            -- Graphics FB IO Select range
          CS_IO_G_n          : out std_logic;                            -- Graphics Options IO Select range
          CS_SWP_MEMBANK_n   : out std_logic;                            -- Move lower 32K into upper block.

          -- Audio.
          AUDIO_L            : out std_logic;
          AUDIO_R            : out std_logic;

          -- Different operations modes.
          CONFIG             : in  std_logic_vector(CONFIG_WIDTH);

          -- I/O                                                         -- I/O down to the core.
          KEYB_SCAN          : out std_logic_vector(3 downto 0);         -- Keyboard scan lines out.
          KEYB_DATA          : in  std_logic_vector(7 downto 0);         -- Keyboard scan data in.
          KEYB_STALL         : out std_logic;                            -- Keyboard Stall out.
          KEYB_BREAKDETECT   : in  std_logic;                            -- Keyboard break detect.

          -- Cassette magnetic tape signals.
          CMT_BUS_OUT        : in  std_logic_vector(CMT_BUS_OUT_WIDTH);
          CMT_BUS_IN         : out std_logic_vector(CMT_BUS_IN_WIDTH);

          -- Video
          VGATE_n            : out std_logic;
          INVERSE_n          : out std_logic;                            -- Invert video display.
          CONFIG_CHAR80      : out std_logic;                            -- 40 Char = 0, 80 Char = 1 select.
          HBLANK             : in  std_logic;                            -- Horizontal Blanking Signal
          VBLANK             : in  std_logic;                            -- Vertical Blanking Signal

          -- 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(31 downto 0);        -- HPS Data to be written into FPGA.
          IOCTL_DIN          : out std_logic_vector(31 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 component;

begin

    --
    -- Instantiation
    --
    CLKGEN0 :  clkgen port map (
            RST              => cold_reset,                              -- Reset

            -- Clocks
            CKBASE           => CLKMASTER,                               -- Input clocks from top level.
            CLKBUS           => CLKBUS,                                  -- Clock signals created by this module.

            -- Different operations modes.
            CONFIG           => CONFIG,

            -- Debug modes.
            DEBUG            => DEBUG
    );

    CPU0 : T80se
        generic map (
            Mode             => 0,                                       -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
            T2Write          => 1,                                       -- 0 => WR_n active in T3, /=0 => WR_n active in T2
            IOWait           => 1                                        -- 0 => Single cycle I/O, 1 => Std I/O cycle
        )
        port map (
            RESET_n          => T80_RST_n,                               -- Reset signal.
            CLK_n            => CLKBUS(CKMASTER),                        -- T80se uses positive level clock.
            CLKEN            => CLKBUS(CKENCPU),                         -- Pulse the master clock at the required CPU frequency.
            WAIT_n           => T80_WAIT_n,                              -- WAIT_n signal into the CPU to prolong a memory cycle.
            INT_n            => T80_INT_n,                               -- INT_n signal for maskable interrupts.
            NMI_n            => T80_NMI_n,                               -- NMI_n non maskable interrupt input.
            BUSRQ_n          => T80_BUSRQ_n,                             -- BUSRQ_n signal to request CPU go into tristate and relinquish bus.
            M1_n             => T80_M1_n,                                -- M1_n Machine Cycle 1 signal. M1 and MREQ active = opcode fetch, M1 and IORQ active = interrupt, vector can be read from D0-D7.
            MREQ_n           => T80_MREQ_n,                              -- MREQ_n signal indicates that the address bus holds a valid address for reading or writing memory.
            IORQ_n           => T80_IORQ_n,                              -- IORQ_n signal indicates that the address bus (A0-A7) holds a valid address for reading or writing and I/O device.
            RD_n             => T80_RD_n,                                -- RD_n signal indicates that data is ready to be read from a memory or I/O device to the CPU.
            WR_n             => T80_WR_n,                                -- WR_n signal indicates that data is going to be written from the CPU data bus to a memory or I/O device.
            RFSH_n           => T80_RFSH_n,                              -- RFSH_n signal to indicate dynamic memory refresh can take place.
            HALT_n           => T80_HALT_n,                              -- HALT_n signal indicates that the CPU has executed a "HALT" instruction.
            BUSAK_n          => T80_BUSAK_n,                             -- BUSAK_n signal indicates that the CPU address bus, data bus, and control signals have entered their HI-Z states, and that the external circuitry can now control these lines.
            A                => T80_A16,                                 -- 16 bit address lines.
            DI               => T80_DI,                                  -- 8 bit data input bus.
            DO               => T80_DO                                   -- 8 bit data output bus.
        );

    -- MZ80 System RAM
    -- 
    SYSRAM : dpram
        generic map (
            init_file        => "./software/mif/combined_mainmemory.mif",
            widthad_a        => 16,
            width_a          => 8,
            widthad_b        => 16,
            width_b          => 8,
            outdata_reg_a    => "UNREGISTERED",
            outdata_reg_b    => "UNREGISTERED"
        )
        port map (
            clock_a          => CLKBUS(CKMASTER), --CLKBUS(CKMEM), 
            clocken_a        => CLKBUS(CKENCPU), --'1',
            address_a        => MZ_SYSMEM_A16,
            data_a           => T80_DO,
            wren_a           => WENSYSRAM,                               -- Pulse width controlled according to Master Clock.
            q_a              => SYSRAM_DO,

            clock_b          => MZ_IOCTL_CLK,
            clocken_b        => '1',
            address_b        => MZ_IOCTL_ADDR(15 downto 0),
            data_b           => MZ_IOCTL_DOUT(7 downto 0),
            wren_b           => MZ_IOCTL_WENRAM,
            q_b              => MZ_IOCTL_DIN_SYSRAM
        );

    -- MZ Monitor ROM
    -- 0  =         80K MROM 4KBytes -> 0000:0fff 0000 bytes padding
    -- 1  =  80x25  80K MROM 4KBytes -> 1000:1fff 0000 bytes padding
    -- 2  =         80C MROM 4KBytes -> 2000:2fff 0000 bytes padding
    -- 3  =  80x25  80C MROM 4KBytes -> 3000:3fff 0000 bytes padding
    -- 4  =        1200 MROM 4KBytes -> 4000:4fff 0000 bytes padding
    -- 5  =  80x25 1200 MROM 4KBytes -> 5000:5fff 0000 bytes padding
    -- 6  =         80A MROM 4KBytes -> 6000:6fff 0000 bytes padding
    -- 7  =  80x25  80A MROM 4KBytes -> 7000:7fff 0000 bytes padding
    -- 8  =         700 MROM 4KBytes -> 8000:8fff 0000 bytes padding
    -- 9  =  80x25  700 MROM 4KBytes -> 9000:9fff 0000 bytes padding
    -- 10 =         80B MROM 2KBytes -> a000:afff 0800 bytes padding
    -- 11 =  80x25  80B MROM 2KBytes -> b000:bfff 0800 bytes padding
    -- 
    --SYSROM : dprom
    SYSROM : dpram
        generic map (
            init_file        => "./software/mif/combined_mrom.mif",
            widthad_a        => 17,
            width_a          => 8,
            widthad_b        => 17,
            width_b          => 8,
            outdata_reg_a    => "UNREGISTERED",
            outdata_reg_b    => "UNREGISTERED"
        )
        port map (
            clock_a          => CLKBUS(CKMASTER), -- CLKBUS(CKMEM),
            clocken_a        => CLKBUS(CKENCPU), --'1',
            address_a        => MROM_BANK & T80_A16(10 downto 0),
            data_a           => T80_DO,
            wren_a           => '0',                                     -- Block writes from Z80 to ROM.
            q_a              => SYSROM_DO,

            clock_b          => MZ_IOCTL_CLK,
            clocken_b        => '1',
            address_b        => MZ_IOCTL_ADDR(16 downto 0),
            data_b           => MZ_IOCTL_DOUT(7 downto 0),
            wren_b           => MZ_IOCTL_WENROM,
            q_b              => MZ_IOCTL_DIN_SYSROM
        );

    CTRL0 : mctrl
        port map (
            -- Clock
            CLKBUS           => CLKBUS,

            -- Reset's
            COLD_RESET       => cold_reset,
            WARM_RESET       => warm_reset,
            SYSTEM_RESET     => MZ_SYSTEM_RESET,

            -- HPS Interface
            IOCTL_CLK        => MZ_IOCTL_CLK,                            -- HPS I/O Clock
            IOCTL_WR         => MZ_IOCTL_WR,
            IOCTL_RD         => MZ_IOCTL_RD,
            IOCTL_ADDR       => MZ_IOCTL_ADDR,
            IOCTL_DOUT       => MZ_IOCTL_DOUT,
            IOCTL_DIN        => MZ_IOCTL_DIN_MCTRL,

            -- Different operations modes.
            CONFIG           => CONFIG,

            -- Cassette magnetic tape signals.
            CMT_BUS_OUT      => MZ_CMT_BUS_OUT,
            CMT_BUS_IN       => MZ_CMT_BUS_IN,

            -- MZ80B series can dynamically change the video frequency to attain 40/80 character display.
            CONFIG_CHAR80    => MZ_DISPLAY_CHAR80,

            -- Debug modes.
            DEBUG            => DEBUG
        );

    VIDEO0 : 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       => VIDEO_WAIT_n,                            -- Wait Request to CPU from Video circuitry.
            T80_DI           => T80_DO,                                  -- CPU Data Bus(in)
            T80_DO           => VRAM_DO,                                 -- CPU Data Bus(out)

            -- Selects.
            CS_VRAM_n        => MZ_CS_VRAM_n,                            -- VRAM Select
            CS_MEM_G_n       => MZ_CS_MEM_G_n,                           -- Peripherals Select
            CS_GRAM_n        => MZ_CS_GRAM_n,                            -- Colour GRAM Select
            CS_GRAM_80B_n    => MZ_CS_GRAM_80B_n,                        -- MZ80B GRAM Select
            CS_IO_GFB_n      => MZ_CS_IO_GFB_n,                          -- Graphics FB IO Select range
            CS_IO_G_n        => MZ_CS_IO_G_n,                            -- Graphics Options IO Select range

            -- Video Signals
            VGATE_n          => MZ_VGATE_n,                              -- Video Output Control
            INVERSE_n        => MZ_DISPLAY_INVERT_n,                     -- Invert video output.
            CONFIG_CHAR80    => MZ_DISPLAY_CHAR80,                       -- 40 Char = 0, 80 Char = 1 select.
            HBLANK           => MZ_HBLANK,                               -- Horizontal Blanking
            VBLANK           => MZ_VBLANK,                               -- Vertical Blanking
            HSYNC_n          => MZ_HSYNC_n,                              -- Horizontal Sync
            VSYNC_n          => MZ_VSYNC_n,                              -- Vertical Sync
            ROUT             => MZ_R,                                    -- Red Output
            GOUT             => MZ_G,                                    -- Green Output
            BOUT             => MZ_B,                                    -- Blue Output

            -- HPS Interface
            IOCTL_DOWNLOAD   => MZ_IOCTL_DOWNLOAD,
            IOCTL_UPLOAD     => MZ_IOCTL_UPLOAD,
            IOCTL_CLK        => MZ_IOCTL_CLK,                            -- HPS I/O Clock.
            IOCTL_WR         => MZ_IOCTL_WR,                             -- HPS Write Enable to FPGA.
            IOCTL_RD         => MZ_IOCTL_RD,                             -- HPS Read Enable to FPGA.
            IOCTL_ADDR       => MZ_IOCTL_ADDR,                           -- HPS Address in FPGA to write into.
            IOCTL_DOUT       => MZ_IOCTL_DOUT,                           -- HPS Data to be written into FPGA.
            IOCTL_DIN        => MZ_IOCTL_DIN_VIDEO                       -- HPS Data to be sent to HPS.
        );

    TAPE0 : cmt
        port map (
            RST              => MZ_SYSTEM_RESET,

            -- Clock signals needed by this module.
            CLKBUS           => CLKBUS,

            -- Different operations modes.
            CONFIG           => CONFIG,

            -- Cassette magnetic tape signals.
            CMT_BUS_OUT      => MZ_CMT_BUS_OUT,                          -- Output is fed from CMT into MCTRL and MZ..
            CMT_BUS_IN       => MZ_CMT_BUS_IN,                           -- Input is fed from MCTRL/MZ into CMT.

            -- HPS Interface
            IOCTL_DOWNLOAD   => MZ_IOCTL_DOWNLOAD,                       -- HPS Downloading to FPGA.
            IOCTL_UPLOAD     => MZ_IOCTL_UPLOAD,                         -- HPS Uploading from FPGA.
            IOCTL_CLK        => MZ_IOCTL_CLK,                            -- HPS I/O Clock.
            IOCTL_WR         => MZ_IOCTL_WR,                             -- HPS Write Enable to FPGA.
            IOCTL_RD         => MZ_IOCTL_RD,                             -- HPS Read Enable from FPGA.
            IOCTL_ADDR       => MZ_IOCTL_ADDR,                           -- HPS Address in FPGA to write into.
            IOCTL_DOUT       => MZ_IOCTL_DOUT,                           -- HPS Data to be written into FPGA.
            IOCTL_DIN        => MZ_IOCTL_DIN_CMT,                        -- HPS Data to be sent to HPS.

            -- Debug Status Leds
            DEBUG_STATUS_LEDS=> MZ_CMT_DEBUG_LEDS(31 downto 0)           -- 24 leds to display cmt internal status.
        );

    KEYS : keymatrix
        port map (
            RST_n            => T80_RST_n,

            -- i8255
            PA               => MZ_KEYB_SCAN,
            PB               => MZ_KEYB_DATA,
            STALL            => MZ_KEYB_STALL,
            BREAKDETECT      => MZ_KEYB_BREAKDETECT,

            -- PS/2 Keyboard Data
            PS2_KEY          => MZ_PS2_KEY,                              -- PS2 Key data.

            -- Different operations modes.
            CONFIG           => CONFIG,

            -- Clock signals created by this module.
            CLKBUS           => CLKBUS,

            -- HPS Interface
            IOCTL_DOWNLOAD   => MZ_IOCTL_DOWNLOAD,                       -- HPS Downloading to FPGA.
            IOCTL_UPLOAD     => MZ_IOCTL_UPLOAD,                         -- HPS Uploading from FPGA.
            IOCTL_CLK        => MZ_IOCTL_CLK,                            -- HPS I/O Clock.
            IOCTL_WR         => MZ_IOCTL_WR,                             -- HPS Write Enable to FPGA.
            IOCTL_RD         => MZ_IOCTL_RD,                             -- HPS Read Enable from FPGA.
            IOCTL_ADDR       => MZ_IOCTL_ADDR,                           -- HPS Address in FPGA to write into.
            IOCTL_DOUT       => MZ_IOCTL_DOUT,                           -- HPS Data to be written into FPGA.
            IOCTL_DIN        => MZ_IOCTL_DIN_KEY                         -- HPS Data to be sent to HPS.
        );

    MZ80HW : mz80c
        port map (
            -- Clocks
            CLKBUS           => CLKBUS,                                  -- Clock signals created by this module.

            -- Resets.
            COLD_RESET       => cold_reset,                              -- Cold reset, one time reset on power up.
            SYSTEM_RESET     => MZ_SYSTEM_RESET,                         -- Reset generated by system based on Cold/Warm or trigger.

            -- Z80 CPU
            T80_RST_n        => T80_RST_n,
            T80_WAIT_n       => MZ80C_WAIT_n,
            T80_INT_n        => MZ80C_INT_n,
            T80_NMI_n        => MZ80C_NMI_n,
            T80_BUSRQ_n      => MZ80C_BUSRQ_n,
            T80_M1_n         => T80_M1_n,
            T80_MREQ_n       => T80_MREQ_n,
            T80_IORQ_n       => T80_IORQ_n,
            T80_RD_n         => T80_RD_n,
            T80_WR_n         => T80_WR_n,
            T80_RFSH_n       => T80_RFSH_n,                              --RFSH_n
            T80_HALT_n       => T80_HALT_n,
            T80_BUSAK_n      => T80_BUSAK_n,
            T80_A16          => T80_A16,
            T80_DI           => MZ80C_DI,
            T80_DO           => T80_DO,

            -- Chip selects to common resources.
            CS_ROM_n         => MZ80C_CS_ROM_n,
            CS_RAM_n         => MZ80C_CS_RAM_n,
            CS_VRAM_n        => MZ80C_CS_VRAM_n,                         -- VRAM Select
            CS_MEM_G_n       => MZ80C_CS_MEM_G_n,                        -- Memory mapped Peripherals Select
            CS_GRAM_n        => MZ80C_CS_GRAM_n,                         -- Colour GRAM Select
            CS_IO_GFB_n      => MZ80C_CS_IO_GFB_n,                       -- Graphics FB IO Select range

            -- Audio.
            AUDIO_L          => MZ80C_AUDIO_L,
            AUDIO_R          => MZ80C_AUDIO_R,

            -- Different operations modes.
            CONFIG           => CONFIG,

            -- Keyboard.
            KEYB_SCAN        => MZ80C_KEYB_SCAN,                         -- Keyboard scan lines out.
            KEYB_DATA        => MZ_KEYB_DATA,                            -- Keyboard scan data in.
            KEYB_STALL       => MZ80C_KEYB_STALL,                        -- Keyboard Stall out.

            -- CMT status signals.
            CMT_BUS_OUT      => MZ_CMT_BUS_OUT,
            CMT_BUS_IN       => MZ80C_CMT_BUS_IN,

            -- Video signals.
            VGATE_n          => MZ80C_VGATE_n,
            HBLANK           => MZ_HBLANK,
            VBLANK           => MZ_VBLANK,

            -- HPS Interface
            IOCTL_DOWNLOAD   => MZ_IOCTL_DOWNLOAD,                    
            IOCTL_UPLOAD     => MZ_IOCTL_UPLOAD,                    
            IOCTL_CLK        => MZ_IOCTL_CLK,                            -- HPS I/O Clock
            IOCTL_WR         => MZ_IOCTL_WR,
            IOCTL_RD         => MZ_IOCTL_RD,
            IOCTL_ADDR       => MZ_IOCTL_ADDR,
            IOCTL_DOUT       => MZ_IOCTL_DOUT,
            IOCTL_DIN        => MZ_IOCTL_DIN_MZ80C,

            -- Debug Status Leds
            DEBUG_STATUS_LEDS=> MZ80C_DEBUG_LEDS
    );

    MZ80BHW : mz80b
        port map (
            -- Clocks
            CLKBUS           => CLKBUS,                                  -- Clock signals created by this module.

            -- Resets.
            COLD_RESET       => cold_reset,                              -- Cold reset, one time reset on power up.
            SYSTEM_RESET     => MZ_SYSTEM_RESET,                         -- Reset generated by system based on Cold/Warm or trigger.

            -- Z80 CPU
            T80_RST_n        => T80_RST_n,
            T80_WAIT_n       => MZ80B_WAIT_n,
            T80_INT_n        => MZ80B_INT_n,
            T80_NMI_n        => MZ80B_NMI_n,
            T80_BUSRQ_n      => MZ80B_BUSRQ_n,
            T80_M1_n         => T80_M1_n,
            T80_MREQ_n       => T80_MREQ_n,
            T80_IORQ_n       => T80_IORQ_n,
            T80_RD_n         => T80_RD_n,
            T80_WR_n         => T80_WR_n,
            T80_RFSH_n       => T80_RFSH_n,                              --RFSH_n
            T80_HALT_n       => T80_HALT_n,
            T80_BUSAK_n      => T80_BUSAK_n,
            T80_A16          => T80_A16,
            T80_DI           => MZ80B_DI,
            T80_DO           => T80_DO,

            -- Chip selects to common resources.
            CS_ROM_n         => MZ80B_CS_ROM_n,
            CS_RAM_n         => MZ80B_CS_RAM_n,
            CS_VRAM_n        => MZ80B_CS_VRAM_n,                         -- VRAM Select
            CS_GRAM_n        => MZ80B_CS_GRAM_n,                         -- Colour GRAM Select
            CS_GRAM_80B_n    => MZ_CS_GRAM_80B_n,                        -- MZ80B GRAM Select
            CS_IO_GFB_n      => MZ80B_CS_IO_GFB_n,                       -- Graphics FB IO Select range
            CS_IO_G_n        => MZ80B_CS_IO_G_n,                         -- Graphics Options IO Select range
            CS_SWP_MEMBANK_n => MZ_SWP_MEM_BANK_n,                       -- Swap lower 32K memory bank into upper 32k block.

            -- Audio.
            AUDIO_L          => MZ80B_AUDIO_L,
            AUDIO_R          => MZ80B_AUDIO_R,

            -- Different operations modes.
            CONFIG           => CONFIG,

            -- Keyboard.
            KEYB_SCAN        => MZ80B_KEYB_SCAN,                         -- Keyboard scan lines out.
            KEYB_DATA        => MZ_KEYB_DATA,                            -- Keyboard scan data in.
            KEYB_STALL       => MZ80B_KEYB_STALL,                        -- Keyboard Stall out.
            KEYB_BREAKDETECT => MZ_KEYB_BREAKDETECT,                     -- Keyboard detects a break.

            -- CMT status signals.
            CMT_BUS_OUT      => MZ_CMT_BUS_OUT,
            CMT_BUS_IN       => MZ80B_CMT_BUS_IN,

            -- Video signals.
            VGATE_n          => MZ80B_VGATE_n,
            INVERSE_n        => MZ_DISPLAY_INVERT_n,                     -- Invert video output.
            CONFIG_CHAR80    => MZ_DISPLAY_CHAR80,                       -- 40 Char = 0, 80 Char = 1 select.
            HBLANK           => MZ_HBLANK,
            VBLANK           => MZ_VBLANK,

            -- HPS Interface
            IOCTL_DOWNLOAD   => MZ_IOCTL_DOWNLOAD,                    
            IOCTL_UPLOAD     => MZ_IOCTL_UPLOAD,                    
            IOCTL_CLK        => MZ_IOCTL_CLK,                            -- HPS I/O Clock
            IOCTL_WR         => MZ_IOCTL_WR,
            IOCTL_RD         => MZ_IOCTL_RD,
            IOCTL_ADDR       => MZ_IOCTL_ADDR,
            IOCTL_DOUT       => MZ_IOCTL_DOUT,
            IOCTL_DIN        => MZ_IOCTL_DIN_MZ80B,

            -- Debug Status Leds
            DEBUG_STATUS_LEDS=> MZ80B_DEBUG_LEDS
    );

    -- Clocks.
    --
    CLKSYS                   <= CLKBUS(CKMASTER);                       -- HPS clock.
    CLKVID                   <= CLKBUS(CKVIDEO);                        -- Video pixel clock output.

    -- Multiplexer -> Signals to enabled hardware.
    --
    T80_WAIT_n               <= VIDEO_WAIT_n      when VIDEO_WAIT_n = '0'     else MZ80C_WAIT_n      when CONFIG(MZ_80C) = '1'   else MZ80B_WAIT_n;
    T80_INT_n                <= MZ80C_INT_n       when CONFIG(MZ_80C) = '1'   else MZ80B_INT_n;
    T80_NMI_n                <= MZ80C_NMI_n       when CONFIG(MZ_80C) = '1'   else MZ80B_NMI_n;
    T80_BUSRQ_n              <= MZ80C_BUSRQ_n     when CONFIG(MZ_80C) = '1'   else MZ80B_BUSRQ_n;
    T80_DI                   <= SYSRAM_DO         when MZ_CS_RAM_n ='0' and T80_RD_n = '0'                    -- Read from System RAM
                                else 
                                SYSROM_DO         when MZ_CS_ROM_n ='0' and T80_RD_n = '0'                    -- Read from System ROM        
                                else 
                                VRAM_DO           when (MZ_CS_VRAM_n ='0' or MZ_CS_GRAM_n = '0' or MZ_CS_GRAM_80B_n = '0') and T80_RD_n = '0' -- Read from Graphics/Video RAM.
                                else 
                                MZ80C_DI          when CONFIG(MZ_80C) = '1'  
                                else
                                MZ80B_DI          when CONFIG(MZ_80B) = '1'
                                else
                                (others=>'1');                                                                -- Float the bus as high when not driven.
    MZ_SYSMEM_A16            <= T80_A16           when CONFIG(MZ_80C) = '1'   else T80_A16           when CONFIG(MZ_80B) = '1' and MZ_SWP_MEM_BANK_n = '1' else '0' & T80_A16(14 downto 0);
    MZ_CS_ROM_n              <= MZ80C_CS_ROM_n    when CONFIG(MZ_80C) = '1'   else MZ80B_CS_ROM_n;
    MZ_CS_RAM_n              <= MZ80C_CS_RAM_n    when CONFIG(MZ_80C) = '1'   else MZ80B_CS_RAM_n;
    MZ_CS_VRAM_n             <= MZ80C_CS_VRAM_n   when CONFIG(MZ_80C) = '1'   else MZ80B_CS_VRAM_n;
    MZ_CS_MEM_G_n            <= MZ80C_CS_MEM_G_n  when CONFIG(MZ_80C) = '1'   else '1';
    MZ_CS_GRAM_n             <= MZ80C_CS_GRAM_n   when CONFIG(MZ_80C) = '1'   else MZ80B_CS_GRAM_n;
    MZ_CS_IO_GFB_n           <= MZ80C_CS_IO_GFB_n when CONFIG(MZ_80C) = '1'   else MZ80B_CS_IO_GFB_n;
    MZ_CS_IO_G_n             <= '1'               when CONFIG(MZ_80C) = '1'   else MZ80B_CS_IO_G_n;
    audio_l_o                <= MZ80C_AUDIO_L     when CONFIG(MZ_80C) = '1'   else MZ80B_AUDIO_L;
    audio_r_o                <= MZ80C_AUDIO_R     when CONFIG(MZ_80C) = '1'   else MZ80B_AUDIO_R;
    MZ_VGATE_n               <= MZ80C_VGATE_n     when CONFIG(MZ_80C) = '1'   else MZ80B_VGATE_n;
    MZ_CMT_BUS_IN            <= MZ80C_CMT_BUS_IN  when CONFIG(MZ_80C) = '1'   else MZ80B_CMT_BUS_IN;

    MZ_KEYB_SCAN             <= MZ80C_KEYB_SCAN   when CONFIG(MZ_80C) = '1'   else MZ80B_KEYB_SCAN;
    MZ_KEYB_STALL            <= MZ80C_KEYB_STALL  when CONFIG(MZ_80C) = '1'   else MZ80B_KEYB_STALL;

    -- VGA output in original format or upscaled.
    --
    VGA_HS_O                 <= not MZ_HSYNC_n;
    VGA_VS_O                 <= not MZ_VSYNC_n;
    VGA_R_O                  <= MZ_R;
    VGA_G_O                  <= MZ_G;
    VGA_B_O                  <= MZ_B;
    VGA_VB_O                 <= MZ_VBLANK;
    VGA_HB_O                 <= MZ_HBLANK;

    -- Parent signals onto local wires.
    --
    MZ_PS2_KEY               <= ps2_key;
    MZ_IOCTL_DOWNLOAD        <= ioctl_download;
    MZ_IOCTL_UPLOAD          <= ioctl_upload;
    MZ_IOCTL_CLK             <= ioctl_clk;
    MZ_IOCTL_WR              <= ioctl_wr;
    MZ_IOCTL_RD              <= ioctl_rd;
    MZ_IOCTL_ADDR            <= ioctl_addr;
    MZ_IOCTL_DOUT            <= ioctl_dout;
    IOCTL_DIN                <= X"000000" & MZ_IOCTL_DIN_SYSROM when MZ_IOCTL_RENROM = '1'                               -- System ROM
                                else
                                X"000000" & MZ_IOCTL_DIN_SYSRAM when MZ_IOCTL_RENRAM = '1'                               -- System RAM
                                else
                                MZ_IOCTL_DIN_VIDEO          when IOCTL_ADDR(24 downto 20) = "00011"                  -- Video RAM
                                else
                                MZ_IOCTL_DIN_VIDEO          when IOCTL_ADDR(24 downto 20) = "00110"                  -- PCG
                                else
                                MZ_IOCTL_DIN_VIDEO          when IOCTL_ADDR(24 downto 20) = "00101"                  -- CGROM
                                else
                                MZ_IOCTL_DIN_MCTRL          when IOCTL_ADDR(24)           = '1'                      -- MCTRL Registers
                                else
                                MZ_IOCTL_DIN_CMT            when IOCTL_ADDR(24 downto 20) = "00100"                  -- CMT
                                else                               
                                MZ_IOCTL_DIN_KEY            when IOCTL_ADDR(24 downto 20) = "00010"                  -- Key Matrix
                                else
                                MZ_IOCTL_DIN_MZ80C          when CONFIG(MZ_80C) = '1'                                -- MZ80C memory.
                                else
                                MZ_IOCTL_DIN_MZ80B          when CONFIG(MZ_80B) = '1'                                -- MZ80B memory.
                                else
                                (others=>'0');

    --
    -- Control Signals
    --
    T80_RST_n                <= not MZ_SYSTEM_RESET;
    --
    MZ_MEMWR                 <= not T80_WR_n;
    WENSYSRAM                <= MZ_MEMWR when MZ_CS_RAM_n = '0'                                          -- Write enable to System RAM
                                else '0';
    MZ_IOCTL_WENROM          <= '1'   when MZ_IOCTL_ADDR(24 downto 20) = "00000" and MZ_IOCTL_WR = '1'   -- Write enable from HPS to ROM.
                                else '0';
    MZ_IOCTL_WENRAM          <= '1'   when MZ_IOCTL_ADDR(24 downto 20) = "00001" and MZ_IOCTL_WR = '1'   -- Write enable from HPS to RAM.
                                else '0';
    MZ_IOCTL_RENROM          <= '1'   when MZ_IOCTL_ADDR(24 downto 20) = "00000" and MZ_IOCTL_RD = '1'   -- Read enable from ROM to HPS.
                                else '0';
    MZ_IOCTL_RENRAM          <= '1'   when MZ_IOCTL_ADDR(24 downto 20) = "00001" and MZ_IOCTL_RD = '1'   -- Read enable from RAM to HPS.
                                else '0';

    -- System ROM. 128K split up into chunks which are enabled according to the running machine. The ROM can be accessed by the
    -- HPS via the IOCTL bus and updated as necessary.
    --
    --                                         16    15   14   13   12   11            16     15   14   13   12   11
    -- K   4096    0         4095    0000000    0    0    0    0    0    0    0000FFF    0    0    0    0    0    1
    --     4096    4096      8191    0001000    0    0    0    0    1    0    0001FFF    0    0    0    0    1    1
    --     2048    8192     10239    0002000    0    0    0    1    0    0    00027FF    0    0    0    1    0    0
    --     2048    10240    12287    0002800    0    0    0    1    0    1    0002FFF    0    0    0    1    0    1
    --     2048    12288    14335    0003000    0    0    0    1    1    0    00037FF    0    0    0    1    1    0
    -- C   4096    14336    18431    0003800    0    0    0    1    1    1    00047FF    0    0    1    0    0    0
    --     4096    18432    22527    0004800    0    0    1    0    0    1    00057FF    0    0    1    0    1    0
    --     2048    22528    22527    0005800    0    0    1    0    1    1    0005FFF    0    0    1    0    1    1
    --     2048    22528    24575    0006000    0    0    1    1    0    0    00067FF    0    0    1    1    0    0
    --     2048    24576    26623    0006800    0    0    1    1    0    1    0006FFF    0    0    1    1    0    1
    -- 12  4096    18432    22527    0007000    0    0    1    1    1    0    0007FFF    0    0    1    1    1    1
    --     4096    22528    26623    0008000    0    1    0    0    0    0    0008FFF    0    1    0    0    0    1
    --     2048    26624    28671    0009000    0    1    0    0    1    0    00097FF    0    1    0    0    1    0
    --     2048    28672    30719    0009800    0    1    0    0    1    1    0009FFF    0    1    0    0    1    1
    --     2048    30720    32767    000A000    0    1    0    1    0    0    000A7FF    0    1    0    1    0    0
    -- A   4096    22528    26623    000A800    0    1    0    1    0    1    000B7FF    0    1    0    1    1    0
    --     4096    26624    30719    000B800    0    1    0    1    1    1    000C7FF    0    1    1    0    0    0
    --     2048    30720    32767    000C800    0    1    1    0    0    1    000CFFF    0    1    1    0    0    1
    --     2048    32768    34815    000D000    0    1    1    0    1    0    000D7FF    0    1    1    0    1    0
    --     2048    34816    36863    000D800    0    1    1    0    1    1    000DFFF    0    1    1    0    1    1
    -- 7   4096    26624    30719    000E000    0    1    1    1    0    0    000EFFF    0    1    1    1    0    1
    --     4096    30720    34815    000F000    0    1    1    1    1    0    000FFFF    0    1    1    1    1    1
    --     2048    34816    36863    0010000    1    0    0    0    0    0    00107FF    1    0    0    0    0    0
    --     2048    36864    38911    0010800    1    0    0    0    0    1    0010FFF    1    0    0    0    0    1
    --     2048    38912    40959    0011000    1    0    0    0    1    0    00117FF    1    0    0    0    1    0
    -- 8   4096    30720    34815    0011800    1    0    0    0    1    1    00127FF    1    0    0    1    0    0
    --     4096    34816    38911    0012800    1    0    0    1    0    1    00137FF    1    0    0    1    1    0
    --     2048    38912    40959    0013800    1    0    0    1    1    1    0013FFF    1    0    0    1    1    1
    --     2048    40960    43007    0014000    1    0    1    0    0    0    00147FF    1    0    1    0    0    0
    --     2048    43008    45055    0014800    1    0    1    0    0    1    0014FFF    1    0    1    0    0    1
    -- B   2048    34816    36863    0015000    1    0    1    0    1    0    00157FF    1    0    1    0    1    0
    --     2048    36864    38911    0015800    1    0    1    0    1    1    0015FFF    1    0    1    0    1    1
    --     2048    38912    40959    0016000    1    0    1    1    0    0    00167FF    1    0    1    1    0    0
    --     2048    40960    43007    0016800    1    0    1    1    0    1    0016FFF    1    0    1    1    0    1
    --     2048    43008    45055    0017000    1    0    1    1    1    0    00177FF    1    0    1    1    1    0
    -- 20  2048    36864    38911    0017800    1    0    1    1    1    1    0017FFF    1    0    1    1    1    1
    --     2048    38912    40959    0018000    1    1    0    0    0    0    00187FF    1    1    0    0    0    0
    --     2048    40960    43007    0018800    1    1    0    0    0    1    0018FFF    1    1    0    0    0    1
    --     2048    43008    45055    0019000    1    1    0    0    1    0    00197FF    1    1    0    0    1    0
    --     2048    45056    47103    0019800    1    1    0    0    1    1    0019FFF    1    1    0    0    1    1
    --
    MROM_BANK                <= "00000" & T80_A16(11)     when CONFIG(MZ80K)                 = '1' and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "00001" & T80_A16(11)     when CONFIG(MZ80K)                 = '1' and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "000100"                  when CONFIG(MZ80K)                 = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "000101"                  when CONFIG(MZ80K)                 = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "000110"                  when CONFIG(MZ80K)                 = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                "000111"                  when CONFIG(pkgs.mctrl_pkg.MZ80C)  = '1' and T80_A16(11) = '0'                 and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "001000"                  when CONFIG(pkgs.mctrl_pkg.MZ80C)  = '1' and T80_A16(11) = '1'                 and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "001001"                  when CONFIG(pkgs.mctrl_pkg.MZ80C)  = '1' and T80_A16(11) = '0'                 and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "001010"                  when CONFIG(pkgs.mctrl_pkg.MZ80C)  = '1' and T80_A16(11) = '1'                 and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "001011"                  when CONFIG(pkgs.mctrl_pkg.MZ80C)  = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "001100"                  when CONFIG(pkgs.mctrl_pkg.MZ80C)  = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "001101"                  when CONFIG(pkgs.mctrl_pkg.MZ80C)  = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                "00111" & T80_A16(11)     when CONFIG(MZ1200)                = '1' and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "01000" & T80_A16(11)     when CONFIG(MZ1200)                = '1' and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "010010"                  when CONFIG(MZ1200)                = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "010011"                  when CONFIG(MZ1200)                = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "010100"                  when CONFIG(MZ1200)                = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                "010101"                  when CONFIG(MZ80A)                 = '1' and T80_A16(11) = '0'                 and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "010110"                  when CONFIG(MZ80A)                 = '1' and T80_A16(11) = '1'                 and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "010111"                  when CONFIG(MZ80A)                 = '1' and T80_A16(11) = '0'                 and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "011000"                  when CONFIG(MZ80A)                 = '1' and T80_A16(11) = '1'                 and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "011001"                  when CONFIG(MZ80A)                 = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "011010"                  when CONFIG(MZ80A)                 = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "011011"                  when CONFIG(MZ80A)                 = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                "01110" & T80_A16(11)     when CONFIG(MZ700)                 = '1' and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "01111" & T80_A16(11)     when CONFIG(MZ700)                 = '1' and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "100000"                  when CONFIG(MZ700)                 = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "100001"                  when CONFIG(MZ700)                 = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "100010"                  when CONFIG(MZ700)                 = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                "100011"                  when CONFIG(MZ800)                 = '1' and T80_A16(11) = '0'                 and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "100100"                  when CONFIG(MZ800)                 = '1' and T80_A16(11) = '1'                 and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "100101"                  when CONFIG(MZ800)                 = '1' and T80_A16(11) = '0'                 and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "100110"                  when CONFIG(MZ800)                 = '1' and T80_A16(11) = '1'                 and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "100111"                  when CONFIG(MZ800)                 = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "101000"                  when CONFIG(MZ800)                 = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "101001"                  when CONFIG(MZ800)                 = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                -- MZ80/2000 Series have different rom requirements.
                                "101010"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "101011"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "101100"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "101101"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "101110"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                "101111"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and (CONFIG(NORMAL80) = '0' and CONFIG(COLOUR80) = '0')
                                else
                                "110000"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and (CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1')
                                else
                                "110001"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and T80_A16(15 downto 11) = "11101"
                                else
                                "110010"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and T80_A16(15 downto 11) = "11110"
                                else
                                "110011"                  when CONFIG(pkgs.mctrl_pkg.MZ80B)  = '1' and T80_A16(15 downto 11) = "11111"
                                else
                                "000000"; -- Default to K ROM.

    -- Debug: Every 5 seconds, change the mb led bank to show a set of values (0 -> 7), bank indicated by 1 second of a bank number.
    --
    DEBUG0: if DEBUG_ENABLE = 1 generate
        process( MZ_SYSTEM_RESET, CLKBUS(CKMASTER), DEBUG) begin
            if MZ_SYSTEM_RESET = '1'  then
                debug_counter <= 0;
                flip_counter  <= 0;
    
            elsif rising_edge(CLKBUS(CKMASTER)) then

                if CLKBUS(CKENLEDS) = '1' then
        
                    -- If debug mode is enabled, enable use of sequencer.
                    --
                    if DEBUG(ENABLED) = '1' then
        
                        -- If LEDS are switched on, run the sample sequencer.
                        --
                        if DEBUG(LEDS_ON) = '1' then
            
                            -- The changing of the values displayed depends on the sample frequency as this drives the process.
                            case DEBUG(SMPFREQ) is
                                when "0000" =>  -- CMT/CPU frequency - default to 1s/5s @ 2MHz.
                                    block_flip <= 250000;
                                    bank_flip  <= 10000000;
                                when "0001" =>  -- 1MHz
                                    block_flip <= 800000;
                                    bank_flip  <= 5000000;
                                when "0010" =>  -- 100KHz
                                    block_flip <= 80000;
                                    bank_flip  <= 500000;
                                when "0011" =>  -- 10KHz
                                    block_flip <= 8000;
                                    bank_flip  <= 50000;
                                when "0100" =>  -- 5KHz
                                    block_flip <= 4000;
                                    bank_flip  <= 25000;
                                when "0101" =>  -- 1KHz
                                    block_flip <= 800;
                                    bank_flip  <= 5000;
                                when "0110" =>  -- 500Hz
                                    block_flip <= 400;
                                    bank_flip  <= 2500;
                                when "0111" =>  -- 100Hz
                                    block_flip <= 80;
                                    bank_flip  <= 500;
                                when "1000" =>  -- 50Hz
                                    block_flip <= 40;
                                    bank_flip  <= 250;
                                when "1001" =>  -- 10Hz
                                    block_flip <= 8;
                                    bank_flip  <= 50;
                                when "1010" =>  -- 5Hz
                                    block_flip <= 4;
                                    bank_flip  <= 25;
                                when "1011" =>  -- 2Hz
                                    block_flip <= 1;
                                    bank_flip  <= 10;
                                when "1100" =>  -- 1Hz
                                    block_flip <= 1;
                                    bank_flip  <= 5;
                                when "1101" =>  -- 0.5Hz
                                    block_flip <= 1;
                                    bank_flip  <= 5;
                                when "1110" =>  -- 0.2Hz
                                    block_flip <= 1;
                                    bank_flip  <= 2;
                                when "1111" =>  -- 0.1Hz
                                    block_flip <= 1;
                                    bank_flip  <= 1;
                            end case;
                
                            -- If a subbank has been provided, we dont cycle through the blocks in the bank,
                            -- just fix on the given subbank.
                            --
                            case DEBUG(LEDS_SUBBANK) is
                                when "001" => debug_counter <= 1;
                                when "010" => debug_counter <= 3;
                                when "011" => debug_counter <= 5;
                                when "100" => debug_counter <= 7;
                                when "101" => debug_counter <= 9;
                                when "110" => debug_counter <= 11;
                                when "111" => debug_counter <= 13;
                                when "000" =>
                                    flip_counter <= flip_counter + 1;
                                    if(flip_counter = block_flip-1 and (debug_counter mod 2) = 0) then
                                        flip_counter <= 0;
                                        debug_counter <= debug_counter + 1;
                                    elsif(flip_counter = bank_flip-1) then
                                        flip_counter <= 0;
                                        debug_counter <= debug_counter + 1;
                                    end if;
                            end case;
                
                            -- Bank 0 : T80 Signals
                            if( DEBUG(LEDS_BANK) = "000") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "00010000";                     
                                    when 1 => main_leds(7 downto 0) <= T80_A16(7 downto 0);            -- Address Bus A0->A7
                                    when 2 => main_leds(7 downto 0) <= "00010001";                     
                                    when 3 => main_leds(7 downto 0) <= T80_A16(15 downto 8);           -- Address Bus A8->A15
                                    when 4 => main_leds(7 downto 0) <= "00010010";                     
                                    when 5 => main_leds(7 downto 0) <= T80_DI(7 downto 0);             -- Data Bus D0->D7
                                    when 6 => main_leds(7 downto 0) <= "00010011";                     
                                    when 7 => main_leds(0)          <= T80_RST_n;                      -- T80 signals
                                              main_leds(1)          <= T80_WAIT_n;
                                              main_leds(2)          <= T80_INT_n; 
                                              main_leds(3)          <= T80_BUSRQ_n;
                                              main_leds(4)          <= T80_M1_n;
                                              main_leds(5)          <= T80_IORQ_n;
                                              main_leds(6)          <= T80_RD_n;                              
                                              main_leds(7)          <= T80_WR_n;
                                    when 8 => main_leds(7 downto 0) <= "00010100";                     
                                    when 10=> main_leds(7 downto 0) <= "00010101";                     
                                    when 12=> main_leds(7 downto 0) <= "00010110";                     
                                    when others => main_leds        <= "00010111";
                                end case;
                
                            -- Bank 1 : Video, Keyboard and CMT
                            elsif( DEBUG(LEDS_BANK) = "001") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "00110000";                     
                                    when 1 => main_leds(0)          <= MZ_VBLANK;                      -- Video signals
                                              main_leds(1)          <= MZ_HBLANK;                      -- Video signals
                                              main_leds(2)          <= '0';
                                              main_leds(3)          <= MZ_HSYNC_n;
                                              main_leds(4)          <= MZ_VSYNC_n;
                                              main_leds(5)          <= MZ_R(7);
                                              main_leds(6)          <= MZ_G(7);
                                              main_leds(7)          <= MZ_B(7);
                                    when 2 => main_leds(7 downto 0) <= "00110001";                     
                                    when 3 => main_leds(0)          <= MZ_PS2_KEY(0);                  -- PS2 Keyboard Data
                                              main_leds(1)          <= MZ_PS2_KEY(1);
                                              main_leds(2)          <= MZ_PS2_KEY(2);
                                              main_leds(3)          <= MZ_PS2_KEY(3);
                                              main_leds(4)          <= MZ_PS2_KEY(4);
                                              main_leds(5)          <= MZ_PS2_KEY(5);
                                              main_leds(6)          <= MZ_PS2_KEY(6);
                                              main_leds(7)          <= MZ_PS2_KEY(7);
                                    when 4 => main_leds(7 downto 0) <= "00110010";                     
                                    when 5 => main_leds(0)          <= MZ_PS2_KEY(9);
                                              main_leds(1)          <= MZ_PS2_KEY(10);
                                              main_leds(2)          <= MZ_CS_ROM_n;
                                              main_leds(3)          <= MZ_CS_RAM_n;
                                              main_leds(4)          <= WENSYSRAM;
                                              main_leds(7 downto 5) <= CONFIG(TURBO);
                                    when 6 => main_leds(7 downto 0) <= "00111011";                     
                                    when 7 => main_leds             <= MZ_CMT_DEBUG_LEDS(7 downto 0);
                                    when 8 => main_leds(7 downto 0) <= "00111100";                     
                                    when 9 => main_leds             <= MZ_CMT_DEBUG_LEDS(15 downto 8);
                                    when 10=> main_leds(7 downto 0) <= "00111101";                     
                                    when 11=> main_leds             <= MZ_CMT_DEBUG_LEDS(23 downto 16);
                                    when 12=> main_leds(7 downto 0) <= "00111110";                     
                                    when 13=> main_leds             <= MZ_CMT_DEBUG_LEDS(31 downto 24);
                                    when others => main_leds        <= "00110111";
                                end case;
                
                            -- Bank 2: IOCTL
                            elsif( DEBUG(LEDS_BANK) = "010") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "01010000";                    
                                    when 1 => main_leds             <= MZ_IOCTL_ADDR(23 downto 16);
                                    when 2 => main_leds(7 downto 0) <= "01010001";                     
                                    when 3 => main_leds             <= MZ_IOCTL_ADDR(15 downto 8);
                                    when 4 => main_leds(7 downto 0) <= "01010010";                     
                                    when 5 => main_leds             <= MZ_IOCTL_ADDR(7 downto 0);
                                    when 6 => main_leds(7 downto 0) <= "01010011";                    
                                    when 7 => main_leds(0)          <= MZ_IOCTL_RD;
                                              main_leds(1)          <= MZ_IOCTL_WR;
                                              main_leds(2)          <= MZ_IOCTL_DOWNLOAD;
                                              main_leds(3)          <= MZ_IOCTL_UPLOAD;
                                              main_leds(4)          <= MZ_IOCTL_WENROM;
                                              main_leds(5)          <= MZ_IOCTL_WENRAM;
                                              main_leds(6)          <= MZ_IOCTL_RENROM;
                                              main_leds(7)          <= MZ_IOCTL_RENRAM;
                                    when 8 => main_leds(7 downto 0) <= "01010100";                     
                                    when 10=> main_leds(7 downto 0) <= "01010101";                     
                                    when 12=> main_leds(7 downto 0) <= "01010110";                     
                                    when others => main_leds        <= "01010111";
                                end case;
                
                            -- Bank 3 : Config
                            elsif( DEBUG(LEDS_BANK) = "011") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "01110000";                    
                                    when 1 => main_leds(0)          <= CONFIG(MZ80K);                  -- Mode of operation.
                                              main_leds(1)          <= CONFIG(pkgs.mctrl_pkg.MZ80C);
                                              main_leds(2)          <= CONFIG(MZ1200);
                                              main_leds(3)          <= CONFIG(MZ80A);
                                              main_leds(4)          <= CONFIG(pkgs.mctrl_pkg.MZ80B);
                                              main_leds(5)          <= CONFIG(MZ2000);
                                              main_leds(6)          <= CONFIG(MZ700);
                                              main_leds(7)          <= CONFIG(MZ800);
                                    when 2 => main_leds(7 downto 0) <= "01110001";                     
                                    when 3 => main_leds(0)          <= CONFIG(MZ_KC);
                                              main_leds(1)          <= CONFIG(MZ_A);
                                              main_leds(2)          <= CONFIG(pkgs.mctrl_pkg.MZ_B);
                                              main_leds(3)          <= CONFIG(MZ_80B);
                                              main_leds(4)          <= CONFIG(MZ_80C);
                                              main_leds(5)          <= CONFIG(NORMAL);
                                              main_leds(6)          <= CONFIG(NORMAL80);
                                              main_leds(7)          <= CONFIG(COLOUR);
                                    when 4 => main_leds(7 downto 0) <= "01110010";                     
                                    when 5 => main_leds(0)          <= CONFIG(AUDIOSRC);
                                              main_leds(3 downto 1) <= CONFIG(TURBO);
                                              main_leds(6 downto 4) <= CONFIG(FASTTAPE);
                                              main_leds(7)          <= CONFIG(PCGRAM);
                                    when 6 => main_leds(7 downto 0) <= "01110011";                    
                                    when 7 => main_leds(3 downto 0) <= CONFIG(CPUSPEED);
                                              main_leds(6 downto 4) <= CONFIG(VIDSPEED);
                                              main_leds(7)          <= '0';
                                    when 8 => main_leds(7 downto 0) <= "01110100";                     
                                    when 9 => main_leds(1 downto 0) <= CONFIG(PERSPEED);
                                              main_leds(3 downto 2) <= CONFIG(RTCSPEED);
                                              main_leds(5 downto 4) <= CONFIG(SNDSPEED);
                                              main_leds(7 downto 6) <= CONFIG(BUTTONS);
                                    when 10=> main_leds(7 downto 0) <= "01110101";                     
                                    when 11=> main_leds             <= "00000000";
                                    when 12=> main_leds(7 downto 0) <= "01110110";                     
                                    when 13=> main_leds             <= "00000000";
                                    when others => main_leds        <= "01110111";
                                end case;
                                
                
                            -- Bank 4 & 5: MZ80C Debug Leds
                            elsif( DEBUG(LEDS_BANK) = "100") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "10010000";                    
                                    when 1 => main_leds             <= MZ80C_DEBUG_LEDS(7 downto 0);
                                    when 2 => main_leds(7 downto 0) <= "10010001";                     
                                    when 3 => main_leds             <= MZ80C_DEBUG_LEDS(15 downto 8);
                                    when 4 => main_leds(7 downto 0) <= "10010010";                     
                                    when 5 => main_leds             <= MZ80C_DEBUG_LEDS(23 downto 16);
                                    when 6 => main_leds(7 downto 0) <= "10010011";                     
                                    when 7 => main_leds             <= MZ80C_DEBUG_LEDS(31 downto 24);
                                    when 8 => main_leds(7 downto 0) <= "10010100";                     
                                    when 9 => main_leds             <= MZ80C_DEBUG_LEDS(39 downto 32);
                                    when 10=> main_leds(7 downto 0) <= "10010101";                     
                                    when 11=> main_leds             <= MZ80C_DEBUG_LEDS(47 downto 40);
                                    when 12=> main_leds(7 downto 0) <= "10010110";                     
                                    when 13=> main_leds             <= MZ80C_DEBUG_LEDS(55 downto 48);
                                    when others => main_leds        <= "10010111";
                                end case;
                            elsif( DEBUG(LEDS_BANK) = "101") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "10110000";                    
                                    when 1 => main_leds             <= MZ80C_DEBUG_LEDS(63 downto 56);
                                    when 2 => main_leds(7 downto 0) <= "10110001";
                                    when 3 => main_leds             <= MZ80C_DEBUG_LEDS(71 downto 64);
                                    when 4 => main_leds(7 downto 0) <= "10110010";                     
                                    when 5 => main_leds             <= MZ80C_DEBUG_LEDS(79 downto 72);
                                    when 6 => main_leds(7 downto 0) <= "10110011";                     
                                    when 7 => main_leds             <= MZ80C_DEBUG_LEDS(87 downto 80);
                                    when 8 => main_leds(7 downto 0) <= "10110100";                     
                                    when 9 => main_leds             <= MZ80C_DEBUG_LEDS(95 downto 88);
                                    when 10=> main_leds(7 downto 0) <= "10110101";                     
                                    when 11=> main_leds             <= MZ80C_DEBUG_LEDS(103 downto 96);
                                    when 12=> main_leds(7 downto 0) <= "10110110";                     
                                    when 13=> main_leds             <= MZ80C_DEBUG_LEDS(111 downto 104);
                                    when others => main_leds        <= "10110111";
                                end case;
                
                            -- Bank 6 & 7 : MZ80B Debug Leds
                            elsif( DEBUG(LEDS_BANK) = "110") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "11010000";                    
                                    when 1 => main_leds             <= MZ80B_DEBUG_LEDS(7 downto 0);
                                    when 2 => main_leds(7 downto 0) <= "11010001";                     
                                    when 3 => main_leds             <= MZ80B_DEBUG_LEDS(15 downto 8);
                                    when 4 => main_leds(7 downto 0) <= "11010010";                     
                                    when 5 => main_leds             <= MZ80B_DEBUG_LEDS(23 downto 16);
                                    when 6 => main_leds(7 downto 0) <= "11010011";                     
                                    when 7 => main_leds             <= MZ80B_DEBUG_LEDS(31 downto 24);
                                    when 8 => main_leds(7 downto 0) <= "11010100";                     
                                    when 9 => main_leds             <= MZ80B_DEBUG_LEDS(39 downto 32);
                                    when 10=> main_leds(7 downto 0) <= "11010101";                     
                                    when 11=> main_leds             <= MZ80B_DEBUG_LEDS(47 downto 40);
                                    when 12=> main_leds(7 downto 0) <= "11010110";                     
                                    when 13=> main_leds             <= MZ80B_DEBUG_LEDS(55 downto 48);
                                    when others => main_leds        <= "11010111";
                                end case;
                            elsif( DEBUG(LEDS_BANK) = "111") then
                                case debug_counter is
                                    when 0 => main_leds(7 downto 0) <= "11110000";                    
                                    when 1 => main_leds             <= MZ80B_DEBUG_LEDS(63 downto 56);
                                    when 2 => main_leds(7 downto 0) <= "11110001";                     
                                    when 3 => main_leds             <= MZ80B_DEBUG_LEDS(71 downto 64);
                                    when 4 => main_leds(7 downto 0) <= "11110010";                     
                                    when 5 => main_leds             <= MZ80B_DEBUG_LEDS(79 downto 72);
                                    when 6 => main_leds(7 downto 0) <= "11110011";                     
                                    when 7 => main_leds             <= MZ80B_DEBUG_LEDS(87 downto 80);
                                    when 8 => main_leds(7 downto 0) <= "11110100";                     
                                    when 9 => main_leds             <= MZ80B_DEBUG_LEDS(95 downto 88);
                                    when 10=> main_leds(7 downto 0) <= "11110101";                     
                                    when 11=> main_leds             <= MZ80B_DEBUG_LEDS(103 downto 96);
                                    when 12=> main_leds(7 downto 0) <= "11110110";                     
                                    when 13=> main_leds             <= MZ80B_DEBUG_LEDS(111 downto 104);
                                    when others => main_leds        <= "11110111";
                                end case;
                            end if;
                        end if;
                    end if;
                end if;
            end if;
        end process;
    end generate;
    DEBUG1: if DEBUG_ENABLE = 0 generate
        main_leds   <= (others => '0');
    end generate;
end rtl;
