CP/M on a Z80: Meeting the address space requirements?

251 views
Skip to first unread message

Jacob Hahn

unread,
May 11, 2021, 10:06:31 AM5/11/21
to retro-comp
Hi everyone,

It's been a while since I've worked on my Z80 SBC since I finished the version running BASIC. However, now that summer is coming around and I'll have some extra time, and I'm blessed to be able to work on it as a school project next year, I'd like to make a version that runs CP/M.
I've seen other versions of SBCs that run CP/M, so this is certainly not a new concept. However, many that I can find use a GAL or similar for glue logic. I would like my design to use all discrete logic for its design, such as what you would find in the 80s.
The biggest struggle I've found is understanding how I can meet the requirements for address space. Importantly, CP/M requires RAM at 0x0000 to run, but the Z80 starts executing from ROM at 0x0000. This overlap presents a problem. Many sources say to simply have ROM at 0x0000 and then swap it to ROM after the CPU executes what it needs, but I don't know how to do this without a GAL.
Grant Searle seems to have accomplished what I'm looking for here. However, I'm having difficulty reading the schematic as my skills aren't too great when it comes to interpreting logic circuits. Can anyone shed some light on its operation?

Thanks,
Jacob.

Sergey Kiselev

unread,
May 11, 2021, 10:22:29 AM5/11/21
to Jacob Hahn, retro-comp
You'll need a memory element, such as a latch or a flip-flop that has a reset input connected to the reset signal of the board/CPU.
The output of that memory element would be connected to the memory chip select logic, that makes it select ROM over RAM after reset.
You'll also need a way to "set" that memory element, so that RAM gets mapped at 0x0000 eventually during boot. There is more than one way to do that. For example, you can connect the "set" input of the flip-flop to an I/O decode logic, so that it gets set when an I/O port is written. Others use high address memory chip select, e.g. once A15 line goes high (meaning that CPU is already executing code from the ROM area).

While back (S-100 times?) another approach was popular, where instead of temporary mapping the ROM to 0x0000, they've built a circuit that was feeding JMP instruction to the CPU right after reset.


--
You received this message because you are subscribed to the Google Groups "retro-comp" group.
To unsubscribe from this group and stop receiving emails from it, send an email to retro-comp+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/retro-comp/44c25d37-de27-4276-9834-547f417c1ff4n%40googlegroups.com.

Sergey Kiselev

unread,
May 11, 2021, 10:33:26 AM5/11/21
to retro-comp
Here are a couple of examples.
One from MSX - it uses a simple SR flip-flop, which is reset by system reset signal, and set when PPI is accessed
MSX_Reset.png
Another one from my Zeta SBC - it uses one of 74*174 six D flip-flops for the reset (and 4 more for ROM address select). It also shows how to build memory chip select that can be forced to map the RAM at 0x0000
Zeta_Reset.png

Bill Shen

unread,
May 11, 2021, 10:47:53 AM5/11/21
to retro-comp
You can also take advantage of output flip flops in existing Z80 peripherals such as the SIO and build a CP/M-capable Z80 SBC without any glue logic--just RAM, ROM, Z80 and SIO.
  Bill

Jacob Hahn

unread,
May 11, 2021, 11:16:56 AM5/11/21
to retro-comp
Sergey,

Thanks for your input, it makes sense to me. I do have plenty of free I/O addresses on the 74HC138 I use in my design and I could use one of those to set the flip-flop. I want to keep this design simple at first so I learn the basics before going into more advanced designs. I have about a year to do this, so that's plenty of time to work and learn. I'll also keep studying Grant Searle's design, as it seems to use a similar flip-flop method.

Thanks,
Jacob.

Douglas Miller

unread,
May 11, 2021, 1:20:22 PM5/11/21
to retro-comp
In addition, some systems had a "write under ROM" feature that made it easier to transition. Basically, there was always RAM and ROM coexisting at 0x0000, but after RESET a /RD would enable only the ROM and /WR would enable only RAM. This way, startup code could do something as simple as:

     ld hl,0
     ld de,0
     ld bc,0800h ; or whatever your ROM size
     ldir
    out (ramport),a ; trigger switch to RAM however...

In this way, the ROM code switches itself into RAM early and then nothing special needs to be done when starting CP/M.

Rob Gray

unread,
May 11, 2021, 4:21:36 PM5/11/21
to retro-comp

In Grant Searle's schematic U7:C and U7:D form a flip flop that is set by the reset button and reset by an IOWR to any address in the 38-3F range. This then appears to enable/disable the lower 16k of the ROM.

Jacob Hahn

unread,
May 14, 2021, 2:27:32 PM5/14/21
to retro-comp
Rob,

Does it just disable the lower 16K? Or the whole ROM?
I'm pretty sure I understand most of the schematic but I'm still puzzling over a few details.

Thanks,
Jacob

Matthew Barrick

unread,
May 14, 2021, 4:35:00 PM5/14/21
to retro-comp
The ROM(U4) on the schematic is a 128Kbit ROM, organized as 16Kx8 (16*1024 address locations, each 8 bits wide). (https://pdf1.alldatasheet.com/datasheet-pdf/view/22823/STMICROELECTRONICS/27128.html). 128Kbit=16Kbyte, the whole ROM is 16K.

The signal bar{BOTTOM 16K} is probably what's confusing.  The bottom 16K of the RAM and the bottom/all 16K of the ROM are wired to the same place in memory. If you look at the address bus (from the Z80,  U1, A0-A15) all  those lines going into the RAM (U9). The Z80 has 16-bit address bus, 16 lines, binary, 2^16 = 64K locations (8-bit data bus, so words are 8-bit=1 byte).  If you look at the address bus connecting to the ROM (U4), only A0-A13 (14 lines) connect to it. 2^14 = 16K, which makes sense since it's a 16KxN ROM.

If look at the line that would go to the ROM if it were bigger, A14 and A15 go into the U6:C. U6 is a 74LS32, just a chip with four OR gates on it. So if the address going out from the CPU has A14 OR A15 High (is in the top 3/4 of the address space), U6:C outputs True which is labeled as bar{BOTTOM 16}, "Not in the Bottom 16K of the address space". You see this goes into an another OR gate U6:D, which ORs that bar{BOTTOM} with the output of the U7 flip-flip which determines whether the ROM has been disable, output is label "ROM DISABLED". So those to two OR gates, when the CPU wants to access an address in memory, figure out the whether it should come from RAM or ROM. If ROM_DISABLED or is NOT(BOTTOM 16K), than we want the RAM. If not that, not ROM_DISABLED and NOT(NOT(BOTTOM 16K)) = ROM_ENABLED and BOTTOM_16K, then the ROM is still being used and the address is in bottom 16K of the address space, so we want ROM.

The mechanism to pick which is the RAM/bar{ROM} sign. If you follow that trace from U6:D (RAM/bar{ROM}), you'll see it goes the Pin 20/bar{CE} on the ROM and and CS2 on the RAM. 

Looking at the datasheet for the ROM (the one linked above is just the first fit when I searched), you'll see it call Pin 20 bar{E}.  This is the Chip Enable signal. As the datasheet details, applying high to it will but the chip into Standby Mode (aka disable the chip). 

This signal goes to Pin 30/CS2 on the RAM. (https://www.jameco.com/Jameco/Products/ProdDS/131810.pdf).  This is called Chip Select. The name comes from the idea that you'd have two of these chips, and you select between the two of them. Name aside, look at the Operation Table on page 5 of the data sheet. CS2 needs to be H (high/true) for Read and Write operations.  If this pin, CS2, is low the only two states for the RAM is standby. 

So if signal coming from U6:D  (labeled 11, I don't know the proper terms for parts of schematics sorry) is High, the ROM is in Standby Mode and the RAM is set to be able to Read/Write. So if the CPU puts out an address, only the RAM will respond. If the signal is Low, the RAM is put in Standby, and the ROM gets 

Not sure what parts you understand or don't, so I erred on the side of detail.  


-mjb

Sergey Kiselev

unread,
May 14, 2021, 4:37:06 PM5/14/21
to retro-comp
It disables the entire ROM, although the 27128 ROM used there is only 16 KB...

Here is how it works:
Following the "cold" reset, the U7:C and U7:D flip-flop is reset, the "ROM DISABLED" signal (output of U7:C, pin 8) will be low, and the "RAM/~ROM" signal (output of U6:D, pin 11) will depend on "~BOTTOM 16K" signal. Such that if "~BOTTOM 16K" is low, the "RAM/~ROM" signal will be also "low", selecting the ROM. Otherwise, if the "~BOTTOM 16K" is high (which will happen if A14 or A15 or both are "high"), the "RAM/~ROM" signal will be high, selecting the SRAM.
Writing any value to any of the ports in 0x30-0x38 range will switch the U7:C and U7:D flip-flop, and it's "ROM DISABLED" output will be low. And the "RAM/~ROM" signal will be high, regardless of "~BOTTOM 16K" signal, selecting the SRAM, until a "cold" reset occurs.

Keep in mind that Grant Searle's design is a minimalistic one, and therefore it is not terrifically flexible.
A few shortcomings:
- It uses HM628128 SRAM, and particularly the active high CS signal that found only in some SRAM ICs (e.g. 62256 doesn't have it)
- It keeps either ROM or RAM selected at all times, which is not the best design practice, especially if you're planning to expand RAM or ROM in the future
- It is impossible to re-enable the ROM from the software. Having software control increases the flexibility. For example, it would be possible to keep the BIOS drivers, data, or the OS code in the ROM, and switch between that and user space application SRAM, increasing the amount of the available SRAM to the applications.

--Sergey

Sergey Kiselev

unread,
May 14, 2021, 4:39:11 PM5/14/21
to retro-comp
Sorry, that is "Writing any value to any of the ports in 0x30-0x38 range will switch the U7:C and U7:D flip-flop, and it's "ROM DISABLED" output will be _high_"
Reply all
Reply to author
Forward
0 new messages