Sharp MZ-80A Video Module — Technical Guide

Sharp MZ-80A Video Module Technical Guide

This guide documents the internal architecture, memory map, programmable register set, GPU command interface, video timing modes, and build system for the Sharp MZ-80A Video Module. It covers all three hardware versions: the v1.0 prototype, the v1.1 recommended discrete design, and the v2.0 FPGA-based design. It is intended for hardware developers, firmware authors, and anyone who needs to understand or program the Video Module at a system level.
For day-to-day usage and installation instructions see the Video Module project page.

Hardware Versions

Three hardware versions of the Video Module exist. They share the same core objective — restoring the 80-column capability that Sharp disabled in the MZ-80A and adding colour output — but differ substantially in implementation. v1.0 is a prototype with known issues and is not recommended for new builds. v1.1 corrects all v1.0 issues with discrete logic and is the recommended choice when a tranZPUter board is not available. v2.0 uses CPLD and FPGA technology and requires a pre-installed tranZPUter board; it delivers the full video capabilities of the Sharp MZ Emulator on real hardware.

v1.0 — Prototype
The v1.0 board was the initial prototype. Five issues were discovered during production and use:
  1. Gate array footprints swapped in KiCad. The MB14298 and MB14299 footprints were transposed. Correction required fine soldering and rewiring on the assembled board.
  2. Oscillator signal quality. The oscillator did not produce a clean signal. Adding a 100 pF ceramic capacitor between U14B pin 4 and GND resolved this; the problem was compounded by the rewiring required for issue 1.
  3. Gate array G signal PCB break. The G signal between the two gate arrays was unconnected on the PCB despite being correctly shown in the schematic. A manual jumper wire was required.
  4. Attribute RAM and control latch address clash at 0xDFFF. A write to the control latch also updated the top location of the attribute RAM mirror, which could corrupt the last visible attribute if the Character RAM was hardware-scrolled to the bottom of the display.
  5. Physical alignment issues. The gate array raiser pin positions were not accurately measured, causing difficulty during installation and stress on the raiser pins.
The schematic was corrected following these findings but v1.0 was not re-spun as a PCB. Work moved directly to v1.1 to address all five issues together.

v1.1 — Current Discrete Design (Recommended)
v1.1 resolves all five v1.0 issues in a redesigned PCB:
  • Issues 1, 2, and 5 were resolved by correcting the KiCad footprints, switching from discrete oscillator components to an oscillator module, and using precise measurements (pencil trace of the MZ-80A motherboard with micrometer verification) for the gate array raiser pin positions.
  • Issue 3 was resolved in the corrected schematic and PCB routing.
  • Issue 4 was resolved by adding a 74HCT123 monostable multivibrator circuit. When a read occurs at 0xDFFF the monostable is triggered, opening a window of approximately one Z80 instruction cycle in which a subsequent write to 0xDFFF is directed to the control latch (IC U11) rather than the attribute RAM. This allows the sequence LD A,(HL); LD (HL),B with HL=0xDFFF to safely update the latch. Any write to 0xDFFF that is not immediately preceded by a read goes to the attribute RAM as normal.
v1.1 does not require a tranZPUter board and is the recommended choice for a standalone colour and 40/80 column upgrade.

v2.0 — FPGA Design
v2.0 replaces all discrete logic with an Altera MAX 7000A CPLD for bus interfacing and level translation, and an Altera Cyclone III FPGA (EP3C25E144C8) for a full software-defined video controller. The FPGA carries all video RAM, attribute RAM, character generator RAM, and graphics frame buffers internally as block RAM, eliminating all external video memory chips. A tranZPUter board must be installed before fitting v2.0, as the Video Module requires signals forwarded from the tranZPUter that are not available on the MZ-80A motherboard expansion connector alone.
v2.0 provides:
  • Full emulation of all Sharp MZ series video modes: MZ-80K, MZ-80C, MZ-1200, MZ-80A, MZ-700, MZ-80B (including GRAM I and II), MZ-800, MZ-2000.
  • VGA output at 640×480, 800×600, and 1024×768 at 60 Hz, in addition to the native 15.62 kHz horizontal scan rate.
  • 8-colour pixel graphics frame buffer at 640×200 (80-column mode) or 320×200 (40-column mode).
  • A programmable character generator RAM (CGRAM) uploadable by the CPU.
  • A GPU with VRAM and GRAM clear/fill commands.
  • A programmable palette system with 256 entries.
  • Double-buffered display in all modes except 640×200 (insufficient block RAM for two full buffers at that resolution).

v1.x Hardware Architecture

The v1.x design implements the colour and 40/80 column circuits using discrete 74HCT-series logic, a 2 KB SRAM for the attribute RAM, and a 32 KB Flash RAM for the character generator. The gate arrays IC20 and IC31 (MB14298 and MB14299) are lifted from the MZ-80A motherboard and re-seated on the daughter card where their signal connections can be rerouted. No signals on the MZ-80A motherboard are cut; the modification is fully reversible.

Memory Map
The v1.x board adds two new memory-mapped regions to the standard MZ-80A address space. The Character RAM at 0xD000–0xD7FF is unchanged from the original machine. The Attribute RAM and control latch occupy 0xD800–0xDFFF:
Address        Size    Contents
───────────────────────────────────────────────────────────────────
0xD000–0xD7FF  2 KB    Character RAM — display characters, unchanged from original MZ-80A.
                       CPU read/write. Scanned by video hardware each frame.
0xD800–0xDFFF  2 KB    Attribute RAM (IC U6, 2 KB SRAM) — colour and CG-ROM selection.
                       Each byte pairs with the corresponding Character RAM location.
                       CPU read/write for 0xD800–0xDFFE.
0xDFFF                 Control latch (74HCT373, IC U9 v1.0 / IC U11 v1.1) — write-only.
                       Address shared with top byte of Attribute RAM.
                       In v1.1: a read of 0xDFFF must immediately precede any write
                       intended for the latch (see monostable circuit description).
───────────────────────────────────────────────────────────────────

Attribute RAM
The 2 KB SRAM at IC U6 is mapped to 0xD800–0xDFFF. Each byte in the attribute RAM corresponds to the character at the same offset in the Character RAM (0xD000–0xD7FF). The video scanning circuit reads both RAMs in parallel; as each character byte is serialised for display the corresponding attribute byte is latched by IC U7 and used to generate colour and CG-ROM selection signals.
The attribute byte layout is:
Bits Field Description
0 Background Blue Background colour blue channel (1=on).
1 Background Red Background colour red channel (1=on).
2 Background Green Background colour green channel (1=on).
3 CG-ROM sub-select bit 0 Selects one of 4 CG-ROM slots within the active group (combined with bit 7).
4 Foreground Blue Foreground colour blue channel (1=on).
5 Foreground Red Foreground colour red channel (1=on).
6 Foreground Green Foreground colour green channel (1=on).
7 CG-ROM sub-select bit 1 Selects one of 4 CG-ROM slots within the active group (combined with bit 3).
Example: to display the character 'A' (0x41) in blue foreground on a black background at screen position (0,0), write 0x41 to 0xD000 and 0x10 to 0xD800. Bit 4 of the attribute byte sets the blue foreground channel; bits 2:0 are clear giving black background. CG-ROM sub-select bits 7 and 3 are both zero, selecting slot 0 of the active group.

Colour Generation
The original Sharp MZ-80A was intended by Sharp to have a colour output board, as documented in the 1982 user manual (a very rare edition). Nibbles Lab discovered and published a working circuit design based on this documentation. The v1.x Video Module implements this circuit with modifications for composite video output.
Colour is generated digitally — each RGB channel is either fully on or fully off, giving 8 possible foreground colours and 8 possible background colours. Foreground RGB is driven by attribute bits 6 (G), 5 (R), and 4 (B); background RGB is driven by bits 2 (G), 1 (R), and 0 (B). The resulting digital signals are fed to separate resistor networks for foreground and background, producing analogue voltage levels appropriate for an RGB monitor. Transistor Q1 blends the RGB outputs with the composite sync signal for composite monitor output.
The available colours are:
Bits 6,5,4 (FG) or 2,1,0 (BG) Colour
0,0,0 Black
0,0,1 Blue
0,1,0 Red
0,1,1 Magenta
1,0,0 Green
1,0,1 Cyan
1,1,0 Yellow
1,1,1 White

Control Latch (0xDFFF)
The control latch is a 74HCT373 octal transparent latch (IC U9 in v1.0, IC U11 in v1.1) mapped write-only to address 0xDFFF. It controls the 40/80 column mode and the CG-ROM group selection. The latch address is shared with the top byte of the attribute RAM. In v1.0 this sharing could cause corruption; in v1.1 the 74HCT123 monostable circuit ensures that a write immediately following a read of 0xDFFF targets the latch, while any other write to 0xDFFF targets the attribute RAM.
Control latch bit map:
Bit Function Description
0 CG-ROM group select bit 0 Together with bit 1, selects one of 4 groups of 4 CG-ROM slots in the 32 KB Flash.
1 CG-ROM group select bit 1  
2–6 Unused Reserved, should be written as 0.
7 40/80 column select 0 = 40 column (default). 1 = 80 column.
To switch to 80-column mode in v1.1 software, use the read-modify-write sequence:
    LD   HL, 0xDFFF        ; target address
    LD   B, 0x80           ; value to latch (bit 7 = 80-column enable)
    LD   A, (HL)           ; read 0xDFFF — triggers monostable, opens latch window
    LD   (HL), B           ; write within window — goes to control latch, not attribute RAM
The monostable pulse is sized to expire in just over one Z80 instruction cycle. The read (LD A,(HL)) and the immediately following write (LD (HL),B) fall within the window. A NOP or any other instruction between the read and write will cause the window to close, and the write will fall through to the attribute RAM instead.

40/80 Column Circuit
The Sharp MZ-80A contains the same video chipset as the MZ-80B business machine but was wired differently by Sharp to disable 80-column output, presumably for marketing differentiation. The v1.x design restores the MZ-80B circuit by lifting gate arrays IC20 and IC31 (MB14298 and MB14299) from the MZ-80A motherboard and re-seating them on the daughter card, where their interconnections can be rerouted to match the MZ-80B configuration.
80-column mode requires a doubled pixel clock. A dedicated oscillator module on the daughter card provides this clock. Bit 7 of the control latch at 0xDFFF selects between the standard 40-column clock and the doubled 80-column clock. The 40/80 switch takes effect immediately; software must reinitialise the display after switching modes.
IC8 (74LS165) on the MZ-80A motherboard must be removed and a socket installed in its place before fitting the daughter card, since the Video Module needs to inject new load and clock signals into the serialiser. This is the only permanent modification to the motherboard; reinstalling the original 74LS165 restores the machine to factory condition.

Character Generator ROM System
The original 2 KB Character Generator ROM (IC15 on the MZ-80A motherboard) is removed and replaced by IC U10, a 32 KB 28C256 Flash RAM on the daughter card. This Flash stores up to 16 CG-ROM images of 2 KB each, or up to 8 images of 4 KB each (occupying two consecutive 2 KB slots).
The 32 KB Flash address space is divided into 4 groups of 4 slots. The active group is selected by control latch bits 1:0. Within the active group, attribute bits 7 and 3 for each character select which of the 4 slots is used for that character's glyph data. This means every character on screen can independently draw its glyph from any of the 4 slots in the active group.
Flash address = (latch bits 1:0) × 8 KB  +  (attr bits 7,3) × 2 KB  +  char_offset

Latch bits 1:0  → group (A14:A13): selects one of four 8 KB regions
Attr bits 7,3   → slot  (A12:A11): selects one of four 2 KB slots within the group
Char + row      → A10:A0: glyph byte address within the 2 KB slot
The current slot allocation shipped in the COLOURBOARD_CG.rom image:
Slot Attr bits 7,3 Latch bits 1:0 Size ROM File Description
0 0,0 0,0 2 KB mz-80acg.rom MZ-80A European CG-ROM
1 0,1 0,0 2 KB MZ80K_cgrom.rom MZ-80K European CG-ROM
2 1,0 0,0 2 KB MZ80K2E_Jap_cgrom.rom MZ-80K Japanese CG-ROM
3 1,1 0,0 2 KB MZFONT.rom Unknown-origin CG-ROM
4–5 0,0–0,1 0,1 4 KB MZ700_cgrom.rom MZ-700 European CG-ROM (two slots)
6–7 1,0–1,1 0,1 4 KB MZ700_cgrom_jp.rom MZ-700 Japanese CG-ROM (two slots)
8 0,0 1,0 2 KB mz-80acg.rom MZ-80A European CG-ROM
9 0,1 1,0 2 KB MZ80B.rom MZ-80B European CG-ROM
10 1,0 1,0 2 KB mz-80acg.rom MZ-80A European CG-ROM
11 1,1 1,0 2 KB mz-80acg.rom MZ-80A European CG-ROM
12 0,0 1,1 2 KB mz-80acg.rom MZ-80A European CG-ROM
13 0,1 1,1 2 KB mz-80acg.rom MZ-80A European CG-ROM
14 1,0 1,1 2 KB mz-80acg.rom MZ-80A European CG-ROM
15 1,1 1,1 2 KB mz-80acg.rom MZ-80A European CG-ROM

v2.0 Hardware Architecture

The v2.0 board uses two programmable logic devices in place of all the discrete logic, relocated gate arrays, SRAM, and Flash RAM of the v1.x design. The CPLD handles the 5V/3.3V boundary and bus control; the FPGA implements the complete video system in internal block RAM and logic elements.

CPLD — Altera MAX 7000A (EPM7128S)
The CPLD (Complex Programmable Logic Device) is an Altera MAX 7000A device, part number EPM7128S, in an 84-pin PLCC package. MAX 7000A devices are 5V tolerant on all I/O pins, which is the principal reason for their selection: the Sharp MZ-80A Z80 bus operates at 5V while the FPGA I/O is 3.3V, and direct connection of 5V signals to a standard 3.3V FPGA input would damage the device.
The CPLD performs the following functions:
  • Voltage level translation — buffers and translates all signals between the 5V MZ-80A bus and the 3.3V FPGA I/O.
  • Clock generation and conditioning — derives the system and video clocks required by the FPGA (8 MHz, 4 MHz, 3.54 MHz, 2 MHz, 1 MHz, 31.5 kHz) from the source oscillator.
  • Address decode and bus control — decodes I/O and memory addresses, generates chip-select signals, and controls bus direction for bidirectional data lines.
  • Replacement gate array logic — provides the functions originally performed by the MB14298 and MB14299 gate arrays that are removed from the motherboard for v2.0.
  • tranZPUter serialiser interface — receives signals forwarded from the tranZPUter board (A15–A11, video RDn/WRn, IORQn) that are not accessible via the motherboard video expansion connector.
VHDL source: CPLD/VideoInterface.vhd. Built with Quartus Prime 13.0.1.

FPGA — Altera Cyclone III (EP3C25E144C8)
The FPGA is an Altera Cyclone III EP3C25E144C8 in a 144-pin LQFP package. It provides all video controller logic and internal memory. Key specifications:
Parameter Value
Device EP3C25E144C8
Package 144-pin LQFP
Logic Elements 25,000
Block RAM 76 KB
I/O voltage 3.3 V (all banks)
VHDL sources FPGA/VideoController.vhd, VideoController_Toplevel.vhd, VideoController_pkg.vhd, functions.vhd
Build tool Quartus Prime 13.1
The FPGA bitstream is stored in an EPCS16 serial Flash device connected to the FPGA's dedicated serial boot pins. On power-up the FPGA automatically loads its configuration from the EPCS16. Direct FPGA programming via JTAG is volatile and lost on power-off; the EPCS16 must be programmed separately to make the configuration persistent.

FPGA Internal Memory Usage
The 76 KB of block RAM inside the Cyclone III is the critical limiting resource. It is allocated as follows:
Block Size Description
Video RAM (VRAM) 2 KB Character display — equivalent to 0xD000–0xD7FF on the original machine. CPU read/write via normal memory bus.
Attribute RAM 2 KB Colour and CG-ROM selection per character — equivalent to 0xD800–0xDFFF on v1.x. CPU read/write.
Character Generator RAM (CGRAM) Variable Programmable CG-ROM image. Can be written by the CPU when enabled via the Memory Page register (0xFD bit 7).
Graphics frame buffer — Red bank 16 KB One bit per pixel for the red channel. Covers 640×200 pixels (80-column) or 320×200 (40-column).
Graphics frame buffer — Green bank 16 KB One bit per pixel for the green channel.
Graphics frame buffer — Blue bank 16 KB One bit per pixel for the blue channel.
Key maps, palette tables Remainder Keyboard mapping tables and the 256-entry palette RAM.
Total graphics frame buffer RAM: 3 × 16 KB = 48 KB. This is the dominant consumer of block RAM. In 640×200 mode the full 48 KB is required for a single frame buffer, leaving insufficient RAM for a second buffer; double buffering is therefore not available in that mode. All other modes use the remaining capacity for a second (hidden) frame buffer, enabling tear-free display updates.

Graphics Frame Buffer
The graphics frame buffer consists of three independent 16 KB banks — Red, Green, and Blue — each holding one bit per pixel. Pixels are stored left-to-right within each row, top-to-bottom across rows, with 8 pixels per byte (MSB = leftmost pixel). For 80-column mode the resolution is 640×200 pixels; for 40-column mode it is 320×200 pixels.
CPU access: Any one of the three banks can be mapped into Z80 address space 0xC000–0xFFFF by setting bit 0 of the Memory Page register (0xFD). The bank to map is selected by bits 1:0 of the Graphics Mode register (0xF9) for reads, and bits 3:2 for writes. Setting write mode to 11 (Indirect) causes a write to update all three banks simultaneously, with each bank write masked by its corresponding Colour Writer register (0xFA for Red, 0xFB for Green, 0xFC for Blue).
Indirect write example: With Red filter = 0x80, Green filter = 0x40, Blue filter = 0x20, writing any non-zero value to 0xC000 will set pixel (0,0) to red, pixel (1,0) to green, and pixel (2,0) to blue. The written data byte itself is masked by each filter register before being stored.
Double buffering: Active for all modes except 640×200. The active display reads from the front buffer while the CPU writes to the back buffer. Buffers are swapped under GPU or CPU control. In 640×200 mode a WAIT state generator can be enabled to avoid display tearing.

Register Map

All v2.0 Video Module registers are accessed via Z80 I/O instructions (IN / OUT). Unless noted otherwise every register is read/write; a read returns the last value written. Registers in the 0xD0–0xD7 range control video mode parameters and the palette. Registers in the 0xF3–0xFD range control the video mode, graphics, GPU, memory paging, and colour writing.
I/O Port Name R/W Description
0xD0 Video Mode Parameter Selector W Selects which timing parameter (0–18) to update via ports 0xD1/0xD2.
0xD1 Video Mode Parameter Low W Lower byte of the parameter selected by 0xD0.
0xD2 Video Mode Parameter High W Upper byte of the parameter selected by 0xD0.
0xD3 Palette Off Pointer W Palette entry number (0–255) for the pixel-off colour configuration.
0xD4 Palette On Pointer W Palette entry number (0–255) for the pixel-on colour configuration.
0xD5 Palette Red Value W 5-bit Red value for the palette entry currently selected by 0xD3 or 0xD4.
0xD6 Palette Green Value W 5-bit Green value for the palette entry currently selected by 0xD3 or 0xD4.
0xD7 Palette Blue Value W 5-bit Blue value for the palette entry currently selected by 0xD3 or 0xD4.
0xF3 VGA Border Colour R/W Bits 2:0 = border colour R/G/B in VGA output modes.
0xF5 Active Palette R/W Selects the active palette. 0 = default system palette. 1–255 = fixed palettes.
0xF6 GPU Parameters R/W 128-bit push/pop FIFO for GPU command parameters. Write pushes, read pops.
0xF7 GPU Command / Status R/W Write: GPU command byte. Read: bit 0 = BUSY flag (1 = GPU busy).
0xF8 Control Register R/W Machine model, column width, colour enable, PCG enable, VGA mode select.
0xF9 Graphics Mode Register R/W GRAM bank select, VRAM/GRAM output enable, blend operator.
0xFA Colour Writer Red R/W 8-pixel red channel mask applied to indirect GRAM writes.
0xFB Colour Writer Green R/W 8-pixel green channel mask applied to indirect GRAM writes.
0xFC Colour Writer Blue R/W 8-pixel blue channel mask applied to indirect GRAM writes.
0xFD Memory Page / Status R/W Write bit 0: map GRAM bank into 0xC000–0xFFFF. Write bit 7: map CGROM into 0xD000–0xDFFF. Read bits 5,6: horizontal/vertical blanking status.

Control Register (0xF8)
The Control Register is the primary mode register. It selects which Sharp MZ machine the Video Module emulates, the column width, whether colour is enabled, whether the programmable character generator is active, and the VGA output resolution.
Bits Function Description
2:0 Machine model 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 Column width 0 = 40 column. 1 = 80 column.
4 Colour enable 0 = Monochrome output. 1 = Colour output.
5 PCG RAM enable 0 = PCG disabled (hardware CG-ROM used). 1 = Programmable CG RAM enabled.
7:6 VGA mode 00 = Native 15.62 kHz horizontal scan. 01 = VGA 640×480 @ 60 Hz. 10 = VGA 1024×768 @ 60 Hz. 11 = VGA 800×600 @ 60 Hz.

Graphics Mode Register (0xF9)
The Graphics Mode Register controls which GRAM bank the CPU reads from and writes to, whether the character display (VRAM) and graphics display (GRAM) contribute to the output, and how the two layers are blended.
Bits Function Description
1:0 Read bank 00 = Red, 01 = Green, 10 = Blue. Selects which GRAM bank is visible at 0xC000–0xFFFF for CPU reads.
3:2 Write bank 00 = Red, 01 = Green, 10 = Blue, 11 = Indirect (write to all three banks simultaneously, masked by Colour Writer registers).
4 VRAM output 0 = Enable character display. 1 = Disable character display.
5 GRAM output 0 = Enable graphics display. 1 = Disable graphics display.
7:6 Blend operator 00 = OR, 01 = AND, 10 = NAND, 11 = XOR. Applied when both VRAM and GRAM outputs are enabled.

Colour Writer Registers (0xFA–0xFC)
The three Colour Writer registers provide an 8-pixel-wide bit mask that is applied to GRAM writes when the write bank is set to Indirect mode (Graphics Mode register bits 3:2 = 11). Each register controls one colour channel. When a byte is written to the GRAM address range 0xC000–0xFFFF in indirect mode, the byte is ANDed with the Red filter and stored in the Red bank, ANDed with the Green filter and stored in the Green bank, and ANDed with the Blue filter and stored in the Blue bank. This allows a single write to set different colours on individual pixels within the byte.
Example: Red filter (0xFA) = 0xFF, Green filter (0xFB) = 0x00, Blue filter (0xFC) = 0x00. An indirect write of 0xFF to 0xC000 sets all 8 pixels in row 0 to red with no green or blue component.
Register Colour Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
0xFA Red Pixel 0 Pixel 1 Pixel 2 Pixel 3 Pixel 4 Pixel 5 Pixel 6 Pixel 7
0xFB Green Pixel 0 Pixel 1 Pixel 2 Pixel 3 Pixel 4 Pixel 5 Pixel 6 Pixel 7
0xFC Blue Pixel 0 Pixel 1 Pixel 2 Pixel 3 Pixel 4 Pixel 5 Pixel 6 Pixel 7
Bit 7 is the leftmost pixel (pixel 0) in each byte; bit 0 is the rightmost (pixel 7).

Memory Page / Status Register (0xFD)
This register controls CPU access to Video Module internal memory and reports display blanking status. Memory mappings set by this register override all other memory page settings, including any MZ-700 or MZ-80B specific page registers.
Bits Dir Function Description
0 R/W GRAM enable 1 = Map the selected 16 KB GRAM bank into 0xC000–0xFFFF. 0 = Normal Z80 memory.
5 R H-blank status 1 = Horizontal blanking interval active.
6 R V-blank status 1 = Vertical blanking interval active.
7 R/W CGROM enable 1 = Map CGROM into 0xD000–0xDFFF for CPU upload. 0 = Normal memory.

GPU — Graphics Processing Unit

The FPGA implements a basic GPU that can execute bulk VRAM and GRAM operations without tying up the Z80 CPU. To use the GPU:
  1. Push all required parameters into the GPU Parameters register (0xF6) in order. Each write shifts the existing 128-bit FIFO left by 8 bits and inserts the new byte at bits 7:0. Parameters are therefore pushed MSB-first (highest-numbered parameter bits first).
  2. Write the command byte to 0xF7.
  3. Poll 0xF7. Bit 0 (BUSY) will be 1 while the GPU is executing. Wait until bit 0 is 0 before issuing the next command.
The RESET command (0xFF) is acted on immediately even if the GPU is busy; all other commands are ignored while BUSY is set.

GPU Commands
Command Parameters (pushed MSB-first to 0xF6) Description
0x00 None No-op. Idle state. Issuing this command has no effect.
0x01 None Clear entire VRAM to space character (0x00) with white foreground on blue background attribute.
0x02 [15:8] = character byte, [7:0] = attribute byte Clear entire VRAM with the specified character and attribute values.
0x03 [47:40] = StartX, [39:32] = StartY, [31:24] = EndX, [23:16] = EndY, [15:8] = character, [7:0] = attribute Fill a rectangular region of VRAM (character coordinates) with the specified character and attribute.
0x81 None Clear all GRAM — sets every pixel in all three (Red, Green, Blue) 16 KB frame buffers to zero.
0x82 [87:72] = StartX, [71:56] = StartY, [55:40] = EndX, [39:24] = EndY, [23:16] = Red filter, [15:8] = Green filter, [7:0] = Blue filter Fill a rectangular region of GRAM (pixel coordinates) according to the filter masks. Each filter is 8 bits wide (bit 7 = leftmost pixel). A 1 bit sets the pixel; a 0 bit clears it.
0xFF None Reset GPU. Cancels any running operation and returns immediately to idle state.
Parameter push order for command 0x82 example: to clear GRAM pixels (0,0)–(639,199) with all pixels set red and all pixels clear green and blue, push bytes in this order to 0xF6: StartX high (0x00), StartX low (0x00), StartY high (0x00), StartY low (0x00), EndX high (0x02), EndX low (0x7F), EndY high (0x00), EndY low (0xC7), Red filter (0xFF), Green filter (0x00), Blue filter (0x00). Then write 0x82 to 0xF7.

Video Timing Modes

The active video timing mode is determined by bits 7:6 (VGA mode) and bit 3 (column width) and bits 2:0 (machine model) of the Control Register (0xF8). Individual timing parameters within a mode can be overridden at runtime using the Video Mode Parameter registers (0xD0–0xD2). The parameter selector (0xD0) takes a parameter number 0–18; the value is written as a 16-bit quantity split across the Low (0xD1) and High (0xD2) byte registers.
Parameter key:
H_DSP_START     Param 0   Horizontal display area start (physical).
H_DSP_END       Param 1   Horizontal display area end.
H_DSP_WND_START Param 2   Horizontal display window start (data output area).
H_DSP_WND_END   Param 3   Horizontal display window end.
V_DSP_START     Param 4   Vertical display area start.
V_DSP_END       Param 5   Vertical display area end.
V_DSP_WND_START Param 6   Vertical display window start.
V_DSP_WND_END   Param 7   Vertical display window end.
H_LINE_END      Param 8   Last horizontal pixel (total line length − 1).
V_LINE_END      Param 9   Last vertical line (total frame height − 1).
MAX_COLUMNS     Param 10  Maximum character columns (40 or 80).
H_SYNC_START    Param 11  Horizontal sync pulse start (= H_DSP_END + front porch).
H_SYNC_END      Param 12  Horizontal sync pulse end.
V_SYNC_START    Param 13  Vertical sync pulse start.
V_SYNC_END      Param 14  Vertical sync pulse end.
H_POLARITY      Param 15  Horizontal sync polarity: 0 = negative, 1 = positive.
V_POLARITY      Param 16  Vertical sync polarity: 0 = negative, 1 = positive.
H_PX            Param 17  Horizontal pixel doubling factor (0=1×, 1=2×, 2=4×).
V_PX            Param 18  Vertical pixel doubling factor (0=1×, 1=2×, 2=4×).
The sixteen predefined modes cover native MZ scan rates and three VGA output rates, each in 40-column and 80-column, monochrome and colour variants:
Mode Description H_DSP V_DSP H_LINE V_LINE MAX_COL H_SYNC V_SYNC H_POL V_POL H_PX V_PX
0 Native 40-col mono (512×260, 320×200 viewable) 0–320 0–200 511 259 40 363–408 219–223 0 0 0 0
1 Native 80-col mono (1024×260, 640×200 viewable) 0–640 0–200 1023 259 80 746–836 219–223 0 0 0 0
2 Native 40-col colour (512×260, 320×200 viewable) 0–320 0–200 511 259 40 363–408 219–223 0 0 0 0
3 Native 80-col colour (1024×260, 640×200 viewable) 0–640 0–200 1023 259 80 746–836 219–223 0 0 0 0
4 VGA 640×480 40-col mono 0–640 0–480 799 524 40 656–752 490–492 0 0 1 1
5 VGA 640×480 80-col mono 0–640 0–480 799 524 80 656–752 490–492 0 0 0 1
6 VGA 640×480 40-col colour 0–640 0–480 799 524 40 656–752 490–492 0 0 1 1
7 VGA 640×480 80-col colour 0–640 0–480 799 524 80 656–752 490–492 0 0 0 1
8 VGA 1024×768 40-col mono 0–1024 0–768 1343 805 40 1048–1184 771–777 0 0 2 2
9 VGA 1024×768 80-col mono 0–1024 0–768 1343 805 80 1048–1184 771–777 0 0 0 2
10 VGA 1024×768 40-col colour 0–1024 0–768 1343 805 40 1048–1184 771–777 0 0 2 2
11 VGA 1024×768 80-col colour 0–1024 0–768 1343 805 80 1048–1184 771–777 0 0 0 2
12 VGA 800×600 40-col mono 0–800 0–600 1055 627 40 840–968 601–605 1 1 1 2
13 VGA 800×600 80-col mono 0–800 0–600 1055 627 80 840–968 601–605 1 1 0 2
14 VGA 800×600 40-col colour 0–800 0–600 1055 627 40 840–968 601–605 1 1 1 2
15 VGA 800×600 80-col colour 0–800 0–600 1055 627 80 840–968 601–605 1 1 0 2

Build System

The v2.0 Video Module has two distinct hardware build targets — the CPLD and the FPGA — each requiring a different version of Quartus Prime. A Docker image is provided that bundles both versions and is the recommended approach, eliminating the need to manage complex native Altera toolchain installations.

CPLD Build (Quartus Prime 13.0.1)
The CPLD VideoInterface is compiled with Quartus Prime 13.0.1, which is the last version to support the Altera MAX 7000A family. The target device is EPM7128S.
File Description
CPLD/VideoInterface.vhd Main VHDL design file — all gate and interconnect logic.
CPLD/VideoInterface_pkg.vhd Package file — constants, types, and function declarations shared across all modules.
CPLD/VideoInterface_TopLevel.vhd Top-level wrapper — pin I/O declarations and component instantiation.
CPLD/build/VideoInterface.qpf Quartus Prime project file. Open this to load the project.
CPLD/build/VideoInterface.qsf Project settings file — pin assignments, device selection, compilation parameters.
CPLD/build/VideoInterface_constraints.sdc Timing constraints for TimeQuest analyser and place-and-route guidance.
CPLD/build/VideoInterface.csv Pin assignment CSV — can be imported into Quartus Prime Pin Planner.
Compilation:
  1. Start Quartus Prime v13.0.1.
  2. File → Open Project → select CPLD/build/VideoInterface.qpf.
  3. Processing → Start Compilation. Warning messages can be ignored.
  4. Output bitstream: CPLD/build/output_files/VideoInterface.sof

Programming:
  1. Connect Altera USB Blaster to the 10-pin JTAG IDC connector on the Video Module.
  2. Tools → Programmer → Hardware Setup → select USB Blaster → Close.
  3. Click Auto Detect. Three devices should appear: EPM7128S, EP3C25E144, EPCS16.
  4. Right-click EPM7128S → Add File → select VideoInterface.sof.
  5. Enable 'Program/Configure' and 'Verify' for EPM7128S.
  6. Click Start.

FPGA Build (Quartus Prime 13.1)
The FPGA VideoController is compiled with Quartus Prime 13.1, which supports the Cyclone III EP3C25 device. The FPGA bitstream is volatile — it must be stored in the companion EPCS16 serial Flash to persist across power cycles.
File Description
FPGA/VideoController.vhd Main VHDL design file — full video controller logic.
FPGA/VideoController_pkg.vhd Package file — constants, types, and shared declarations.
FPGA/VideoController_Toplevel.vhd Top-level wrapper — FPGA pin I/O and component instantiation.
FPGA/functions.vhd Shared utility functions.
FPGA/build/VideoController.qpf Quartus Prime project file.
FPGA/build/VideoController.qsf Project settings — pin assignments, device, compilation options.
FPGA/build/VideoController_constraints.sdc Timing constraints.
FPGA/build/VideoController.csv Pin assignment CSV.
Compilation:
  1. Start Quartus Prime v13.1.
  2. File → Open Project → select FPGA/build/VideoController.qpf.
  3. Processing → Start Compilation. Warning messages can be ignored.
  4. Output bitstream: FPGA/build/output_files/VideoController.sof

Programming FPGA (volatile — lost on power-off):
  1. Connect USB Blaster to the 10-pin JTAG connector.
  2. Tools → Programmer → Hardware Setup → select USB Blaster → Close.
  3. Auto Detect — three devices should appear.
  4. Right-click EP3C25E144 → Add File → select VideoController.sof.
  5. Enable 'Program/Configure' for EP3C25E144.
  6. Click Start.

Programming EPCS16 (persistent — survives power cycles):
  1. File → Convert Programming Files.
  2. Programming File Type: JTAG Indirect Configuration File (.jic).
  3. Configuration Device: EPCS16.
  4. Flash Loader → Add Device → Cyclone III → EP3C25 → OK.
  5. SOF Data → Add File → select VideoController.sof → OK.
  6. File Name: set output path for VideoController.jic.
  7. Click Generate → Close.
  8. Tools → Programmer → Auto Detect.
  9. Add VideoController.sof to EP3C25E144 (Program/Configure).
  10. Add VideoController.jic to EPCS16 (Program/Configure + Verify).
  11. Click Start. FPGA and EPCS16 are now both programmed.

Docker Build Environment
Installing Quartus Prime natively on Linux can be unreliable due to missing or conflicting package dependencies. A Docker image is provided that bundles Ubuntu, all required packages, Quartus Prime 13.0.1 (for the CPLD), and Quartus Prime 13.1 (for the FPGA). X11 forwarding allows the Quartus GUI to display on the host machine. The USB Blaster is passed through from the host to the container via udev rules installed in the image.
# Clone the Docker build repository:
cd ~
git clone https://git.eaw.app/eaw/zpu.git
cd zpu/docker/QuartusPrime

# (Optional) Switch from Lite to Standard edition before building:
#   Edit Dockerfile.13.0.1:
#     Uncomment: ARG QUARTUS=QuartusSetup-13.0.1.232.run
#     Comment:   ARG QUARTUS=QuartusSetupWeb-13.0.1.232.run

# (Optional) Install a license file:
#   cp <your license> files/license.dat
#   Edit run.sh and set MAC_ADDR to match your license MAC address.

# Build the Docker image for Quartus 13.0.1 (CPLD):
docker build -f Dockerfile.13.0.1 -t quartus-ii-13.0.1 \
    --build-arg user_uid=`id -u` \
    --build-arg user_gid=`id -g` \
    --build-arg user_name=`whoami` .

# For Quartus 13.1 (FPGA), repeat with Dockerfile.13.1.

# Configure X11 forwarding on host:
export DISPLAY=<x-server-ip>:0
xhost +  # or xhost <docker-host-ip> for security on shared networks

# Configure project directory mapping:
#   Edit run_quartus.sh:
#     PROJECT_DIR_HOST=<host path to project>
#     PROJECT_DIR_IMAGE=<container path to project>

# Start Quartus in the container:
./run_quartus.sh

# Stop the container:
docker stop quartus
On first launch, Quartus Prime will prompt for a license. Select "Run the Quartus Prime software" and click OK. The USB Blaster will appear in the Programmer tool automatically if plugged in after the container has started, provided the udev rules are active on the host.

CG-ROM Image Build
The 32 KB Character Generator Flash RAM image (COLOURBOARD_CG.rom) is assembled by concatenating the 16 individual 2 KB CG-ROM slot images in order. The shell script software/tools/make_cgrom.sh performs this concatenation automatically. The output file can be flashed directly into a 28C256 Flash RAM for use on a v1.x board, or loaded as a memory initialisation file into the FPGA for v2.0.
cd <repository root>/software
./tools/make_cgrom.sh
# Output: ../../MZ80A_80COLOUR/software/roms/COLOURBOARD_CG.rom  (32 KB)

Reference Sites

Resource Link
Video Module project page /sharpmz-upgrades-videomodule/
tranZPUter project page /sharpmz-upgrades-tranzputer/
Sharp MZ Emulator /sharpmz-emulator/
RFS Technical Guide /sharpmz-upgrades-rfs-technicalguide/
Nibbles Lab Sharp MZ museum http://retropc.net/ohishi/museum/mz1200.htm
Altera Quartus Prime (legacy) https://www.intel.com/content/www/us/en/collections/products/fpga/software/downloads.html
Docker build repository https://git.eaw.app/eaw/zpu