NEO-ZMC
Package | SOIC24 |
Manufacturer | |
First use | 1995 ? |
Used on | cartridges |
Z80 Memory Controller. Provides a hardwired 32KiB bank and switchable 16, 8, 4, and 2KiB banks arranged as a register file. To save pins, the Z80's upper address lines (A15~A18) are used for data input. The chip's write strobe is port address decoded inside the system.
Pinout
Pins 10, 11, 12 are certainly not connected since the addressing scheme doesn't allow mapping over 512KiB.
- SDA0, SDA1, SDA8~15: Z80 address bus
- M1 A11~M1 A18: M1 ROM address lines
- SDRD0: Decoded write signal from NEO-D0 (latch on rising edge)
Operation
SDA8~15 is used for the bank number (data), SDA0 and SDA1 for selecting the bank zone.
SDA1 | SDA0 | Z80 port | Bank zone | Address range | Size | Latch size |
---|---|---|---|---|---|---|
0 | 0 | $08 | 0 | $F000~$F7FF | 2KiB | 8 bits |
0 | 1 | $09 | 1 | $E000~$EFFF | 4KiB | 7 bits |
1 | 0 | $0A | 2 | $C000~$DFFF | 8KiB | 6 bits |
1 | 1 | $0B | 3 | $8000~$BFFF | 16KiB | 5 bits |
Details
SDRD0 must be high before configuring banks.
To configure a bank to be accessed (e.g. bank 0 in the $8000~$BFFF range):
- Set SDRD0 low (prepare for new bank configuration, outputs are tri-stated)
- Set SDA0~15 = $8003 (select bank 0 and 16k range size) Why $8003 and not just $0003 ?
- Set SDRD0 high (latch bank, ready to convert inputs to proper output signals)
- Now, when the Z80 reads the $8000~BFFF range, NEO-ZMC will map this to the M1 ROM zone $00000~$03FFF;
To configure a bank to be accessed (e.g. bank 1 in the $8000~$BFFF range):
- Set SDRD0 low (prepare for new bank configuration, outputs are tri-stated)
- Set SDA0~15 = $8103 (select bank 1 and 16k range size) Why $8103 and not just $0103 ?
- Set SDRD0 high (latch bank, ready to convert inputs to proper output signals)
- Now, when the Z80 reads the $8000~BFFF range, NEO-ZMC will map this to the M1 ROM zone $04000~$07FFF;
Logic definition
Not tested.
reg [7:0] WINDOW_0; reg [6:0] WINDOW_1; reg [5:0] WINDOW_2; reg [4:0] WINDOW_3; assign MA = (!SDA[15]) ? {4'b0000, SDA[14:11]} : // Pass-through (SDA[15:12] == 4'b1111) ? WINDOW_0 : (SDA[15:12] == 4'b1110) ? {WINDOW_1, SDA[11]} : (SDA[15:13] == 3'b110) ? {WINDOW_2, SDA[12:11]} : {WINDOW_3, SDA[13:11]}; always @(posedge nSDRD0) begin case (SDA[1:0]) 0: WINDOW_0 <= SDA[15:8]; 1: WINDOW_1 <= SDA[14:8]; 2: WINDOW_2 <= SDA[13:8]; 3: WINDOW_3 <= SDA[12:8]; endcase end