Sharp MZ Series Emulator v2.0 - Developer’s Guide

Part 1 — Introduction & Target Audience

This guide is aimed at developers who want to understand, modify, or extend the Sharp MZ Series FPGA Emulator running on the tranZPUter SW-700 hardware platform. It covers the complete architecture — from the VHDL design synthesised into the Cyclone IV FPGA and the MAX7000AE CPLD bus manager, through the I/O Processor (K64F ARM Cortex-M4) interface protocol, to the emulation subsystems that faithfully reproduce up to eight Sharp MZ computers in a single FPGA. By the end of this guide, you should be able to add a new emulated machine model, extend an existing peripheral, integrate a new hardware subsystem, or debug timing and functional issues in the design.

Who is this guide for?

Background What you will gain
FPGA / HDL developer Deep understanding of the VHDL architecture, clock domains, memory map, CONFIG bus, and how to add hardware modules
Embedded developer How the K64F ARM I/O Processor communicates with the FPGA via the IOP interface, chip select protocol, and interrupt servicing
tranZPUter hardware owner Complete picture of how the SW-700 board emulates multiple Sharp MZ computers and how to switch between modes
Student / hobbyist End-to-end view of a non-trivial multi-machine FPGA emulation project with real-world build, CI/CD, and debug workflows

Repositories

Repository Content URL
tranZPUter FPGA + CPLD VHDL, schematics, PCB, TZFS software git.eaw.app/eaw/tranZPUter
TZFS tranZPUter Filing System (Z80 assembly) git.eaw.app/eaw/TZFS
SharpMZ Shared Sharp MZ emulation VHDL (common ancestor) git.eaw.app/eaw/SharpMZ

Emulated machines

Model Series Status Key differences
MZ-80K Personal Complete Original 1978 model, Z80 @ 2MHz, monochrome 40x25
MZ-80C Personal Complete Cost-reduced MZ-80K
MZ-1200 Personal Complete Compact desktop, MZ-80A predecessor
MZ-80A Personal Complete Enhanced MZ-80K, most popular model
MZ-700 Personal Complete Colour display, different keyboard matrix, 3.58MHz
MZ-800 Personal Partial Extended MZ-700, enhanced graphics modes, QD drive
MZ-80B Business Complete Business series, 80-column display, GRAM, Z80 PIO
MZ-2000 Business Partial Enhanced MZ-80B, FDD support, APSS tape

For hardware architecture and schematics see the tranZPUter SW-700 page. For user-facing operation and TZFS commands see the TZFS User Manual. For TZFS source walkthrough see the TZFS Developer’s Guide. For the MiSTer (Cyclone V) variant of this emulator see the Sharp MZ MiSTer Developer’s Guide.


Part 2 — Hardware Platform Overview

The tranZPUter SW-700 v1.3 is a custom PCB that physically replaces the Z80 CPU in a Sharp MZ-700, MZ-80A, or MZ-2000. It sits in the Z80 socket on the host machine's mainboard and presents itself electrically as the original CPU, while internally hosting an FPGA, a CPLD, an ARM microcontroller, and 512KB of SRAM. The board can operate in several modes: as a transparent pass-through (hard Z80 on the mainboard still executes), as a video enhancement (FPGA provides upgraded display output), as a soft CPU host (T80 Z80 or ZPU Evolution running in the FPGA), or as a complete Sharp MZ series emulator (the emuMZ build).

FPGA: Cyclone IV E (CYC1000 module)

The FPGA is an Intel (Altera) Cyclone IV E device mounted on a CYC1000 carrier module. Two device variants are supported:
Parameter EP4CE115F23I7 EP4CE75F23I7
Logic elements 114,480 75,408
Embedded memory 3,981 Kbits 2,745 Kbits
Embedded multipliers 266 (18x18) 200 (18x18)
PLLs 4 4
Package FBGA-484 FBGA-484
Speed grade I7 (industrial) I7 (industrial)
The larger EP4CE115 is the primary target for the full emuMZ build, which requires substantial block RAM for ROM/RAM storage and logic for eight machine emulations. The EP4CE75 can accommodate the coreMZ (video-only) and coreMZ_SoftCPU builds but is tight for the full emuMZ variant.

CPLD: MAX7000AE (EPM7512AETC144-10)

The CPLD is an Altera MAX7000AE with 512 macro cells. It sits between the host mainboard's 5V Z80 bus and the 3.3V FPGA/SRAM, performing voltage translation, bus arbitration, memory mode decoding, and clock multiplexing. The CPLD is 5V-tolerant on all inputs, allowing it to interface directly with TTL-level mainboard signals without external level translators.

I/O Processor: ARM Cortex-M4 (K64F)

The K64F is a Freescale (NXP) Kinetis ARM Cortex-M4 microcontroller running at 120MHz. In the tranZPUter architecture it serves as the I/O Processor (IOP), providing services that the FPGA cannot efficiently handle in hardware: SD card file system access, tape image loading/saving, floppy disk image management, user interface menus, and host configuration. The K64F communicates with the FPGA through a parallel interface consisting of chip select lines, a 6-bit address bus, an 8-bit bidirectional data bus, and read/write strobes.

SRAM: 512KB Static RAM

A 512KB SRAM device provides the Z80 memory space, mapped in 64KB pages controlled by the CPLD's TZMM (tranZPUter Memory Mode) register. The SRAM is accessible by both the hard Z80 (via the CPLD) and the soft T80 (via the FPGA), with the CPLD controlling page selection and the FPGA providing additional address decoding for the emuMZ variant.

Host machine support

Host Socket CPLD variant Notes
MZ-700 Z80 DIP-40 tranZPUterSW700 Primary development target
MZ-80A Z80 DIP-40 tzpuSW700_MZ80A Different mainboard I/O decode
MZ-2000 Z80 DIP-40 tzpuSW700_MZ2000 Business series bus timing

Part 3 — Architecture Overview

The FPGA design is organised into three build variants, each implemented as a distinct top-level VHDL entity. All three share the VideoController module; they differ in whether they include soft CPU cores and/or the full Sharp MZ emulation subsystem.

Three build variants

Variant Top-level entity Contents FPGA utilisation (EP4CE115)
coreMZ coreMZ.vhd VideoController only ~15% LE, ~20% BRAM
coreMZ_SoftCPU coreMZ_SoftCPU.vhd VideoController + T80 + ZPU Evolution ~35% LE, ~45% BRAM
coreMZ_emuMZ coreMZ_emuMZ.vhd VideoController + full Sharp MZ emulation ~70% LE, ~85% BRAM

Module hierarchy (coreMZ_emuMZ variant)

coreMZ (top-level entity, 1783 lines)
├── clkgen          - 128MHz PLL, programmable clock dividers (571 lines)
│                     CKMASTER 8MHz, CKENCPU variable 2-32MHz, CKENHOST, CKSOUND, CKRTC
├── VideoController - Multi-mode video rendering engine (5400 lines)
│                     40/80 col, mono/colour, VGA scaling, OSD overlays, palette
├── mctrl           - Machine control: 91-bit CONFIG bus, register decode, reset (689 lines)
├── T80             - Z80-compatible soft CPU core (T80se wrapper)
├── arbiter         - Round-robin bus arbitration with 1-second watchdog (653 lines)
├── keymatrix       - PS/2 to Sharp MZ keyboard translation (1222 lines)
├── cmt             - Cassette tape interface with APSS support (1806 lines)
├── fdd             - Floppy disk controller, WD1793 emulation (355 lines)
├── iointr          - 8-interrupt FIFO for I/O processor (325 lines)
├── snd             - SN76489 sound + i8253 audio subsystem (369 lines)
├── mz80k_hw        - Personal series hardware controller (1416 lines)
│                     MZ-80K/C/1200/80A/700/800 memory map and I/O
│   ├── i8255       - Programmable Peripheral Interface
│   └── i8254       - Programmable Interval Timer
└── mz80b_hw        - Business series hardware controller (676 lines)
                      MZ-80B/2000/2200/2500 memory map and I/O
    ├── i8255       - PPI (alternate configuration)
    ├── i8254       - PIT (cascade mode)
    └── z8420       - Z80 PIO (Parallel I/O)

Data flow

The emuMZ variant has two independent data paths:
  1. Emulation path — the T80 soft CPU executes Sharp MZ software, reading/writing ROM, RAM, video, peripherals, and cassette via address-decoded chip selects. This runs entirely within the FPGA clock domain using the CKMASTER clock with clock enables.

  2. IOP path — the K64F ARM processor communicates with the FPGA via the parallel IOP interface, sending configuration registers, ROM images, tape data, floppy disk images, and keyboard maps. This is asynchronous to the emulation clock.

Both paths can access shared resources (CONFIG registers, CMT buffers, keyboard matrix) without contention because the arbiter module serialises competing requests using a round-robin scheme.

Part 4 — FPGA Top-Level Entity

The top-level entity coreMZ (defined in coreMZ_emuMZ.vhd) declares all physical FPGA pin connections and contains the instantiation of every sub-module. Its architecture (rtl) is primarily a wiring exercise — it connects sub-module ports via internal signals and contains the tri-state bus multiplexing logic that switches between hard Z80 bus signals and soft CPU bus signals.

Entity ports

The entity port list groups signals by function:
Group Signals Direction Purpose
Clocks CLOCK_50, CTLCLK, SYSCLK, VZ80_CLK in 50MHz base, external override, mainboard system, Z80 bus clock
Address bus VZ80_ADDR[15:0] inout Z80 address — active output when soft CPU drives, input when hard Z80 active
Data bus VZ80_DATA[7:0] inout Z80 data — active output on reads from FPGA resources, input on writes
Control VZ80_MREQn, IORQn, RDn, WRn, M1n inout Active output from soft CPU or input from hard Z80
Video decoded VIDEO_RDn, VIDEO_WRn in CPLD-decoded video controller access strobes
VGA output VGA_R/G/B[3:0], HSYNC_OUTn, VSYNC_OUTn out 4-bit per channel RGB + sync
Composite COLR_OUT, CSYNC_OUTn, CSYNC_OUT out Composite video signals
Mainboard video in V_CSYNC, V_HSYNCn, V_VSYNCn, V_R, V_G, V_B in Original mainboard video for pass-through or blending
Multiplexed pins VWAITn_A21_V_CSYNC, etc. inout Pins shared between address extension, CPU control, and video input

Tri-state bus multiplexing

The address and data buses are shared between the hard Z80 on the mainboard and the soft T80 in the FPGA. The top-level entity contains tri-state drivers controlled by the CPU_CFG_DATA register and the MODE_EMU flag:
-- When emuMZ is active, the FPGA drives the address and data buses.
-- When the hard Z80 is active, these pins are high-impedance inputs.
VZ80_ADDR <= T80_ADDR           when MODE_EMU = '1' and VZ80_BUSACKni = '0'
             else (others => 'Z');

VZ80_DATA <= T80_DATA_OUT       when MODE_EMU = '1' and CORE_WRn = '0'
             else (others => 'Z');
The multiplexed pins (VWAITn_A21_V_CSYNC, VZ80_A20_RFSHn_V_HSYNCn, etc.) serve triple duty depending on the active mode. In emuMZ mode they carry the upper address bits (A16-A21) for accessing FPGA block RAM beyond the 64KB Z80 space. In video-only mode they carry the mainboard's video sync signals. In soft CPU mode they carry CPU status outputs (HALT, RFSH).

Key internal signals

Signal Width Purpose
CPU_CFG_DATA 8 bits CPU selection and control register (I/O 0x6C)
CPLD_CFG_DATA 8 bits CPLD configuration register (I/O 0x6E)
MODE_EMU 1 bit Flag: emuMZ module active
CORE_ADDR 24 bits Extended address from active CPU (supports FPGA memory beyond 64KB)
CORE_DATA_OUT/IN 32 bits Wide data path for ZPU and video controller word access
CONFIG 91 bits Machine configuration bus from mctrl
CLKBUS 7 bits Clock distribution bus from clkgen

Part 5 — Clock Architecture

The clkgen module (571 lines) generates all clocks from a single 50MHz input using a PLL to produce a 128MHz master and programmable divider chains. A key design principle is that all variable-frequency clocks use clock enables on the master clock, not separate clock domains. This eliminates clock domain crossing issues and simplifies timing analysis.

Clock bus (CLKBUS)

A 7-bit CLKBUS vector distributes all clocks to every module:
Index Name Function Typical frequency
0 CKMASTER Master synchronous clock 8MHz (from 128MHz PLL /16)
1 CKENHOST Host machine clock enable ~2MHz (original machine speed)
2 CKSOUND Sound generation clock 3.58MHz or 4MHz
3 CKRTC Real-time clock ~1Hz derived
4 CKENCPU CPU clock enable (variable) 2-32MHz (via TURBO config)
5 CKENPERIPH Peripheral clock enable (i8254, i8255) Machine-dependent
6 CKENFDC Floppy disk controller clock 8MHz

Clock enable technique

Rather than generating separate clock domains — which causes timing closure issues and requires explicit synchronisers — the design uses a single CKMASTER clock with pulsed clock enable signals. The T80 CPU, for example, is clocked at CKMASTER speed but only advances state when CKENCPU pulses high:
-- CPU executes only when CKENCPU pulses
T80se_inst : T80se
    port map (
        CLK_n   => CLKBUS(CKMASTER),
        CLKEN   => CLKBUS(CKENCPU),
        RESET_n => T80_RESETn,
        ...
    );
This keeps the entire design in a single clock domain while supporting variable CPU speeds. All state machines, counters, and registers sample CKMASTER and qualify their updates with the appropriate clock enable.

PLL configuration

The PLL takes the 50MHz CLOCK_50 input and produces:
PLL output Frequency Use
c0 128MHz Master PLL output, divided down for all enables
c1 75MHz Video pixel clock (optional high-res modes)
The 128MHz output feeds a chain of binary dividers. Each divider produces a clock enable pulse at the target frequency by toggling a single-cycle pulse every N master cycles. For example, to generate a 2MHz CPU enable from 128MHz, the divider counts to 64 and emits a one-cycle pulse.

Configurable frequencies

The CONFIG bus from mctrl controls frequency selection via these bit fields:
CONFIG bits Parameter Options
[61:59] TURBO CPU speed: 2MHz, 4MHz, 8MHz, 16MHz, 32MHz
[84:81] CPUSPEED Active CPU speed (derived from TURBO + machine type)
[86:85] PERSPEED Peripheral clock selection
[88:87] RTCSPEED RTC clock selection
[90:89] SNDSPEED Sound clock selection
When the user or I/O processor changes TURBO via the CONFIG registers, clkgen recalculates the divider value and seamlessly transitions to the new frequency on the next divider cycle. There is no glitch because the enable pulse simply changes spacing — the underlying CKMASTER clock remains constant.

Part 6 — Machine Control & Configuration

The mctrl module (689 lines, plus the mctrl_pkg package at the top of the same file) is the central configuration authority for the emulation. It maintains the 91-bit CONFIG bus that controls every aspect of the emulated machine — which computer model is active, display mode, CPU speed, audio source, tape speed, floppy options, and more. It also manages reset distribution.

CONFIG bus bit assignments

The CONFIG bus is a wide vector that acts as a hardware configuration register file. Every module reads the bits relevant to its function. The complete map (from mctrl_pkg):
Bits Constant Purpose
[10:0] CURRENTMACHINE Machine type — one-hot encoding (MZ80K=0, MZ80C=1, … MZ2500=10)
[11] MZ_KC Aggregate: machine is MZ-80K or MZ-80C series
[12] MZ_A Aggregate: machine is MZ-1200 or MZ-80A series
[13] MZ_B Aggregate: machine is MZ-2000/MZ-80B series
[15] MZ_K Aggregate: machine is any Personal series
[19:16] CURRENTDISPLAY Display mode: NORMAL(16), NORMAL80(17), COLOUR(18), COLOUR80(19)
[23:20] VGAMODE VGA output mode (640x400, 640x480, pixel doubling)
[24] USERROM User ROM (E800-EFFF) enable
[25] FDCROM FDC ROM (F000-FFFF) enable
[26] FDDENABLE Floppy Disk Controller enable
[27] FDDINTEN FDC interrupt enable
[31:28] FDDDISKREADY Per-drive disk loaded status (4 drives)
[35:32] FDDPOLARITY Per-drive data polarity
[39:36] FDDWRPROTECT Per-drive write protect
[42:40] RAMINSTALLED RAM installed configuration
[50:43] GRAPHICSOPTION GRAM options (GRAMI/II/III, PCG, MZ1R25)
[51] AUDIOSRC Audio source: 0=sound generator, 1=tape audio
[55:52] AUDIOVOL Volume (4-bit, 16 levels)
[57:56] AUDIOMIX Audio channel mixing
[58] AUDIOHW Audio hardware selection (host or FPGA)
[61:59] TURBO CPU speed selection
[64:62] FASTTAPE Tape read/write speed multiplier
[66:65] BUTTONS External button state (CMT play/record)
[67] PCGRAM PCG mode: ROM(0) or RAM(1)
[68] VRAMWAIT Insert video wait states on CPU access
[69] VRAMDISABLE Disable VRAM display output
[70] GRAMDISABLE Disable GRAM display output
[71] MENUENABLE Enable OSD menu overlay
[72] STATUSENABLE Enable OSD status overlay
[73] BOOT_RESET MZ-80B/2000 Boot IPL Reset enable
[74] CMTASCII_IN CMT Sharp ASCII to ASCII conversion (inbound)
[75] CMTASCII_OUT CMT ASCII to Sharp ASCII conversion (outbound)
[76] CMT_HWMODE Hardware CMT drive(1) or emulation(0)
[80:77] MZ800_SWITCH MZ-800 hardware selection switches
[84:81] CPUSPEED Active CPU speed (derived)
[86:85] PERSPEED Active peripheral speed
[88:87] RTCSPEED Active RTC speed
[90:89] SNDSPEED Active sound speed

I/O Processor register interface

The mctrl module presents 16 addressable registers to the I/O Processor. The K64F writes to these registers (via the IOP bus with IOP_MCTRL_CSn asserted) to configure the emulation. Each register maps to a subset of CONFIG bits:
IOP Address Register CONFIG bits affected
0x00 Machine select [10:0] CURRENTMACHINE + aggregate flags
0x01 Display mode [19:16] CURRENTDISPLAY, [23:20] VGAMODE
0x02 CPU/tape speed [61:59] TURBO, [64:62] FASTTAPE
0x03 Audio config [51] AUDIOSRC, [55:52] AUDIOVOL, [57:56] AUDIOMIX
0x04 ROM enables [24] USERROM, [25] FDCROM
0x05 FDD config [26] FDDENABLE, [27] FDDINTEN, [31:28] FDDDISKREADY
0x06 RAM config [42:40] RAMINSTALLED, [50:43] GRAPHICSOPTION
0x07 OSD/misc [71] MENUENABLE, [72] STATUSENABLE, [67] PCGRAM
0x08 CMT config [74] CMTASCII_IN, [75] CMTASCII_OUT, [76] CMT_HWMODE
0x0F Reset control System-wide reset generation

Reset management

The mctrl module generates a unified MCTRL_RESETn signal from three sources:
  1. Cold reset — power-on reset counter (4-bit, ~16 CKMASTER cycles)
  2. Warm reset — I/O Processor writes to reset register (0x0F)
  3. CPU reset — CPU_CFG_DATA bit 7 set
All resets are synchronised to CKMASTER to prevent metastability. The reset output fans out to every sub-module.

Part 7 — CPU Switching Mechanism

One of the defining features of the tranZPUter SW-700 is its ability to switch between multiple CPUs at runtime. The mechanism is controlled through the CPU_CFG_DATA register at I/O address 0x6C and coordinated between the CPLD bus manager and the FPGA.

CPU Configuration Register (I/O 0x6C)

Bit(s) Function Values
[5:0] CPU selection 000000=Hard Z80, 000001=T80, 000010=ZPU, 000100=emuMZ
[6] Clock enable 1=soft CPU clock running, 0=halted
[7] CPU Reset 1=hold soft CPU in reset

Available CPU modes

Mode CPU_CFG_DATA[5:0] CPU Description
Hard Z80 000000 Mainboard Z80 Original CPU on the host machine, FPGA provides video only
Soft T80 000001 T80 in FPGA Z80-compatible soft core, runs TZFS and Sharp MZ software
ZPU Evolution 000010 ZPU in FPGA 32-bit stack processor, runs zOS
emuMZ 000100 T80 + full emulation Complete Sharp MZ emulation, all peripherals in FPGA

Switching sequence

The CPU switch is initiated by TZFS (running on the current CPU) writing to I/O port 0x6C. The sequence is:
  1. TZFS writes the new CPU_CFG_DATA value with bit 7 (reset) set — this holds the target CPU in reset.
  2. The CPLD detects the I/O write to 0x6C and updates its internal CPU mode register.
  3. If switching away from the hard Z80, the CPLD asserts BUSRQn to the mainboard Z80. When BUSACKn is received, the hard Z80 tri-states its bus and the FPGA takes control.
  4. If switching to the hard Z80, the FPGA tri-states its bus drivers and the CPLD releases BUSRQn.
  5. TZFS (or the I/O processor) clears bit 7 to release the target CPU from reset.
  6. The new CPU begins executing from its reset vector.

emuMZ mode entry

When emuMZ mode is selected (CPU_CFG_DATA[2]=1), additional initialisation occurs:
  1. The arbiter module activates, taking control of bus arbitration between the T80, keyboard scanner, CMT interface, interrupt generator, and sound modules.
  2. The mctrl module loads the default CONFIG for the selected machine model.
  3. The I/O processor loads the appropriate monitor ROM into the FPGA block RAM.
  4. The T80 is released from reset and begins executing the monitor ROM at address 0x0000.

Part 8 — Video Controller

The VideoController module (5400 lines in VideoController/VideoController.vhd) is the largest single module in the design. It implements the complete display system for all emulated machines, including character rendering, colour attribute overlay, graphics framebuffer compositing, VGA upscaling, palette management, and OSD (On-Screen Display) overlays for the menu and status systems.

Display modes

Mode Resolution Colours Machines
Monochrome 40x25 320x200 Green/White MZ-80K/C/1200/80A
Colour 40x25 320x200 8 colours MZ-700/800
Monochrome 80x25 640x200 Green/White MZ-80A (enhanced)
Colour 80x25 640x200 8 colours MZ-80B/2000
Graphics 320x200 320x200 8 colours MZ-700/800 (GRAM)
Graphics 640x200 640x200 8 colours MZ-80B/2000 (GRAM I/II/III)

Rendering pipeline

The video rendering pipeline processes each scanline in a pipelined sequence:
  1. Timing generation: Horizontal and vertical counters produce sync, blanking, and active display windows. Each machine model has its own timing parameters selected by CONFIG[10:0].

  2. Character fetch: During each character cell (8 pixels wide), the VRAM address is computed from the H/V position, the character code is read from VRAM, and the corresponding glyph row is fetched from CGROM (or CGRAM if PCG is enabled).

  3. Attribute fetch: The same character cell address reads the colour attribute from ARAM. The attribute byte encodes foreground colour (3 bits), background colour (3 bits), and optional blink/underline flags.

  4. Graphics overlay: For machines with GRAM (MZ-80B/2000 or MZ-700/800 with graphics extension), the corresponding graphics pixel row is read from the Red, Green, and Blue framebuffers. The blend mode (XOR, OR, AND, replace) is selected by the graphics control register.

  5. Palette mapping: The 3-bit colour index is expanded to 12-bit RGB (4 bits per channel) through a programmable palette LUT. The palette supports 4096 colours.

  6. VGA upscaling: The native resolution (320x200 or 640x200) is scaled to the configured VGA output mode (640x400, 640x480, or 800x600) using pixel doubling and line replication.

  7. OSD compositing: If the menu or status overlay is enabled, the OSD framebuffer pixels are composited on top of the emulation display during the appropriate screen regions.

Video memory map (direct 24-bit addressing)

When the video controller is accessed via the extended 24-bit address bus (used by the ZPU or I/O processor), the following memory map applies:
Address range Size Content
0x200000-0x20FFFF 64KB I/O registers (palette, GPU control, mode select)
0x210000-0x21FFFF 64KB Video RAM, attribute RAM, character generator RAM
0x240000-0x243FFF 16KB Red framebuffer plane
0x250000-0x253FFF 16KB Blue framebuffer plane
0x260000-0x263FFF 16KB Green framebuffer plane
0x270000-0x2A1FFF ~200KB OSD framebuffers (menu + status)
0x320000 8KB Status frame buffer
0x322000 8KB Menu overlay frame buffer
0x324000 1KB Video parameter array (32x32 entries)
0x324400 4B Current video mode register

Z80 address space video access

From the Z80's perspective (16-bit addressing), video memory is mapped into the standard Sharp MZ locations:
Machine VRAM ARAM CGROM/RAM
MZ-80K/C/1200/80A D000-D7FF (2KB) D800-DFFF (2KB) Read-only CG ROM
MZ-700 D000-D7FF (2KB) D800-DFFF (2KB) Colour attribute in ARAM
MZ-80B/2000 D000-DFFF (4KB) - E000-E7FF (GRAM access)

Part 9 — Memory Architecture

The emuMZ build uses FPGA block RAM exclusively for all emulated machine memory. Unlike the coreMZ and coreMZ_SoftCPU builds (which use the external 512KB SRAM via the CPLD), the emuMZ variant is self-contained within the FPGA — it does not access the host mainboard's RAM at all.

Block RAM allocation

Memory Size Type Init file Purpose
SYSROM 128KB Dual-port ROM combined_mrom.mif Monitor ROMs for all machine models
SYSRAM 64KB Dual-port RAM combined_mainmemory.mif Z80 main memory
VRAM 4KB Dual-port RAM Text display buffer
ARAM 4KB Dual-port RAM Colour attribute RAM
CGROM 32KB Dual-port ROM Character generator ROM (all models)
CGRAM 32KB Dual-port RAM Programmable character RAM (PCG)
GRAM (Red) 16KB Dual-port RAM Graphics framebuffer red plane
GRAM (Green) 16KB Dual-port RAM Graphics framebuffer green plane
GRAM (Blue) 16KB Dual-port RAM Graphics framebuffer blue plane
CMT HDR 128B Dual-port RAM Tape file header cache
CMT DATA 64KB Dual-port RAM Tape data cache
KEYMAP 2KB Dual-port RAM Keyboard mapping table

ROM banking

The SYSROM stores monitor ROMs for all machine models in a single 128KB block. Bank selection is controlled by MROM_BANK[5:0], driven from the CONFIG bus machine selection bits. The upper address bits of the SYSROM select the bank:
Machine Bank index ROM size Address range within SYSROM
MZ-80K 0, 1 4KB + 2KB 0x00000-0x00FFF
MZ-80C 2, 3 4KB + 2KB 0x02000-0x02FFF
MZ-1200 4, 5 4KB + 2KB 0x04000-0x04FFF
MZ-80A 6, 7 4KB + 2KB 0x06000-0x06FFF
MZ-700 8, 9 4KB (1Z-013A) 0x08000-0x08FFF
MZ-800 10, 11 8KB 0x0A000-0x0BFFF
MZ-80B 12, 13 4KB + IPL 0x0C000-0x0CFFF
MZ-2000 14, 15 4KB + IPL 0x0E000-0x0EFFF
Switching machine models at runtime simply changes the bank select — no reloading required. The I/O processor can also write individual ROM banks via the IOP interface for custom ROM testing.

Z80 address decoding

The 64KB Z80 address space is decoded differently per machine family. The mz80k_hw and mz80b_hw modules generate chip selects based on the CONFIG machine type and the Z80 address.

MZ-80A (typical Personal series):

Address range Component Chip select
0x0000-0x0FFF Monitor ROM CS_ROM_n
0x1000-0xCFFF User RAM (48KB) CS_RAM_n
0xD000-0xD7FF VRAM (2KB) CS_VRAM_n
0xD800-0xDFFF Colour attribute RAM CS_ARAM_n
0xE000-0xE007 i8255 PPI CS_IO_PPI_n
0xE008-0xE00B i8254 PIT CS_IO_PIT_n
0xE800-0xEFFF User ROM (optional) CS_USERROM_n
0xF000-0xFFFF FDC ROM (optional) CS_FDCROM_n

MZ-700 (colour Personal series):

Address range Component Chip select
0x0000-0x0FFF Monitor ROM (banked out after boot) CS_ROM_n
0x0000-0xFFFF 64KB RAM (when ROM banked out) CS_RAM_n
0xD000-0xD7FF VRAM CS_VRAM_n
0xD800-0xDFFF Colour attribute RAM CS_ARAM_n
0xE000-0xE003 i8255 PPI CS_IO_PPI_n
0xE004-0xE007 i8254 PIT CS_IO_PIT_n
0xE008 Memory bank control CS_BANKCTL_n

MZ-80B/2000 (Business series):

Address range Component Chip select
0x0000-0x07FF IPL ROM (boot, then banked out) CS_IPL_n
0x0000-0xFFFF 64KB RAM CS_RAM_n
0xD000-0xDFFF VRAM (4KB) CS_VRAM_n
0xE000-0xFFFF GRAM access window CS_GRAM_n
I/O 0xD8-0xDB i8255 PPI CS_IO_PPI_n
I/O 0xD4-0xD7 i8254 PIT CS_IO_PIT_n
I/O 0xF4-0xF7 Z80 PIO CS_IO_PIO_n
I/O 0xF8-0xFD Graphics control CS_IO_GRAM_n

CPU data bus multiplexing

The T80 data input is multiplexed from all memory and peripheral sources:
T80_DI <= SYSROM_DO       when CS_ROM_n     = '0' else
          SYSRAM_DO       when CS_RAM_n     = '0' else
          VIDEO_DO        when CS_VRAM_n    = '0' else
          ARAM_DO         when CS_ARAM_n    = '0' else
          PPI_DO          when CS_IO_PPI_n  = '0' else
          PIT_DO          when CS_IO_PIT_n  = '0' else
          FDD_DO          when CS_FDD_n     = '0' else
          (others => '1');  -- Open-drain pullup simulation
The default '1' simulates the open-drain bus behaviour of real hardware, where unselected devices float high.

Part 10 — Cassette Tape Subsystem

The cmt module (1806 lines) emulates the cassette tape interface for all Sharp MZ models. It implements PWM bit encoding/decoding (matching the original hardware's Manchester-like encoding), tape motor control, the APSS (Automatic Program Search System) for MZ-2000, and a tape data queue managed by the I/O processor.

CMT bus signals

Output signals (CMT_BUS_OUT, 17 bits — FPGA to I/O processor):

Bit Constant Function
0 PLAY_READY Tape playback buffer loaded, ready for playback
1 PLAYING Tape playback in progress
2 RECORD_READY Record buffer full (data available for save)
3 RECORDING Tape recording in progress
4 ACTIVE Transfer active
5 SENSE Tape state sense output to Z80 PPI
6 WRITEBIT Bit value being sent to Z80 (playback)
7 TAPEREADY Cassette loaded in virtual deck
8 WRITEREADY Write permitted
9 APSS_SEEK Start seeking next program (per APSS_DIR)
10 APSS_DIR Seek direction: 0=Rewind, 1=Forward
11 APSS_EJECT Eject cassette
12 APSS_PLAY Play cassette
13 APSS_STOP Stop play/rwd/ff
14 APSS_AUTOREW Deck auto-rewind at tape end
15 APSS_AUTOPLAY Auto-play after APSS action
16 ENDOFTAPE End of tape detected

Input signals (CMT_BUS_IN, 13 bits — Z80 machine to CMT):

Bit Constant Function
0 READBIT Bit value from Z80 (recording)
1 REEL_MOTOR APSS reel motor on/off
2 STOP Stop motor
3 PLAY Play command
4 SEEK Seek (FF/REW)
5 DIRECTION Seek direction: L=Rewind, H=Fast Forward
6 EJECT Eject cassette
7 WRITEENABLE Enable recording
8 AUTOPLAY Enable playback at end of rewind
9 AUTOREW Enable auto-rewind
10 CMTFF Fast forward
11 CMTREW Rewind
12 KINH Keyboard inhibit (blocks FF/REW/STOP/EJECT)

Tape data flow

I/O Processor (K64F)              FPGA (CMT module)                 Z80 CPU (T80)

Load .MZF file ─────────────────→ CMT DATA RAM (64KB) ─── PWM ──→ READBIT → i8255 PPI
 │                                 CMT HDR RAM (128B)               (Port C bit)
 │ (IOP writes via IOP_CMT0_CSn)
 │
 │                                 CMT DATA RAM ←──── PWM ←─────── WRITEBIT → PPI
Save .MZF file ←────────────────── CMT HDR RAM                     (recording)
 (IOP reads via IOP_CMT1_CSn)

MZF tape format

The Sharp MZ tape format (.MZF) consists of a 128-byte header followed by the data body:
Offset Size Content
0x00 1 File type (01=binary, 02=MZ-80K BASIC, 03=data, 05=MZ-700 binary)
0x01 17 Filename (Sharp ASCII, padded with 0x0D)
0x12 2 File size (little-endian)
0x14 2 Load address (little-endian)
0x16 2 Execute address (little-endian)
0x18 104 Comment/padding
0x80+ N Data body (N = file size)

Speed options (FASTTAPE config)

CONFIG[64:62] Speed Baud equivalent
000 1x (original) 1200 baud (MZ-80K) or 2400 baud (MZ-700)
001 2x Slightly faster loading
010 4x Practical loading
011 8x Quick testing
100 16x Development
101 32x Near-instant load

APSS (MZ-2000)

The MZ-2000 supports APSS — Automatic Program Search System — which allows the tape deck to automatically fast-forward or rewind to the next program. The CMT module implements the APSS state machine using the APSS_SEEK, APSS_DIR, APSS_PLAY, and APSS_STOP signals. The I/O processor manages the tape queue (multiple MZF files concatenated on a virtual tape), advancing the file pointer when APSS_SEEK is asserted.

Part 11 — Keyboard & Input

The keymatrix module (1222 lines) translates PS/2 keyboard input into the Sharp MZ keyboard matrix expected by the emulated machines. Each Sharp MZ model uses a different keyboard matrix layout, and the module maintains separate translation tables for each.

PS/2 to Sharp MZ translation

The translation process operates in two stages:
  1. PS/2 decode: The PS/2 serial protocol is decoded into scan codes. Make codes (key press) and break codes (key release) are distinguished by the 0xF0 prefix byte.

  2. Matrix mapping: Each PS/2 scan code is mapped to a (row, column) pair in the Sharp MZ keyboard matrix. The mapping is stored in a lookup table loaded by the I/O processor and can be customised per machine model.

Keyboard matrix sizes

Machine Rows Columns Matrix size
MZ-80K/C/1200 10 8 80 keys
MZ-80A 10 8 80 keys (different layout)
MZ-700 10 8 70 keys (reduced)
MZ-80B/2000 10 8 80 keys (business layout)

Key scanning protocol

The Sharp MZ keyboard interface works through the i8255 PPI. The Z80 writes a scan row number to PPI Port A, then reads the column data from PPI Port B. The keymatrix module intercepts these PPI transactions:
-- When Z80 writes to PPI Port A, latch the scan row
MZ_KEYB_SCAN <= PPI_PORT_A(3 downto 0);

-- When Z80 reads PPI Port B, return the matrix column data for the active row
PPI_PORT_B <= KEYB_MATRIX(to_integer(unsigned(MZ_KEYB_SCAN)));

I/O processor keyboard interface

The I/O processor can also inject keystrokes by writing directly to the keyboard matrix via IOP_KEYB_CSn. This is used for automated testing and for the OSD menu navigation (the menu system runs on the K64F and sends synthetic key events to select menu items).

Break key detection

The MZ_KEYB_BREAKDETECT signal provides a direct indication when the Break key is pressed, bypassing the normal matrix scanning. This is used by the I/O processor to trigger an NMI to the emulated CPU for interactive debugging.

Arbiter interaction

The keyboard module requires bus access to perform its scanning — it must read PPI ports, which are on the emulated Z80 bus. The arbiter grants the keyboard a time slot in the round-robin schedule. The MZ_KEYB_GRANTn signal indicates when the keyboard has bus access; MZ_KEYB_BUSYn tells the arbiter the keyboard is still using the bus.

Part 12 — Sound Subsystem

The snd module (369 lines) implements the audio subsystem, combining the SN76489 sound generator (used by the MZ-700 and MZ-800) with the i8253/i8254 timer-based audio used by the MZ-80K/C/1200/80A families. Audio output is via a sigma-delta DAC or PWM DAC that drives an analogue output pin.

Sound sources

Source Component Machines Capability
i8254 Counter 0 Programmable Interval Timer All Personal series Square wave tone generator
SN76489 Texas Instruments PSG MZ-700, MZ-800 3 tone channels + 1 noise
i8253 (business) Timer MZ-80B, MZ-2000 Square wave via PIT cascade

SN76489 integration

The SN76489 PSG (Programmable Sound Generator) provides three independent tone generators and one noise generator. Each tone channel has a 10-bit frequency divider and a 4-bit volume attenuator. The noise channel supports white noise and periodic noise modes. The module uses an open-source SN76489 VHDL core.

Audio mixing and output

The CONFIG bus controls audio source selection and mixing:
CONFIG bit(s) Function
[51] AUDIOSRC 0=sound generator, 1=tape audio
[55:52] AUDIOVOL 16-level volume control
[57:56] AUDIOMIX Left/right channel blend
[58] AUDIOHW Use host(0) or FPGA(1) audio hardware
The final audio is output through a sigma-delta DAC (sigma_delta_dac module) that converts the digital audio samples to a 1-bit PWM stream. This is low-pass filtered on the PCB to produce the analogue audio signal.

Arbiter interaction

Like the keyboard, the sound module occasionally needs bus access (to process I/O register writes from the Z80). The arbiter grants it a slot via MZ_SND_GRANTn / MZ_SND_BUSYn.

Part 13 — Floppy Disk Controller

The fdd module (355 lines) emulates the Western Digital WD1793 floppy disk controller used by the MZ-80B, MZ-2000, and MZ-800 (with the optional floppy disk interface). The module implements the WD1793 register set and command state machine, with actual disk image data provided by the I/O processor from SD card.

WD1793 register map

Address offset Read Write
0 Status register Command register
1 Track register Track register
2 Sector register Sector register
3 Data register Data register

Drive configuration

Up to four virtual drives are supported, configured via the CONFIG bus:
CONFIG bits Function
[26] FDDENABLE Master enable for FDD subsystem
[27] FDDINTEN Enable interrupt generation on FDD operations
[31:28] FDDDISKREADY Per-drive disk loaded status (4 bits, one per drive)
[35:32] FDDPOLARITY Per-drive data polarity (inverted vs. normal)
[39:36] FDDWRPROTECT Per-drive write protection

Data flow

The I/O processor manages the disk images. When the WD1793 receives a read sector command:
  1. The FDD module generates an interrupt to the I/O processor via the iointr module.
  2. The I/O processor reads the requested track/sector/side from the disk image file on SD card.
  3. The I/O processor writes the sector data into the FDD’s data buffer via IOP_FDD_CSn.
  4. The FDD module presents the data byte-by-byte on the WD1793 data register with appropriate DRQ (Data Request) timing.
Write operations reverse the flow — the FDD module accepts data from the Z80, buffers it, and interrupts the I/O processor to write the sector back to the disk image.

FDC clock

The WD1793 requires a separate clock for its internal timing (step rate, head load, etc.). This is provided by CLKBUS[6] (CKENFDC), typically at 8MHz.

Part 14 — Bus Arbitration

The arbiter module (653 lines) provides a round-robin bus arbitration service for the emulated Z80 bus. In emuMZ mode, multiple agents need access to the emulated bus — the T80 CPU, the keyboard scanner, the CMT interface, the interrupt generator, and the sound module. The arbiter serialises these requests to prevent bus contention.

Arbitration scheme

The arbiter uses a round-robin priority scheme with four bus agents plus the T80 CPU as the default bus master:
Agent Grant signal Busy signal Reset signal Priority slot
T80 CPU (default master) Always active unless preempted
Keyboard MZ_KEYB_GRANTn MZ_KEYB_BUSYn MZ_KEYB_RESETn 0
CMT MZ_CMT_GRANTn MZ_CMT_BUSYn MZ_CMT_RESETn 1
Interrupt MZ_INTR_GRANTn MZ_INTR_BUSYn MZ_INTR_RESETn 2
Sound MZ_SND_GRANTn MZ_SND_BUSYn MZ_SND_RESETn 3

Protocol

Each agent that needs bus access asserts its BUSYn signal low (requesting the bus). The arbiter cycles through agents in round-robin order and asserts GRANTn low for the next requesting agent. While granted, the agent drives the emulated bus (address, data, control) and performs its transaction. When finished, the agent deasserts BUSYn, and the arbiter moves to the next slot.

T80 wait state injection

When an agent other than the T80 has the bus, the arbiter asserts MEMWAITn low, which freezes the T80 via its WAIT input. This ensures the T80 does not attempt a memory or I/O cycle while the bus is occupied. The wait state is transparent to the running Z80 software — it simply extends the current bus cycle.

Watchdog timer

The arbiter includes a 1-second watchdog. If any agent holds the bus for longer than ~1 second without deasserting BUSYn, the arbiter forcibly resets that agent (via its RESETn signal) and releases the bus. This prevents a hung peripheral from locking up the entire emulation.

I/O processor bus request

The I/O processor (K64F) can also request the bus via the BUSRQn input to the arbiter. This is a higher priority than the round-robin agents and is used when the I/O processor needs to perform operations like loading ROM images or reading/writing tape data buffers. When the I/O processor is granted the bus, the T80 receives a BUSRQ and must acknowledge with BUSACK before the I/O processor proceeds.

Initialisation

The ARB_INIT output signal pulses during the initial power-up sequence, allowing all agents to synchronise their state machines before the T80 begins execution.

Part 15 — I/O Processor Interface

The I/O Processor (IOP) interface is the communication path between the K64F ARM Cortex-M4 microcontroller and the FPGA. It uses a parallel bus with chip selects, address, data, and read/write control signals.

Physical signals

Signal Width Direction Function
IOP_CSn (multiple) 1 each K64F → FPGA Chip select for each module (active low)
IOP_ADDR[5:0] 6 K64F → FPGA Register address within selected module
IOP_DIN[7:0] 8 K64F → FPGA Write data
IOP_DOUT[7:0] 8 FPGA → K64F Read data
IOP_WRn 1 K64F → FPGA Write strobe (active low)
IOP_RDn 1 K64F → FPGA Read strobe (active low)

Chip select map

Chip select Module Registers Purpose
IOP_MCTRL_CSn mctrl 16 Machine configuration, reset
IOP_MZ80K_CSn mz80k_hw 16 Personal series PPI/PIT config
IOP_MZ80B_CSn mz80b_hw 16 Business series PPI/PIT/PIO config
IOP_KEYB_CSn keymatrix 16 Keyboard matrix injection, mapping
IOP_FDD_CSn fdd 16 FDD data transfer, status
IOP_CMT0_CSn cmt (write) 64 CMT data write (tape loading)
IOP_CMT1_CSn cmt (read) 64 CMT data read (tape saving)
IOP_INTR_CSn iointr 16 Interrupt acknowledge, vector read
IOP_SND_CSn snd 16 Sound configuration

Transaction protocol

A typical IOP write transaction:
  1. K64F sets the target module’s CSn low.
  2. K64F drives IOP_ADDR with the register offset.
  3. K64F drives IOP_DIN with the data byte.
  4. K64F asserts IOP_WRn low for at least 2 CKMASTER cycles.
  5. K64F deasserts IOP_WRn.
  6. K64F releases CSn.
A typical IOP read transaction:
  1. K64F sets the target module’s CSn low.
  2. K64F drives IOP_ADDR with the register offset.
  3. K64F asserts IOP_RDn low.
  4. FPGA drives IOP_DOUT with the register value (one CKMASTER cycle latency).
  5. K64F reads IOP_DOUT.
  6. K64F deasserts IOP_RDn and CSn.

Data output multiplexing

Each module produces its own IOP_xxx_DOUT signal. The top-level entity multiplexes them based on which chip select is active:
IOP_DOUT <= IOP_MCTRL_DOUT when IOP_MCTRL_CSn = '0' else
            IOP_MZ80K_DOUT when IOP_MZ80K_CSn = '0' else
            IOP_MZ80B_DOUT when IOP_MZ80B_CSn = '0' else
            IOP_KEYB_DOUT  when IOP_KEYB_CSn  = '0' else
            IOP_FDD_DOUT   when IOP_FDD_CSn   = '0' else
            IOP_CMT0_DOUT  when IOP_CMT0_CSn  = '0' else
            IOP_CMT1_DOUT  when IOP_CMT1_CSn  = '0' else
            IOP_INTR_DOUT  when IOP_INTR_CSn  = '0' else
            IOP_SND_DOUT   when IOP_SND_CSn   = '0' else
            (others => '1');

Part 16 — Interrupt System

The iointr module (325 lines) provides an interrupt aggregation and queuing service between the FPGA emulation modules and the I/O processor. It accepts up to 8 independent interrupt sources, queues them in a FIFO, and generates a single interrupt output to the K64F.

Interrupt sources

Input Source Typical trigger
INTR0n CMT module Tape buffer empty (needs refill) or full (needs save)
INTR1n FDD module Sector read/write request
INTR2n Keyboard Break key detection
INTR3n mctrl Machine model change notification
INTR4n Sound Buffer underrun
INTR5n-7n Reserved Available for future expansion

FIFO queue

Each interrupt source triggers a single-entry write to a FIFO. The FIFO stores the interrupt source number (3 bits) as a reason code. When the K64F reads the interrupt reason register (via IOP_INTR_CSn), it receives the oldest queued interrupt and the entry is dequeued. This allows multiple interrupts to be serviced in order even if the K64F cannot respond immediately.

Interrupt handling flow

  1. A peripheral (e.g., CMT) asserts its INTRn signal low.
  2. The iointr module latches the source number and pushes it to the FIFO.
  3. The iointr module asserts the aggregate interrupt output to the K64F.
  4. The K64F’s interrupt handler reads the reason register via IOP_INTR_CSn.
  5. Based on the reason code, the K64F performs the required service (e.g., load next tape block).
  6. The K64F writes an acknowledge to clear the interrupt.
  7. If more entries remain in the FIFO, the interrupt stays asserted.

Arbiter interaction

The iointr module itself requires bus access to write the interrupt vector to the Z80 bus during an interrupt acknowledge cycle (M1 + IORQ). This is arbitrated through the MZ_INTR_GRANTn / MZ_INTR_BUSYn mechanism.

Part 17 — CPLD Bus Manager

The CPLD (MAX7000AE EPM7512AETC144-10) sits between the Sharp MZ mainboard's 5V bus and the 3.3V FPGA and SRAM. It handles all timing-critical glue that cannot tolerate FPGA configuration latency and provides the first level of bus decode on every transaction.

CPLD source files

File Purpose
tranZPUterSW700.vhd (MZ-700) / tzpuSW700_MZ80A.vhd (MZ-80A) Main architecture
tranZPUterSW700_Toplevel.vhd Top-level entity, I/O pin assignments
tranZPUterSW700_pkg.vhd Package (constants, type definitions)

CPLD Configuration Register (I/O 0x6E)

Bit(s) Function
[2:0] Video mode: 000=MZ-80K, 001=MZ-80C, 010=MZ-1200, 011=MZ-80A, 100=MZ-700, 101=MZ-800, 110=MZ-80B, 111=MZ-2000
[3] Mainboard video enable (1=mainboard video active)
[4] WAIT state enable
[7] Preserve config (prevent reset from clearing mode register)

Key CPLD functions

Level translation and bus interface: The CPLD drives the VZ80_* signals (3.3V, FPGA-side) from the Z80_* signals (5V, mainboard-side). All mainboard-facing pins operate at 5V tolerance; all FPGA-facing pins drive 3.3V.
BUSRQ/BUSACK handshake: When the FPGA (or K64F) needs to take control of the mainboard bus, the CPLD manages the Z80 BUSRQ/BUSACK protocol. S-R latches ensure glitch-free transitions between bus master states.
Clock frequency switching: Two D flip-flops implement a glitch-free clock multiplexer. The Z80 can run on either the mainboard SYSCLK (original speed) or CTLCLK (programmable frequency from K64F). The changeover waits for both clocks to be idle.
TZMM mode register (MEM_MODE_LATCH): The 8-bit memory mode latch (I/O port 0x60) selects which 64KB page of the 512KB SRAM is mapped into the Z80 address space. Bits [4:0] are forwarded on Z80_MEM[4:0] to the FPGA. Bit 5 enables the I/O wait state generator.
I/O address decode: The CPLD decodes writes to the tranZPUter I/O range 0x60-0x6F into individual chip-select signals for the FPGA's CPU configuration, CPLD configuration, memory mode, and video control registers.
Video access decode: The CPLD generates the VIDEO_RDn and VIDEO_WRn signals by decoding memory access to the video RAM address range (typically D000-DFFF), forwarding these as dedicated strobes to the FPGA video controller.

Build variants

CPLD project Host machine Differences
tranZPUterSW700 MZ-700 Default I/O decode, colour video access
tzpuSW700_MZ80A MZ-80A Modified I/O decode for MZ-80A memory map
tzpuSW700_MZ2000 MZ-2000 Business series bus timing, GRAM access decode
The CPLD is built with Quartus Prime 13.0 SP1 (the last version supporting MAX7000AE) using the CPLDfit fitter. Programming uses a standard USB-Blaster cable in JTAG mode.

Part 18 — Personal Series Hardware

The mz80k_hw module (1416 lines) implements the hardware for the Personal series Sharp MZ computers: MZ-80K, MZ-80C, MZ-1200, MZ-80A, MZ-700, and MZ-800. It contains the Z80 address decoder, I/O address decoder, and instantiates the machine-specific peripherals.

Peripherals

Component Instance Function
i8255 PPI Keyboard scanning (Port A), keyboard data (Port B), cassette/sound control (Port C)
i8254 PIT Counter 0 = sound tone, Counter 1 = cascaded, Counter 2 = RTC

I/O address map (Personal series)

Address Read Write Machine
0xE000 PPI Port A (key scan) PPI Port A All
0xE001 PPI Port B (key data) PPI Port B All
0xE002 PPI Port C (status) PPI Port C (control) All
0xE003 PPI control word All
0xE004-E007 PIT Counter 0-2 + control PIT Counter 0-2 + control All
0xE008 Memory bank control MZ-700 only
0xE9 Graphics bank switch reset MZ-700/800 (with GRAM)
0xEA Graphics control Graphics control MZ-700/800 (with GRAM)

Memory banking (MZ-700)

The MZ-700 uses a unique memory banking scheme controlled by writes to address 0xE008. At boot, the monitor ROM occupies 0x0000-0x0FFF; after loading a program, the ROM is banked out and the full 64KB RAM is accessible. Additionally, the MZ-700 can bank in/out the VRAM/ARAM at 0xD000-0xDFFF and I/O at 0xE000-0xFFFF:
Bank control write Effect
0xE0 to 0xE000 Bank out ROM, bank in RAM at 0x0000
0xE1 to 0xE000 Bank in ROM at 0x0000
0xE2 to 0xE000 Bank out VRAM/IO, bank in RAM at 0xD000-0xFFFF
0xE3 to 0xE000 Bank in VRAM/IO at 0xD000-0xFFFF

Machine-specific differences

The CONFIG[10:0] CURRENTMACHINE bits select which machine model is emulated. The mz80k_hw module uses these bits to:
  • Select the correct ROM bank from SYSROM
  • Enable or disable colour attribute RAM (mono machines have no ARAM)
  • Configure the PPI Port C bit assignments (which differ between MZ-80K and MZ-700)
  • Enable/disable the SN76489 sound (MZ-700/800 only)
  • Configure PCG support (MZ-700 with PCG option)

Part 19 — Business Series Hardware

The mz80b_hw module (676 lines) implements the hardware for the Business series: MZ-80B, MZ-2000, MZ-2200, and MZ-2500. These machines have a fundamentally different architecture from the Personal series, with IPL boot ROM, a Z80 PIO, 80-column display, three-plane graphics RAM, and an APSS-capable cassette interface.

Additional peripherals

Component Instance Function
i8255 PPI Similar to Personal series but different port assignments
i8254 PIT Counter cascade mode for timing
z8420 PIO Z80 Parallel I/O — interrupt-driven input/output

I/O address map (Business series)

Address Function Notes
0xD4-0xD7 i8254 PIT Different base address from Personal series
0xD8-0xDB i8255 PPI Business series configuration
0xDC-0xDD Memory control RAM/ROM banking
0xE0-0xE3 CRTC / video control Display timing registers
0xE4-0xE7 Reserved
0xE8-0xED Graphics control Frame buffer bank/colour select
0xF4-0xF7 Z80 PIO Port A/B Data and control registers
0xFE-0xFF IPL / Boot control IPL ROM enable/disable

Graphics Frame Buffer

The MZ-80B/2000 graphics subsystem provides three independent frame buffer planes (Red, Green, Blue), each 16KB, mapped into the Z80 address space at 0xC000-0xFFFF via bank switching:
Register Address Function
0xE8 Graphics bank switch set Select R/W bank (R/G/B) for C000-FFFF window
0xE9 Graphics bank switch reset Deselect bank
0xEA Control register Read bank select, write bank select, VRAM/GRAM enable, blend operator
0xEB Red colour writer Write byte to red plane
0xEC Green colour writer Write byte to green plane
0xED Blue colour writer Write byte to blue plane
The colour writer registers allow simultaneous writes to one or more planes with a single I/O instruction, enabling fast screen fills and colour setting operations.

IPL Boot sequence

The MZ-80B and MZ-2000 use an IPL (Initial Program Load) ROM that is active only during boot. When CONFIG[73] BOOT_RESET is set, the IPL ROM appears at address 0x0000. After the IPL loads the monitor from cassette (or FDD), it banks out the IPL ROM and jumps to the loaded code. The BOOT_RESET configuration allows the I/O processor to trigger a clean boot cycle.

Part 20 — Graphics Frame Buffer

The graphics frame buffer is a shared subsystem used by both the Personal series (MZ-700/800 with GRAM option) and the Business series (MZ-80B/2000 native). It provides three 16KB frame buffer planes that can be independently addressed and composited with the character display.

Memory layout

Plane FPGA address Size Z80 access
Red 0x240000-0x243FFF 16KB Via bank switch register (0xE8/0xE9)
Blue 0x250000-0x253FFF 16KB Via bank switch register
Green 0x260000-0x263FFF 16KB Via bank switch register

Blend modes (Control register 0xEA)

Mode bits Operation Description
00 Replace Graphics pixels replace character display
01 OR Graphics OR’d with character display
10 AND Graphics AND’d with character display
11 XOR Graphics XOR’d with character display

Colour writer operation

The colour writer registers (0xEB-0xED) provide a hardware-accelerated method for setting pixel colours across multiple planes simultaneously. Writing a byte to the Red colour writer (0xEB) sets 8 horizontal pixels in the Red plane. Writing to Green (0xEC) and Blue (0xED) does the same for their respective planes. The address within each plane is set by the Z80's current address in the 0xC000-0xFFFF window:
-- Colour writer: when Z80 writes to colour register, the value is
-- written to the corresponding plane at the current GRAM address.
if CS_GRAM_WR = '1' then
    case GRAM_BANK is
        when "001" => GRAM_RED(GRAM_ADDR)   <= Z80_DATA;
        when "010" => GRAM_GREEN(GRAM_ADDR) <= Z80_DATA;
        when "100" => GRAM_BLUE(GRAM_ADDR)  <= Z80_DATA;
        when others => null;
    end case;
end if;

GRAM options (CONFIG bits)

CONFIG bit Constant Function
43 OPT_GRAMI MZ-80B GRAM I / MZ-2000 Blue installed
44 OPT_GRAMII MZ-80B GRAM II / MZ-2000 Red installed
45 OPT_GRAMIII MZ-2000 Green installed
46 OPT_PCG PCG (Programmable Character Generator) installed
47 OPT_MZ1R25 16KB Video RAM expansion installed

Part 21 — Status & Menu Frame Buffers

The VideoController provides two OSD (On-Screen Display) overlays: a status bar and a configuration menu. Both are rendered into dedicated frame buffers and composited on top of the emulation display.

Status overlay

The status bar occupies the bottom portion of the screen and displays real-time information: current machine model, CPU speed, tape status, and drive activity. It is enabled by CONFIG[72] STATUSENABLE. The I/O processor writes status text into the status frame buffer at address 0x320000.
The configuration menu allows the user to change machine model, display mode, CPU speed, audio settings, and other options without a host computer. It is enabled by CONFIG[71] MENUENABLE. The I/O processor manages the menu state machine and writes the rendered menu into the menu frame buffer at address 0x322000.

Video parameter table

A 32x32 parameter table at address 0x324000 stores per-mode display timing parameters. Each entry contains horizontal/vertical total, active, sync start/end values. The VideoController reads the active entry to configure its timing generators when the display mode changes. The current video mode index is stored at 0x324400.

OSD compositing

During the active display period, the VideoController checks whether the current pixel position falls within the OSD region. If it does and the corresponding OSD pixel is non-transparent, the OSD colour replaces the emulation output. The OSD uses a semi-transparent background to remain readable over any emulation display mode.

Part 22 — Adding a New Emulated Machine

This section provides a step-by-step guide for adding support for a new Sharp MZ model (or a closely related Z80 machine) to the emuMZ emulator.

Step 1: Define the machine constant

Add a new machine constant in mctrl_pkg (at the top of mctrl.vhd):
constant MZ_NEW_MODEL : integer := 11;  -- Next available index after MZ2500
Extend the CURRENTMACHINE subtype range if necessary.

Step 2: Add ROM bank

Allocate a bank pair in the SYSROM for the new machine's monitor ROM. Update the ROM initialisation file (combined_mrom.mif) to include the binary image at the correct offset.

Step 3: Choose controller branch

Decide whether the new machine belongs to the Personal series (extend mz80k_hw.vhd) or Business series (extend mz80b_hw.vhd). Add the new CONFIG machine bit to the relevant controller's decode logic.

Step 4: Define memory map

Add address decode logic in the chosen controller for the new machine's memory map. Use the CONFIG[10:0] machine bit to gate the new decode:
if CONFIG(MZ_NEW_MODEL) = '1' then
    -- New machine's memory map
    CS_ROM_n  <= '0' when Z80_ADDR(15 downto 12) = "0000" else '1';
    CS_RAM_n  <= '0' when Z80_ADDR(15 downto 12) /= "0000" else '1';
    -- ... etc
end if;

Step 5: Add machine-specific peripherals

If the new machine has peripherals not already in the design, create new VHDL modules and instantiate them in the controller. Register them with the arbiter if they need bus access.

Step 6: Update keyboard mapping

If the keyboard layout differs, add a new mapping table in keymatrix.vhd selected by the CONFIG machine bits.

Step 7: Update video timing

If the display timing differs, add a new timing parameter set in the VideoController. Add the new mode constant to VideoController_pkg.vhd.

Step 8: Update I/O processor

Update the K64F firmware to recognise the new machine model: add the ROM filename, display name, and default configuration values. Update the OSD menu to include the new model in the machine selection list.

Step 9: Test

Build the FPGA project, program the device, select the new machine via the OSD menu, and verify that the monitor ROM executes correctly. Use Signal Tap or slow clocks for debugging if needed.

Part 23 — Building from Source

Prerequisites

Tool Version Purpose
Intel Quartus Prime 17.1.1 (Lite or Standard) FPGA synthesis, place & route
Intel Quartus II 13.0 SP1 (Web Edition) CPLD synthesis (MAX7000AE)
USB-Blaster JTAG programming cable
Docker Latest Containerised build environment for CI/CD

FPGA build

The FPGA project files are under FPGA/SW700/v1.3/MZ700/build/. Each build variant has its own Quartus project file:
Project file Build variant Top entity
coreMZ.qpf / coreMZ.qsf Video-only coreMZ
coreMZ_SoftCPU.qpf / coreMZ_SoftCPU.qsf Video + soft CPUs coreMZ
coreMZ_emuMZ.qpf / coreMZ_emuMZ.qsf Full emulation coreMZ
To build manually:
cd FPGA/SW700/v1.3/MZ700/build/
quartus_sh --flow compile coreMZ_emuMZ
The build produces:
Output file Purpose
coreMZ_emuMZ.sof SRAM Object File — volatile JTAG programming
coreMZ_emuMZ.pof Programmer Object File — non-volatile EPCS programming
coreMZ_emuMZ.rbf Raw Binary File — for loading via K64F

CPLD build

The CPLD project files are under CPLD/, one directory per target machine:
cd CPLD/SW700/MZ700/build/
quartus_sh --flow compile tranZPUterSW700

Build matrix

FPGA builds (Quartus 17.1.1):

Target FPGA Variant Total
SW700 v1.3 EP4CE115 coreMZ, coreMZ_SoftCPU, coreMZ_emuMZ 3
SW700 v1.3 EP4CE75 coreMZ, coreMZ_SoftCPU 2
Fusion v1.0 EP4CE115 coreMZ, coreMZ_SoftCPU, coreMZ_emuMZ 3
Fusion v1.0 EP4CE75 coreMZ, coreMZ_SoftCPU 2
With three host machines (MZ-700, MZ-80A, MZ-2000) per FPGA variant, the complete SW700 FPGA build matrix is 3 machines x 2 FPGAs x 3 modes = 18 builds.

CPLD builds (Quartus 13.0 SP1):

Target Host CPLD project
SW700 v1.3 MZ-700 tranZPUterSW700
SW700 v1.3 MZ-80A tzpuSW700_MZ80A
SW700 v1.3 MZ-2000 tzpuSW700_MZ2000
FusionX v1.0 MZ-700 tzpuFusionX (MZ700)
FusionX v1.0 MZ-80A tzpuFusionX (MZ80A)
FusionX v1.0 MZ-2000 tzpuFusionX (MZ2000)

Part 24 — Jenkins CI/CD Pipeline

Build overview

The tranZPUter-Build Jenkins pipeline automates the entire FPGA and CPLD build matrix, producing versioned release packages. The pipeline is triggered by Gitea push webhooks on the master branch.
Stage Tool Output
Checkout Git (Gitea) tranZPUter source tree
Version Gitea API Auto-incremented version number
FPGA Build (×N) Quartus 17.1.1 (Docker) .sof, .pof, .rbf per variant
CPLD Build (×N) Quartus 13.0.1 (Docker) .pof per target
Package tar/gz Versioned release archives
Release Gitea API Tagged release with downloadable assets

Docker build environments

Image Version Purpose
quartus-prime-17.1.1 Intel Quartus Prime 17.1.1 Lite FPGA synthesis for Cyclone IV
quartus-ii-13.0.1 Intel Quartus II 13.0 SP1 CPLD synthesis for MAX7000AE

Triggering builds

  • Automatic: Gitea push webhook on master branch
  • Manual: Jenkins “Build Now” at https://jenkins.eaw.app/job/tranZPUter-Build/

Build artifacts

Each build produces programming files for all variants in the matrix. The release package includes:
  • FPGA .sof/.pof/.rbf files for each machine/FPGA/variant combination
  • CPLD .pof files for each machine target
  • ROM initialisation files (combined_mrom.mif)
  • Release notes

Part 25 — Development Workflow

Edit-compile-test cycle

The typical development workflow is:
  1. Edit VHDL — Modify the relevant source file(s) in a text editor or Quartus.
  2. Compile — Run quartus_sh --flow compile coreMZ_emuMZ (or use Quartus GUI “Start Compilation”). A full emuMZ build takes approximately 15-25 minutes on a modern workstation.
  3. Program — Connect USB-Blaster to the JTAG header. Use quartus_pgm or Quartus Programmer to load the .sof file. JTAG programming takes ~10 seconds and is volatile (lost on power-off).
  4. Test — Power on the host machine. The FPGA loads from the JTAG image and the emulation starts. Use the OSD menu (if compiled in) to select machine model and verify operation.
  5. Iterate — If issues are found, return to step 1. Use Signal Tap for debugging if the issue is internal to the FPGA.

Debug techniques

Technique Tool Use case
Signal Tap Quartus (JTAG) Capture internal FPGA signals at full speed, view waveforms
Slow clocks CONFIG debug register Set CPU to 0.1-100Hz for human-observable execution
LED indicators Board LEDs Quick status indication (bus state, mode, errors)
IOP register dump K64F serial console Read back CONFIG, CMT status, arbiter state
VRAM inspection IOP VRAM read Verify video memory contents match expected state
Logic analyser External probe Capture external bus signals (VZ80_ADDR, VZ80_DATA, etc.)

Signal Tap setup

Signal Tap II is Quartus's built-in logic analyser. To add it to the emuMZ build:
  1. Open the Quartus project (coreMZ_emuMZ.qpf).
  2. Go to Tools → Signal Tap II Logic Analyzer.
  3. Add signals of interest (e.g., T80_ADDR, T80_DATA_OUT, CORE_MREQn, CLKBUS).
  4. Set the sample clock to CLKBUS(CKMASTER) and the sample depth (limited by available block RAM).
  5. Define trigger conditions (e.g., T80_ADDR = 0x0000 to capture the first instruction fetch after reset).
  6. Recompile — Signal Tap adds instrumentation logic and uses block RAM for the capture buffer.
  7. Program the FPGA and run the capture from the Signal Tap GUI.
Note: Signal Tap consumes block RAM. On the EP4CE75, this may cause the emuMZ build to exceed memory limits. Use the EP4CE115 for Signal Tap sessions.

Timing analysis

After compilation, always check the Quartus Timing Analyzer report. The SDC constraints file (coreMZ_emuMZ_constraints.sdc) defines all clock relationships. Key items to verify:
  • All setup/hold requirements met (no negative slack)
  • CKMASTER-to-register paths meet timing at 128MHz
  • Cross-domain paths (CLOCK_50 to PLL output) properly constrained

Part 26 — Extending the Design

Adding a new peripheral

To add a new peripheral to the emulation:
  1. Create the VHDL module — Follow the existing module pattern: entity with CLKBUS, CONFIG, IOP, and bus signals; architecture with clocked processes on CKMASTER.

  2. Add IOP chip select — If the peripheral needs I/O processor access, add a new IOP_xxx_CSn signal in the top-level entity and connect it to the K64F’s chip select decoder.

  3. Register with arbiter — If the peripheral needs emulated bus access, add a new agent slot to the arbiter. Extend the round-robin with a new GRANT/BUSY/RESET signal triplet.

  4. Connect to top-level — Instantiate the new module in coreMZ_emuMZ.vhd and wire its ports to the appropriate internal signals.

  5. Add to QIP — Add the new VHDL file to the coreMZ_emuMZ.qip file list so Quartus includes it in compilation.

  6. Update CONFIG — If the peripheral needs configuration bits, extend the CONFIG bus in mctrl_pkg and add the corresponding IOP register in mctrl.vhd.

Memory expansion

The emuMZ variant uses FPGA block RAM exclusively. To add more memory:
  • Block RAM: Instantiate additional dpram modules. Check FPGA utilisation — the EP4CE115 has 3,981 Kbits total.
  • External SRAM: Route through the CPLD. This requires changes to the CPLD decode logic and FPGA top-level entity to add SRAM address/data/control signals.
  • SDRAM controller: The devices/sysbus/SDRAM/ directory contains SDRAM controller IP for W9864G6 and 48LC16M16 devices. These can be instantiated for large memory applications (e.g., ZPU Evolution with megabytes of RAM).

Porting to a new FPGA

The VHDL is largely portable. Platform-specific items that require modification:
Item File(s) What to change
PLL PLL/ directory Replace Altera PLL megafunction with target vendor equivalent
Block RAM dpram.vhd, BRAM templates Replace Altera RAM megafunctions
SFL SFL/ directory Serial Flash Loader — remove or replace
Pin assignments .qsf file Map to new FPGA package pins
SDC constraints coreMZ_emuMZ_constraints.sdc Update clock and timing constraints
The T80 Z80 core, all peripheral controllers (i8254, i8255, z8420, WD1793, SN76489), and the VideoController are pure VHDL and synthesise on any FPGA vendor's tools.

Part 27 — Source File Reference

FPGA/SW700/v1.3/MZ700/ (main source tree)

File Lines Purpose
coreMZ.vhd ~800 Top-level entity — video-only build
coreMZ_SoftCPU.vhd ~1200 Top-level — video + soft CPUs (T80 + ZPU)
coreMZ_emuMZ.vhd 1783 Top-level — full Sharp MZ emulation
coreMZ_pkg.vhd 187 Package: host model constants, utility functions
functions.vhd ~200 Shared utility functions

FPGA/SW700/v1.3/MZ700/VideoController/

File Lines Purpose
VideoController.vhd 5400 Complete video pipeline (character, graphics, OSD, palette)
VideoController_pkg.vhd 201 Video mode constants, host hardware mode definitions
ChrGenRAM_DP_3208.vhd Character generator dual-port BRAM template
VideoRAM_DP_3216.vhd Video RAM dual-port BRAM template

FPGA/SW700/v1.3/MZ700/emuMZ/ (emulation core)

File Lines Purpose
mctrl.vhd 689 Machine control: CONFIG bus, register decode, reset management
clkgen.vhd 571 Clock generation: PLL, dividers, clock enables
arbiter.vhd 653 Round-robin bus arbitration with watchdog
cmt.vhd 1806 Cassette tape: PWM encode/decode, APSS, data cache
keymatrix.vhd 1222 PS/2 to Sharp MZ keyboard translation
mz80k_hw.vhd 1416 Personal series hardware (MZ-80K/C/1200/80A/700/800)
mz80b_hw.vhd 676 Business series hardware (MZ-80B/2000/2200/2500)
fdd.vhd 355 Floppy disk controller (WD1793 emulation)
iointr.vhd 325 I/O processor interrupt aggregation FIFO
snd.vhd 369 Sound: SN76489 + i8253 audio

FPGA/SW700/v1.3/MZ700/emuMZ/ (sub-directories)

Directory Contents
i8254/ Intel 8254 Programmable Interval Timer VHDL
i8255/ Intel 8255 Programmable Peripheral Interface VHDL
wd1793/ WD1793 Floppy Disk Controller VHDL
z8420/ Zilog Z80 PIO VHDL
common/T80/ T80 Z80 CPU core (T80.vhd, T80_ALU.vhd, T80_MCode.vhd, T80_Reg.vhd, T80_Pack.vhd)
mz80c/, mz80b/ Machine-specific sub-modules
mif/ Memory initialisation files (.mif)

FPGA/SW700/v1.3/MZ700/softT80/

File Purpose
softT80.vhd T80 soft Z80 wrapper module
softT80_pkg.vhd T80 configuration package
T80/ T80 Z80 IP core source (shared with emuMZ)

FPGA/SW700/v1.3/MZ700/softZPU/

File Purpose
softZPU.vhd ZPU Evolution soft CPU wrapper
softZPU_pkg.vhd ZPU configuration package
ZPU/ ZPU Evolution core VHDL

Other directories

Path Contents
FPGA/SW700/v1.3/MZ700/PLL/ Altera PLL megafunction instances
FPGA/SW700/v1.3/MZ700/SFL/ Serial Flash Loader megafunction (EPCS boot ROM programming)
FPGA/SW700/v1.3/MZ700/devices/ Peripheral IP: BRAM, SDRAM, UART, timer, interrupt, SD/MMC, RAM
FPGA/SW700/v1.3/MZ700/build/ Quartus project files (.qpf, .qsf, .sdc per variant)
CPLD/ CPLD VHDL source per target machine
schematics/SW700/ KiCad schematics per board revision (v1.0-v1.4)
pcb/SW700/ Gerber PCB files (v1.2a, v1.3, v1.3a)
tools/ Build utilities: build_meminitfiles.sh, Python BRAM init scripts

Resource URL
tranZPUter source git.eaw.app/eaw/tranZPUter
TZFS source git.eaw.app/eaw/TZFS
SharpMZ (MiSTer) source git.eaw.app/eaw/SharpMZ_MiSTer
Jenkins CI jenkins.eaw.app/job/tranZPUter-Build
Sharp MZ Emulator (tranZPUter) eaw.app/sharpmz-emulator-tzpu-700
Sharp MZ Emulator (MiSTer) eaw.app/sharpmz-emulator-de10-nano
tranZPUter SW-700 page eaw.app/sharpmz-700-upgrades-tranzputer-sw
TZFS User Manual eaw.app/tzfs-usermanual

Reference documentation

Document Content
T80 CPU core (opencores.org) Z80 instruction set implementation, bus timing
Intel i8255A datasheet Programmable Peripheral Interface specification
Intel i8254 datasheet Programmable Interval Timer specification
Zilog Z8420 datasheet Z80 PIO specification
WD1793 datasheet Floppy Disk Controller command set and timing
SN76489 datasheet Programmable Sound Generator specification
Intel Quartus Prime Handbook FPGA synthesis, timing analysis, Signal Tap
Quartus II 13.0 CPLD Handbook MAX7000AE fitting, programming

Sharp MZ technical references

Machine Key specifications
MZ-80K/C/1200 Z80 @ 2MHz, 48KB RAM, 4KB ROM, 40x25 mono, cassette 1200 baud
MZ-80A Z80 @ 2MHz, 48KB RAM, 4KB ROM, 40x25 mono, improved keyboard
MZ-700 Z80 @ 3.58MHz, 64KB RAM, colour display, PCG option, built-in plotter
MZ-800 Z80 @ 3.58MHz, 64KB RAM, QD drive, enhanced graphics
MZ-80B Z80 @ 4MHz, 64KB RAM, 80-column display, GRAM I/II, IPL boot
MZ-2000 Z80 @ 4MHz, 64KB RAM, GRAM I/II/III, FDD, APSS cassette

Acronym reference

Acronym Meaning
APSS Automatic Program Search System
ARAM Attribute RAM (colour attributes per character cell)
BRAM Block RAM (FPGA embedded memory)
CGRAM Character Generator RAM (programmable characters)
CGROM Character Generator ROM (fixed font)
CMT Cassette Magnetic Tape
CONFIG 91-bit machine configuration bus
CPLD Complex Programmable Logic Device
DRQ Data Request (WD1793 handshake)
emuMZ Sharp MZ Series FPGA Emulation build variant
FDC Floppy Disk Controller
FDD Floppy Disk Drive
FPGA Field-Programmable Gate Array
GRAM Graphics RAM (frame buffer memory)
IOP I/O Processor (K64F ARM Cortex-M4)
IPL Initial Program Load (boot ROM)
JTAG Joint Test Action Group (debug/programming interface)
MZF Sharp MZ tape File format
OSD On-Screen Display
PCG Programmable Character Generator
PIO Parallel Input/Output (Z80 PIO Z8420)
PIT Programmable Interval Timer (i8254)
PLL Phase-Locked Loop
PPI Programmable Peripheral Interface (i8255)
PSG Programmable Sound Generator (SN76489)
SDC Synopsys Design Constraints (timing constraints file)
SFL Serial Flash Loader
SOF SRAM Object File (volatile JTAG programming)
T80 Open-source Z80 CPU core (VHDL)
TZMM tranZPUter Memory Mode
TZFS tranZPUter Filing System
VRAM Video RAM (character display memory)
ZPU Zylin Processing Unit (32-bit stack CPU)