6502-in-PC
What is it?
A PC ISA card that contains a 6502, a Memory Management Unit (MMU), some I/O, RAM and ROM. The PC acts as the terminal and drive station(s) for this "6502 system".State: Schematics and board.
Background
The fact is that I already had a "6502-in-PC" project but it actually contained a 65816. But then I wanted a project with 6502 and changed the name of the origanal project to: 65816-in-PC.I also have this CP/M 3.0 for the PC project, also known as Z80-in-PC, Which should enable a PC to run CP/M. And, like the 65816 design, this design can handle 1 MB of memory. The 65816 can handle up to 16 MB, so no problem here. But the 6502 can handle only 64 KB and so it needed some extra help in the form of a MMU. This project is, more or less, based on the Z80 design.
Why ISA and not not PCI (-Express)? The answer is very simple: I have no idea how to do it for the PCI bus. It will most probably need a FPGA or another fancy IC and these are out of my scope. So ISA it is.
I created this project in the first place pure out of curiosity but then I had some afterthoughts. If you want to run the ROMs of, for example, the CBM 8032, on the 65816 project, I have to copy everything to RAM and disable the ROM. But with this project it is just a matter changing a few registers of the MMU. And it is real ROM, no chance that an accidental write messes up the code.
The hardware
The idea is based, as said before, on the last MMU version of CP/M 3.0 for the PC and you can say that I only swapped the Z80 for a 6502. Of course this is not completely true. To be honest, I really thought it would be easy until I ran into the I/O part. But I think I solved that.Keyboard and screen
It should be clear now that this system does not have its own keyboard and screen. So what about displaying text or reading the keyboard? The routines that send characters to the screen now send it to the 8255 together with some codes to tell the PC where to place it on its screen. The routine that reads the keyboards now asks the PC if a key has been pressed.The schematic
I'm going to use a GAL of course but staring at a GAL won't explain how it really works. So here is the IC version:
The 6502 has to communicate with the PC in one or another way. I had no doubt about how to do that: two 8255s, one for the 6502 part (IC3), the other for the PC (IC2). Why not a 6522? I already found out in the hard way that, if I wanted to have a small board, that was impossible.
Why the 8255? It has two 8-bits ports that can be used for exchanging data, one for incoming and one for outgoing data. And it has two 4-bits ports for control lines. The 8255 does not have an INT/IRQ output and I don't know if this could be a disadvantage. Just in case I provided one my self, see later.
Selecting the 8255 for the PC is done by using a 74LS688, an 8-bits comparator. Dip switch block SW1 enables the user to select an address ranging from 000h to 3FCh in steps of four bytes. AEN, IOWR and IORD make sure that the 8255 is only selected when I/O is addressed.
Remark: it is up to the user to select an address range not occupied by any other hardware!
I needed something to test the card and debug the software in some way. So I added four LEDs and their drivers to port C: two for the lower port and two for the upper port. So once the direction of each half port is set, I always have two LEDs at the disposal of both the PC and Z80 system.
When writing this page I thought about providing an interrupt of my own to both systems. Having four control lines, which is rather much, why not using one for each of the interrupts?
I cannot use the output of one of the pins directly directly towards the PC because after a reset it acts as an input. Because an open input is seen by another input as (H) and the INT inputs are triggered by an (H), I decided to tap the signal from the output of one of the inverters. Jumper J1 enables the user to disable this feature.
Another pin of port C provides a mean to trigger the INT input of the Z80. J2 can disable this feature.
Like in the 65816-in-PC project, an oscillator generates the clock And a 74LS393 gives us the choice out of three frequncies by means of a jumper, JP3. The result is fed into the PHI0 input of the 6502
The reset signal of the ISA bus is active (H), just what the 8255 needs. The 6502 OTOH needs an active (L) signal and we create that by inverting it by using IC12A.
The RAM and ROM have been connected to the 6502 in a normal way, no weird details. The 8255, IC3, is an Intel IC and therefore needs a separate read (RD) and write (WR) line. These two are generated by IC4A, a 74LS139 2-to-4 demultiplexer. The 6502's R/W line determines which output, Y0 or Y3, becomes active but only if PHI1 is (L).
The biggest challenge is the selection of the RAM, ROM and I/O. One idea is to be able to run the BASIC 4.0 of the Commodore 8032. This BASIC runs in ROM but I have no intention to populate this system with the needed ROM, the idea is too load it in RAM and then run it.
The I/O of the 8032 is situated in the range $E800..$EFFF so this will be the case here as well.
We have to have ROM, we cannot avoid that. The question is, do we need 4 or 8 KB? I'm going for 4 KB but don't forget: we are dealing with a GAL and reserving 8 KB of the range for ROM is peanuts.
This will give us a mapping that wil look like this:
$000000 - $00E7FF RAM $00EE00 - $00EFFF I/O for the 8255 $00F000 - $00F7FF RAM, maybe ROM $00F800 - $00FFFF ROM $010000 - $07FFFF RAM $080000 - $0FFFFF ROMIC4B, a 74LS139 2-to-4 demultiplexer, takes car of generating the main CS signals for the RAM and ROM.
IC11B, a 74LS139 2-to-4 demultiplexor, and IC5, a 74LS133 3-to-8 demultiplexor, take care of generating the signals for the I/O in general. IC11a takes care of:
- selecting the 8255
- selecting the MMU
- setting the Mapping Mode flipflop
- resetting the Mapping Mode flipflop
The last two will be explained later.
The MMU part
The heart of the first version is the 74LS612. The MMU has two working modes: the "pass mode" and the "mapping mode". In the "pass mode" outputs MO8..11 reflect the input levels of MA0..3. In "mapping mode" the outputs MO0..11 reflect the status of 16 internal registers. But after a power-up the state of these registers is completely unknown so we first have to make sure that after a reset the MMU is in "pass mode". The level of input MM (Map Mode) determines in what mode the MMU is put. (H) means "pass mode", (L) means "mapping mode". Unfortunately the 74LS612 does not have something like an internal reset and that means that some external hardware has to set the level of MM to "pass mode" after a reset.This external hardware is a flipflop made out of two 3-input NAND gates, IC9A and IC9B. What at this moment is important to know is that the flipflop is resetted by feeding the inverted reset signal of the ISA bus that is mentioned above, to one of the inputs of IC9C. The output of IC9C, (H) after a reset, is fed to the MM input and so the MMU is put into "pass mode".
In "pass mode" the outputs MO8..11 just output the signals that are presented at the inputs MA0..3. In this case these inputs are address lines A12..15 but in reverse order. The other MO lines output a (L) in "pass mode". This means that in "pass mode" the 6502 will address 64 KB of ROM.
Within the 1 MB range, the first 512 KB are occupied by ROM and the other 512 KB by RAM. But we need to fill the RAM with the 8032 ROM or we need RAM for the Stack so how can we do that? There are two options:
- Set up the mapping system as soon as possible.
- "Write through", that is: reading from an address where the ROM is situated will read the value of that address from the ROM. But writing to an address where the ROM is situated will write the value to the RAM.
First: IC4B, a 74LS139, is used for selecting either the ROM or the RAM. It is enabled by the PHI1 signal and these signals can only become active if there is no I/O access. An OR gate, IC13A, combines MA19 and an inverted R/W (IC12C). When the ROM is read, R/W is (H) and thus input 1 of the OR gate will be (L). The output will then follow MA19 and thus the ROM will be read indeed. But during a write, input 1 will be (H) and this means that the 139 will select the RAM.
And then I ran into a difficulty: whatever the mapping is, the Z80 can always access the I/O due to its seperate IORQ pin. But in case of the 6502, I/O is memory mapped. I have thought about mapping everything in blocks of 2 KB, the size of the I/O area. But then I would need 32 registers (the MMU has only 16)or I could only use the upper 32 KB of the complete range. But then I would need extra hardware, something I didn't want.
Then the idea rose to disable the "mapping mode", and thus enabling the "pass mode", the moment the I/O, $E800..$EFFF, is addressed. Any mapping that involves the range $E000..$EFFF wil be discarded for that moment. This is done by ORing (IC13B) with the inverted (IC12B) I/O signal with the output of the NAND gate IC9B and feeding the result to the MM pin of the MMU. An active (L) I/O signal will set input MM (H) and put the MMU in "pass mode".
The GAL version
I ran into a little trouble. Because I need a lot of address lines to decode the I/O, I ended up with 13 inputs and 12 outputs for the GAL. Even when using a GAL22V8 that are too much in- and outputs :( Adding a 74LS139 means saving several pins: 2 input pins and 3 output pins. Schematic:
Board:
Communication between the 6502 system and PC
Here I can be very short: after the reset of the 6502 and when both systems know that the other system is present, it is the 6502 that initializes every action. The only thing the PC does is waiting for the 6502 to send a command.The use of the extra RAM and ROM
During those afterthoughts I mentioned above, I thought about all that extra RAM and ROM: is it really needed? The ROM can be used to store the system ROM of several different systems. And it can be used as a ROM floppy: reading data from the ROM is much faster than reading it using those 8255s.Using the RAM is a bit more difficult. When emulating the CBM 8032, there is hardly, maybe no use at all for it for the simple reason that the 8032 is not aware of it. And the only way to access it is through the MMU, a device the 8032 doesn't know at all. I will at least research if I can emulate the extra RAM of the CBM 8096 and 8296 in some way.
The only way IMHO to make it useful is to use an Operating System that supports extra RAM in some way like CP/M. Yes, there exists a CP/M for the 6502: David Given's CPM65
The MMU part, a 6522 version?
I have thought about using a 6522 instead of the 74LS612 because that has some advantages. But there is one big disadvantage: using a 74LS612 means I can replace any block of 4 KB of RAM or ROM with any other block of 4 KB of RAM or ROM. Using a 6522 means I can replace only one specific dedicated range of RAM with another block of 4 KB of RAM and I can only replace the ROM in the $Fxxx range with another block of 4 KB of ROM. IMHO that limits the possibilities of the system, compared to the 74LS612 version, too much.You can email me here.