Ruud's Commodore Site: 74LS612 - MMU Home Email

74LS612 - MMU

What is it?

The 612 is an MMU, Memory Management Unit, which enables you (in this specific case) to expand your system with 8 extra address lines. For example, a Commodore 64 or VIC-20 could be expanded up to 16 MB!

Notify the fact that I use the word "system" and NOT processor! The processor itself won't be aware at all of those extra address lines, it is the Operating System that must handle all the extra address space. Seen from the outside, the processor will only see parts of the complete configuration.
This is realized by feeding a part of the address lines to some very fast RAM. This RAM outputs the new address lines. In case of the 612 it is 4*12 bits ie. 16 registers of 12 bits each.

How does a MMU work?

If you own a C64 then this is easier to understand. It has 64 KB of RAM, 4 KB of I/O and at least 20 KB of ROM. But the 6510 has a 16 bit address bus and therefore is only capable of addressing 64 KB. How do these numbers match? Many programmers know that they can read the contents of the RAM "under" the BASIC or KERNAL ROM but cannot access that ROM at the same time: it is either RAM or ROM but not both!
A more experienced user knows that the I/O registers of the 6510 and the PLA give the C64 the ability to handle more memory then the processor itself is capable of. This ability to switch between various parts of memory or I/O is called 'Bank switching'.

The 74LS612 does about the same but is much more flexible: it does not only give you the capability of bank switching but also allows you to decide where which part of the memory or I/O should show up.

How do these 8 extra address lines fit in the system?

As said before, the 612 has 16 registers of 12 bits each. The normal procedure is to address these registers using the four most significant address lines; in case of a 6510 the address lines A12..A15.
The 12 bits represent the 12 address lines the 612 can output. Four of those lines (can) reflect the state of the four originally attached address lines. The other eight are the extra eight address lines.
Every bit can be programmed as the user wishes, meaning that the four bits reflecting the original address lines can completely differ from the original values. Reconfiguring the original address lines gives you the ability to rearrange the original configuration of the memory map. For example: one cannot use the RAM under the Kernal ROM to test a new one; the reset procedure resets the I/O register of the 6510, thereby disabling the RAM under the ROM. Skipping this particular routine is a possibility but then this Kernal would not be really the real thing. With a MMU you could swap the range $8000/$9FFF with $E000/$FFFF. As the Kernal has no knowledge of the existence of the MMU, it won't reset it and the 6510 will run the new Kernal in $8000/$9FFF as if it was in $E000/$FFFF. But be aware: this will only work with jumping to the new Kernal under software (also called: soft reset); a hard reset can reset 612 as well and then the 6510 will see the original Kernal as well.

But a remark is on its place here: reconfiguring the original memory map does not mean that you are now able to place the CHAR-ROM at $2000 and the I/O on $4000. With the MMU you move address ranges, not specific hardware. In the above example of swapping the Kernal it also means there is no RAM under the new Kernal. So you cannot test a new Kernal with a program which normally uses the RAM under ROM. In this case the program will overwrite the Kernal for sure with all devastating effects!

An idea how to use the MMU.

The extra eight lines can be used to add extra memory (RAM, ROM) or I/O in any way you want. One idea what I have in mind is to connect a complete 1541 to my CBM 3032 by means of a small interface which replaces the 6502 of the 1541. This interface is addressable from $01000 to $01FFFF. Now it should be possible to run a program that first loads the new Kernal into memory range $4000/$7FFF and then reconfigures the 3032 in such a way that the 6502 sees the range $0000/$1FFF of the 1541 as its own $0000/$1FFF range and its own range $4000/$007FFF as $C000/$FFFF. The last action is a jump to the new Kernal and the CBM should now behave like a 1541.
This method allows you to test a new Kernal for the 1541 in a very comfortable way. (The originator of this idea is Andre Fachat, Leipzig, Germany)
Remark to this idea: it made sense when I had to work with EPROMs that took time to be programmed and even more time to be erased. Now I use EEPROMs that can be reprogrammed in a matter of seconds.

The moment you rearrange the internal configuration, you have to take care of one important thing: make always sure you have access to the MMU! The reason is very simple: once you have placed the MMU out of the memory map, you won't be able to change its configuration anymore and you are stuck with the momentary one for "the rest of your life".

Pin outs

   RS2   -+  1               40 +-   +5V
          |                     |
   MA3   -+  2               39 +-   MA2
          |                     |
   RS3   -+  3               38 +-   RS1
          |                     |
  /CS    -+  4               37 +-   MA1
          |                     |
/STROBE  -+  5               36 +-   RS0
          |                     |
   R/W   -+  6               35 +-   MA0
          |                     |
   D0    -+  7               34 +-   D11
          |                     |
   D1    -+  8               33 +-   D10
          |                     |
   D2    -+  9               32 +-   D9
          |                     |
   D3    -+ 10               31 +-   D8
          |      74LS612        |
   D4    -+ 11               30 +-   D7
          |                     |
   D5    -+ 12               29 +-   D6
          |                     |
   MM    -+ 13               28 +-   NC / C (see text)
          |                     |
   MO0   -+ 14               27 +-   MO11
          |                     |
   MO1   -+ 15               26 +-   MO10
          |                     |
   MO2   -+ 16               25 +-   MO9
          |                     |
   MO3   -+ 17               24 +-   MO8
          |                     |
   MO4   -+ 18               23 +-   MO7
          |                     |
   MO5   -+ 19               22 +-   MO6
          |                     |
   GND   -+ 20               21 +-   /ME
          |                     |

Pin functions:
D0 through D11    =  Connection to the data bus when programming the registers 
RS0 through RS3   =  Connection to the address bus when programming the registers,
                     normally A0 through A3
R/W               =  Read, active (H) and Write, active (L)
STROBE            =  input to enter data into chosen register, active (L) 
CS                =  chip select, active (L)
MA0 through MA3   =  input, to be connected to the address bus of the processor.
                     These inputs choose an internal 12-bits register.
MO0 through MO11  =  The generated address lines
MM                =  Map Mode input. When (H), MO8/MO11 reflect MA0/MA03 and
                     MO0/MO7 are (L). When (L), MO0/MO11 reflect the 12 bits of
                     the chosen register.
ME                =  When (H), MO0/MO11 are tristate else active.
NC                =  Not connected.

74LS610, 74LS611 and 74LS613.

The 610 is like a 612 but has an extra 12 bits latch at its outputs. So with the 610 you can freeze the output as long as you want. This is archived with an extra input line at pin 28, C (= Clock). A (H) on this input will the 610 cause to behave like a 612, a (L) freezes the configuration.
The 611 and 613 are the Open Collector versions of the 610 and 612.

The 12 bit registers of the 74LS612 - part 1

The intention is to use the MMU in combination with a 65xx based Commodore. But as you know the 65xx's are all 8-bitters and the 612 is a 12-bitter. This means we either have to disregard 4 bits or use a trick to be able to use all 12 bits. In the first case we are still able to address up to 1 MB of memory or I/O. If you still want have those extra 4 bits then a simple 74LS573, 8-bit latch, can do the trick. Of course you'll need a decoder for this 573. But as you need one for the MMU as well, it won't be that much difficult to combine them into one decoder. (for more details, see part 2)

Connecting the MMU to a 6502.

Connecting a MMU to a 6502 can be split up in two parts anyway:
- the memory part
- the I/O part

Memory part
If you only want to reconfigure your system within its own 64 KB, then you only have to "cut" the address lines A12 through A15 and to place the MMU in the created gap. Practically this probably means you replace the processor by a small circuit board with onboard the original processor, the MMU and some logic to perform I/O operations with the MMU.
If you want to use the extra address lines as well, you have to take care of the fact that the original hardware does not know of the addresses above $00FFFF. So for any decoder on the original system reading from/writing to $01C000, $02C000 or any address above $00FFFF is equal to reading from/writing to the address $0C000. There are two solutions for this problem:
- Include the original decoder
- Fool the original system

Include the original decoder
The C64 uses an 82S100 PLA as decoder. This IC has a CS line of its own but it is tied to Ground. Tying this line to a decoder, which decodes the address lines above A15, solves the problem.

Fooling the original system
Sometimes the above solution is impossible due to the way the decoding is done. In case of the CBM 8032 the range from $8000 to $FFFF is decoded by a 74LS154. But the range below $8000 is decoded by gates. This simply means that you have a lot of soldering to do.
With "fool the system" we force the original system to read a safe address during the time the processor is handling an address above $0FFFF. AFAIK a safe address for all Commodores is $FFFF. But reading implies outputting data, which we have to shield from the processor. This can be realized by using a buffer like the 74LS245. The fake address is realized by placing buffers in the address lines between the original system and the processor/MMU. Using $FFFF has the advantage that we only need some pull-up resistors to generate this address the moment the bus is disabled.

I/O part
Another decision to be made is where to place the address decoding of the MMU in the memory map: behind or before the MMU itself. If you place it before the MMU it always will be accessible but the disadvantage is that it can get in the way when there is a need to remap certain areas to the area the MMU occupies. If you place it behind the MMU and you make a mistake with programming the MMU, it is possible you cannot access the MMU anymore meaning you are stuck with the momentary configuration unless you reset your system.

Enabling the MMU.

Negating the "Map mode" input enables the function of the MMU. So we need at least a programmable 1-bit register. But it is a MUST that its output always is (H) after a reset. A 74LS74 could do the trick. Connect its Preset input with the reset line, the data input with a data line and clock input with an active (L) chip select line. If you intend to use all 12 bits, this 74 can be placed parallel to the used 573.

The 12 bits registers of the 74LS612 - part 2

We already know we have to provide four extra data bits for the MMU. We also need a bit for enabling the MMU mode. As said a 74LS573 could do the trick but only using a 573 means we cannot check in one or another way what we actually have written to the MMU. We could add a 74LS541 buffer to solve a part of the problem but in that case I propose to use a CIA, PIA, VIA, PIO or other equivalent type of IC. Which type you use partly depends on the processor used in the system.
One advantage of using such IC is that you have much more functionality then when using the 573/541 combination. Another advantage is that one I/O line can be used for steering the "Map Mode" input of the MMU. I will use the 6522 VIA as example from now on.
Now we are able to read the data written towards the MMU but we are still not able to read the contents of all bits of the 16 registers of the MMU. Luckily I found a solution where we only need an extra 573 and inverter. The input and outputs of four bits of the 573 are connected to the four I/O lines responsible for the four extra bits of the MMU. The data on these lines is latched every time the /CS input of the MMU is enabled (the 04 inverts this CS signal to the right level for the clock input of the 573). An I/O line of the 6522 takes care of dis/enabling the output of the 573.
- The moment we want the 65xx to write towards the MMU, the output of the 573 must be disabled. The I/O lines of the 6522 must have been programmed as outputs and have been filled with valid data.
- The moment we want the 65xx to read data from the MMU, the I/O lines must be programmed as input and the output of the 573 must be disabled.
- The moment we want to output the latched data of the 573 to be read by the 6522, its I/O lines must be programmed as inputs.

As after a RESET of the system all the I/O lines have been switched to input mode, a resistor should take care of pulling the MM input (H), disabling the map mode in this way. Another resistor must take care of disabling the output of the 573.

Extra functionalities of the 6522

I also have another reason to use the 6522. I intend to use the 65816 instead of the 6510 (C64) or 8502 (C128). But these processors have an onboard I/O port which the 65816 lacks. The 6522 can supply this port.


Nick Coplin had some ideas for using the 74LS612 only to find out that they are hard to get. The ones I have I got by recycling old PC motherboards but I cannot expect everyone having a load of old motherboards for scrapping laying around. So I decided to make a MMU of my own.

Interseting: Andre Fachat made a replacement for the 74LS610 MMU.

Having questions or comment? You want more information?
You can email me here.