15

In a nutshell, could the Z80 address 64 KB of ROM and 64 KB of RAM, or just 64 KB for both RAM and ROM?

Unfortunately, I couldn't find an exact and a direct answer to my question while searching. Excuse me if my question has a very very direct answer, that I don't understand

Now whenever I see how memory a Z80 could address on many sites, Wikipedia and so it states 64 KB, but the type of memory isn't specified ROM or RAM. At the same time on other sites, it is specified that RAM and ROM share the 64 KB address space, so 32 KB for RAM and 32 KB for ROM. At other places I saw that the maximum RAM space is 64 KB, hence there should be extra space for ROM.

I became very confused, and tried to open the Z80 datasheet directly, but due to my simple understanding, I couldn't get a rigid answer, but I found what's called a stack pointer which is holding a 16-bit address for external RAM plus there is a pin called MREQ which supposedly becomes active when the Z80 is using RAM. Now some evidence suggest that the Z80 could address a total 64 KB total ROM and RAM, and some suggest that is could address 64 KB ROM and 64 KB RAM, so 128 KB total for both of the memory types.

7
  • 6
    MREQ and IORQ distinguish memory-addresses from IO-addresses. It appears to be an error that MREQ means "RAM" access; I suppose the cause to be an assumption that "memory" and "RAM" are synonyms. If ROM and RAM were separate address-spaces, the instruction set would need to distinguish RAM-read from ROM-read: which address 1234h does "read from address 1234h" mean? – another-dave Nov 15 '20 at 18:34
  • 5
    The Z80 has total memory address space of 64kB, so the answer to your question would be no. However it can be filled with ROM and RAM as you see fit, and with some extra hardware to change memory mappings on the fly, you could set a 16k block in Z80 address space to be a window to a 16k block in a megabyte of memory. – Justme Nov 15 '20 at 18:52
  • To follow up, the GameBoy was run on a Z80 emulated chip. It used ROM banking to keep 2 pages in memory at all times (Page 0 always and then the Page 1 - whatever the max ROM size was on the other). The Color GameBoy did this for ROM and RAM to allow it to access 32k of RAM. Yes, only 64k of addressable space, but banking let you get around that without too much effort. The ROM sizes got up to around 1M towards the end of the life cycle... – Michael Dorgan Nov 17 '20 at 23:33
  • Some processors have an output pin that lets you differentiate between code spaces and data spaces, such as the 68000. The Z80 had no such distinction. – Mark Ransom Nov 18 '20 at 18:05
44

The Z80 has an address space of 64KB. That means it can perform 8 bit reads or writes to 65,536 distinct locations as specified by the 16 address pins on the CPU. As far as the Z80 is concerned that's all it knows about.

Now it's up to the system designer to decide which of those locations lead to RAM, which lead to ROM, which might lead to memory mapped peripherals and which lead nowhere. The CPU doesn't know the difference between them and it will happily try to write to ROM even though that has no effect. On a system like the original 48KB ZX Spectrum the first 16KB of the address space led to 16KB of ROM while the rest led to 48KB of RAM.

Of course this kind of arrangement doesn't need to be set in stone. Bank Switching is a design where you can change what is connected to different address ranges dynamically in response to a command (such as writing a bank number to a specially chosen address or port). The CPU still only has 64KB of address space but you swap what portions of that address space actually connect to.

The ZX Spectrum 128 had more than 64KB of RAM and used bank switching to let programs access all of it. So the first 16KB of the address space still led to ROM, the next 32KB still led to the same fixed RAM but that last 16KB could be switched in between operations to connect to any one of eight 16KB banks of RAM in the system (the 16KB ROM could also be switched between accessing the original BASIC and a new 16KB editor).

11
  • 1
    @MSalters: The Z80 has separate I/O space, so if one had a spare decode and used that to load data into a 4x4 register file, one could easily switch any of the four regions independently of the others by writing a 4-bit value to one of four I/O addresses. – supercat Nov 16 '20 at 15:12
  • 1
    Incidentally the way you bank switch old ROM is usually by writing to it. – Joshua Nov 16 '20 at 16:48
  • 4
    The Z80 has two address spaces, each of 64K. You could (in theory) attach memory to the I/O address space if you wanted. Obviously, it's less convenient to access this memory, and you couldn't directly run code stored in it. And (if you used the whole I/O space) you wouldn't have any means of interacting with the World... – Toby Speight Nov 16 '20 at 17:24
  • 2
    When I was like 13 years old, I had an idea how to make a Z80-based computer with preemptive multitasking and bankswitched RAM. Unfortunately I never built it. – md2perpe Nov 16 '20 at 18:02
  • 1
    @md2perpe Can you write down the design? It'd be really interesting – the ideas you have when first introduced to a concept can be better than your later ideas. (Some of the tricks involved might be novel.) – wizzwizz4 Nov 16 '20 at 20:24
12

TL;DR:

It's 64 KiB total in any combination imaginable.


Or more general:

The Z80 features

  • 16 address lines (A15..A0),
  • sufficient to address 64 KiB (via D7..D0),

which can be used to access one of two address spaces

  • default memory (with next to all instructions, indicated by /MREQ) or
  • I/O locations (with IN and OUT instructions, indicated by /IORQ).

Either address space can be filled at will with

  • RAM,
  • ROM,
  • I/O or
  • not at all.

Pick your choice.

(Not to mention swapping RAM/ROM/IO in and out by reconfiguration of address decoding - but that'll be design/machine specific and not due to CPU design)


In Detail:

Whenever I see how Memory a Z80 could address in many sites, Wikipedia and so it states 64KB, but type type of memory isn't specified ROM or RAM,

Because it's an address space of 64 Ki, independent of what is placed there.

I could understand that your confusion comes from modern SoC with separate channels for each use case. The Z80, like basically all classic CPUs offer only a single, generic bus for all types connected. All devices use the same interface. Selection is done by address decoding outside the CPU.

it is specified that RAM and ROM share the 64KB address so 32KB for RAM and 32KB for ROM,

Why does it have to be 32+32 KiB? Any split is possible. Some systems will have only a small 2-4 KiB Boot ROM, able to load some OS from an external media.

in other places I saw that maximum RAM space is 64KB, hence there should be extra space for ROM.

No, not necessary, as ROM may only be needed during boot and will be disabled after some OS is booted - the usual way for CP/M machines.

tried to open the Z80 datasheet directly [...] I found what's called a stack pointer which is holding 16bit address for external RAM

That's the software side. If you want to see how hardware is interfaced, you ned to look at the pins and their function. Like A15..A0 holding an address.

plus there is a pin called MREQ which supposedly becomes active when the Z80 is using RAM.

No, it's active when it accesses memory - independent of being RAM or ROM (or whatever). It distinguishes access to memory address space to I/O address space (marked by /IORQ).

Now some evidence suggest that the Z80 could address a total 64KB total ROM and RAM, and some suggest that is could address 64KB ROM and 64KB RAM so 128KB total for both of the memory types.

Now that would be nice to see that evidence. Because all I ever found is reference to a 16-bit address space that can be populated with anything.

13
  • 5
    I worked with a design where someone had the brilliant idea of using M1 to select between RAM and ROM, but unfortunately that will only really work if one doesn't mind using a very constrained portion of the Z80 instruction set. It may be useful to have M1 accesses to a region of storage trigger actions that would not be triggered by a non-M1 access (e.g. on a system with two ROM chips, one of which is always enabled but separated from the bus by a 3-state buffer which would be enabled when accessing the chip, say that an M1 access to... – supercat Nov 15 '20 at 21:05
  • 2
    @Tommy: The problem with using M1 as an address selector is that it is only driven during an opcode fetch, and is not driven during operand fetches. Thus, if one tried to execute a JMP from ROM address 1234h, the opcode would be fetched from address 1234h of ROM, but the new program counter value would be fetched from addresses 1235h and 1236h of RAM. – supercat Nov 15 '20 at 22:03
  • 1
    And, as an aside, I don't understand the downvote for this answer, unless somebody thinks the TL;DR may be misleading given bank switching? Given that the question is about what can be addressed by the Z80, not what external hardware can do to adjust what sits at each address I wouldn't support a negative reaction for that. So something else? – Tommy Nov 15 '20 at 22:34
  • 1
    You're both right - it's a quite easy method on both CPUs. Have implemented it for a 6502 system already in the 1980s. – Raffzahn Nov 15 '20 at 22:35
  • 1
    @supercat I would have to look it up for the Z80, but for 6502 it doesn't need a ROM, just a bit of decoding. All xxxx.0xxx are decoded as 2 cycles of code fetch, all xxxx.1xxx as 3 cycles, except xxxx.10x0 being 1 cycle and xxx1.1001 being 3 cycles. Everything thereafter is data access, so no state machine, just cointing 1,2,3 :) After that, only JSR needs to be taken account for, as it's the only one with a mixed sequence (code, data, data, code, data) ... caveat, this is from memory, so I may have missed some detail. – Raffzahn Nov 16 '20 at 2:05
5

We had a clone of ZX Spectrum called Didaktik Gama (with single m indeed). It had 16kB ROM and 80kB RAM total. As all Z80 based computers, it had 16bit address space - addresses 0 - 65535, with memory mapping like this:

Address          Contents
0 - 16383        16kB ROM (BASIC)
16384 - 32767    16kB RAM (starting with video memory)
32768 - 65535    two switcheable 32kB RAM banks (0 and 1)

Upon boot there was a default bank 0 mapped, and it was up to user to "manually" switch to the second bank. The data in the bank 1 survived reboot! That was a luxury back then, when normally you'd have to spend like 3-5 minutes after each reboot to load your programme from tape cassette. So many times, I just loaded my assembler development environment (I chose address above 32768 to load it) into bank 1 and it just stayed there (until a physical power off :)). If my assembler program screwed up, I just rebooted the computer, switched to bank 1 and everything was already there! Didn't have to wait 5 minutes again till my assembler environment loads from tape cassette :-)) Big luxury back then.

I didn't work with ZX Spectrum 128, but according to the description here it had 128kB RAM (not including ROM) and it used similar bank switching principle, just using the top 16kB address space (instead of 32kB) to switch between extra 16kB banks (scheme from the above link):

enter image description here

I personally preferred the 32kB banks because I had 32kB of continuous RAM safe from any reboot :-)

2
2

Yes, it could, with some help :)

I had an oddball CP/M (Z80) machine that had additional logic that let you switch at runtime between a Harvard and Von Neumann memory addressing. It had 128kB of RAM (and a little bit of EPROM overlapping some of it), and both 64kB address spaces could be used simultaneously when in the Harvard mode: you had independent 64kB of code space, and 64kB of data space.

On Z80, opcode fetches are signaled by asserting the M1 output signal. There was some discrete logic state machine that used M1 along with the contents of the data bus (i.e. the opcode(s)) to determine which operands came from the machine instructions (immediate operands and displacements), and which were actual data loads/stores. The output of that state machine classified each memory access as either code fetch (immediate operands/displacements) or data load/store.

There were a couple bits in configuration registers that let you customize this - it was quite flexible, in spite of how little logic was used to implement it. There were three kinds of accesses on CPU side: code, data, and I/O, and each could be mapped to any of the address spaces: code space, data space, or I/O space. The I/O accesses couldn't be mapped to the data space IIRC, since that'd be useless.

One of the configuration registers was used when within an interrupt handler, the other at all other times - the state machine used the /INT pin and opcode monitoring to determine when an ISR was entered and exited, to select the proper config register.

The default configuration provided 192kB of non-banked address space, split between three address classes: 64kB of code space, 64kB of data space, and 64kB of I/O space. The code and data spaces each had 64kB of dedicated RAM mapped to them, with some of both spaces also overlapped by EPROM, so that you could store both data and code in the EPROM.

There was no other memory banking, i.e. the RAM was always evenly split between the code and data address spaces. Two of the unused/invalid opcodes had special treatment by the state machine: a NOP would be placed on the data lines, and a "code space override" or "data space override" was latched, so that the subsequent instruction would do all accesses from that space no matter what was configured. This effectively added two prefixes not unlike segment override opcodes on 8086 - likely that was where the inspiration came from, I guess.

2
  • "some discrete logic state machine" probably includes some serious ugliness! – Toby Speight Nov 27 '20 at 16:34
  • I guess if you’d write it down as logic equations, it wouldn’t be super complex, but still… I bet there was some bipolar 74 series PROM or two to cut down on combinatorial logic. I vividly recall that there weren’t all that many chips on that CPU board, and no PALs were in use either - it was a classic “if it’s not in the TI Databook then it doesn’t exist” kind of a thing. But I was used to seeing big cards with over a hundred LSI chips on them, so my recollection may we’ll be colored by that. – Kuba hasn't forgotten Monica Nov 27 '20 at 17:45
1

Practically, you could map 64k of memory into the I/O space but you couldn’t execute code from it since it requires special op codes to read/write. A typical application might be to store an audio recording and then read it out one sample at a time. Even with 1980s 8-bit sampling and 8ksps playback you’d have room for only 8 seconds of audio, but might be enough for some dings and beeps for a video game.

0

I owned a 128kb TRS-80 Mod IV.

64kb was available at any one time. There was a port you could write to that would swap in either of the extra 32kb banks in place of the normal ones--I forget all the details by now.

In practice the only safe way to handle it was to disable interrupts (which means you couldn't do it for too long), swap it in, do whatever you needed to with the data there and swap it back out. You had to ensure you code wasn't in the swap region and that your stack wasn't in the swap region. Thus it was realistically only useful as data space, you couldn't run code from it.

You could, however, store code there. One of the most useful things I did with it was write a program that would on boot load all the swappable OS pieces into the upper bank, then intercept the call to load them and bring them in from memory instead. (Some rather tricky coding as resident programs normally lived at the top of memory, but the OS swaps were fairly low in memory--there was no place to swap the bank to. I ended up writing the loader as a normal program and the part it left behind was partially written in a small hole in OS memory and partially overwriting part of the OS swapper that was no longer needed.)

-2

The Z80 had a total address space of 128K, but one had to be very careful with ones coding. There was an early "multimedia" computer from- I think- Sony, which had a Z80, 128K of memory, and an optical disc.

This is from memory, but I was given chapter and verse on this a number of years ago by somebody who'd (professionally) written games for Z80-based systems.

The majority of opcodes assumed direct access to 64K of memory space (RAM+ROM with some arbitrary split, or with ROM only visible at boot, or with some form of bank switching).

In addition, the I/O opcodes were documented as handling 256 (2^8) port addresses, but in actual fact there was an indirect mode which handled 64K (2^16) port addresses... I think there was something odd in there like the indirection being nibble-swapped.

The Sony system (and perhaps some others) used this to support 128K of memory. I don't know what the performance was like, and I don't know how it handled I/O ports.

I note the older discussion at Z80 16-bit I/O port addresses which deals fairly concisely with 16-bit port address issue. Google etc. has a lot of noise relating to the the Spectrum 128K, I don't know how the extra memory on that was addressed but generally speaking it looks as though the port address bits were used for the keyboard etc.

9
  • 2
    128K memory was nothing the Z80 processor by itself could access without some sort of memory banking system. A Z80 based system with memory banking might. It might even access more. – UncleBod Nov 16 '20 at 15:53
  • @UncleBod Disagree, read my answer. I'm afraid that I don't have a model name, but it was featured (cover art etc.) in Personal Computer World circa 1980. – Mark Morgan Lloyd Nov 16 '20 at 16:54
  • 1
    Re "The Z80 had a total address space of 128K": I think that is too much of a stretch of the word address space. A possible 65636 I/O ports used for memory reads/writes instead of actual physical I/O. – Peter Mortensen Nov 16 '20 at 17:43
  • 2
    @UncleBod: Using a 16-bit I/O port space makes it possible without bank switching (effectively using MREQ / IORQ as the 17th address line). The actual I/O could go to actual I/O ports. And using two sets of instructions for accessing the lower and upper part of memory. – Peter Mortensen Nov 16 '20 at 17:55
  • Perhaps qualify the 128 KB right at the beginning? Otherwise it reads as if you are claiming a 17-bit linear memory address space. E.g., the second half can only be used for data, not executing code in. – Peter Mortensen Nov 16 '20 at 18:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.