[[File:crt_zmc.jpg|right|thumb|NEO-ZMC chip on a MVS [[cartridges|cartridge]]. Picture courtesy of [[http://www.mvs-scans.com MVS-Scans]].]]
{{ChipInfo
|picture=crt_zmc.jpg
|pkg=SOIC24
|manu=fujitsu
|date=1995 ?
|gates=
|used_on=[[cartridges]]
}}
Z80 memory controller. Has a hardwired 32KiB bank and switchable 16/8/4/2KiB banks arranged as a register file. To save pins the high address lines (A15-A8) are used for data input. The chip's write strobe is (port) address decoded inside the console.
{{Chipname|Z80}} '''M'''emory '''C'''ontroller. Handles the [[Z80]] bankswitching in cartridges. To save pins, the Z80's upper address line are also used as data input. The chip's write strobe SDRD0 is [[Z80 port map|port]] address decoded inside the system.
=Pinout=
=Pinout=
[[File:Neo-zmc_pinout.png]]
OpenOffice Draw file: [[File:neo-zmc.odg]]
{{Pinout|NEO-ZMC|512}}
=Operation=
Pins 10, 11, 12 may be M1 higher address bits ?
SDA10,SDA9,SDA8 are the bank selector and SDA1,SDA0 is the bank size selector
* SDA0, SDA1, SDA8~15: Z80 address bus
* M1 A11~M1 A18: [[M1 ROM]] address lines
* SDRD0: Decoded write signal from {{Chipname|NEO-D0}} (latch on rising edge)
SDA1,SDA0 = 0,0 select bank ranges of 2Kbytes (64k M1)
=Operation=
SDA1,SDA0 = 0,1 select bank ranges of 4Kbytes (128k M1)
SDA8~SDA15 are used for the bank number (data), SDA0 and SDA1 for selecting the window.
SDA1,SDA0 = 1,0 select bank ranges of 8Kbytes (256k M1)
SDA1,SDA0 = 1,1 select bank ranges of 16Kbytes (512k M1)
SDRD0 is the memory operation selector WRITE (set bank and range size) / READ (access M1 based in previous configuration)
'''Details:'''
We must put SDRD0 is in high logic level before configure any bank;
To configure a bank to be accessed (e.g. bank0):
Set SDRD0 from H to L (prepare for new bank configuration, let output in tri-state and accept inputs)
Set SDA[15..0] = '''$8003''' (select bank 0 and 16k range size)
Set SDRD0 from L to H (fix bank, and ready to convert inputs in proper outputs signals)
With SDRD0 in H, send inputs SDA[15..0] from '''$8000~BFFF''', ZMC will convert this range in M1 range from '''$00000~$03FFF''';
Set SDRD0 from H to L (prepare for new bank configuration, let output in tri-state and accept inputs)
Set SDA[15..0] = '''$8103''' (select bank 1 and 16k range size)
Set SDRD0 from L to H (fix bank, and ready to convert inputs in proper outputs signals)
With SDRD0 in H, send inputs SDA[15..0] from '''$8000~BFFF''', ZMC will convert this range in M1 range from '''$04000~$07FFF''';
Set SDRD0 from H to L (prepare for new bank configuration, let output in tri-state and accept inputs)
Set SDA[15..0] = '''$8203''' (select bank 2 and 16k range size)
Set SDRD0 from L to H (fix bank, and ready to convert inputs in proper outputs signals)
With SDRD0 in H, send inputs SDA[15..0] from '''$8000~BFFF''', ZMC will convert this range in M1 range from '''$08000~$0BFFF''';
Set SDRD0 from H to L (prepare for new bank configuration, let output in tri-state and accept inputs)
Set SDA[15..0] = '''$8303''' (select bank 3 and 16k range size)
Set SDRD0 from L to H (fix bank, and ready to convert inputs in proper outputs signals)
With SDRD0 in H, send inputs SDA[15..0] from '''$8000~BFFF''', ZMC will convert this range in M1 range from '''$0C000~$0FFFF''';
... and so on...
[[File:Neo-zmz operation.png|right|thumb]]
{|class="wikitable"
{|class="wikitable"
!DWORD (SDA[15..0])
!SDA1
!BANK
!SDA0
!INPUT RANGE (SDA[15..0])
!Z80 port
!OUTPUT RANGE (A[18..0])
!Window
|-
!Address range
|$8003
!Size
|bank 00
!Latch size
|$8000~$BFFF
|$00000~$03FFF
|-
|$8103
|bank 01
|$8000~$BFFF
|$04000~$07FFF
|-
|$8203
|bank 02
|$8000~$BFFF
|$08000~$0BFFF
|-
|$8303
|bank 03
|$8000~$BFFF
|$0C000~$0FFFF
|-
|$8403
|bank 04
|$8000~$BFFF
|$10000~$13FFF
|-
|$8503
|bank 05
|$8000~$BFFF
|$14000~$17FFF
|-
|$8603
|bank 06
|$8000~$BFFF
|$18000~$1BFFF
|-
|$8703
|bank 07
|$8000~$BFFF
|$1C000~$1FFFF
|-
|$8803
|bank 08
|$8000~$BFFF
|$20000~$23FFF
|-
|$8903
|bank 09
|$8000~$BFFF
|$24000~$27FFF
|-
|$8A03
|bank 10
|$8000~$BFFF
|$28000~$2BFFF
|-
|$8B03
|bank 11
|$8000~$BFFF
|$2C000~$2FFFF
|-
|$8C03
|bank 12
|$8000~$BFFF
|$30000~$33FFF
|-
|$8D03
|bank 13
|$8000~$BFFF
|$34000~$37FFF
|-
|$8E03
|bank 14
|$8000~$BFFF
|$38000~$3BFFF
|-
|$8F03
|bank 15
|$8000~$BFFF
|$3C000~$3FFFF
|-
|$9003
|bank 16
|$8000~$BFFF
|$40000~$43FFF
|-
|$9103
|bank 17
|$8000~$BFFF
|$40000~$47FFF
|-
|$9203
|bank 18
|$8000~$BFFF
|$40000~$4BFFF
|-
|$9303
|bank 19
|$8000~$BFFF
|$40000~$4FFFF
|-
|$9403
|bank 20
|$8000~$BFFF
|$50000~$53FFF
|-
|$9503
|bank 21
|$8000~$BFFF
|$54000~$57FFF
|-
|$9603
|bank 22
|$8000~$BFFF
|$58000~$5BFFF
|-
|$9703
|bank 23
|$8000~$BFFF
|$5C000~$5FFFF
|-
|$9803
|bank 24
|$8000~$BFFF
|$60000~$63FFF
|-
|$9903
|bank 25
|$8000~$BFFF
|$64000~$67FFF
|-
|$9A03
|bank 26
|$8000~$BFFF
|$68000~$6BFFF
|-
|$9B03
|bank 27
|$8000~$BFFF
|$6C000~$6FFFF
|-
|-
|$9C03
|0||0||$08||0||$F000~$F7FF||2KiB||8 bits
|bank 28
|$8000~$BFFF
|$70000~$73FFF
|-
|-
|$9D03
|0||1||$09||1||$E000~$EFFF||4KiB||7 bits
|bank 29
|$8000~$BFFF
|$74000~$77FFF
|-
|-
|$9E03
|1||0||$0A||2||$C000~$DFFF||8KiB||6 bits
|bank 30
|$8000~$BFFF
|$78000~$7BFFF
|-
|-
|$9F03
|1||1||$0B||3||$8000~$BFFF||16KiB||5 bits
|bank 31
|$8000~$BFFF
|$7C000~$7FFFF
|}
|}
==Details==
[[File:Neo-zmz_operation.png|thumb]]
SDRD0 must be high before configuring banks.
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 16KiB bank 1 in window 3 (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'''
Z80Memory Controller. Handles the Z80 bankswitching in cartridges. To save pins, the Z80's upper address line are also used as data input. The chip's write strobe SDRD0 is port address decoded inside the system.