tranZPUter SW

Foreword

The tranZPUter and tranZPUter SW are actively being developed and changes are reflected in the documentation on a regular basis.

The tranZPUter SW is an offshoot from the tranZPUter project and utilises a Freescale K64F processor as the IO Control processor as opposed to the ZPU in the original tranZPUter project.

During testing of the tranZPUter v1.0 and with the advent of the RFS v2.0 upgrade with CP/M it was noticed that the tranZPUter should be updated so that the Z80 had additional memory and was able to run at higher clock frequencies. It should also run independent of the controlling IO processor, ie. the ZPU Evo on FPGA fabric or the K64F.

V1.0 of the tranZPUter had design restrictions which in all honesty make the project much harder to complete, for example, because of my lack of experience soldering BGA (Ball Grid Array) IC's, I chose the next best thing, a pre-fab FPGA board, the CYC1000 with the FPGA already soldered. This device and all other possibilities for the given size and FPGA ALM requirements had too few general I/O pins. This meant that multiplexing had to be used with tri-state register latches. KISS comes back to mind, Keep It Simple Stupid! So in order to further the concept and design I took a step back, looked at what was needed at the Z80 side to realise the CP/M requirements and looked at what was needed for the controlling IO Processor. As I am still not happy about soldering a 30+ pound IC where only an X-Ray machine can validate that it was soldered correctly, I opted for a powerful mini-development board, the Teensy 3.5 which has more than enough general I/O pins and is 5V tolerant, hence this interim design (which is actually better for anyone who is a software programmer and is not happy with electronics or VHDL yet wants to enhance a Z80 machine).

Everything will be written in C/C++ (FLW - Famous Last Words - I had to write the interrupt service routines in ARM Thumb assembler as the K64F isnt quite powerful enough using compiled C) and once working, I can take the bold step into speccing a tranZPUter v2.0 with a BGA knowing that the ZPU will run all the software just written.

Overview

The Sharp MZ80A is based on the Z80 CPU running at 2MHz. It is vintage (albeit the Z80 is still widely used in new industrial designs clocking at 33MHz and above)) and under powered compared with modern computers (or a Raspberry Pi). Besides being part of history, it has a software base that is useful from time to time and still has followers. A software Emulator could be written to prolong the usage of the software but there is something special about using original hardware and this is an alternative to keep the machine original yet provide an upgrade that can power the machine with additional processing capabilities, storage and with multiple different CPU's based in software like the PiCoPro on the BBC Micro. This is all made possible with bus mastering where the original CPU is tri-stated and the K64F takes control of the bus and the underlying original mainboard peripherals, when needed.

The upgrade also extends the Z80 hardware capabilities by providing additional RAM to allow for a 64K version of CP/M and to increase the speed of the processor whilst maintaining the original speed when accessing the Sharp MZ80A motherboard peripherals.

This design is a work in progress, working in tandem with the tranZPUter. The C/C++ control software written for the tranZPUter SW is intended to work on the tranZPUter under the ZPU.

As the design replaces a Z80 in-situ it is not limited to the MZ80A but can be used in any Z80 based computer with the right software adaptations, ie. the MZ-700 or MZ-80B.

tranZPUter SW

The tranZPUter gets its name from: A TRANsformable ZPU compuTER as the base CPU in the original tranZPUter is the ZPU Evo. The ZPU Evo provides the intended Menu, SD, Video Overlay services to the Sharp MZ80A by tri-stating the original Z80 and accessing the MZ80A memory and peripherals as though they were ZPU devices.

The tranZPUter SW follows on from the tranZPUter design in it's goals and makes an improvement on the underlying Z80 hardware at the same time. It uses a Freescale K64F ARM Cortex-M4 in place of the ZPU Evo as the tranZPUter SW is more a software solution to the requirement rather than the ZPU Evo which is based on VHDL on an FPGA. The project adds the suffix SW for *S*oft*W*are to distinguish the two designs.

To provide different CPU's it is just a matter of taking existing CPU emulators, for example those used in the PiCoPro and adapting them to use the CPU signals on the MZ80A bus via this designs interface. The program memory could either be that on the MZ80A or the faster K64F memory. ie. There is no real need to use the MZ80A memory when using a soft CPU. The benefits of using a soft CPU is potentially better performance albeit this is yet to be determined as the K64F only runs at 120MHz. The design of the tranZPUter SW upgrades the Z80 hardware and can clock the processor, detached from the Sharp MZ80A motherboard, at much higher clock rates, potentially to 20MHz using the Z8400 20MHz CPU. Higher CPU performance will be a benefit to programs such as CP/M or databases such as DBase II.

In the gallery are pictures of the current design and files uploaded onto github are relatively stable, WIP files wont be uploaded as they are in constant flux.

Hardware

The basics of this design lie in Z80 bus mastering, ie. the ability to switch the Z80 out of circuit and control the remaining computer hardware as required. Bus mastering was typically used by devices such as DMA for fast transfer of data from an I/O device to memory, or memory to memory for applications such as video/graphics. The device taking control of the Z80 bus could transfer data much faster than the Z80 running a program to perform the same action, hence the benefit.

Bus mastering is used to take control of the Z80 bus and to transfer data between main memory and an SD Card or between the I/O processor and the Video display buffer for presentation of menu's. It is also used where a soft processor completely idle's the hard Z80 and acts as the main computer CPU. ie. using a soft CPU emulator, it can process applications in local memory and slow down to access I/O and the Video buffer on the host machine as needed presenting a completely different computing experience. Imagine, a 6809 or a 68000 based Sharp MZ80A!

The design centres around lifting the original Z80 onto a daughter card and rerouting several of its signals such that they can be controlled as needed.

v1.0 Z80 Upgrade Schematic

Sheet 1

In order to be able to run programs for other Sharp models (ie.MZ-700) or 64K CP/M the design adds a 512KB Static RAM device with necessary paging logic. As the design needs to be flexible at this stage on memory remapping (ie. mapping blocks of the underlying Sharp MZ80A address space out and mapping in blocks of the 512Kbyte static RAM), a programmable decoder in the form of a Flash RAM is used. This allows maximum flexibility during development to settle on a final set of memory maps for required functionality and a v2.0 of this project can use hardwired logic in a PAL/GAL rather than the Flash RAM to save cost and board space.

The above schematic has been designed such that the basic board can be installed without an IO processor, just plug this board into the Z80 socket on the Sharp MZ80A and it runs as standard and the additional features can be accessed programaticaly in BASIC/Assembler. If the RFS board has been installed then an update to the RFS software will make use of the additional enhanced hardware features. If the RFS board has not been installed and you add the IO Control processor (a Teensy 3.5) then a whole new range of options becomes available which match and exceed those available with the RFS board. Using this design it will be easier to use an FPGA in place of the Teensy 3.5 for the final tranZPUter project.

As the project has progressed small changes have been made to the first cut PCB to reflect fixes and enhancements. The above revision, 1.0d adds extra logic which on the prototype PCB is realised with p-p wiring and piggyback IC's. The design fully works now and version 1.1 will see logic reduction as far as possible but keep the use of discrete logic rather than a GAL/PAL. Version 1.1 will also use more SMD devices to shrink the PCB size such that it will fit inside the casing of the MZ-80A, MZ-80B and MZ-700. A future version 2 will see the removal of all discrete logic and the 512KB Flash RAM decoder and be replaced with a CPLD.

v1.0 Teensy 3.5 Schematic

Sheet 2

The second schematic is the Teensy 3.5 development board which comes in a 48pin DIL package (with further contact pads on the underside for additional GPIOs) and is ideal to place onto a project board such as the tranZPUter. It contains the Freescale K64F processor, an SD card and USB logic to upload programs into its memory. Very little supporting hardware is needed to enable the Teensy3.5 to control the Z80 in this project due to it's 5V tolerant core.

v1.0 PCB


As per previous schematics and PCB boards, this project has been designed with KiCad Schematic Capture and PCB Layout. Below are the finished boards awaiting components and assembly.

PCB TopSide

PCB UnderSide


v1.1 Z80 Upgrade Schematic

Sheet 1

Version 1.1 is very similar in functionality to v1.0d, just reducing some of the gates, using existing gate count and adding ENIOWAIT, a control to enable the wait state generator (so original software wont be affected unless it is explicitly enabled).

v1.1 Teensy 3.5 Schematic

Sheet 2


Version 1.1 is very similar to v1.0d, just adding of ENIOWAIT to detect when the wait state generator is enabled.

v1.1 PCB


Version 1.1 of the PCB compacts the design a little. I was hoping to make 1 board to fit both the Sharp MZ-80A and MZ-700 but the restrictions placed on the PCB by the MZ-700 (opposite way Z80, gap to insert/remove SD card, clearance etc) means two boards will need to be designed.

The board below is the Kicad image of the Sharp MZ-80A board which is currently being manufactured, the version 1.1 design and PCB is just an iterative design given all the changes needed from v1.0 -> v1.0d.

PCB TopSide

PCB UnderSide

Assembled PCB

Assembled PCB


v2.0 Z80 Upgrade Schematic

Sheet 1

Version 2.0 replaces the discrete logic with a CPLD. The design uses too much discrete logic to manufacture a small PCB to fit into the MZ-700 so the aim is to reduce component count and increase potential functionality along with shrinking the board size to better suit the MZ-700. Looking at the MZ-80B the clearance distance between the Z80B, 8255 and the connectors such as CN6 means the board has a max size of 50x100mm. The CPU faces the same direction as the MZ-700 so hopefully one board will service both machines.

v2.0 Teensy 3.5 Schematic

Sheet 2

Version 2.0 is very similar to v1.1, just adding additional connectivity as the list of ideas grow.

v2.0 PCB


Version 2.0 of the PCB compacts the design quite a bit. It is still not so easy to make one board to fit both the Sharp MZ-80A and MZ-700 unless I go to 4 layer which is the intention when the project reaches maturity.

The board below is the Kicad image of the Sharp MZ-80A board which has been manufactured and partly assembled. I made a real blunder on this board and still wondering how I did it!!! I wanted to use the AS6C4008 sTSOP device to minimise space and ended up with the TSSOP, probably late nights but the fact I never spotted the blunder until I actually ordered the parts means I need to change tact and order parts as I design the board to minimise this kind of mistake.

PCB TopSide

PCB UnderSide

Assembled PCB


v2.1 Z80 Upgrade Schematic

Sheet 1

Version 2.1 takes the mistake from v2.0 and the ongoing requirements list and replaces the 160 macro cell CPLD with the lower power 512 macro cell AE. These devices are quite old but cheaply available hence using them. The reason for the larger CPLD is I want to add functionality at the hardware level to map the model differences, ie. MZ80B uses I/O ports for keyboard and control whereas the MZ80A/MZ700 use memory mapped ports. The idea is that the CPLD, when in the MZ80B mode, intercepts the I/O operations, tri-states the Z80 and writes the correct values to the memory mapped ports on the Sharp MZ80A host. The same for read operations and mapping of the keyboard strobe signals as well so that the Sharp MZ80A keyboard appears as an MZ700 or MZ80B mode as needed.

v2.1 Teensy 3.5 Schematic

Sheet 2


Version 2.1 is very similar to v2.0, just adding even more connectivity especially as we are operating at 3.3V now as the K64F isnt 5V tolerant on all pins.

v2.1 PCB


Version 2.1 of the PCB follows on from v2.0 using higher density TQFP packaging and the Correct! SRAM package, which is now correctly specc'd as TSOP and ordered. TSOP was chosen rather than sTTSOP due to PCB routing, it proved quite a challenge with the narrower pins.

The board below is the Kicad image of the PCB for the Sharp MZ-80A.

PCB TopSide

PCB UnderSide

Assembled PCB

Assembled PCB


v2.2 Z80 Upgrade Schematic

Sheet 1

All versions to date have been very difficult to assemble using the optional Teensy 3.5 48pin DIL development board. The Teensy 3.5 design makes a lot of the K64F GPIO pins accessible although many are on underslung solder pads. These pads are very fiddly to connect and a bit hit/miss as to success, failure to correctly and reliably attach an underside pad means the board is unserviceable, nigh-on impossible to correct. Version 2.2 corrects this situation by bringing the MK64FX512 processor into the tranZPUter SW design and removing the Teensy 3.5. The I/O processor is now an integral part of the design.

For compatibility, if needed, the Teensy 3.5 bootstrap MCU can be optionally installed otherwise programming is achieved via the JTAG interface.

v2.2 The K64 I/O Processor

Sheet 2


Version 2.2 replaces the Teensy 3.5 development board with a 100pin QFP MK64FX512 processor and the ability to optionally add a Teensy bootstrap MCU for ease of programming if needed.

v2.2 PCB


Version 2.2 of the PCB follows on from v2.1 using higher density TQFP packaging and places a forward facing SD Card and micro USB type B interface for ease of access.

The board below is the Kicad image of the PCB for the Sharp MZ-80A, designed in Kicad and sent out for manufacture.

PCB TopSide

PCB UnderSide

Assembled PCB

Assembled PCB


Version 2.1 and v2.2 are used as the base to forward the original ZPU version of the tranZPUter board which is currently in design. The Z80 upgrade circuit remains a constant but v2.0 of the tranZPUter replaces the K64F I/O processor with a Cyclone IV FPGA, CPLD and 2MB RAM. This allows the instantiation of the ZPU as the controlling I/O processor and potentially any other processor or logic that can be crammed into 110K LE FPGA.

Design Detail

This section provides internal design information for understanding how the tranZPUter functions and its interactions between the Host (the original conputer, currently tested on a Sharp MZ-80A and an MZ-700), the tranZPUter SW daughter board and the K64F processor.

K64F Z80 Host API

The API is based on a common block of RAM within the 64K memory space of the Z80 through which interprocessor communications take place. On the K64F this is declared in C as a structure and on the Z80 as an assembler reference to memory variables.
// Structure to contain inter CPU communications memory for command service processing and results.
// Typically the z80 places a command into the structure in it's memory space and asserts an I/O request,
// the K64F detects the request and reads the lower portion of the struct from z80 memory space, 
// determines the command and then either reads the remainder or writes to the remainder. This struct
// exists in both the z80 and K64F domains and data is sync'd between them as needed.
//
typedef struct __attribute__((__packed__)) {
    uint8_t                          cmd;                                // Command request.
    uint8_t                          result;                             // Result code. 0xFE - set by Z80, command available, 0xFE - set by K64F, command ack and processing. 0x00-0xF0 = cmd complete and result of processing.
    union {
        uint8_t                      dirSector;                          // Virtual directory sector number.
        uint8_t                      fileSector;                         // Sector within open file to read/write.
        uint8_t                      vDriveNo;                           // Virtual or physical SD card drive number.
    };
    union {
        struct {
            uint16_t                 trackNo;                            // For virtual drives with track and sector this is the track number
            uint16_t                 sectorNo;                           // For virtual drives with track and sector this is the sector number. NB For LBA access, this is 32bit and overwrites fileNo/fileType which arent used during raw SD access.
        };
        uint32_t                     sectorLBA;                          // For LBA access, this is 32bit and used during raw SD access.
    };
    uint8_t                          fileNo;                             // File number of a file within the last directory listing to open/update.
    uint8_t                          fileType;                           // Type of file being processed.
    union {
        uint16_t                     loadAddr;                           // Load address for ROM/File images which need to be dynamic.
        uint16_t                     saveAddr;                           // Save address for ROM/File images which need to be dynamic.
        uint16_t                     cpuFreq;                            // CPU Frequency in KHz - used for setting of the alternate CPU clock frequency.
    };
    union {
        uint16_t                     loadSize;                           // Size for ROM/File to be loaded.
        uint16_t                     saveSize;                           // Size for ROM/File to be saved.
    };
    uint8_t                          directory[TZSVC_DIRNAME_SIZE];      // Directory in which to look for a file. If no directory is given default to MZF.
    uint8_t                          filename[TZSVC_FILENAME_SIZE];      // File to open or create.
    uint8_t                          wildcard[TZSVC_WILDCARD_SIZE];      // A basic wildcard pattern match filter to be applied to a directory search.
    uint8_t                          sector[TZSVC_SECTOR_SIZE];          // Sector buffer generally for disk read/write.
} t_svcControl;

Communications are all instigated by the Z80. When it needs a service, it will write a command into the svcControl.cmd field and set the svcControl.result field to REQUEST. The Z80 then writes to an output port (configurable but generally 0x68) which in turn sends an interrupt to the K64F. The K64F reads the command and sets the svcControl.result to PROCESSING - the Z80 waits for this handshake, if it doesnt see it after a timeout period it will resend the command. The Z80 then waits for a valid result, again if it doesnt get a result in a reasonable time period it retries the sequence and after a number of attempts gives up with an error.

Once the K64F has processed the command (ie. read directory) and stored any necessary data into the structure, it sets the svcControl.result to a valid result (success, fail or error code) to complete the transaction.

API Command List

Command Cmd# Description
TZSVC_CMD_READDIR 0x01 Open a directory and return the first block of entries.
TZSVC_CMD_NEXTDIR 0x02 Return the next block in an open directory.
TZSVC_CMD_READFILE 0x03 Open a file and return the first block.
TZSVC_CMD_NEXTREADFILE 0x04 Return the next block in an open file.
TZSVC_CMD_WRITEFILE 0x05 Create a file and save the first block.
TZSVC_CMD_NEXTWRITEFILE 0x06 Write the next block to the open file.
TZSVC_CMD_CLOSE 0x07 Close any open file or directory.
TZSVC_CMD_LOADFILE 0x08 Load a file directly into tranZPUter memory.
TZSVC_CMD_SAVEFILE 0x09 Save a file directly from tranZPUter memory.
TZSVC_CMD_ERASEFILE 0x0a Erase a file on the SD card.
TZSVC_CMD_CHANGEDIR 0x0b Change active directory on the SD card.
TZSVC_CMD_LOAD40ABIOS 0x20 Request 40 column version of the SA1510 BIOS to be loaded, change frequency to match the Sharp MZ-80A.
TZSVC_CMD_LOAD80ABIOS 0x21 Request 80 column version of the SA1510 BIOS to be loaded, change frequency to match the Sharp MZ-80A.
TZSVC_CMD_LOAD700BIOS40 0x22 Request 40 column version of the 1Z-013A MZ-700 BIOS to be loaded, change frequency to match the Sharp MZ-700 and action memory page commands.
TZSVC_CMD_LOAD700BIOS80 0x23 Request 80 column version of the 1Z-013A MZ-700 BIOS to be loaded, change frequency to match the Sharp MZ-700 and action memory page commands.
TZSVC_CMD_LOAD80BIPL 0x24 Request the loading of the MZ-80B IPL, switch frequency and enable Sharp MZ-80B compatible mode.
TZSVC_CMD_LOADBDOS 0x30 Reload CPM BDOS+CCP.
TZSVC_CMD_ADDSDDRIVE 0x31 Attach a CPM disk to a drive number.
TZSVC_CMD_READSDDRIVE 0x32 Read an attached SD file as a CPM disk drive.
TZSVC_CMD_WRITESDDRIVE 0x33 Write to a CPM disk drive which is an attached SD file.
TZSVC_CMD_CPU_BASEFREQ 0x40 Set the tranZPUter to use the mainboard frequency for the Z80.
TZSVC_CMD_CPU_ALTFREQ 0x41 Switch the Z80 to use the K64F generated clock, ie. alternative frequency.
TZSVC_CMD_CPU_CHGFREQ 0x42 Change the Z80 frequency generated by the K64F to the Hertz value given in svcControl.cpuFreq, the Z80 will be clocked at the nearest timer resolution of this frequency.
TZSVC_CMD_CPU_SETZ80 0x50 Switch to the external Z80 hard cpu.
TZSVC_CMD_CPU_SETT80 0x51 Switch to the internal T80 soft cpu.
TZSVC_CMD_CPU_SETZPUEVO 0x52 Switch to the internal ZPU Evolution cpu.
TZSVC_CMD_SD_DISKINIT 0x60 Initialise and provide raw access to the underlying SD card.
TZSVC_CMD_SD_READSECTOR 0x61 Provide raw read access to the underlying SD card.
TZSVC_CMD_SD_WRITESECTOR 0x62 Provide raw write access to the underlying SD card.
TZSVC_CMD_EXIT 0x7F Terminate TZFS and restart the machine in original mode.

API Result List

Command Result# Description
TZSVC_STATUS_OK 0x00 The K64F processing completed successfully.
TZSVC_STATUS_FILE_ERROR 0x01 A file or directory error.
TZSVC_STATUS_BAD_CMD 0x02 Bad service command was requested.
TZSVC_STATUS_BAD_REQ 0x03 Bad request was made, the service status request flag was not set.
TZSVC_STATUS_REQUEST 0xFE Z80 has posted a request.
TZSVC_STATUS_PROCESSING 0xFF K64F is processing a command.

API Result List

Command Result# Description
TZSVC_STATUS_OK 0x00 The K64F processing completed successfully.
TZSVC_STATUS_FILE_ERROR 0x01 A file or directory error.
TZSVC_STATUS_REQUEST 0xFE Z80 has posted a request.
TZSVC_STATUS_PROCESSING 0xFF K64F is processing a command.

GPIO Organisation

In this design the K64F works in a supervisory and service role. The Z80 can function standalone without the K64F being present which leaves the host machine completely original and in addtion, the tranZPUter board also offers some new upgrades such as 512K Static RAM which the Z80 can make use of as needed.

If advanced services are needed such as SD card access or hardware emulation then it needs the K64F to provide these services, the Z80 see's the K64F as a hardware extension, it makes an I/O request and gets functionality in return.

If the Z80 for example requests a BIOS load, it generates an I/O out request which interrupts the K64F, the K64F puts the Z80 into tri-state bus mastered mode and then reads the BIOS from the SD card and operates the Z80 lines to write the BIOS data into the Z80 RAM. Additionally, if the tranZPUter is emulating a machine such as the MZ-700, the K64F needs to read all Z80 I/O transactions to intercept a memory mode change request, tri-state the Z80, write the correct memory mode to the memory mode latch on the tranZPUter then release the Z80 therefore adding hardware emulation.

In order to provide this functionality, the K64 needs to be able to read/write ALL of the Z80 signals when needed. One of the advantages of the K64F is that it has an abundance of digitial I/O ports which are 5V tolerant, therefore connection and operation of a 5V Z80 system is relatively straight forward. Unfortunately the Teensy 3.5 (the small dev board containing the K64F processor) doesnt use a linear allocation of port/pin which is further complicated by the K64F not instantiating certain bits depending on the model. This leads to a disjointed allocation of Z80 signal to GPIO Port/Pin and makes it more time consuming for software to piece together a 16bit address or 8bit data value which it needs to decode realtime in order to detect and act on an event and provide a service if necessary.

The allocation of Z80 pins to GPIO Port/Pins led to some headaches in the interrupt service routine but these have now been solved by the addition of a hardware wait state generator. When an I/O operation is made to the Sharp I/O system range of 0xE0-0xFF a WAIT signal is automatically asserted and cancelled when the ISR raises the BUSRQ signal. Under most situations there is no actual WAIT state inserted, when a delay is created due to a competing interrupt (thread scheduler, millisecond timer) then the mechanism adds a WAIT which keeps the signals valid until the ISR can process them.

In order to understand the issues, the following tables have been created to show Z80 signals to their associated K64F pins. The signals are spread across 5 x 32bit internal K64F registers.
K64F Port and Bit allocation
BIT / PORT 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
A                             Z80_A0 Z80_A11 Z80_A12 Z80_A13 Z80_D4 Z80_D3               Z80_A14        
B                 CTL_RFSH Z80_INT Z80_MEM0 Z80_NMI Z80_A9 Z80_A10 Z80_D1 Z80_D0         Z80_A7 Z80_A8         Z80_MEM4 Z80_MEM3 CTL_HALT CTL_CLKSLCT Z80_BUSACK CTL_BUSACK
C                                         Z80_A1 Z80_A2 Z80_A3 Z80_A4 Z80_RD SYSCLK Z80_WAIT Z80_WR Z80_MREQ Z80_A16 Z80_A17 Z80_BUSRQ
D                                 Z80_RESET       TZ_BUSACK   Z80_MEM2 Z80_MEM1 Z80_D5 Z80_A18 CTL_M1 Z80_D6 Z80_IORQ Z80_D7 CTL_CLK Z80_D2
E           Z80_A15 Z80_A5 Z80_A6                         SYSREQ SVCREQ                    
GPIO bits to Z80 Address Line mapping
ADDR 18 ADDR 17 ADDR 16 ADDR 15 ADDR 14 ADDR 13 ADDR 12 ADDR 11 ADDR 10 ADDR 9 ADDR 8 ADDR 7 ADDR 6 ADDR 5 ADDR 4 ADDR 3 ADDR 2 ADDR 1 ADDR 0
PORT D:6 PORT C:1 PORT C:2 PORT E:26 PORT A:4 PORT A:14 PORT A:15 PORT A:16 PORT B:18 PORT B:19 PORT B:10 PORT B:11 PORT E:24 PORT E:25 PORT C:8 PORT C:9 PORT C:10 PORT C:11 PORT A:17
                                     
GPIO bits to Z80 Data Line mapping
DATA 7 DATA 6 DATA 5 DATA 4 DATA 3 DATA 2 DATA 1 DATA 0
PORT D:2 PORT D:4 PORT D:7 PORT A:13 PORT A:12 PORT D:0 PORT B:17 PORT B:16

Memory Modes

One of the features of the tranZPUterSW hardware design is the ability to create memory maps freely within the 512K Flash RAM. These maps are assigned to a Memory Mode and are selected by the Memory Mode Latch. They define how tranZPUter SW Memory is mapped into the Z80 memory address space along with the original mainboard components. This ability is put to good use in order to realise TZFS, CP/M and the compatible modes of the Sharp MZ-700 and MZ-80B.

Modes which have beed defined are in the table below leaving a few available slots for further expansion.
Mode Target Range Block   Function DRAM Refresh Description
0 Original 0000:0FFF Main MROM Yes Default, normal Sharp MZ80A operating mode, all memory and IO (except tranZPUter control I/O block) are on the mainboard
    1000:CFFF Main D-RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF Main User ROM    
    F000:FFFF Main FDC ROM    
1 Orig+ UROM 0000:0FFF RAM 0 MROM Yes As 0 except User ROM is mapped to tranZPUter RAM and used for loadable BIOS images.
    1000:CFFF Main D-RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF Main User ROM    
    F000:FFFF Main FDC ROM    
2 TZFS 0000:0FFF RAM 0 MROM No Boot mode for TZFS or any other software requiring use of the tranZPUter RAM. User ROM appears as ROM to the Monitor so it will call the entry point at 0xE800 as part of it’s normal startup procedure. The software stored at 0xE800 can switch out the mainboard and run in tranZPUter RAM as required. Two small holes at F3FE and F7FE exist for the Floppy disk controller (which have to be 64 bytes from F3C0 and F7C0 due to the granularity of the address lines into the Flash RAM), these locations need to be on the mainboard. The floppy disk controller uses them as part of its data read/write as the Z80 isnt fast enough to poll the FDC.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 0 FDC ROM    
3 TZFS 0000:0FFF RAM 0 MROM No Page mode for TZFS, all RAM in tranZPUter Block 0 except F000:FFFF which is in Block 1, this is page bank2 of TZFS.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 0 VRAM    
    D800:DFFF RAM 0 ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 1 FDC ROM    
4 TZFS 0000:0FFF RAM 0 MROM No As mode 3 but F000:FFFF is in Block 2, this is page bank3 of TZFS.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 0 VRAM    
    D800:DFFF RAM 0 ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 2 FDC ROM    
5 TZFS 0000:0FFF RAM 0 MROM No As mode 3 but F000:FFFF is in Block 3, this is page bank4 of TZFS.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 0 VRAM    
    D800:DFFF RAM 0 ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 3 FDC ROM    
6 CP/M 0000:FFFF RAM 4 Main RAM No CP/M, all memory on the tranZPUter board. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
7 CP/M 0000:0100 RAM 4 CP/M Vectors No CP/M main CBIOS area, 48K + 2K available for the CBIOS and direct access to mainboard hardware. F000:FFFF remains in bank 4 and used as the gateway between this memory mode and mode 6.
    0100:CFFF RAM 5 Main RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF RAM 5 User ROM    
    F000:FFFF RAM 4 FDC ROM    
8 Orig+ Emu 0000:0FFF Main MROM Yes Original mode but with the main RAM in the tranZPUter bank 0. This mode is used to bootstrap programs such as MZ-700 programs which bank change on startup and expect the loaded program to be within the main memory which is within a tranZPUter RAM bank.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF Main User ROM    
    F000:FFFF Main FDC ROM    
10 MZ-700 0000:0FFF RAM 6 Main RAM No MZ-700 mode (OUT $E0) - Monitor RAM replaced with Main RAM
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF Main User ROM    
    F000:FFFF Main FDC ROM    
11 MZ-700 0000:0FFF RAM 0 MROM No MZ-700 mode (OUT $E0 + $E1) - I/O and Video block replaced with Main RAM
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 6 VRAM    
    D800:DFFF RAM 6 ARAM    
    E000:E7FF RAM 6 MM I/O    
    E800:EFFF RAM 6 User ROM    
    F000:FFFF RAM 6 FDC ROM    
12 MZ-700 0000:0FFF RAM 6 Main RAM No MZ-700 mode (OUT $E1 + $E2) - Monitor RAM replaced with RAM and I/O and Video block replaced with Main RAM
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 6 VRAM    
    D800:DFFF RAM 6 ARAM    
    E000:E7FF RAM 6 MM I/O    
    E800:EFFF RAM 6 User ROM    
    F000:FFFF RAM 6 FDC ROM    
13 MZ-700 0000:0FFF RAM 0 MROM No MZ-700 mode (OUT $E5) - Upper memory locked out, Monitor ROM paged in.
    1000:CFFF RAM 0 Main RAM    
    D000:FFFF n/a Undefined    
14 MZ-700 0000:0FFF RAM 6 Main RAM No MZ-700 mode (OUT $E6) - Monitor RAM replaced with RAM and Upper memory locked out.
    1000:CFFF RAM 0 Main RAM    
    D000:FFFF n/a Undefined    
15 MZ-800/MZ-700         See table below. Memory mode is as per the MZ-800.
21 K64F Access 000000:FFFFFF n/a FPGA Resources No Reserved for use on the tranZPUter SW-700 board.
22 FPGA Access 0000:FFFF n/a Host Resources Yes Reserved for use on the tranZPUter SW-700 board.
23 K64F Access 000000:FFFFFF RAM Main RAM No Reserved for use on the tranZPUter SW-700 board.
24 K64F Access 0000:FFFF RAM 0 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 0 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
25 ”” 0000:FFFF RAM 1 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 1 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
26 ”” 0000:FFFF RAM 2 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 2 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
27 ”” 0000:FFFF RAM 3 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 3 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
28 ”” 0000:FFFF RAM 4 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 4 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
29 ”” 0000:FFFF RAM 5 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 5 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
30 ”” 0000:FFFF RAM 6 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 6 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
31 ”” 0000:FFFF RAM 7 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 7 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
Key:
MROM = Monitor ROM, the original boot firmware ie. SA-1510
D-RAM = Dynamic RAM on the mainboard.
VRAM = Video RAM on the mainboard.
ARAM = Colour Attribute RAM on the mainboard.
MM I/O = Memory Mapped I/O controllers on the mainboard.
RAM 0 .. 7 = 64K RAM Block number within the 512K Static RAM chip.
Main = Host computer mainboard, ie the Sharp MZ-80A mainboard.
MZ700/MZ800 Memory Mode
MZ-700           MZ-800            
Register 0000:0FFF 1000:1FFF 1000:CFFF C000:CFFF D000:FFFF 0000:7FFF 1000:1FFF 2000:7FFF 8000:BFFF C000:CFFF C000:DFFF E000:FFFF
OUT 0xE0 DRAM         DRAM            
OUT 0xE1         DRAM             DRAM
OUT 0xE2 MONITOR         MONITOR            
OUT 0xE3         Memory Mapped I/O             Upper MONITOR ROM
OUT 0xE4 MONITOR   DRAM   Memory Mapped I/O MONITOR CGROM DRAM VRAM   DRAM Upper MONITOR ROM
OUT 0xE5         Inhibit             Inhibit
OUT 0xE6                    
IN 0xE0   CGROM*   VRAM*     CGROM   VRAM      
IN 0xE1   DRAM   DRAM       DRAM      
Key:
<return> = Return to the state prior to the complimentary command being invoked.
* = MZ-800 host only.

Z80 CPU Frequency Switching

In order to make the tranZPUter SW compatible with other machines it is necessary to clock the CPU at the speed of that machine. It is also desirable to clock the CPU as fast as possible when using software such as CP/M for maximum performance.

One of the main issues with frequency switching is that the underlying host cannot have its frequency changed, the host is generally generating the clock and it's circuits have been designed to operate within it's clock tolerances.

To fulfil the requirement to have a switchable Z80 CPU frequency a positive edge triggered frequency switch has been implemented which takes the host frequency as one input and a square wave generator from the K64F as its second input. The switching mechanism is tied to the bus control logic and so any access to the host will see the frequency of the CPU being changed to that of the host which ensures continued reliable operation. Under startup conditions, the Z80 is always clocked by the host clock to ensure original specifications of the machine are met.

A second frequency can be selected if the K64F is present as it has the ability using its onboard timers to generate a programmable square wave output. The K64F sets the frequency of this second clock source and the Z80 can select it via an I/O OUT command. This gives the software running on the Z80 to opportunity to change it's own frequency, albeit to a fixed set one. An extension to the K64F Host API allows the Z80 to make a request of the K64F to set the Z80 CPU frequency to any possible value, this is useful in TZFS or CP/M so a user can select their own frequency.

Current testing on a CMOS Z84C0020 20MHz CPU has the following observations:
  • tranZPUTer reliable in the range 1Hz to 20MHz for all functionality.
  • tranZPUter reliable @ 24MHz on the tranZPUter v2.1 board. When the mainboard is accessed the frequency slows to 2MHz (or the system clock) and returns to the higher frequency after the mainboard access has completed. Under development is the MZ80A Video Module which controls the mainboard frequency, so it should be feasible to clock the mainboard at 4+MHz shortly. I overclocked my original Sharp MZ80A to 4MHz, thus from previous experience and analysing the mainboard components inside the Sharp MZ80A, it should be feasible to overclock.

It is also possible to slow down the CPU for training or debugging purposes albeit access to the host circuitry will always run at the host clock frequency,

On the Z80, the following table outlines the I/O ports to which it must read/write in order to switch frequencies. Frequency switching on v1.1 boards requires the K64F to be present as it generates the secondary frequency. On the v2.1 board you have the option for an external oscillator or using the K64F.

Port Function
0x62 Switch Z80 CPU frequency to the second source, ie. the frequency generated by the K64F or external oscillator.
0x64 Switch Z80 CPU frequency to default host source. This is the default on RESET.

System Configuration

The CPLD holds an internal configuration register to change how it operates with the underlying host. The table below outlines the ports along with each bits function.

System Configuration Register (0x6E - 110 decimal)
Bits Dir Description
2:0 R/W Set hardware model compatibility. This configures the CPLD to remap host hardware to be compatible with the configured 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 R/W Reserved for use on the tranZPUter SW-700 board, enables or disables the mainboard video.
4 R/W Reserved for use on the tranZPUter SW-700 board, enables or disables the mainboard video.
7 R/W Preserve configuration over reset (=1) or set to default on reset (=0).

NB: The compatibility modes which have been implemented appear in the paragraphs below, all other modes are yet to be implemented. Selecting a mode which hasnt been implemented results in no mapping and reverts to the base MZ-700 hardware.

The CPLD also holds a read only information register which indicates the capabilities of the running machine.

System Information Register (0x6F - 111 decimal)
Bits Dir Description
2:0 R The underlying host model in which the tranZPUter is installed, ie. the physical computer hardware.
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 R FPGA Video Module installed, 0 = not installed, 1 = installed.
7:5 R Version number of the CPLD. Used by Z80 code when newer versions of the CPLD VHDL provide differing features.

Sharp MZ-700 Mode

One of the aims of the tranZPUter was to be able to run, as much as possible, software from other models on the host. The original host is an MZ-80A and the aim was to run software for an MZ-700/MZ-800/MZ-80B on this machine. The tranZPUter itself can be plugged into a real Sharp MZ-700 or MZ-80B and the tranZPUter has been tested on these machines, so additionally the design aim has been extended such that the tranZPUter, when hosted on a 700 or 80B is able to run MZ-80A software as well.

Differences between the MZ-700 and the MZ-80A:
Sharp MZ80A Sharp MZ-700
48K RAM, contiguous block from 1000:CFFFH with the option to swap the ROM at 0000:0FFFH and RAM at C000:CFFFH. 64K RAM, contigous block from 1000:CFFFH, pageable blocks from 0000:0FFFH and D000:FFFFH
Keyboard - business layout with numeric keypad. Hardware identical to MZ-700 but strobe and data lines identifying a key differ. Keyboard - personal layout.
Display - 40 character Monochrome. Base hardware same as the MZ-700. Colour Display - adds attribute RAM to provide foreground and background colours. Adds a larger Character Generator ROM for alternative characters.
CPU Frequency - 2MHz CPU Frequency 3.58MHz
In order to be compatible with an MZ-700 I took two different approaches according to the tranZPUter hardware available.

tranZPUter v1.1

My initial design thoughts intended that the K64F would read real-time Z80 bus transactions and intercept them as needed to 'fake' any differences in hardware. This would all be done using high priorty interrupts to minimise latency. The K64F would be interrupted when a triggering IO or memory transaction takes place and depending on the run state would make the necessary changes and override the Z80 Bus transaction or perform a write-back to fake the hardware.

A trigger, for example, would be OUT commands used by the Sharp MZ-700 to page its 64K RAM. These would be intercepted and the necessary changes made to the tranZPUter memory mode so that the correct memory appeared to the MZ-700.

After spending quite some time on ARM assembler code it became apparent that the K64F just wasnt fast enough even when overclocked to 168MHz. Lower priority interrupts such as a thread or timer interrupt were interfering with the higher priority and latency was affected such that the K64F missed the 1 cycle window of opportunity it had to override the Z80 bus transaction. If it couldnt intercept 1 cycle of a 2MHz Z80 transaction then there was no scope for faster processors or overclocking.

Looking at the problem, the solution was to update v1.0 hardware and add a WAIT state generator. If an IN/OUT command was made in the Sharp reserved area of 0xE0-0xFF then the WAIT line on the Z80 would be asserted and only cleared by a RESET or a BUSRQ signal. With the WAIT state active the issue seen above is no longer a problem, once the K64F begins to service the IO interrupt it immediately asserts BUSRQ which releaes the WAIT state and the Z80 continues on to the end of it's current instruction. This gives time for the K64F to decipher what was on the bus and make appropriate hardware updates before releasing the tri-stated Z80 bus. In practise, viewing on an oscilloscope, the WAIT state is rarely active long enough for the Z80 to action it, thus the host sees no WAIT delay and only minimal delay due to tri-stating of the bus.

The next incompatibility was CPU frequency, 2MHz on the MZ-80A vs 3.58MHz on the MZ-700. To solve this I added a CPU frequency switch with the K64F generating the secondary frequency. This allowed the K64F to set a CPU frequency of 3.58Mhz when operating in MZ-700 mode. As the host board is running at 2MHz the frequency slows down to 2MHz during hardware access which may be an issue for some timing sensitive games but in general is compatible.

The MZ80A COLOUR BOARD v1.0 solves the display incompatibility with one small caveat. When I designed the colour board I opted to follow the original Sharp MZ80A colour upgrad attribute mapping even though this board was never commercially sold. This makes slight incompatibilities with an MZ-700 in colour choice but in general works well. A few minutes with a soldering iron can correct this if needed. The colour board also provides the MZ-700 character generator maps so all characters seen on an MZ-700 can be displayed on the MZ-80A.

The last incompatibility was to solve the keyboard differences. I have the source code for the 1Z-013A BIOS so a solution was to update the keyscan mappings allowing it to operate correctly on the MZ-80A keyboard. This solution works well but may not work for MZ-700 software which doesnt use the BIOS. Depending on the software being run, the keyscan mappings are either performed in the BIOS or the software incorporates its own keyboard functionality, ie. S-BASIC. On analysis the software which incorporates its own keyboard functionality is using the same mapping table logic as the BIOS. My intention is to detect this in the K64F and overlay the mapping table which will allow more MZ-700 software to function correctly.

Combining all the solutions, using TZFS, you can enter the MZ-700 mode via a command which loads the 1Z-013A BIOS, sets the CPU frequency to 3.58MHz and installs the correct interrupt drivers on the K64F to intercept Z80 transactions and translate them. This results in the host, for all intents and purposes, behaving like a Sharp MZ-700. Loading S-BASIC sees the venerable 'BASIC INTERPRETER 1Z-013B' signon appear, 36439 Bytes free and the Ready prompt. Doesnt sound so impressive but when you realise that S-BASIC is paging in/out various memory blocks just to run it is quite a step forward.

tranZPUter v2.1

The tranZPUter Version 2.1 design uses a CPLD (complex logic device) rather than discrete hardwired logic. This provides a lot of scope to add hardware level compatibility in logic. Using the CPLD both memory management and keyboard remapping are made within hardware and do not need K64F services. This provides many benefits, for example, using a tranZPUter v2.1 in tandem with a Rom Filing System (v1.0 or 1.1) board but without the K64F processor allows the Sharp MZ-80A to behave as if it was a Sharp MZ-700. If a K64F is present then there is no longer a need for complicated interrupt processing.

Keyboard Mapping

Mapping has been made by copying the MZ-700 keyboard layout onto the MZ-80A.

MZ-80A Key MZ-700 Key   MZ-80A Key MZ-700 Key
BREAK/CTRL GRAPH   GRPH ALPHA
INST/DEL CTRL   CLR/HOME BREAK
Cursor Left/Right Unmarked key   Cursor Up/Down Down arrow/Pound symbol
Numeric 7 INST/CLR   Numeric 8 Cursor Up
Numeric 9 DEL/HOME   Numeric 4 Cursor Left
Nuemric 5 No function   Numeric 6 Cursor Right
Numeric 1 F1 Key   Numeric 2 Cursor Down
Numeric 3 F5 Key   Numeric 0 F2 Key
Numeric 00 F3 Key   Numeric . F4 Key
Nuemric + No function   Nuemric - No function

All other keys are the same between the machines.


Sharp MZ-80B Mode

As per the MZ-700 mode, a design aim of the tranZPUter is to be able to run Sharp MZ-80B software on an MZ-80A host or additionally on an MZ-700 host.

The MZ-80B has many similarities with the MZ-80A/MZ-700 albeit the keyboard is different and the IO is not memory mapped but IO mapped. The 64K Main memory is also banked. The MZ-80A/MZ-80B/MZ-700 share common Character based Video hardware and also a common Floppy Disk Controller so this aids in running disk based software.

Studying the MZ-80B it is my intention to intercept IO transactions and convert them into memory mapped transactions with the help of the wait state generator. Memory, as per the MZ-700 will be accomodated by memory mappings in the 512K Flash RAM decoder. The Character based Video is common amongst all machines at 0xD000 so it should be possible to run most MZ-80B software on the MZ-80A/MZ-700. Graphics will be possible with the upcoming update of the MZ80A COLOUR BOARD but little steps first, get the IPL to boot and load cassette basic…

Version 2.1 of the tranZPUter SW board is now fully built and operational and I spent a lot of time trying to create a hardware level MZ-80B compatibility mode. Functional requirements and lack of resources in the CPLD (even with a 512 macrocell device) led me to postpone this mode, either I split the requirements between the CPLD and the K64F or I just wait for the tranZPUter v2.0 which is under development. The tranZPUter v2.0 board hosts a 115K LE FPGA alongside a 512 macrocell CPLD and will return to the original concept of using the ZPU as the I/O processor and hardware to realise requirements such as compatibility modes. WIP!

Hardware Description Language

The tranZPUter SW makes extensive use of a CPLD (Complex Programmable Logic Device) in order to replace discrete logic and provide the ability more flexibility in advancing the design and correcting bugs. This device is an array of hardware logic elements which need to be interconnected to form a circuit. To configure the device requires a bitmap, which upon uploading into the CPLD, configures the device to form the required circuit.

There are various means of creating a bitmap but generally a Hardware Descripion Language is used which resembles software source code. I chose to use VHDL as this was based on ADA, a language I learnt at university. I have used Verilog and System Verilog and find these languages also to be excellent and indeed used in my Sharp MZ Emulator, but for this project, VHDL is the HDL of choice.

The CPLD, a 512 Macro cell MAX 7000A device, was chosen due to its 5V tolerant capabilities which are not found in more recent devices and would thus require additional voltage translation circuitry to read Sharp MZ-80A signals.

Complex Logic Device - MAX 7000A

The CPLD replaces the discreet logic and Flash RAM decoder found on the original tranZPUter SW. It interfaces directly with the Z80 signals from the Sharp MZ-80A and the tranZPUter Z80 upgrade logic. It’s purpose is to provide

  • Z80 Memory Map decoding
  • Z80 BUS control
  • WAIT State generation
  • Hardware remapping
  • Voltage translation

The source files which form the CPLD configuration are:

Module Description
tranZPUterSW_TopLevel.vhd The top level design file, akin to the root schematic of a circuit. It lays out the main component signals entering the CPLD and how they are used.
tranZPUterSW_pkg.vhd This file contains functions, constant declarations and parameters and is used by all compiled VHDL files/modules.
tranZPUterSW.vhd The main design file, it contains all the logic to form gate and wire interconnects in the target circuit within the CPLD.
build/tranZPUterSW.qpf The project file used by Quartus Prime to declare the project and all its files.
build/tranZPUterSW.qsf The definitions and assignments file. It sets all the parameters for compilation, fitting, pins used and their name, their parameters etc. This file is created by Quartus Prime but often it is quicker to change by hand instead of via the Quartus Prime GUI.
build/tranZPUterSW_constraints.sdc The timing constraints file created and used by the Time Quest Timing Analysed and also used by the compiler and fitter in deciding on locations where components in the CPLD will be placed.

Building the CPLD bitstream

To build or compile the VHDL code into a bitstream which can be uploaded into the CPLD you need to use Quartus Prime v13.0.1 from Altera. This is an excellent piece of software and the web edition is free to download and use. It is suitable for developing all but the most recent Altera products.

You can either install Quartus Prime onto your Windows/Linux workstation or you can create a Docker image as I detail below. After a number of installations on various Linux flavours, using Docker is by far the easiest way to use this complex package.

Compilation:

   1. Start Quartus Prime v13.0.1, either your local installation or a Docker image.
   2. Go to 'File->Open Project' and search for the directory where your repository clone is stored then select the file in <Clone Path>/tranZPUter/CPLD/SW/build/tranZPUterSW.qpf, this will open the CPLD tranZPUterSW project.
   3. Select 'Processing->Start' Compilation - you can safely ignore the warning messages.
   4. When completed, a bitstream will have been created with the name: tranZPUterSW.sof in the <Clone Path>/tranZPUter/CPLD/SW/build/output_files directory.

Programming:

   1. To upload the bitstream into the CPLD, you need an Altera USB Blaster connected via USB port to the 10pin JTAG IDC connector on the tranZPUterSW board.
   2. In Quartus Prime, go to 'Tools->Programmer' which will start a new Programmer window.
   3. In the Programmer window, click on 'Hardware Setup' and choose your USB adapter and then 'Close'
   4. Click on 'Auto Detect' and it should find 1 device, an EPM7512AET144.
   5. Right click on the EPM7512AET144 device, select Add File then choose the sof file located in <Clone Path>/tranZPUter/CPLD/SW/build/output_files/tranZPUterSW.sof and click Open.
   6. Select 'Program/Configure' and 'Verify' tick boxes against the EPM7512AET144.
   7. Click on 'Start' and the CPLD should be programmed with the compiled bitstream.

Software

The existing ZPU software, ZPUTA and zOS have been ported to the K64F platform for use with this design. zOS will be the integral OS platform on the K64F processor and the I/O processor specific operations will be handled within a thread of the OS and external applications.

zOS

Please see the section on zOS for details on the operating system. In addition to the standard features and tools, the following applications have been added:

Command Description
tzload Upload and Download files to the tranZPUter memory, grab a video frame or set a new frame.
TZLOAD v1.1

Commands:-
  -h | --help              This help text.
  -d | --download <file>   File into which memory contents from the tranZPUter are stored.
  -u | --upload   <file>   File whose contents are uploaded into the traZPUter memory.
  -U | --uploadset <file>:<addr>,...,<file>:<addr>
                           Upload a set of files at the specified locations. --mainboard specifies mainboard is target, default is tranZPUter.
  -V | --video             The specified input file is uploaded into the video frame buffer or the specified output file is filled with the video frame buffe.

Options:-
  -a | --addr              Memory address to read/write.
  -l | --size              Size of memory block to read. This option is only used when reading tranZPUter memory, for writing, the file size is used.
  -s | --swap              Read tranZPUter memory and store in <infile> then write out <outfile> to the same memory location.
  -f | --fpga              Operations will take place in the FPGA memory. Default without this flag is to target the tranZPUter memory.
  -m | --mainboard         Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter memory.
  -M | --mempage           Operations on mainboard will page in all DRAM banks prior to operation. ie. MZ-700 will page in lower and upper DRAM banks so 0000:FFFF = DRAM
  -z | --mzf               File operations are to process the file as an MZF format file, --addr and --size will override the MZF header values if needed.
  -v | --verbose           Output more messages.

Examples:
  tzload --download monitor.rom -a 0x000000      # Load the file monitor.rom into the tranZPUter memory at address 0x000000.
tzdump Dump tranZPUter memory to screen
TZDUMP v1.1

Commands:-
  -h | --help              This help text.
  -a | --start             Start address.

Options:-
  -e | --end               End address (alternatively use --size).
  -s | --size              Size of memory block to dump (alternatively use --end).
  -f | --fpga              Operations will take place in the FPGA memory. Default without this flag is to target the tranZPUter memory.
  -m | --mainboard         Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter memory.
  -v | --verbose           Output more messages.

Examples:
  tzdump -a 0x000000 -s 0x200   # Dump tranZPUter memory from 0x000000 to 0x000200.
tzclear Clear tranZPUter memory.
TZCLEAR v1.1

Commands:-
  -h | --help              This help text.
  -a | --start             Start address.

Options:-
  -e | --end               End address (alternatively use --size).
  -s | --size              Size of memory block to clear (alternatively use --end).
  -b | --byte              Byte value to place into each cleared memory location, defaults to 0x00.
  -f | --fpga              Operations will take place in the FPGA memory. Default without this flag is to target the tranZPUter memory.
  -m | --mainboard         Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter memory.
  -v | --verbose           Output more messages.

Examples:
  tzclear -a 0x000000 -s 0x200 -b 0xAA  # Clears memory locations in the tranZPUter memory from 0x000000 to 0x000200 using value 0xAA.
tzclk Set the alternative Z80 CPU frequency.
TZCLK v1.0

Commands:-
  -h | --help              This help text.
  -f | --freq              Desired CPU clock frequency.

Options:-
  -e | --enable            Enable the secondary CPU clock.
  -d | --disable           Disable the secondary CPU clock.
  -v | --verbose           Output more messages.

Examples:
  tzclk --freq 4000000 --enable  # Set the secondary CPU clock frequency to 4MHz and enable its use on the tranZPUter board.
tzreset Reset the tranZPUter.
TZRESET v1.0

Commands:-
  -h | --help              This help text.
  -r | --reset             Perform a hardware reset.
  -l | --load              Reload the default ROMS.
  -m | --memorymode <val>  Set the memory mode.

Options:-
  -v | --verbose           Output more messages.

Examples:
  tzreset -r        # Resets the Z80 and associated tranZPUter logic.
tzio Z80 I/O Port read/write tool.
TZIO v1.1

Commands:-
  -h | --help              This help text.
  -o | --out <port>        Output to I/O address.
  -i | --in <port>         Input from I/O address.

Options:-
  -b | --byte              Byte value to send to the I/O port in the --out command, defaults to 0x00.
  -m | --mainboard         Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter I/O domain.
  -v | --verbose           Output more messages.

Examples:
  tzio --out 0xf8 --byte 0x10    # Setup the FPGA Video mode at address 0xf8.
tzflupd K64F FlashRAM update tool. Update the running zOS/ZPUTA kernel with a later version.
TZFLUPD v1.1

Commands:-
  -h | --help              This help text.
  -f | --file              Binary file to upload and flash into K64F.

Options:-
  -v | --verbose           Output more messages.

Examples:
  tzflupd -f zOS_22012021_001.bin --verbose   # Upload and program the zOS_22012021_001.bin file into the K64F flash memory.
tzmtest TranZPUter memory test program. K64F will loop through several methods to test tranZPUter static RAM and FPGA BRAM.
TZMTEST v1.0

Commands:-
  -h | --help              This help text.
  -a | --start             Start address.

Options:-
  -e | --end               End address (alternatively use --size).
  -s | --size              Size of memory block to test (alternatively use --end).
  -f | --fpga              Operations will take place in the FPGA memory. Default without this flag is to target the tranZPUter memory.
  -i | --iter              Number of test iterations, default = 1.
  -t | --test              Specify test as a bit value, bit 0 = R/W inc ascending test, 1 = R/W inc walking test, 2 = W ascending then R,
                           bit 3 = W walking then R, bit 4 = echo and stick bit test.
  -v | --verbose           Output more messages.

Examples:
  tzmtest -a 0x000000 -s 0x20000   # Test 128K tranZPUter memory from 0x000000 to 0x020000.

TranZputer Filing System

The TranZputer Filing System is a port of the Rom Filing System used on the MZ-80A Rom Disk upgrade board. It reuses much of the same software functionality and consequently provides the same services, the differences lie in the use of a different memory model. It’s purpose is to provide methods to manipulate files stored on the SD card and provide an extended command line interface, the TZFS Monitor. The command set includes SD file manipulation and backup along with a number of commands found on the MZ700/800 computers.

The SD card and ROM's are managed by the K64F I/O processor. A service request API has been written where by a common shared memory block (640byte) is used in conjunction with a physical I/O request to pass commands and data between the Z80 and the K64F. ie. When the Z80 wants to read an SD file, it creates a request to open a file in the memory block, makes a physical I/O operation which the K64F detects via interrupt, it opens the file and passes the data back to the Z80 one sector at a time in the shared memory.

Under RFS the software had to be split into many ROM pages and accessed via paging as necessary, the same is true for TZFS but the pages are larger and thus less pages are needed. The Z80 software which forms the TranZputer Filing System can be found in the repository within the <software> directory.

The following files form the TranZputer Filing System:

Module Target Location Size Bank Description
tzfs.asm 0xE800:0xFFFF 6K 0 Primary TranZputer Filing System and MZ700/MZ800 Monitor tools.
tzfs_bank2.asm 0xF000:0xFFFF 4K 1 Message printing routines, static messages, ascii conversion and help screen.
tzfs_bank3.asm 0xF000:0xFFFF 4K 2 Unused.
tzfs_bank4.asm 0xF000:0xFFFF 4K 3 Unused.
monitor_SA1510.asm 0x00000:0x01000 4K 0 Original SA1510 Monitor for 40 character display loaded into 64K Bank 0 of tranZPUter memory.
monitor_80c_SA1510.asm 0x00000:0x01000 4K 0 Original SA1510 Monitor patched for 80 character display loaded upon demand into 64K Bank 0 of tranZPUter memory.
monitor_1Z-013A.asm 0x00000:0x01000 4K 0 Original 1Z-013A Monitor for the Sharp MZ-700 patched to use the MZ-80A keybaord and attribute RAM colours.
monitor_80c_1Z-013A.asm 0x00000:0x01000 4K 0 Original 1Z-013A Monitor for the Sharp MZ-700 patched to use the MZ-80A keybaord, attribute RAM colours and 80 column mode.
MZ80B_IPL.asm 0x00000:0x01000 4K 0 Original Sharp MZ-80B IPL firmware to bootstrap MZ-80B programs.

In addition there are several shell scripts to aid in the building of TZFS software, namely:

Script Description
assemble_tzfs.sh A bash script to build the TranZputer Filing System binary images.
assemble_roms.sh A bash script to build all the standard MZ80A ROMS, such as the SA-1510 monitor ROM needed by TZFS.
flashmmcfg A binary program to generate the decoding map file for the tranZPUter SW FlashRAM decoder.
glass-0.5.1.jar A bug fixed version of Glass release 0.5. 0.5 refused to fill to 0xFFFF leaving 1 byte missing, hence the bug fix.

CP/M

CPM v2.23 has been ported to the tranZPUter from the RFS project and enhanced to utilise the full 64K memory available as opposed to 48K under RFS. The Custom BIOS makes use of the tranZPUter memory and saves valuable CP/M TPA space by relocating logic into another memory bank.

The following files form the CBIOS and CP/M Operating System:

Module Target Location Size Bank Description
cbios.asm 0xF000:0xFFFF 4K 0 CPM CBIOS stubs, interrupt service routines (RTC, keyboard etc) and CP/M disk description tables, buffers etc.
cbiosII.asm 0x0000:0xCFFF 48K 1 CPM CBIOS, I/O Processor Service API, SD Card Controller functions, Floppy Disk Controller functions, Screen and ANSI Terminal functions, Utilities and Audio functions.
  0xE800:0xEFFF 2K 1 Additional space for CBIOSII, currently not used.
cpm22.asm 0xDA00:0xEFFF 5K 0 The CP/M operating system comprised of the CCP (Console Command Processor) and the BDOS (Basic Disk Operating System). These components can be overwritten by applications that dont need CPM services and are reloaded when an application terminates.
cpm22-bios.asm     0 The Custom Bios is self contained and this stub no longer contains code.

Additionally there are several shell scripts to aid in the building of the CP/M software, namely:

Script Description
assemble_cpm.sh A shell script to build the CPM binary in the MZF format application for loading via TZFS.
make_cpmdisks.sh A bash script to build a set of CPM disks, created as binary files for use on the FAT32 formatted SD Card. CPC Extended Disk Formats for use in a Floppy disk emulator or copying to physical medium are also created.
glass-0.5.1.jar A bug fixed version of Glass release 0.5. 0.5 refused to fill to 0xFFFF leaving 1 byte missing, hence the bug fix.

Please refer to the CP/M section for more details,



TZFS Monitor

On power up of the Sharp MZ80A, a copmmand line interface called the monitor is presented to the user to enable basic actions such as bootstrapping a tape or manual execution of preloaded software. The TZFS monitor is an extension to the basic monitor and once the tranZPUter SW card has been inserted into the Z80 socket on the mainboard, entering the following command at the monitor prompt '\*' will start TZFS:

JE800<cr>

It is possible to automate the startup of the computer directly into TZFS. To do this create an empty file in the root directory of the SD card called:

'TZFSBOOT.FLG'

On startup of the K64F processor, it will boot zOS and then if zOS detects this file it will perform the necessary tasks to ensure TZFS is automatically started on the Sharp MZ80A.

Once TZFS has booted, the typical SA-1510 monitor signon banner will appear and be appended with "+ TZFS" postfix if all works well. The usual '*' prompt appears and you can then issue any of the original SA-1510 commands along with a set of enhanced commands, some of which were seen on the MZ700/ MZ800 range and others are custom. The full set of commands are listed in the table below:

Command Parameters Description
4 n/a Switch to 40 Character mode if the 40/80 Column display upgrade has been added.
8 n/a Switch to 80 Character mode if the 40/80 Column display upgrade has been added.
80B n/a Switch to Sharp MZ-80B compatible mode.< /s>
700 n/a Switch to Sharp MZ-700 40 column BIOS and mode.
7008 n/a Switch to Sharp MZ-700 80 column BIOS and mode.
B n/a Enable/Disable key entry beep.
BASIC n/a Locates the first BASIC interpreter on the SD card, loads and runs it.
C [<8 bit value>] Initialise memory from 0x1200 to Top of RAM with 0x00 or provided value.
CD [<directory>] Switch to given SD card directory <directory>. If no directory given, reset to \MZF which is the default. After a directory change the DIR command may take a few seconds to output information as the I/O processor caches the directory contents.
CPM n/a Locates CP/M 2.23 on the SD card, loads and runs it.
D <address>[<address2>] Dump memory from <address> to <address2> (or 20 lines) in hex and ascii. When a screen is full, the output is paused until a key is pressed.

Subsequent ‘D’ commands without an address value continue on from last displayed address.

Recognised keys during paging are:
‘D’ - page down, ‘U’ - page up, ‘X’ - exit, all other keys list another screen of data.
DIR <wild card> Listing of the files stored on the SD Card. Each file title is preceded with a hex number which can be used to identify the file.
A wildcard pattern can be given to filter the results, ie. ‘*BASIC*’ will list all files with BASIC in their name.
Output is in the form HH<seperator>FileName, where <seperator> identifies the type of file:
’.’ = Machine code, ‘-‘ = BASIC MZ80K/C/A, ‘<-‘ = BASIC MZ-700/800, ‘+’ = Other.
EC <name> or
<file number>
Erase file from SD Card. The SD Card is searched for a file with <name> or <file number> and if found, erased.
EX n/a Exit from TZFS and return machine to original state, I/O processor will be disabled.
F [<drive number>] Boot from the given Floppy Disk, if no disk number is given, you will be prompted to enter one.
FREQ <frequency in KHz> Change the CPU frequency to the value given, 0 for default. Any frequency is possible, the CPU is the limiting factor. On the installed 20MHz Z80 CPU frequencies upto 24MHz have been verified.
H n/a Help screen of all these commands.
J <address> Jump (start execution) at location <address>.
L | LT n/a Load file into memory from Tape and execute.
LTNX n/a Load file into memory from Tape, dont execute.
LC <name> or
<file number>[,<target model>]
Load file into memory from SD Card. The SD Card is searched for a file with <name> or <file number> and if found, loaded and executed.
Option argument <target model> allows setting the target under which the loaded software should run. This argument is intended for machines such as the MZ-800 where the default is to execute as an MZ-800 but specifying this flag you can force the MZ-700 compatibility mode. The flag is also used to target and run software into the original machine memory. Current flags:
8 - Force MZ-800 mode on an MZ-800 host.
7 - Force MZ-700 mode on an MZ-800 host.
O - Load into the host memory and run as original.
LCNX <name> or
<file number>[,<target model>]
Load file into memory from SD Card. The SD Card is searched for a file with <name> or <file number> and if found, loaded and not executed.
<target model> as per LC above.
M <address> Edit and change memory locations starting at <address>.
P n/a Run a test on connected printer.
R n/a Run a memory test on main mmemory.
S <start addr> <end addr> <exec addr> Save a block of memory to tape. You will be prompted to enter the filename.

Ie. S120020001203 - Save starting at 0x1200 up until 0x2000 and set execution address to 0x1203.
SC <start addr> <end addr> <exec addr> Save a block of memory to the SD Card as an MZF file. You will be prompted to enter the filename which will be used as the name the file is created under on the SD card.
SD2T <name> or
<file number>
Copy a file from SD Card to Tape. The SD Card is searched for a file with <name> or <file number> and if found, copied to a tape in the CMT.
T n/a Test the 8253 timer.
T2SD[B] n/a Copy a file from Tape onto the SD Card. A program is loaded from Tape and written to a free position in the SD Card. Adding B onto the end of the command invokes Batch mode where the command enters a loop converting all programs on 1 or more cassettes, only stops if BREAK key is pressed or an error occurs.
V n/a Verify a file just written to tape with the original data stored in memory
VBORDER <colour> Set a VGA border colour.
0 = Black
1 = Green
2 = Blue
3 = Cyan
4 = Red
5 = Yellow
6 = Magenta
7 = White..
VMODE <video mode> Select a video mode using the enhanced FPGA video module. The FPGA reconfigures itself to emulate the video hardware of the chosen machine.
0 = MZ-80K
1 = MZ-80C
2 = MZ- 1200
3 = MZ-80A
4 = MZ-700
5 = MZ-800
6 = MZ-80B
7 = MZ-2000
OFF = Revert to original video hardware.
VGA <vga mode> Select a VGA compatible output mode.
0 = Original Sharp mode
1 = 640x480 @ 60Hz
2 = 1024x768 @ 60Hz
3 = 800x600 @ 60Hz.

If the 40/80 column card is installed, typing ‘4’ switches to 40 Column display, typing ‘8’ switches to 80 Column display. For the directory listing commands, 4 columns of output will be shown when in 80 column mode.


Sharp BASIC SA-5510

During further development of the Rom Filing System I disassembled the SA-5510 BASIC interpreter (which is standard for an MZ-80A) to make it compatible with an SD card under RFS. As this interpreter is compatible with Sharp MZ-80A/MZ-700/800 machines on which the tranZPUter operates I decided to port it to TZFS.

The Byte location of the interpreter is critical as some programs are written to expect functions at known locations so disassembly had to be accurate and modifications/enhancements made outside of the main program. Luckily there is a block of self replication within the interpreter that isnt needed for TZFS so this area was used for additional functionality.

Unlike RFS where I could embed a drive specification into the LOAD/SAVE command, TZFS is more powerful and thus required seperate commands to specify SD card directories and wildcards. In addition TZFS has several useful features such as CPU clock thus requiring further command additions.

The table below lists the command extensions with a brief description.
Command Parameter Description
LOAD ”[<filename>]” Look for the program “<filename>” in the current SD card directory or CMT (cassette). If <filename> isnt given, load the next sequential file.
SAVE ”[<filename>]” Save the program in memory to the current SD card directory or CMT (cassette) under the name “<filename>”.
If <filename> isnt given, save with the name ‘DEFAULT<number>’ where <number> is a sequential number starting from 0.
DIR ”[<wildcard>]” List out the current SD card directory in TZFS format applying any given <wildcard> filter, ie. DIR M* to list all programs beginning with M.
CD [<path>] Change the active SD directory to <path>. If no <path> given change to root directory. If path = C, ie. CDC then switch to CMT (cassette), all other arguments switch to SD card.
FREQ [<freq>] Change CPU to the give frequency <freq>. <freq> is specified in KHz, ie. 10000 = 10MHz. If no <freq> given revert to original mainboard frequency.

To LOAD or SAVE to the builtin cassette drive, use the commands:
    CDC
    LOAD
or
    CDC
    SAVE “EXAMPLE”

The new version of BASIC SA-5510 is named “BASIC SA-5510-TZ”. </div>

NB: I havent yet fully implemented the random file read/write BASIC operations as I dont fully understand the logic. Once I get a suitable program I can analyse I will adapt TZFS so that it works according to the CMT specification.


Microsoft BASIC

The Sharp machines have several versions of BASIC available to use, on cassette or floppy, although they have limited compatibility with each other (ie. MZ80A SA5510 differs to the MZ-700 S-BASIC). Each machine can have several variants, ie. SA-6510 for disk drive use or third party versions such as OM-500. Most of these BASIC interpreters run well under TZFS so long as they were intended for use on a Sharp MZ80K/A/700 albeit they are limited to CMT (cassette) or Floppy storage only.

One drawback of the existing BASIC interpreters is availability of source code to update them with TZFS extensions. Unless you disassemble the binary or edit the binary directly adding TZFS commands is not possible. I came across this same issue during the development of RFS and needing a version of BASIC to aid in the more complicated tranZPUter hardware debugging I settled on using a version of Microsoft Basic where the source code was freely available, ie. the NASCOM v4.7b version of BASIC from Microsoft. This version of Basic has quite a large following in the retro world and consequently a plethora of existing BASIC programs. It is also fairly simple to extend with additional commands.

There are two versions of the NASCOM 4.7b source code available on the internet, either the original or a version stripped of several hardware dependent commands such as LOAD /SAVE /SCREEN but tweaked to add binary/hex variables by Grant Searle for his multicomp project. I took both versions to make a third, writing and expanding on available commands including the missing tape commands.

As the projects developed, Microsoft BASIC needed to support a variety of configurations, 5 under RFS and 4 under TZFS. Not counting the RFS versions, on the tranZPUter running TZFS the following are available:
  • MS-BASIC(MZ-80A) - Original 48K hardware which can be booted from cassette.
  • MS-BASIC(MZ-700) - Original 64K hardware which can be booted from cassette.
  • MS-BASIC(TZFS40) - TZFS upgrade with no video upgrade hardware installed.
  • MS-BASIC(TZFS80) - TZFS upgrade with a video module FPGA upgrade installed offering 80 column display.

Each appears on the TZFS drive and should be used according to hardware and need. The original NASCOM Basic Manual should be consulted for the standard set of commands and functions. The table below outlines additions which I have added to better suite the MZ-80A Rom Disk hardware.

Command Parameters Description
CLOAD ”<filename>” Load a cassette image from SD card, ie. tokenised BASIC program.
CSAVE ”<filename>” Save current BASIC program to SD card in tokenised cassette image format.
LOAD ”<filename>” Load a standard ASCII text BASIC program from SD card.
SAVE ”<filename>” Save current BASIC program to SD card in ASCII text format.
DIR <wildcard> List out the current directory using any given wildcard.
CD <FAT32 PATH> Change the working directory to the path given. All commands will now use this directory. On startup, CLOAD/CSAVE default to 0:\CAS and LOAD/SAVE default to 0:\BAS, this command unifies them to use the given directory. To return to using the defaults, type CD without a path.
FREQ <frequency in KHz> Set the CPU to the given KHz frequency, use 0 to switch to the default mainboard frequency. Tested ranges 100KHz to 24MHz, dependent on Z80 in use. Will overclock if Z80 is capable.
ANSITERM 0 = Off, 1 = On Disable or enable (default) the inbuilt Ansi Terminal processor which recognises ANSI escape sequences and converts them into screen actions. This allows for use of portable BASIC programs which dont depend on specialised screen commands. FYI: The Star Trek V2 BASIC program uses ANSI escape sequences.
NASCOM Cassette Image Converter Tool
NASCOM BASIC programs can be found on the internet as Cassette image files. These files contain all the tape formatting data with embedded tokenised BASIC code. In order to be able to use these files I wrote a converter program which strips out the tape formatting data and reconstructs the BASIC code. In addition, as this version of BASIC has been enhanced to support new commands, the token values have changed and so this program will automatically update the token value during conversion.

The converter is designed to run on the command line and it’s synopsis is:

NASCONV v1.0

Required:-
  -i | --image <file>      Image file to be converted.
  -o | --output <file>     Target destination file for converted data.

Options:-
  -l | --loadaddr <addr>   MZ80A basic start address. NASCOM address is used to set correct MZ80A address.
  -n | --nasaddr <addr>    Original NASCOM basic start address.
  -h | --help              This help test.
  -v | --verbose           Output more messages.

Examples:
  nasconv --image 3dnc.cas --output 3dnc.bas --nasaddr 0x10fa --loadaddr 0x4341    Convert the file 3dnc.cas from NASCOM cassette format.

Memory Decoder Tool

The early tranZPUter SW designs ( < v2.0) used a 512KB Flash RAM as the active decoder. This was chosen intentionally to allow multiple different memory maps so as the development progressed the tranZPUter SW could run software from the MZ80K/C/B/700/800 machines as they all are similar just with different memory maps (graphics can differ but the MZ80A Colour Board does a pretty good job at providing compatible video for an MZ-700 and with the advent of the Video Module v2.0 it will enable MZ80B/800 capable pixel graphics as well.

In order to generate the decoder bit map I have written a tool in C which creates the map based on Z80 signal logic. The logic uses Z80 signals so it is relatively straight forward to say ‘Memory map 5, Z80 WR and Addr:0xE800:EFFF has tranZPUter RAM mapped into it’.

An example of creating a decoder map using signals within the C program:

    // Pre transaction setup. The address lines contain the next address prior to the RD/WR/MREQ/IORQ signals being asserted. If a set
    // uses mixed resources, ie tranZPUter ond mainboard then their is a propogation delay from the FlashRAM being presented with the signals
    // to it outputting a signal plus additional delays for the 279 SR latch, 74HCT08 AND gate and the tristate buffers on the mainboard. This
    // action on the address to pre enable the mainboard or tranZPUter removes the propagation effect on the BUSACK signal on the main board.
    //
    switch(set)
    {
        // Set 3 - Monitor ROM 0000-0FFF, Main RAM area 0x1000-0xD000, User ROM 0xE800-EFFF are in tranZPUter memory block 0, Floppy ROM F000-FFFF are in tranZPUter memory block 1.
        // NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
        case 3:
            if( (Z80_ADDR >= 0x0000 && Z80_ADDR < 0xD000) || (Z80_ADDR >= 0xE800 && Z80_ADDR < 0xF000)) 
            {
                flashRAM[set].tranche[inSignals].DISABLE_BUS = 0;
                flashRAM[set].tranche[inSignals].ENABLE_BUS = 1;
            } else if ((Z80_ADDR >= 0xF000 && Z80_ADDR < 0xF3C0) || (Z80_ADDR >= 0xF400 && Z80_ADDR < 0xF7C0) || (Z80_ADDR >= 0xF800 && Z80_ADDR < 0x10000))
            {
                flashRAM[set].tranche[inSignals].DISABLE_BUS = 0;
                flashRAM[set].tranche[inSignals].ENABLE_BUS = 1;
                flashRAM[set].tranche[inSignals].A16 = 1;
                flashRAM[set].tranche[inSignals].A17 = 0;
                flashRAM[set].tranche[inSignals].A18 = 0;
            } else
            {
                flashRAM[set].tranche[inSignals].DISABLE_BUS = 1;
                flashRAM[set].tranche[inSignals].ENABLE_BUS = 0;
            } 
            break;

            ...

    // Specific mapping for Memory Writes.
    if(Z80_MEM_WRITE)
    {
        switch(set)
        {
            // Set 3 - Monitor ROM 0000-0FFF, Main RAM area 0x1000-0xD000, User ROM 0xE800-EFFF are in tranZPUter memory block 0, Floppy ROM F000-FFFF are in tranZPUter memory block 1.
            // NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
            case 3:
                if( (Z80_ADDR >= 0x0000 && Z80_ADDR < 0xD000) || (Z80_ADDR >= 0xE840 && Z80_ADDR < 0xF3C0) || (Z80_ADDR >= 0xF400 && Z80_ADDR < 0xF7C0) || (Z80_ADDR >= 0xF800 && Z80_ADDR < 0x10000)) 
                {
                    flashRAM[set].tranche[inSignals].DISABLE_BUS = 0;
                    flashRAM[set].tranche[inSignals].RAM_WE = 0;
                    flashRAM[set].tranche[inSignals].RAM_OE = 1;
                }
                break;

              ...

The decoder tool is designed to run on the command line and it’s synopsis is:

FLASHMMCFG v1.0

Options:-
  -h | --help              This help test.
  -i | --io-addr <addr>    Base address for the IO Control Registers.
  -o | --output <file>     Output the final binary image to the given file. This file is programmed into the Flash RAM.
  -v | --verbose           Output more messages.

Examples:
  flashmmcfg --output Decode1.bin --io-addr 0x20       Create the mapping binary using 0x20 as the base address for the IO Control Registers.

Building tranZPUter SW Software

The tranZPUter SW board requires several software components to function:

  • zOS - the integral operating system running on the K64F I/O processor
  • TZFS - the Z80 based operating or filing system running on the Sharp MZ80A
  • Memory decoder - the 512Kbyte map which forms the hardware decoder logic of the tranZPUter board
  • CP/M - A real operating system for Microcomputers which I ported to the Sharp MZ80A and it benefits from a plethora of applications.

Building the software requires different procedures and these are described in the sections below.


Paths

For ease of reading, the following shortnames refer to the corresponding path in this chapter. Two repositories are used, the primary one for the tranZPUter and zSoft for the operating system.

zSoft Repository (zOS)

Short Name Path Description
[<ABS PATH>]   The path where this repository was extracted on your system.
<zsoft> [<ABS PATH>]/zsoft/ Root directory for the zSoft software.
<z-apps> [<ABS PATH>]/zsoft/apps Application directory. All zOS/ZPUTA applications are located here along with their makefiles.
<z-build> [<ABS PATH>]/zsoft/build A target output directory for the compiled software, ie. <z-build>/SD contains all files to be written to an SD card.
<z-common> [<ABS PATH>]/zsoft/common Common C/C++ methods which are not assembled into a library.
<z-libraries> [<ABS PATH>]/zsoft/libraries C/C++ libraries, usually part of a C/C++ installation but for embedded work, especially on the ZPU need to be created seperately.
<z-teensy3> [<ABS PATH>]/zsoft/teensy3 The K64F based Teensy 3.5 software, some of which is used in the K64F version of zOS. Very rich libraries and can be easily added into a K64F program.
<z-include> [<ABS PATH>]/zsoft/include Common include header files.
<z-startup> [<ABS PATH>]/zsoft/startup Embedded processor startup files, generally in Assembler. Templates and macros are used to create the correct targets memory model startup code.
<z-iocp> [<ABS PATH>]/zsoft/iocp The IO Control Program, my initial bootloader for bootstrapping an application on the ZPU.
<z-zOS> [<ABS PATH>]/zsoft/zOS The zOS source code, parameterised for the different target CPU’s.
<z-zputa> [<ABS PATH>]/zsoft/zputa The ZPUTA source code, parameterised for the different target CPU’s.
<z-rtl> [<ABS PATH>]/zsoft/rtl Register Transfer Level files. These are generated memory definition and initialisation files required when building for a ZPU target project.
<z-docs> [<ABS PATH>]/zsoft/docs Any relevant documentation for the software.
<z-tools> [<ABS PATH>]/zsoft/tools Tools to aid in the compilation and creation of target files.

tranZPUter Repository

Short Name Path Description
<cpu> [<ABS PATH>]/tranZPUter/cpu ZPU VHDL definition files.
<build> [<ABS PATH>]/tranZPUter/build Build files for developing and tesing of the ZPU based tranZPUter board.
<devices> [<ABS PATH>]/tranZPUter/devices RTL definitions of hardware devices used in the ZPU development or tranZPUter development.
<docs> [<ABS PATH>]/tranZPUter/docs Any relevant documentation for the project.
<pcb> [<ABS PATH>]/tranZPUter/pcb Gerber files, each tranZPUter version (SW, SW-700 and tranZPUter) within it’s own sub-directory.
<schematics> [<ABS PATH>]/tranZPUter/schematics Kicad schematics and PCB design files including component library definitions.
<software> [<ABS PATH>]/tranZPUter/software Root directory for software used in the project.
<tools> [<ABS PATH>]/tranZPUter/software/tools Tools to aid in the compilation and creation of target files.
<asm> [<ABS PATH>]/tranZPUter/software/asm Z80 assembler files for TZFS, CP/M and various original monitor ROMS.
<roms> [<ABS PATH>]/tranZPUter/software/roms ROM files created by assembling the Z80 source.
<srctools> [<ABS PATH>]/tranZPUter/software/src/tools tranZPUter v1 Flash RAM memory map decoder file creation tool and NASCOM Basic converter tool.
<cpm> [<ABS PATH>]/tranZPUter/software/CPM Original CPM software, grouped according to application including generated Floppy Disk and SD Card images.
<mzf> [<ABS PATH>]/tranZPUter/software/MZF Original Sharp MZF format applications which will be added into any generated SD Card image.
<bas> [<ABS PATH>]/tranZPUter/software/BAS A collection of converted NASCOM Basic programs in readable text format. These are added to generated SD Card images.
<cas> [<ABS PATH>]/tranZPUter/software/CAS A collection of NASCOM Basic tokenized tape programs converted from the NASCOM tape images. These are added to generated SD Card images.
<cas> [<ABS PATH>]/tranZPUter/software/NASCAS A collection of original NASCOM cassette images which havent been converted. Use the nasconv tool to convert.
<config> [<ABS PATH>]/tranZPUter/software/config Configuration files for tools. Currently the disk definition description file for generation of CP/M images.

Tools


All development has been made under Linux, specifically Debian/Ubuntu. I use Windows for flashing the Flash RAM's and using the GUI version of CP/M Tools but havent dedicated any time into building the TZFS under Windows. I will in due course create a Docker image with all necessary tools installed, but in the meantime, in order to assemble the Z80 code, the C programs and work with the CP/M software and CP/M disk images, you will need to obtain and install the following tools.

For the Teensy3.5/K64F the ARM compatible toolchain is currently stored in the repo within the build tree.

   
ZPU GCC ToolChain The GCC toolchain for ZPU development. Install into /opt or similar common area.
Arduino The Arduino development environment, not really needed unless adding features to the K64F version of zOS from the extensive Arduino library. Not really needed, more for reference.
Teensyduino The Teensy3 Arduino extensions to work with the Teensy3.5 board at the Arduino level. Not really needed, more for reference.
Z80 Glass Assembler A Z80 Assembler for converting Assembly files into machine code. I have had to fix a bug in the 0.5 release as it wouldnt create a byte at location 0xFFFF, this fixed version is stored in the <tools> directory in the repository.
samdisk A multi-os command line based low level disk manipulation tool.
cpmtools A multi-os command line CP/M disk manipulation tool.
CPMToolsGUI A Windows based GUI CP/M disk manipulation tool.
z88dk An excellent C development kit for the Z80 CPU.
sdcc Another excellent Small Device C compiler, the Z80 being one of its targets. z88dk provides an enhanced (for the Z80) version of this tool within its package.

Build zOS

To build zOS please refer to the zOS build section.

A typical buid line would be:

build.sh -C K64F -O zos  -N 0x10000 -d -T

This builds a zOS image for the K64F processor with a primary heap of 64K (-N 0x10000) and adds the tranZPUter extensions (-T).

The output file would be <z-zOS>/main.hex which can be uploaded into the Teensy 3.5 board.


Build TZFS

Building the software and final load image can be done by cloning the repository and running some of the shell scripts and binaries provided.

TZFS is built as follows:

  1. Make the TZFS binary using <tools>/assemble_tzfs.sh, this creates a ROM image <roms>/tzfs.rom which contains all the main and banked code.
  2. Make the original MZ80A monitor roms using <tools>/assemble_roms.sh, this creates <roms>/monitor_SA1510.rom and <roms>/monitor_80c_SA1510.rom.
  3. Copy and/or delete any required Sharp MZF files into the MZF directory.
  4. Copy files to the SD card.

See below for the typical build stages.


Build the Memory Decoder

To build the memory decoder map for flashing into a 512K Fash RAM clone the repository and follow the steps below:

  1. Change to directory and issue command: make make install
  2. Run the command: /flashmmcfg --output /tranZPUterDecoderMappingFile.bin
  3. Flash the file:/tranZPUterDecoderMappingFile.bin to a suitable 512KB Flash RAM.

Adding decoding logic is a matter of editting the file <software>/src/tools/flashmmcfg.c and adding suitable clauses in the setMap() method.


Build CPM

To build CP/M please refer to the CP/M build section for additional information.

The CP/M version for the tranZPUter is slightly simpler to build as it doesnt involve preparing a special SD card or compacted ROM images.

The CP/M system is built in 4 parts,

1. the cpm22.bin which contains the CCP, BDOS and a CBIOS stub.
2. the banked CBIOS which has its primary source in a 4K page located at 0xF000:FFFF and a
   larger, upto 48K page, located in a seperate 64K RAM block.
3. the concatenation of 1 + 2 + MZF Header into an MZF format file which TZFS can load.
4. creation of the CPM disk drives which are stored as 16MB FAT32 files on the K64F SD card.

All of the above are encoded into 2 bash scripts, namely ‘assemble_cpm.sh’ and ‘make_cpmdisks.sh’ which can be executed as follows:

cd <software>
tools/assemble_cpm.sh
tools/make_cpmdisks.sh

The CPM disk images can be found in <cpm>/1M44/RAW for the raw images or <cpm>/1M44/DSK for the CPC Extended format disk images. These images are built from the directories in <cpm>, each directory starting with CPM* is packaged into one 1.44MB drive image. NB. In addition, the directories are also packaged into all the other supported disks as images in a corresponding directory, ie <cpm>/SDC16M for the 16MB SD Card drive image.

The CPM disks which exist as files on the SD Card are stored in <CPM>/SDC16M/RAW and have the format CPMDSK<number>.RAW, where <number> is 00, 01 … n and corresponds to the disk drive under CP/M to which they are attached (ie. standard boot, 00 = drive A, 01 = drive B etc. If the Floppy Disk Controller has priority then 00 = drive C, 01 = drive D). Under a typical run of CP/M upto 6 disks will be attached (the attachment is dynamic but limited to available memory).


A Typical Build

A quick start to building the software, creating the SD card and installing it has been summarized below.

# Build zOS
cd <zsoft>
./build.sh -C K64F -O zos  -N 0x10000 -d -T
# Flash <z-zOS>/main.hex into the K64F processor via USB or OpenSDA.
cp -r build/SD/* <SD CARD>/

# Build TZFS
cd <software>
tools/assemble_tzfs.sh
# Build the required host (Sharp) ROMS.
tools/assemble_roms.sh
# Build CPM
tools/assemble_cpm.sh
# Build the CPM disks.
tools/make_cpmdisks.sh

# Create the target directories on the SD card and copy all the necessary applications and roms.
mkdir -p <SD CARD>/TZFS/
mkdir -p <SD CARD>/MZF/
mkdir -p <SD CARD>/CPM/
mkdir -p <SD CARD>/BAS
mkdir -p <SD CARD>/CAS
cp <software>/roms/tzfs.rom                   <SD CARD>/TZFS/
cp <software>/roms/monitor_SA1510.rom         <SD CARD>/TZFS/SA1510.rom
cp <software>/roms/monitor_80c_SA1510.rom     <SD CARD>/TZFS/SA1510-8.rom
cp <software>/roms/monitor_1Z-013A.rom        <SD CARD>/TZFS/1Z-013A.rom
cp <software>/roms/monitor_80c_1Z-013A.rom    <SD CARD>/TZFS/1Z-013A-8.rom
cp <software>/roms/monitor_1Z-013A-KM.rom     <SD CARD>/TZFS/1Z-013A-KM.rom
cp <software>/roms/monitor_80c_1Z-013A-KM.rom <SD CARD>/TZFS/1Z-013A-KM-8.rom
cp <software>/roms/MZ80B_IPL.rom              <SD CARD>/TZFS/MZ80B_IPL.rom
cp <software>/MZF/CPM223.MZF                  <SD CARD>/MZF/
cp <software>/roms/cpm22.bin                  <SD CARD>/CPM/
cp <software>/CPM/SDC16M/RAW/*                <SD CARD>/CPM/
cp <software>/MZF/*                           <SD CARD>/MZF/
cp <software>/BAS/*                           <SD CARD>/BAS/
cp <software>/CAS/*                           <SD CARD>/CAS/

# If you want TZFS to autostart, create an empty flag file as follows.
> <SD CARD>/TZFSBOOT.FLG

# If you want to run TZFS commands on each boot, create an autoexec.bat file and place required commands into the file.
> <SD CARD>/AUTOEXEC.BAT

# Eject the card and insert it into the Teensy3.5 reader on the tranZPUter board.
# Remove the Z80 from the Sharp MZ machine and install the tranZPUter board into the Z80 socket.
# Power on. If the autostart flag has been created, you should see the familiar monitor
# signon message followed by +TZFS. If the autostart flag hasnt been created, enter the command
# JE800 into the monitor to initialise TZFS.

Flash K64F MPU

The original tranZPUter SW made use of the excellent Teensy development board from PJRC which was replaced in later tranZPUter SW releases by a 100pin TQFP version of the Freescale K64FX512 processor.

As the method developed by PJRC for programming the K64FX512 processor is so simple it made sense, for rapid development, to include it on the tranZPUter SW-700 board along with the OpenSDA JTAG method. At board assembly time, if you install the PJRC boot MCU (U6) and set the jumper pins 1-2 on JP1-5 then it is possible to program the K64F via the USB using PJRC's Teensy Tool. If U6 is not installed, programming is made via an OpenSDA programmer connected to the JTAG port using the SWD protocol. In this instance, connect jumper pins 2-3 on JP1-4 and pins 1-2 on JP5.

To use the Teensy Tool for programming, all the necessary files and executables can be found in the <z-tools> directory within the zSoft repository,

To program the K64F after an OS build, follow the steps below:
1. Connect the tranZPUter SW-700 board to your PC with the USB cable.
2. Launch the Teensy programming application: 
   <z-soft>/teensy 
3. In the Teensy application, select File->Open HEX file and navigate to the <z-zOS> or \z<zputa> directory (depending on which OS your uploading) and select the file 'main.hex'.
4. Press the 'K64F PROG' button on the tranZPUter SW-700 board.
5. In the Teensy application, select Operation->Program - this programs the onboard Flash RAM.
6. Ensure you have a terminal emulator open configured to the virtual serial device (if unsure, issue the 'dmesg' command from within Linux to see the latest USB attachment and its name). Normally the device is /dev/ttyACM0. There is no need to set the Baud rate or Bits/Parity, this is a virtual serial port and operates at USB speed.
7. In the Teensy application, select Operation->Reboot - this will now reboot the K64F and it will startup running zOS or ZPUTA.
8. Interact with the OS via the terminal emulator. 
A zOS application is being developed for zOS v1.2 which will allow the flashing of new firmware into the K64F via the zOS console from an SD card. Apart from the initial programming of the K64F where a SWD device would need to be used, this application will remove the need to use the PJRC or JTAG tools.

Flash Teensy3.5

For earlier versions of the tranZPUter SW which use a Teensy 3.5 development board, you need to flash the program via its USB connector.

All the necessary files and executables to program the Teensy can be found in the <z-tools> directory within the zSoft repository,

To program the Teensy after an OS build, follow the steps below:

1. Connect the teensy 3.5 board to your PC with the USB cable.
2. Launch the Teensy programming application: 
   \<z-soft>/teensy 
3. In the Teensy application, select File->Open HEX file and navigate to the \<z-zOS> or \z<zputa> directory (depending on which OS your uploading) and select the file 'main.hex'.
4. Press the RESET button on the Teensy 3.5
5. In the Teensy application, select Operation->Program - this programs the onboard Flash RAM.
6. Ensure you have a terminal emulator open configured to the virtual serial device (if unsure, issue the 'dmesg' command from within Linux to see the latest USB attachment and its name). Normally the device is /dev/ttyACM0. There is no need to set the Baud rate or Bits/Parity, this is a virtual serial port and operates at USB speed.
7. In the Teensy application, select Operation->Reboot - this will now reboot the K64F and it will startup running zOS or ZPUTA.
8. Interact with the OS via the terminal emulator. 

For further information on the Teensy programming tool, see the Teensy basic usage guide.


Credits

Where I have used or based any component on a 3rd parties design I have included the original authors copyright notice. All 3rd party software, to my knowledge and research, is open source and freely useable, if there is found to be any component with licensing restrictions, it will be removed from this repository and a suitable link/config provided.


Licenses

This design, hardware and software, is licensed under the GNU Public Licence v3.

The Gnu Public License v3

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.

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.

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