The eZ80 has 24 address lines, giving a maximum 16M address space. The CPCNG will use 4M blocks in the CPCNG mode. Each 4M region of the 16M address space is mapable to any of 256 4M blocks in the large SDRAM. This gives a maxmimum possible memory size of 1G, though CPCNG users will themselves decide how much memory they want to buy, so the OS must be capable of detecting memory size and operating with whatever is available. Addressing 1 GByte requires 30 address lines. The CPCNG is even able to function when NO main memory is present on the board, in this case it still runs in the CPC mode, with 128 RAM provided by the video RAM.
The mapping takes place as follows:
In CPCNG mode, there are four 8-bit registers CPCNGA0 - 3, one for each of the 4M blocks in the 16M eZ80 address space. These registers reside in the FPGA and are written using I/O ports &0018-&001B. The lower 22 address lines of the eZ80 address bus, a0 - a21 connect directly to the memory. During memory access the upper 2 lines a22 and a23 select one of the 4 8-bit banking registers. The output 8-bits of the selected register drive address lines a22 - a29 of the large memory.
CPCNG mode summary:
|a0 - a21
||from a0 - a21 of CPU
|a22 - a29
||from 1 of 4 banking registers CPCNGA0 - 3, selected by a22 and a23 of CPU
In the CPC mode, the eZ80 is in native Z80 mode and resets a16 - a23 of its address bus to '0'. In this mode, a0 - a13 still drives the memory directly. a22 and a23 are '0' and therefore in CPC mode only the lowest 4M block of the 16M address space is used. All 16K memory blocks that are used for the CPC mode must therefore exist in the same contiguous 4M block of memory, but that can be any 4M block chosen from the entire memory. One 4M block contains 256 16K CPC blocks.
In CPC mode, four 8-bit FPGA registers CPCRDA0 - 3 on I/O ports &0010-&0013 select four 16K blocks for reading from memory. a14 and a15 of the eZ80 address bus select one of these 4 registers which drives address lines a14 - a21 of the main memory. Therefore each of the 4 16K sections of the native Z80 mode 64K address space can be mapped for reading from any of 256 16K blocks of the selected 4M block from main memory.
Similarly, another four 8-bit registers CPCWRA0 - 3 on I/O ports &0014-&0017 select 4 16K blocks for writing to memory.
The reason for having separate registers for the reading and writing memory maps is that in a real CPC, if the ROM is mapped to a particular 16K block, reading takes place from ROM but writing to addresses in the block writes to the underlying RAM. In the CPCNG in CPC mode, I allow different parts of memory to be used for reading and writing for each of the 16K blocks. If a 16K block was to be used as ordinary RAM, the read and write registers would contain the same value. If a 16K block of the CPC was to be mapped as ROM, any 16K block of the main memory can be used for that ROM, and a different 16K block for the RAM at that location.
All of the CPC memory mappings are available using this method (100% compatibility), and it is possible to accomodate without too much difficulty in hardware, peacefully coexisting with the larger available memory and CPCNG mode mapping. Crucially, when an I/O occurs in CPC software, this will be handled by the I/O intercept trick: a /NMI (non maskable interrupt) is generated, calling routine at &0066. This will decode the CPC I/O request and in the case of memory mapping I/O, translate the old-style codes as documented at http://andercheran.aiind.upv.es/~amstrad/, to the necessary values for the 8 CPC-mode memory map registers CPCRDA0 - 3 and CPCWRA0 - 3.
CPC mode summary:
|a0 - a13
||from a0 - a13 of CPU
|a13 - a21
||READ: from 1 of 4 banking registers CPCRDA0-3, WRITE: from 1 of 4 banking registers CPCWRA0-3, selected by a22 and a23 of CPU
|a22 - a29
||from NG-mode banking register CPCNGA0
Below is my draft circuit diagram for the mapping unit using equivalent TTL 74LS-series part numbers. The multiplexer switches A14-A21 of the memory address bus from A14-A21 of the CPU address bus in CPCNG mode to the outputs of the CPC-mode mapping registers.
What of the video RAM? The 128K of video RAM can appear at any desired location in the 16MByte address space of the eZ80, on a 128K boundary. An 8-bit register VRAMA on port &001C selects this location. Bits d0 - d6 of VRAMA specify the 128K block (address lines a23 - a29) where the 128K VRAM will appear. Bit d7 will be '1' to disable the VRAM (but the CRTC still accesses it), bit d7 will be '0' to map the VRAM to the 128K block specified by the 7 bits d0 - d6. A comparator in the FPGA compares a23 - a29 with bits d0 - d6 of VRAMA, and selects the VRAM chip instead of main memory if there is an exact match. Effectively the 128K VRAM replaces main memory at the 128K block where it is mapped. When the CPU reads or writes to any address within the 128K block allocated VRAM, the request is routed to the VRAM rather than main memory. In CPC mode, the 128K VRAM should simply be mapped to a convenient 128K block in the first 4 MBytes of the eZ80 address space. The contents of CPCRDA0 - 3 and CPCWRA0 - 3, and the programming of the CRTC itself, take care of exactly replicating the CPC mode address map.
Arbitration of the video RAM between the CPU and CRTC is a separate matter that will be discussed elsewhere (/BUSREQ etc).
The CPCNG must also have a boot ROM. It will have a 128K EEPROM, this is more than enough to contain the boot code, and also if desired the 16K of CPC OS ROM, and 16K of CPC BASIC ROM. Similar to the way the VRAM is mapped, the 128K ROM will be mapped by bits d0 - d6 of another 8-bit I/O register called ROMA, appearing on I/O port &001D. Bit 7 = '1' disables the ROM. Any read in that 128K block will be routed from the ROM rather than main SDRAM memory. Likewise in CPC mode, the ROM can be mapped somewhere convenient in the lower 4M of the eZ80 address space, the contents of CPCRDA0 - 3 and CPCWRA0-3 taking care of exactly replicating the CPC memory map. At switch on, the ROM appears at &000000 so that boot can occur from it.
The CPC ROMs do not have to be in the CPCNG ROM. Instead it would be equally possible to have them loaded into RAM from the hard drive. The mapping registers allow the CPC ROM to be located in main memory if required.
This ROM must contain meaningful code at &0066 to handle the I/O intercept trick (/NMI). When in CPC mode an I/O attempt occurs, the hardware immediately switches the ROM bank to appear at &000000 so that the I/O intercept routing can operate. On returning from the /NMI call, the hardware returns the ROM bank to its programmed location as specified by ROMA.
Below is my draft circuit diagram for the memory select generator using equivalent TTL 74LS-series part numbers. The two registers hold the location to map the ROM and Video RAM. A match occurs when bits 0-6 of the stored value match A23-A29 of the CPU address bus, bit 7 must also be zero (compared against a hard-wired '0'). The output gating ensures that only one select is activated at a time. In case of conflict (both VRAM and ROM mapped to the same location) the preference is ROM then VRAM then main memory.
Summary of I/O registers for memory mapping:
||1 of 256 16K blocks for READ at &0000-&3FFF
||1 of 256 16K blocks for READ at &4000-&7FFF
||1 of 256 16K blocks for READ at &8000-&BFFF
||1 of 256 16K blocks for READ at &C000-&FFFF
||1 of 256 16K blocks for WRITE at &0000-&3FFF
||1 of 256 16K blocks for WRITE at &4000-&7FFF
||1 of 256 16K blocks for WRITE at &8000-&BFFF
||1 of 256 16K blocks for WRITE at &C000-&FFFF
||1 of 256 4M blocks for &000000-&3FFFFF
||1 of 256 4M blocks for &400000-&7FFFFF
||1 of 256 4M blocks for &800000-&BFFFFF
||1 of 256 4M blocks for &C00000-&FFFFFF
||Location of 128K Video RAM mapping
||Location of 128K ROM mapping