# SFD700

**Website:** [engineers@work](https://eaw.app) | **Repository:** [git.eaw.app/eaw/SFD700](https://git.eaw.app/eaw/SFD700)

---

<div style="text-align: justify">

<font style="color: green;" size="4">&nbsp;  <b>Update February 2024</b> - The v1.2 hardware is fully functional and has been tested on my MZ-80A, MZ-700 and MZ-1500 using the EXT700 adapter and in the MZ-2000 expansion unit. Issues have been reported using the MZ-1U06 which needs to be investigated, seems a CPLD timing issue. The CPLD logic (VHDL) is complete and all ROM/RAM paging and host-mode logic works correctly. The Rom Filing System software ported to the SFD-700 is functional for basic FDC operations (floppy boot via 'F' command) but does not yet include the full suite of floppy disk monitor tools; this is under ongoing development. Client workload has slowed progress — please check the <a href="https://git.eaw.app/eaw/SFD700">Gitea repository</a> for the latest state. The board hasnt been tested in other MZ series machines, hopefully I will do this in due course.</font>

<div style="padding-top: 0.8em;"></div>
One of the most needed accessories for the Sharp MZ series is the venerable Floppy Disk Controller.  These are in relative short supply as not many people used them, mainly due to cost during the Sharp MZ era. 

<div style="padding-top: 0.8em;"></div>
Sharp designed and released multiple floppy disk expansion cards, some built into the base machine, such as the MZ-2500/2800/3500/5600/6500 series, others required a plug in card. They initially started with a custom controller within the MZ-80K series, then
with the advent of the MZ-80B business machine, Sharp standardised on the Western Digital Floppy Disk Controller architecture and designed and produced their own controller IC, the MB8866.

<div style="padding-top: 0.8em;"></div>
The MZ-80B design assumed all floppy disk control firmware would be stored in the machine's IPL (Initial Program Loader), which persisted into the MZ-800/MZ-1500/MZ-2000/MZ-2200 designs, maintaining controller compatibility with these newer machines.

<div style="padding-top: 0.8em;"></div>
Unfortunately, for lesser models, such as the MZ-80A/MZ-700, floppy disks were not considered at the design stage and thus required newer controller expansion cards with onboard ROM to be developed in order to provide the necessary floppy disk bootstrap firmware.
In addition, as the MZ-80A ran at 2MHz, it wasn't fast enough to read the DRQ flag and then read the available data in a steady stream, so Sharp had to make the DRQ line toggle a ROM address line in order to speed up processing to handle the data flow.

<div style="padding-top: 0.8em;"></div>
Sharp floppy disk expansion cards were expensive. creating a window of opportunity for third parties to produce cheaper offerings. A company in Germany, K&P Partners GmbH was such a company and it offered two products, the <a href="/sfd800/">SFD-800</a> for MZ-800 machines,
which was also compatible with the MZ-80B/MZ-1500/MZ-2000/MZ-2200 hosts, and the SFD-700 which was targeted at the MZ-700.

<div style="padding-top: 0.8em;"></div>
I initially, like the SFD-800, considered a replica design, but after studying the various circuits, observed a fatal flaw in the K&P SFD-700, memory paging. The card was designed to work in the MZ-1U06 expansion unit which had paging logic to disable access to
expansion card memory according to the paging state registers of the MZ-700. If this card was used in a custom expansion unit, it wouldn't work. I also had MZ-80A's which needed a floppy controller so came to the conclusion a single card, which would work in
all the MZ series from the MZ-80A onwards (excluding those with built in controllers) would be the way forward. Hence the concept of an SFD-700 mkII was born, same name as the K&P product but greater functionality.

<div style="padding-top: 0.8em;"></div>
This document outlines the new schematic, the programmable logic and any issues discovered on each machine.
</div>

## <font style="color: yellow;" size="6">Host Compatibility</font>

<div style="text-align: justify">
The SFD-700 v1.2 supports all Sharp MZ series machines from the MZ-80A onwards (excluding machines with built-in floppy controllers). The target host is selected by a 3-bit MODE jumper on the PCB which is latched at reset. The table below lists the supported machines and corresponding jumper value.
<div style="padding-top: 0.8em;"></div>
</div>

| MODE | Host Machine |
| ---- | ------------ |
| 0    | Sharp MZ-80A / MZ-1200 |
| 1    | Sharp MZ-700 |
| 2    | Sharp MZ-80B |
| 3    | Sharp MZ-800 |
| 4    | Sharp MZ-1500 |
| 5    | Sharp MZ-2000 |
| 6    | Sharp MZ-2200 |

<div style="text-align: justify">
On MZ-80A/MZ-1200, the CPU runs at 2 MHz which is insufficient to poll the WD1773 DRQ flag and read the data register before the next byte arrives. The CPLD handles this by routing the DRQ signal to Flash ROM address bit A10, so duplicate firmware code appears in each 1 KB segment of the ROM. This removes the need for software polling — the DRQ line directly selects the correct read or wait path in the ROM bootstrap.
</div>

## <font style="color: yellow;" size="6">Schematic</font>

![Schematic](../images/SFD700_Schematic-3.png)

<a name="programmable-logic" id="programmable-logic"></a>
## <font style="color: yellow;" size="6">Programmable Logic</font>

<div style="text-align: justify">

<b>v1.0 / v1.1 — GAL-based design</b>

<div style="padding-top: 0.8em;"></div>
The early revisions used two GAL devices: a Lattice GAL26CV12 as the primary I/O address decoder and MZ-700 memory management controller, and a Lattice GAL16V8 as the ROM address decoder and host-mode selector. The designs were written in CUPL (Compiler for Universal Programmable Logic) and compiled with the original Logical Devices CUPL v4.0 toolchain.
<div style="padding-top: 0.8em;"></div>

The GAL26CV12 was chosen because it provided enough product terms and registered outputs to decode the wide I/O address range and manage the MZ-700 memory paging state, which required more macrocells than a standard 16V8 or 22V10 could offer. Unfortunately, the 26CV12 brought two practical problems. First, tool support: when Microchip Technology acquired Atmel (who had acquired Logical Devices and the CUPL toolchain), the successor product WinCUPL was updated to target only Atmel-compatible devices, dropping support for the Lattice 26CV12. Compilation for v1.0/v1.1 therefore requires the original DOS-era CUPL v4.0 or an equivalent toolchain rather than WinCUPL. Second, programmer support: no current off-the-shelf programmer such as the TL-866 II+ supports the 26CV12 without a PLCC-to-DIP adapter and a custom device configuration file for Minipro.
<div style="padding-top: 0.8em;"></div>

Despite these hurdles, v1.0 and v1.1 were functional on the MZ-700 for basic floppy operations. The GAL26CV12 register count was nevertheless a binding constraint: the device has only one registered output cluster and a limited expander pool, so it was not possible to simultaneously implement full MZ-700 memory management state tracking and the independent ROM/RAM page registers needed for the ROM Filing System — this limitation is the primary reason v1.2 moved to a CPLD.

<div style="padding-top: 0.8em;"></div>
<b>v1.2 — CPLD (VHDL)</b>

<div style="padding-top: 0.8em;"></div>
Version 1.2 replaced both GAL devices with a single Altera MAX7000S <b>EPM7128SLC84-15</b> CPLD (PLCC-84, 128 macrocells), implemented in VHDL and compiled with Quartus II 13.0.1 SP1. This resolved the register-count limitations of the GAL26CV12 and enabled full MZ-700/MZ-1500 memory mapping logic alongside independent ROM/RAM paging across two memory windows. The VHDL source files (<code>sfd700.vhd</code>, <code>sfd700_Toplevel.vhd</code>, <code>sfd700_pkg.vhd</code>) are in the <code>CPLD/v1.2/</code> directory of the Gitea repository. The earlier CUPL files for v1.0/v1.1 remain in the <code>CUPL/</code> directory for reference.
</div>

--------------------------------------------------------------------------------------------------------

<a name="gal" id="gal"></a>
## <font style="color: yellow;" size="6">GAL (v1.0 / v1.1)</font>

<a name="gal-devices" id="gal-devices"></a>
<font style="color: yellow;" size="5">Devices</font>

<div style="text-align: justify">
Two Lattice GAL devices implement all programmable logic on v1.0 and v1.1 boards. GAL devices are EEPROM-based PLDs (Programmable Logic Devices) — they implement sum-of-products logic in a fuse array and support both combinatorial and registered (flip-flop) outputs. Unlike the later CPLD, each GAL is a single-level device: there is no routing fabric between devices, so signals that need to span both GALs must be routed on the PCB.
</div>

| Device | Package | Macrocells | Registered Outputs | Role |
|--------|---------|------------|-------------------|------|
| GAL26CV12 | 28-pin DIP | 12 | 12 | I/O decoder, FDC control, MZ-700 memory management |
| GAL16V8 | 20-pin DIP | 8 | 8 | ROM address decode, mode select, DRQ multiplexer |

<a name="gal1" id="gal1"></a>
<font style="color: yellow;" size="5">GAL1 — GAL26CV12 (I/O Decoder)</font>

<div style="text-align: justify">
The GAL26CV12 (<code>SFD700_GAL1</code>) is the primary logic device. It decodes the Z80 I/O address bus to generate all FDC control signals, manages the bidirectional data bus buffer, tracks MZ-700 memory paging state, and controls the interrupt enable flag.
<div style="padding-top: 0.8em;"></div>

<b>I/O Address Decoding</b><br>
Eight address lines (A0–A7) are combined with the IORQn, RDn, and WRn control inputs to identify each register access. Separate read and write selects are generated for the WD1773 FDC register block so that the bidirectional bus buffer can be switched in the correct direction: IOBUSDIRn goes low (Z80→FDC direction) only on FDC reads, and the FDCn chip select is asserted on both reads and writes.
<div style="padding-top: 0.8em;"></div>

<b>FDC Peripheral Control</b><br>
Writes to 0xDC, 0xDD, and 0xDE produce single-cycle strobe outputs (DRIVEn, SIDEn, DDENn) that clock the drive selection, head side, and data density latches on the PCB. The FDCRESETn output is tied directly to the Z80 RESET signal so the WD1773 is always reset on system power-up or hardware reset.
<div style="padding-top: 0.8em;"></div>

<b>MZ-700 Memory Management</b><br>
The MZ-700 uses I/O writes to ports 0xE1–0xE6 to bank its internal DRAM and CGROM in and out of the upper address space. The GAL tracks two independent state bits using its registered outputs, clocked by the decoded port strobes:
<ul style="line-height: 1.6em;"><font size="3">
  <li>DISROM — set by writes to 0xE3/0xE4, cleared by 0xE1 and by RESET. When set it signals that the host has mapped its DRAM over the card's ROM window.</li>
  <li>INHROM — set by writes to 0xE5, cleared by 0xE6 and by RESET. When set it inhibits the card's ROM entirely, regardless of DISROM state.</li>
</font></ul>
Both state bits are output as active-low strobes (DISROMSET/DISROMCLR and INROMHSET/INHROMCLR) which drive set/clear inputs of discrete flip-flops on the PCB — the GAL26CV12's single registered output cluster was insufficient to hold both bits as true registered values inside the device, which was one of the limiting constraints of the design.
<div style="padding-top: 0.8em;"></div>

<b>Interrupt Enable</b><br>
The INTEN registered output is clocked by the INTCLK strobe generated from an access to port 0xE7. A write sets the enable (INTEN.D follows !WRn); a read clears it. INTEN is asynchronously reset by the system RESET input. The INTCLK output feeds the clock input of an external flip-flop on the PCB.
</div>

| Pin | Signal | Dir | Description |
|-----|--------|-----|-------------|
| 1 | CLK | In | Registered output clock |
| 2–6, 8–11 | A0–A7 | In | Z80 I/O address bus |
| 11 | IORQn | In | Z80 I/O request (active low) |
| 12 | WRn | In | Z80 write strobe (active low) |
| 13 | RDn | In | Z80 read strobe (active low) |
| 28 | RESET | In | System reset (active high) |
| 15 | DISROMSET | Out | ROM-disable set strobe (active low) |
| 16 | DISROMCLR | Out | ROM-disable clear strobe (active low) |
| 17 | INTCLK | Out | Interrupt enable flip-flop clock |
| 18 | INROMHSET | Out | ROM-inhibit set strobe (active low) |
| 19 | INTEN | Out | Interrupt enable registered output (active low) |
| 20 | IOBUSDIRn | Out | Bus buffer direction — low = Z80→FDC |
| 22 | INHROMCLR | Out | ROM-inhibit clear strobe |
| 23 | SIDEn | Out | Head side select strobe (active low) |
| 24 | FDCRESETn | Out | WD1773 reset (active low, tied to RESET) |
| 25 | DDENn | Out | Double-density enable strobe (active low) |
| 26 | DRIVEn | Out | Drive select strobe (active low) |
| 27 | FDCn | Out | WD1773 chip select (active low) |

<a name="gal2" id="gal2"></a>
<font style="color: yellow;" size="5">GAL2 — GAL16V8 (ROM Decoder)</font>

<div style="text-align: justify">
The GAL16V8 (<code>SFD700_GAL2</code>) handles the memory-side address decoding: it generates the ROM chip select when the Z80 addresses the firmware window at 0xF000–0xFFFF, and multiplexes address lines onto the ROM to select the correct firmware page and handle the MZ-80A DRQ trick.
<div style="padding-top: 0.8em;"></div>

<b>ROM Chip Select</b><br>
MREQn and RDn are combined with the high address lines (A12–A15) to detect accesses to 0xF000–0xFFFF. The ROMCSn output is a registered value so that chip-select glitches caused by address bus settling are suppressed — the select only propagates on the clock edge.
<div style="padding-top: 0.8em;"></div>

<b>ROM Address Multiplexing</b><br>
Two additional outputs drive ROM address lines beyond A9:
<ul style="line-height: 1.6em;"><font size="3">
  <li><b>ROMA15</b> — driven from the MODESEL1 jumper input, it selects between two firmware images (MZ-700 page and MZ-80A page) stored in the upper and lower halves of the ROM address space.</li>
  <li><b>ROMA10</b> — this is the most complex output. On MZ-80A targets (MODESEL1 low) it is multiplexed with the WD1773 DRQ signal: when the ROM is selected and DRQ is asserted, ROMA10 selects one 1 KB mirror of the read routine; when DRQ is not asserted it selects the other mirror containing the wait/retry path. This allows the 2 MHz Z80 to service FDC data transfers via a simple linear jump through ROM rather than a polled software loop it cannot execute fast enough. On MZ-700 targets (MODESEL1 high), ROMA10 is driven directly from DRQ without the address qualification.</li>
</font></ul>

Two machine-specific variants exist in the CUPL source tree:
<ul style="line-height: 1.6em;"><font size="3">
  <li><code>SFD700_2.PLD.MZ700</code> — simplified ROMA10 logic: output follows DRQ directly.</li>
  <li><code>SFD700_2.PLD.MZ80A</code> — full multiplexed ROMA10 with address qualification and commented-out output-enable controls used during development.</li>
</font></ul>
</div>

| Pin | Signal | Dir | Description |
|-----|--------|-----|-------------|
| 1 | CLK | In | Registered output clock |
| 2–7 | A10–A15 | In | Z80 high address bus |
| 8 | MREQn | In | Z80 memory request (active low) |
| 9 | RDn | In | Z80 read strobe (active low) |
| 12 | MODESEL0 | In | Mode jumper bit 0 |
| 13 | MODESEL1 | In | Mode jumper bit 1 — selects ROM page / DRQ logic |
| 14 | ROMINH | In | ROM inhibit state from GAL1 |
| 15 | ROMDIS | In | ROM disable state from GAL1 |
| 16 | DRQ | In | WD1773 data request |
| 17 | ROMA15 | Out | ROM address bit 15 (firmware page select) |
| 18 | ROMA10 | Out | ROM address bit 10 (DRQ multiplexer on MZ-80A) |
| 19 | ROMCSn | Out | ROM chip select (active low, registered) |

<a name="gal-build" id="gal-build"></a>
<font style="color: yellow;" size="5">Building with CUPL</font>

<div style="text-align: justify">
The PLD source files are compiled with the <b>Logical Devices CUPL v4.0</b> (also referred to as CUPL 5.0a in compiler output headers) DOS-era toolchain. This version is required because WinCUPL — the Windows-era successor — targets only Atmel-compatible GAL devices and does not support the Lattice GAL26CV12. The CUPL v4.0 binary can be run under DOSBox or a similar DOS emulator on a modern host. Alternatively, the pre-compiled JEDEC files in the <code>CUPL/</code> directory can be used directly without recompilation.
<div style="padding-top: 0.8em;"></div>

To recompile from source, use the batch scripts included in the <code>CUPL/</code> directory:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;"># Compile GAL1 (GAL26CV12) — run inside CUPL directory
cupl -j -f -a g26cv12 SFD700_1

# Compile GAL2 (GAL16V8)
cupl -j -f -a g16v8 SFD700_2</pre>

<div style="text-align: justify">
The <code>-j</code> flag produces JEDEC output (<code>.JED</code>), <code>-f</code> produces the fuse plot (<code>.DOC</code>), and <code>-a &lt;device&gt;</code> specifies the target device. Compiled outputs are written to the same directory:
<ul style="line-height: 1.6em;"><font size="3">
  <li><code>SFD700_1.JED</code> — JEDEC fuse file for GAL1, ready for programming.</li>
  <li><code>SFD700_2.JED</code> — JEDEC fuse file for GAL2, ready for programming.</li>
  <li><code>SFD700_1.DOC</code> / <code>SFD700_2.DOC</code> — human-readable fuse plots and chip diagrams for verification.</li>
  <li><code>SFD700_1.ABS</code> / <code>SFD700_2.ABS</code> — binary intermediate files used by some programmer utilities.</li>
</font></ul>
</div>

<a name="gal-program" id="gal-program"></a>
<font style="color: yellow;" size="5">Programming the GALs</font>

<div style="text-align: justify">
<b>GAL16V8 (GAL2)</b><br>
The GAL16V8 is supported natively by virtually all modern device programmers. Using a TL-866 II+ or similar with the open-source <code>minipro</code> utility:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">minipro -p GAL16V8 -w SFD700_2.JED</pre>

<div style="text-align: justify">
A Minipro-format JED (<code>SFD700_G.JED</code>) is also provided in the <code>CUPL/</code> directory for direct use. Verify after programming with:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">minipro -p GAL16V8 -v SFD700_2.JED</pre>

<div style="text-align: justify">
<b>GAL26CV12 (GAL1)</b><br>
The GAL26CV12 is a 28-pin PLCC/DIP device that is not listed in the standard TL-866 II+ device database. Programming requires a PLCC-28 to DIP-28 adapter and a custom device entry in the Minipro <code>infoic.xml</code> database — a pre-configured <code>infoic.xml</code> is included in the <code>CUPL/</code> directory. With the adapter fitted and the custom database in place:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">minipro -p GAL26CV12 -w SFD700_1.JED</pre>

<div style="text-align: justify">
If using an older dedicated GAL programmer (e.g. BP Microsystems, Data I/O), use the standard JEDEC <code>.JED</code> file directly — all compliant GAL programmers accept the JEDEC 3C format that CUPL produces.
<div style="padding-top: 0.8em;"></div>
Both GAL devices retain their programmed configuration in EEPROM and are ready immediately at power-on with no load delay. They can be erased and reprogrammed in-circuit if JTAG test points are provided, or removed from their sockets for bench programming.
</div>

--------------------------------------------------------------------------------------------------------

<a name="cpld" id="cpld"></a>
## <font style="color: yellow;" size="6">CPLD</font>

<a name="cpld-device" id="cpld-device"></a>
<font style="color: yellow;" size="5">Device</font>

<div style="text-align: justify">
The SFD-700 v1.2 CPLD is an Altera MAX7000S <b>EPM7128SLC84-15</b> in an 84-pin PLCC package. It is a 5 V-tolerant EEPROM-based CPLD with a maximum propagation delay of 15 ns and in-system programmability via JTAG. Resource utilisation after a successful build is as follows:
</div>

| Resource | Used | Available | Utilisation |
|----------|------|-----------|-------------|
| Macrocells | 72 | 128 | 56% |
| Registers | 37 | 128 | 29% |
| I/O pins | 65 | 68 | 96% |
| Product terms | 179 | — | — |
| Global clocks | 2 | 2 | 100% |

<a name="cpld-architecture" id="cpld-architecture"></a>
<font style="color: yellow;" size="5">Architecture</font>

<div style="text-align: justify">
The 72 macrocells are partitioned into eight functional blocks. Two signals are assigned to dedicated global routing resources: <code>CLK_16M</code> (the primary clock) and <code>Z80_RESETn</code> (synchronous reset), minimising clock and reset skew across the device.
<div style="padding-top: 0.8em;"></div>

<b>Clock Generation</b><br>
The on-board 16 MHz crystal oscillator drives the <code>CLK_16M</code> global clock input. A single registered toggle macrocell divides this by two to produce <code>CLK_FDC</code>, the 8 MHz clock fed directly to the WD1773 FDC chip-clock input.
<div style="padding-top: 0.8em;"></div>

<b>I/O Address Decoder</b><br>
Purely combinatorial logic decodes Z80 I/O cycles (IORQn asserted with RDn or WRn) across three address blocks: the WD1773 FDC registers at 0xD8–0xDB, the FDC control registers at 0xDC–0xDF, and the paging and mode registers at 0x60–0x63. On MZ-700 and MZ-1500 targets (MODE 1 and 4) the decoder also captures writes to I/O ports 0xE0–0xE6 to track the host memory management state. The maximum fan-out node in the design originates from the address decode tree and drives 67 macrocell inputs.
<div style="padding-top: 0.8em;"></div>

<b>Memory Address Decoder</b><br>
Decodes Z80 memory cycles (MREQn with RDn or WRn) to generate active-low chip-select outputs for the on-board Flash ROM (<code>ROM_CSn</code>) and static RAM (<code>RAM_CSn</code>). Two independent 7-bit page registers — EXXX_PAGE (loaded via 0x60) and FXXX_PAGE (loaded via 0x61) — are driven onto address bits <code>ROM_A10</code> and <code>RAM_A10</code>, bank-switching 4 KB windows within up to 512 KB of addressable storage.
<div style="padding-top: 0.8em;"></div>

<b>Drive and Motor Control</b><br>
A write to I/O port 0xDC loads an 8-bit registered value that drives the four active-low drive-select outputs (DRVSAn–DRVSDn) and the motor-enable line (MOTOR). Bits [2:0] encode the selected drive (values 4–7 select drives A–D; 0 deselects all); bit 7 controls the spindle motor. Head-side selection (0xDD) and double-density mode (0xDE) are managed by separate single-bit registers.
<div style="padding-top: 0.8em;"></div>

<b>Data Bus Inversion and Multiplexing</b><br>
The WD1773 requires bitwise-inverted data. The CPLD connects to a dedicated 8-bit inverted data bus (<code>ID[7:0]</code>) and handles the polarity inversion transparently in both read and write directions. On a Z80 read of an FDC register the inverted bus is re-inverted onto the Z80 data bus; on a write to an FDC register the Z80 data bus is inverted onto <code>ID[7:0]</code>. When a page register is read back by the host, the CPLD drives the stored page value directly onto the Z80 data bus instead.
<div style="padding-top: 0.8em;"></div>

On MZ-80A and MZ-1200 targets (MODE 0) the WD1773 DRQ signal is multiplexed onto Flash ROM address bit A10 (<code>ROM_A10</code>). Each 1 KB segment of the boot ROM contains a mirrored copy of the read routine; the DRQ state selects the correct copy directly, bypassing the software polling loop that the 2 MHz Z80 cannot execute fast enough to service the FDC data rate reliably.
<div style="padding-top: 0.8em;"></div>

<b>Interrupt Control</b><br>
The WD1773 INTRQ output is gated by a single registered enable bit. A write to I/O port 0xDF enables routing of INTRQ to the Z80 INT line; a read from 0xDF clears the enable. A secondary output, Z80_EXWAITn, is available to insert external wait states during FDC register access if required by host timing.
<div style="padding-top: 0.8em;"></div>

<b>MZ-700 / MZ-1500 Memory Management</b><br>
The MZ-700 and MZ-1500 use I/O writes to 0xE0–0xE6 to bank their internal DRAM and ROM in and out of the upper address space. The CPLD monitors these writes and maintains a two-bit state register: writing 0xE5 sets the inhibit state, suppressing <code>ROM_CSn</code> and <code>RAM_CSn</code> regardless of page register contents; writing 0xE3, 0xE4, or 0xE6 clears the inhibit and re-enables the expansion card windows.
<div style="padding-top: 0.8em;"></div>

<b>Mode Register</b><br>
Three mode jumper inputs (MODE[2:0]) are sampled and latched into a registered value on the rising edge of Z80_RESETn. Reading I/O port 0x63 returns this value, allowing boot firmware to auto-detect the host machine without DIP switches or manual configuration.
</div>

<a name="cpld-pins" id="cpld-pins"></a>
<font style="color: yellow;" size="5">Pin Assignment</font>

<div style="text-align: justify">
Key pin assignments for the EPM7128SLC84-15 (84-pin PLCC). All I/O is 3.3 V LVTTL; the MAX7000S family is 5 V input-tolerant, making it directly compatible with the 5 V Sharp MZ bus.
</div>

| Signal | Pin | Direction | Description |
|--------|-----|-----------|-------------|
| CLK_16M | 83 | In | 16 MHz crystal oscillator — global clock |
| CLK_FDC | 81 | Out | 8 MHz clock to WD1773 |
| CLK_BUS0 | 2 | In | Host Z80 bus clock |
| Z80_RESETn | — | In | Active-low reset — global resource, latches MODE |
| A[15:0] | 4–25 | In | Z80 address bus |
| D[7:0] | 27–35 | Bidir | Z80 data bus |
| ID[7:0] | 64–74 | Bidir | Inverted data bus (WD1773 side) |
| M1n | 36 | In | Z80 M1 machine-cycle indicator |
| RDn | 37 | In | Z80 read strobe |
| WRn | 39 | In | Z80 write strobe |
| IORQn | 40 | In | Z80 I/O request |
| MREQn | 41 | In | Z80 memory request |
| Z80_INT | 44 | Out | Interrupt output to Z80 (gated INTRQ) |
| Z80_EXWAITn | 45 | Out | External wait request to Z80 |
| FDCn | 63 | Out | WD1773 chip select (active low) |
| INTRQ | 61 | In | WD1773 interrupt request |
| DRQ | 60 | In | WD1773 data request |
| DDENn | 58 | Out | Double-density enable to WD1773 (active low) |
| SIDE1 | 57 | Out | Head side select |
| MOTOR | 56 | Out | Spindle motor enable |
| DRVSAn | 55 | Out | Drive A select (active low) |
| DRVSBn | 54 | Out | Drive B select (active low) |
| DRVSCn | 52 | Out | Drive C select (active low) |
| DRVSDn | 51 | Out | Drive D select (active low) |
| ROM_CSn | 77 | Out | Flash ROM chip select (active low) |
| RAM_CSn | 76 | Out | Static RAM chip select (active low) |
| ROM_A10 | 80 | Out | ROM page address bit / DRQ mux (MZ-80A MODE) |
| RAM_A10 | 79 | Out | RAM page address bit |
| MODE[2:0] | 49,48,50 | In | Host machine mode jumpers |

<a name="cpld-build" id="cpld-build"></a>
<font style="color: yellow;" size="5">Building the CPLD Bitstream</font>

<div style="text-align: justify">
The CPLD bitstream is compiled using <b>Quartus II 13.0.1 SP1 Web Edition</b>. This specific version is required because Quartus releases after 13.x dropped support for the MAX7000S device family. The Web Edition is freely available from the Intel FPGA Software Archive.
<div style="padding-top: 0.8em;"></div>

Clone the repository and open the project:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">git clone https://git.eaw.app/eaw/SFD700
cd SFD700/CPLD/v1.2/build</pre>

<div style="text-align: justify">
To compile from the command line:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">quartus_map --read_settings_files=on sfd700   # Analysis & Synthesis
quartus_fit --read_settings_files=on sfd700   # Fitter (Place & Route)
quartus_asm --read_settings_files=on sfd700   # Assembler — generates sfd700.pof
quartus_sta sfd700                            # Timing analysis (optional)</pre>

<div style="text-align: justify">
Alternatively, open <code>CPLD/v1.2/build/sfd700.qpf</code> in the Quartus II GUI and use <b>Processing → Start Compilation</b>. On a successful build the output programming file is written to:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">CPLD/v1.2/build/output_files/sfd700.pof</pre>

<div style="text-align: justify">
Expected resource utilisation: 72/128 macrocells (56%), 65/68 pins (96%), 37 registers. Any significant deviation indicates a synthesis settings mismatch — confirm the device is set to <code>EPM7128SLC84-15</code> (MAX7000S family) in the Quartus project settings.
</div>

<a name="cpld-program" id="cpld-program"></a>
<font style="color: yellow;" size="5">Programming the CPLD</font>

<div style="text-align: justify">
The EPM7128SLC84-15 is programmed via its four-pin JTAG port (TDI, TDO, TMS, TCK) using an Altera USB-Blaster or a compatible clone. Connect the USB-Blaster to the 10-pin JTAG header on the SFD-700 PCB and to a USB port on the programming host.
<div style="padding-top: 0.8em;"></div>

To program from the command line:
</div>

<pre style="font-size: 0.70em; line-height: 1.4em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">quartus_pgm -c "USB-Blaster" -m JTAG \
  -o "p;CPLD/v1.2/build/output_files/sfd700.pof"</pre>

<div style="text-align: justify">
Or use the Quartus II Programmer GUI:
<ol>
  <li>Open <b>Tools → Programmer</b>.</li>
  <li>Click <b>Hardware Setup</b> and select <b>USB-Blaster</b>.</li>
  <li>Click <b>Add File</b> and select <code>output_files/sfd700.pof</code>.</li>
  <li>Tick <b>Program/Configure</b> and optionally <b>Verify</b>.</li>
  <li>Click <b>Start</b>. Programming completes in a few seconds.</li>
</ol>
The MAX7000S uses EEPROM cells for configuration storage. The programmed state is retained indefinitely without power and is available immediately at every subsequent power-on — no bitstream loading delay occurs.
</div>

## <font style="color: yellow;" size="6">I/O Register Map</font>

<div style="text-align: justify">
The CPLD decodes the Z80 I/O address bus to implement the following register set. The WD1773 uses inverted data; the CPLD handles the inversion transparently.
<div style="padding-top: 0.8em;"></div>
</div>

| Port | R/W | Description |
| ---- | --- | ----------- |
| 0xD8–0xDB | R/W | WD1773 FDC registers (Status, Command, Track, Sector, Data). |
| 0xDC | W   | Drive & motor: bits [2:0] select drive (4=A, 5=B, 6=C, 7=D, 0=none); bit [7] controls motor. |
| 0xDD | W   | Head side: D0=0 → side 1, D0=1 → side 0. |
| 0xDE | W   | Data rate: D0=0 → double density, D0=1 → single density. |
| 0xDF | W/R | Interrupt: write → enable WD1773 INT to host; read → disable WD1773 INT. |
| 0x60 | R/W | EXXX page register: bits [6:0] select a 4 KB Flash ROM/RAM page mapped into E300:EFFF. |
| 0x61 | R/W | FXXX page register: bits [6:0] select a 4 KB Flash ROM/RAM page mapped into F000:FFFF. |
| 0x62 | R/W | Storage select: D0=0 → Flash ROM enabled; D0=1 → RAM enabled. |
| 0x63 | R   | Mode register: reads back the MODE jumper value (0–6). |
| 0xE1 | W   | MZ-700/MZ-1500 only: disable onboard ROM (host maps DRAM to D000:FFFF). |
| 0xE3, 0xE4 | W | MZ-700/MZ-1500 only: re-enable onboard ROM. |
| 0xE5 | W   | MZ-700/MZ-1500 only: inhibit all onboard ROM/RAM access. |
| 0xE6 | W   | MZ-700/MZ-1500 only: clear ROM inhibit, re-enable onboard ROM/RAM. |

## <font style="color: yellow;" size="6">Memory Map</font>

<div style="text-align: justify">
The CPLD makes the onboard Flash ROM and static RAM visible to the host through two paged windows in the upper address space. Each window is 4 KB and its physical page is set independently via I/O ports 0x60 and 0x61, allowing up to 128 × 4 KB = 512 KB of addressable Flash or RAM storage.
<div style="padding-top: 0.8em;"></div>
</div>

| Window | Address Range | Page Register | Notes |
| ------ | ------------- | ------------- | ----- |
| EXXX   | E300:EFFF     | 0x60          | E000:E2FF is reserved for MZ-700/MZ-1500 memory-mapped I/O, so only 3.75 KB of the 4 KB page is usable by firmware (RFS). |
| FXXX   | F000:FFFF     | 0x61          | Full 4 KB window. Default page 0 holds the MZ-80A AFI ROM; default page 1 holds the MZ-700 AFI ROM. |

<div style="text-align: justify">
On the MZ-80A and MZ-1200 the CPLD routes the WD1773 DRQ signal to Flash ROM address line A10. Both sides of the address line contain mirror copies of the read routine with the short path taken when DRQ is asserted. This removes the need for software polling and enables reliable data transfer at 2 MHz.
</div>

## <font style="color: yellow;" size="6">PCB</font>

#### <font style="color: yellow;" size="4">v1.1 PCB</font>

The PCB is more complex than the SFD-800 as it requires a CPLD, ROM/RAM storage and additional support circuitry (earlier v1.0/v1.1 revisions used two GAL devices instead of the CPLD).

![PCB Top](../images/SFD700_PCB_Top.png)
![PCB Bottom](../images/SFD700_PCB_Bottom.png)

#### <font style="color: yellow;" size="4">v1.2 PCB</font>

![PCB Top](../images/SFD700_topside_v12_pcb.png)
![PCB Bottom](../images/SFD700_underside_v12_pcb.png)
![PCB 3D Top](../images/SFD700_topside_v12.png)
![PCB 3D Bottom](../images/SFD700_underside_v12.png)

## <font style="color: yellow;" size="6">Manuals</font>

<div style="text-align: justify">
Detailed documentation for the SFD-700 mkII is available in three separate manuals:
</div>
<div style="padding-top: 0.8em;"></div>

| Manual | Description |
|--------|-------------|
| [User Manual](/sfd700-usermanual/) | Board overview, MODE jumper setup, drive installation, ROM Filing System usage, and troubleshooting |
| [Technical Guide](/sfd700-technicalguide/) | Hardware architecture, CPLD design, I/O register map, memory map, and build/programming procedures |
| [Developer's Guide](/sfd700-developersguide/) | Full VHDL source code walkthrough with VHDL explained for non-VHDL programmers, process-by-process analysis, and CPLD modification guide |

--------------------------------------------------------------------------------------------------------

## <font style="color: yellow;" size="6">Documentation</font>

[K&P SFD800 Manual](/Downloads/Manuals/KandP/sfd_mfd800.pdf)

The above link downloads the original K&P SFD-800 User Manual which is relevant to this design. It is in German so for non German speakers, the best way to translate is to use your smart phone, load the Google translate app, set to realtime camera translate and set the language as German->\<your language\>.

## <font style="color: yellow;" size="6">Files</font>

Please see [Gitea](https://git.eaw.app/eaw/SFD700) for all project files.


The v1.2 PCB Gerbers are available in the <code>releases/</code> directory of the Gitea repository. Six spare v1.2 boards are available — contact via the website if interested, postage cost only.

--------------------------------------------------------------------------------------------------------

## <font style="color: yellow;" size="6">Credits</font>

<div style="text-align: justify">
The original SFD-700 design is copyright 1985 Kersten & Partners GmbH from Aachen, Germany, a company that has since ceased trading. Attempts were made to contact them at their last known address to seek permission for reproduction, but no response was received.<br><br>
The SFD-700 mkII is a new design inspired by the original concept. The PCB layout, schematic and programmable logic (CUPL for v1.0/v1.1; VHDL for v1.2) were written from scratch. It is not a direct replica — the host-mode logic, ROM/RAM paging and MZ-80A DRQ-to-address-line adaptation are original additions not present in the K&P product.
</div>

--------------------------------------------------------------------------------------------------------

## <font style="color: yellow;" size="6">Licenses</font>

<div style="text-align: justify">
This design, hardware and software, is licensed under the GNU Public Licence v3.
</div>

--------------------------------------------------------------------------------------------------------

## <font style="color: yellow;" size="6">The Gnu Public License v3</font>

<div style="text-align: justify">
 The source and binary files in this project marked as GPL v3 are free software: you can redistribute it and-or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
<br><br>

 The source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
<br><br>

 You should have received a copy of the GNU General Public License along with this program.  If not, see http://www.gnu.org/licenses/.
</div>
