Updated notes on an X16 CP/M card

Chat about anything CX16 related that doesn't fit elsewhere
Post Reply
BruceRMcF
Posts: 248
Joined: Sat Jan 07, 2023 10:33 pm

Updated notes on an X16 CP/M card

Post by BruceRMcF »

I've commented on the "Feature Request" for the X16 to support CP/M, but as a Feature Request, the answer is that the X16 already supports that feature, since it has a card slot specification that has everything required to support a Z80 card.

My earlier notion from now expunged forum sections was a CP/M board organized around using the ubiquitous SPI serial Flash IC's. A couple of two-bit auto-direction sensing voltage translators to convert from 3.3v to 5v ... and the 3.3v is available directly from the slot ... and you easily have the three SPI lines output to the SPI flash and the one SPI line input from it bridged between the 3.3v domain and the 5v domain. Using a virtual 512KB drive (32 128-byte sector per 4KB "track -- Flash RAM block -- and 128 tracks per drive), there can be four virtual disks in a 16Mbit (2MBx8) SPI Flash RAM.

CP/M systems traditionally worked based on a terminal for user interface -- the "luggable" CP/M systems effectively bundled the CP/M system and the terminal together in the same box -- so for communication with the X16, the Z80 system can be designed with a UART, and then the same UART as is used in the Serial/Internet card can be used on the X16 side to talk to it. If the Z80 system does not have a FIFO, it could be a four wire connection between the two, including hardware flow control. The existing X16 terminal program can then be used as the terminal, for any CP/M software that supports or can be patched to support that terminal.

A Z80 compatible CPU, RAM, storage, User I/O ... there's a system that can be brought up to run CP/M.

One thing I was worrying about back in the previous incarnation of this was the PROM / FlashROM needed for the bootloader, with the issue being how much I wanted to invest in a parallel FlashROM programmer. However, that was before I stumbled across the use of a 22V10 SPLD as a 32 byte bootloader. It turns out that by specifying what bits you wanted each of the databus outputs to show for each combination of five address lines, the program to fit the VHDL specification to the SPLD could figure out what combinations of OR's AND's loopbacks and XOR's are required to give the right byte for the right combination of address lines. Since the logical combinations available to different line are not symmetric for the 22V10, sometimes the data lines have to be re-arranged to make it work, but if it works for some specific 32byte code for a 22V10, I expect it would certainly work for an ATF750, which has the same form factor but symmetric macrocells, and with internal macrocells in addition to the macrocells on the I/O pins.

Now, someone familiar with the ATF750 might wonder how that gets me over the expense of a programmer, since programmers that are able to program ATF750's are not as common as FlashROM programmers. However, the answer is the next step up the Atmel CPLD line, the 64 Macrocell ATF1504, where the smaller form factor versions have 32 I/O pins and 32 internal Macrocells and, critically, also have the lines supporting a JTAG interface, allowing it to be programmed from the USB port of a PC with a USB to JTAG interface cable.

So an ATF1504 can be used for memory select, supporting SPI interface capabilities, latching the control bits for SPI selects, SPI mode control, a heartbeat LED, toggling the PROM out of the memory map, and if a larger than 64KB SRAM is used, memory banking bits.

Also, an ATF1504 can be used for a self-addressing PROM which knows when it is selected and when it is deselected, and which half of memory it appears in, and only asserts the bootloader code when and where it is supposed to.

Whether that is one ATF1504 or two depends entirely on whether the memory / SPI controller function leaves enough pins and free Macrocells to program the bootloader.

Since a Serial Flash RAM IC can be programmed In-Service with a USB interface to a clip that hooks directly to the IC, that implies a board that can set up entirely by ISP from laptop USB ports ... or a USB hub connected to the mini-PC I used to put video on my TV that works better from a web video interface than from a Smart TV app.

The final question is the CPU. The three reasonable choices are an original Z80, the Z180, and the eZ80.

--------------
--- Z80 -----
--------------

The Z80 is no longer in production. It seems like many that are advertised as new-old stock are in fact recycled pulls, and are not always guaranteed to actually be Z80's. However, if you can get an actual Z80 pull, they are widely available in DIP form factor for easier bread-boarding. The original Z80 is, of course, just the CPU, without internal integration of commonly used components, so a UART would be required ... but if an SPI port is being provided for the SPI Flash "drives", then just one more select line allows use of an SPI->UART bridge like the Maxim3100. The ATF1504 is available in a small enough PLCC that bread-boarding sockets are available for less than an arm and a leg. And 16Mbit serial flash RAM is available on breakout boards from Adafruit for $3, including automatic +5v to +3.3v level shifting.

I have already looked at an output control latch, Memory controller, and simple SPI interface for the Z80, and more than 32 I/O pins required for that and the self-addressing PROM function, so the question of whether the bootloader code could be fit into one ATF1504 alongside the other functionality is a moot point ... 2 ATF1504's would be used, one for a self-addressing PROM.

The breadboard version might use a 32KB RAM, which is enough to support many (though not all) CP/M applications. This is more proof of concept than a finished board, but with very few changes the same CP/M BIOS that would work for this breadboard computer would work for the next one as well. And as a breadboard computer, budget techniques can be borrowed from Ben Eater's builds, such as a slow clock from a 555 timer, allowing the broadboard computer to be run at the clock frequency that a Pi Pico and a smartphone app can handle as a simple "$5 oscilloscope".

--------------
--- Z180 ----
--------------

Now, hypothetically, if the Z80 breadboard could be made to work, I don't think I would target a Z80 based CP/M board, because except for being rare in a DIP form factor, there is a much better Zilog CPU for this particular use case.

The Z180 is no longer in production, but several versions are still readily available as new-old stock. The readily available Z180 parts are Surface Mount form factor, including both 10MHz and 20MHz parts, so with a surface mount ATF1504 and a surface mount SPI Flash "drive", it would make sense to add a surface mount SRAM and a surface mount version of the X16 side UART and get the board built complete ... with a JTAG connector wired to the ATF1504 JTAG lines, so that the built version of the board is not functional until the ATF1504 is programmed.

The Z180 includes a memory controller, which substantially reduces the complexity of a memory banking. It also includes an integrated dual UART, increasing the efficiency of terminal access to the X16. It also includes a one-way serial clocked port. This allows the SPI circuit to be simplified to just allowing the Z180 to clock out one output bit at a time, with the CSOI register set up to automatically read in the data from the SPI MISO line.

With components integrated into the Z180, a single ATF1504 has enough I/O pins for both SRAM select and SPI support, including latching all required control bits, and also for a 32byte or 64byte bootloader, and with very few internal macrocells used by the SRAM select and SPI support, it appears likely that the self-addressing bootloader PROM function can be contained in the single ATF1504.

Since an SPI bus is already built in, the card could also offer two "EXT" SPI servant selects, with a pair of block headers with power, GND, the three lines of the SPI bus, and one of the select lines going to each block header offering two SPI I/O "slots".

My initial target would be for a CP/M 2.2 BIOS, which only handles 64KB directly. However, the Z180 includes the MMU to support CP/M Plus style banked memory, including A0-A19 lines for a 1MB physical address space, so I would likely opt for a 128KB SRAM directly tied to the first 17 address lines of the Z180 to be upward compatible with a future CP/M Plus system.

--------------
--- eZ80 ----
--------------

Finally, the 16bit eZ80 microcontroller has Z80 instruction set backward compatibility built in. It comes with integrated UART with 16-byte FIFOs and an integrated SPI bus interface, and versions include integrated 64KB (or larger) Flash ROM ... programmable from a PC USB port over a JTAG connector.

The eZ80 also runs faster than the Z80 at the same clock speed. The Z80 requires multiple clock cycles for each step of its fetch-process-execute cycle. It could pipeline the execution phase with the following first instruction byte fetch, for register-to-register operations, so some instructions were only 4 cycles long ... but many Z80 instructions are multi-byte instructions, and each data read or write cycle required three clocks. The eZ80 can execute on a single-cycle-per-byte basis, like the 6502, making it over twice as fast as the Z80.

In addition, the eZ80 has a pipeline which in the best case allows one instruction to be fetched as the previous one is being processed and the one before that to be executed, so in that best case an instruction adds a single clock to the execution time of a routine. Not all code will get this much speed-up, since the "three deep" execution requires that the execution of the earliest opcode in the queue did not require a memory access, leaving the data bus free for fetching the third byte in the pipeline ... but with the broad collection of register to register operations in the Z80 instruction set, that is not uncommon. So while the pipeline will only be two deep if the earlier opcode operates on memory, and must be flushed for every branch, jump or call, combined with the single clock per memory access it still offer s a dramatic speed-up over the conventional Z80 fetch-process-execute module.

So if there was any interest in the Z180 CP/M card, I assume that someone else would implement an eZ80 card on a similar basis, and after that point, the demand for the Z180 CP/M card would then be limited to those who wanted a "real 8bit" CPU on their CP/M card.
BruceRMcF
Posts: 248
Joined: Sat Jan 07, 2023 10:33 pm

Re: Updated notes on an X16 CP/M card

Post by BruceRMcF »

Latching of control bits

In the Z80 version, the I/O port address in Z80 IN and OUT instructions is basically ignored: every output is putting a MOSI bit onto the SPI bus and every input is reading a MISO bit that has been latched from the SPI bus.

So how do SPI device selects, a hearbeat LED, toggling the "self-addressing PROM" (aka saP) out of the address space and, if more than 64KB of SRAM is added, memory banking bits get out of the Z80?

One of the features of the Z80 is that it generates a running 7bit count that is put out onto the low 7 bit address lines during the two clock cycles of an instruction cycle that the Z80 is processing the instruction. This simplified the DRAM refresh support system. During a "Refresh" cycle, the R register contains the value placed on the low 8 lines of the address bus.

The specific circuit generating the running R count-up is not a generic counter, but rather works for some specific data widths, with the 7bit wide version being the one implemented in the Z80. So the high bit of the R register is not affected by the running refresh counter. This is used for the "heartbeat" LED. On Reset, the value of the top bit is set to 0, and when the top bit is set to 1:

Code: Select all

        LD A,FFh
        LD R,A
... the heartbeat LED will light.

R(7) =: A(7) =: HeartLED

There are three Interrupt Modes in the Z80: an 8080 style interrupt where the interrupting device supplies an instruction to be executed, an interrupt similar to the 6502 interrupt, where a vector at 0038h is executed, and an interrupt where an interrupting device supplies the low byte of the address of an interrupt vector and the I register contains the high address ... so up to 128 interrupt vectors can be supports so long as the interrupting device knows where it's vector is supposed to be in the vector table.

The CP/M card might support the X16 interrupting the Z80, but I would not use Mode2 for this, so the I register is free. And it just so happens that during the refresh cycle, "I" is placed on the high eight lines of the Z80 address bus. So the I register is used to contain setting bits. For SPI selects, the SPI control circuit will invert the select, so that when I is zeroed at restart, no SPI devices will be selected at the outset. A pair of RAM banking values -- which for CP/M would be the first 32KB of the logical address space, 0000h-7FFFh -- are latched directly, so that in a 128KB SRAM, "Bank0" is at 000000h-007FFFh, "Bank1" is at 008000h-00FFFFh and "Bank2" is at 010000h-017FFFh, while logical 8000h-FFFFh is always at physical addresses 018000h-01FFFFh.

The "SPIMODE" control signal enables the conversion of the system Mode3 SPI bus to a Mode0 SPI bus (as required for SD cards in SPI mode).

The layout of the Interrupt register might be:
  • I(0) =: A(8) =: ~SPI_SELECT(0) -- UART (Z80 system only) / Bus Expander (Z180 system only)
  • I(1) =: A(9) =: ~SPI_SELECT(1) -- SPI Flash RAM
  • I(2) =: A(10) =: ~SPI_SELECT(2) -- Ext0 (Mode0, +3.3v)
  • I(3) =: A(11) =: ~SPI_SELECT(3) -- Ext1 (Mode3, +5v)
  • I(4) =: A(12) =: SPI_MODE
  • I(5) =: A(13) =: BANK0
  • I(6) =: A(14) =: BANK1
  • I(7) =: A(15) =: ~PROM
Post Reply