Ruud's Commodore Site: PC-card 2 Home Email

PC-card 2




What is it

PC-card describes a way to attach 16-bit PC ISA-cards to your C64 or C128. Jeri Ellsworth's Commodore One crossed my design a little bit so I started to think about another use for this design. I own a CBM 8032 SK equipped with a 65816 and the idea raised to combine the PC-card with the ability of the 65816 to address up to 16 MB. Knowing that it is very hard to lay your hands on a 65816, I decided to add a 74LS612, Memory Management Unit, to the design. A MMU enables a 6502 to access up to 16 MB as well.
Unfortunately I found out that the 74LS612 is hard to get as well nowadays. The ones I own originate from scrapped old PC-motherboards. So I decided to make my own MMU and to use that instead.

Remark: the design has become so huge, that it is advised to use a CPLD or FPGA.


Schematics

You'll find them here.


Used codes with ICs

All used ICs can be of the 74LS, 74ALS or 74F type. I refer to a IC with its own code plus the place where to find it in the schematic. The first character refers to the characters left and right of the drawing. The second character, a number refers to the numbers at the bottom and top of the drawing. A possible third character refers to the position in side the given quadrant:
* a = left/top
* b = right/top
* c = left/bottom
* d = right/bottom
* t = top
* l = left
* r = right
* o = bottom
* m = middle

Example 1: 32, U3C-A5d. This is a 74LS32, identified by U3, third gate, found in quadrant A5, right/bottom.
Example 2: 573, U14-D2b. This is a 74ALS573, identified by U14, found in quadrant D2, right/top.
The position inside a quadrant is not always given for various reasons.

Remark: the U-codes were generated by UltiCap and not by me. For example this can result in some illogical use of gates in the same IC.


Theory and hardware

If you are unfamiliar with the so called ISA-bus of the PC, please read The ISA-bus first.


Combining the 65816 with an MMU

The original idea was a "65816-only"design. The addition of the 74LS612 MMU is not a real addition as I meant to replace four 573's of the original design: U27, U28, U30 and U31. These ICs take care of generating the address lines A16..23. Using a MMU means I only need to solder 40 pins instead of 80. Having a 65816 it only would be needed for DMA operations. Then the idea rose to use the MMU for the CPU as well.

Both the 65816 and MMU can address up to 16 MB. But the MMU has a feature the 65816 lacks: the ability to reconfigure the complete memory map. For example this enables an user to remap the IDE-interface inside the original mapping of his CBM. This can come in handy as he wants to use the hard disk drive in combination with software written specific for the 6502. The idea is very simple: when the 65816 accesses the first 64K-segment, the MMU-mode is enabled ie, the MMU controls the address lines A16..A23. When accessing any other 64K-segment, the 65816 controls these lines.
Why the first segment? To be able to access any other segment, the 65816 needs to be in native mode in the first place. And then it makes less sense to use the MMU. For those people not font of using the MMU, I made a design without it.

The idea how to do it is not new. A 573 (U31-D8l) generates the address lines A16..23 out of the data bus. These address lines are decoded using a 682 (U32-D8r). Its output tells the system whether or not the first 64K-segment is accessed. This information must be available all times so we need another 573 (U29-D8a) to generate another set of address lines for the rest of the system.


What about other computers with a 6502?

The idea is to add the card by replacing the original processor. In this way the design can be used for any other computer having a 6502 (alike CPU). The only catch is the availability of an 8 or 4 MHz signal, which can replace the DOT-clock, generated by a C64 or C128. The 4 MHz signal is needed to clock the 8237's and to generate the delays for the refresh- and read/write-signals.
If not available, the delay can be generated using a '125 ns-delay' as used on older PC motherboards or a RC-network. A separate 4 MHz module can generate the needed 4 MHz. AFAIK this 4 MHz signal doesn't need to be synchronised with PHI2. Hmmm, then what about using a 5 MHz module?


When not using a 65816?

When a 65816 is not available, it means that the MMU should control the address bus all the time. So I made a second design with a 6502 as CPU. The 6502 cannot be tristated so this meant I had to provide the means to do so by using some buffers for the address- and data bus and R/W-line: 541-, 245- and 125-buffers.
Remark: when I mention the BE-input, you have to think of the signal used to disable the above buffers. BE is active (L). The enable-signals for above buffers are active (L) as well which means we need an inverter to imitate AEC

This designs can be used as example to adapt the design to other processors like the 7501/8501 used in the C16 and Plus4. One step further: the idea is even usable for computers equipped with the Motorola 6800-family.


Accessing attached PC-cards

Able to access 16 MB it means that the original C= has to become a part of the 16 MB range. This is archived by separating the original system from this design by some buffers. The moment the processor wants to access another area then the original one, the address bus must present the original system a safe address like $FFFF. (see later)

The 65816 and MMU address the first 64 K range after a reset so it is a logical choice to place the C= here. But this isn't a must. I had the idea to make that configurable: this enables one to start the system from an EPROM placed on, for example, an ISA-card. A small program enables one to choose from several configurations. One could enable the MMU to reconfigure the memory map in such a way that the original system is remapped to $00xxxx and can be used as so.
But the above logic can also be used in the other way around: the original system is located in $00xxxx but has a new EPROM. This EPROM contains the similar small program as mentioned above. The only thing the program has to do is to remap the original Kernal into its original area to use the original system as so.
Making it configurable has its drawbacks as well. Software written for a system where the original system resides at $01xxxx probably cannot be used for a system where the original system resides at $00xxxx.
So I decided to place the original system at $00xxxx.


Mapping the original system

Two 5-input NOR-gates (U44b-A8a, U44a-B8c) and a NAND-gate (U43b-B8c) decode the address line A18..23 which come from the MMU. A 139, 2-to-4 demultiplexer (U45a-A8l), decodes the four 64K-segments within the given 256K-segment. The first two segments are reserved for the original system. Why two segments? In this way the 65816 can always address the original system if needed. This could come in handy when something went wrong with configuring the MMU.
The third one is reserved for accessing the I/O-cards connected to the ISA-bus. This means we now deal with memory mapped I/O and don't have to set or reset bits to tell the system what kind of operation we want.
The last 64K-segment I have reserved to be able to connect cartridges or other C= related hardware to the system. But why do I need a separate 64K-segment? The timing of the address bus and certainly the timing of the MEMx- and IOxx-signals, are not suited for some hardware like the 6522. The idea is to connect a bus of my own to the design. This bus is not drawn.

What ever range we choose, we have to separate the original C= hardware from the rest the moment the 65816 addresses another 64K-segment. This can be realized by two 541's for the address bus ((U24-B8, U25-B8), a 245 for the data bus (U39-C8), and a 125 for the R/W-line (U1b-B8b). Some resistor arrays pull all lines (H) to ensure the neutral address $FFFF I proposed.
The outputs of the 139 selecting the original system, are ANDed (U22b-A8l) first. Its output is fed to an inverter (U51a-A8r). The output of this inverter is fed to a 2-input NAND-gate (U43c-A8r) which on its turn enables the enable-inputs of the various buffers mentioned above.
The second input of the NAND-gate is used to disable the access to the original system the moment the I/O-part of this card is accessed because, although mapped inside the system, this I/O is actually situated outside it.


The I/O

Having a PET or CBM choosing the I/O area is quite easy: we have $E900 to $EFFF to our disposal :) A 688 (U40-A8d) and 8 dipswitches are used to decode the wanted page. The 688 is enabled by the AND-gate (U22b) mentioned above. A 139 (U45b-A7o) decodes the page into the 64-byte segment we need. The selected output is fed to the second input of the NAND-gate (U43c) described above and enables another 139 (U50a-A7o). This 139 selects the two DMA-ICs (U15-B5, U16-A5), a 6522 (U53-B7c) and another 139 (U50b-A7m).
This 139 enables a 138 3-to-8 decoder (U52-B7c) and selects the SRAM of the MMU.

This 138 decoder combines two address lines and the R/W-line to 8 active (L) outputs for addressing all needed buffers and latches:
1r: reading IRQ buffer 1, 541 (U13-D4l)
2r: reading IRQ buffer 2, 541 (U14-D4c)
3w: writing D8..15 -> ISA-bus register, 573 (U64-D2d)
3r: reading D8..15 -> ISA-bus register, 573 (U65-D1o)


To make sure the timing is according PHI2, the "G"-enable-input of the 138 is connected to PHI2.


The MMU

The core of the MMU is made of two fast cache-RAMs represented by two 6116's, 2K*8 SRAMs (U39-D6t, U40-D6m). I have chosen for a 14-bits MMU replacing or generating A10..A23. U40 takes care of mapping A10..15, U39 of A16..23. Two 157's (U37-D7b, U38-D7r) select which address lines and signals go to the two SRAMs depending on the mode the MMU is in:
SRAM:      original:      MMU:
A0         PA0            A10
A1         PA1            A11
A2         PA2            A12
A3         PA3            A13
A4         PA4            A14
A5         PA5            A15
A6..A10    GND            GND
CE/OE      select         GND
WE         R/W            +5V
When in original mode the 6522 generates the signals PA0..5 needed to drive the first six address lines of the SRAMs. In MMU-mode the address lines A10..15 coming directly from the 65816 drive these lines.
In MMU-mode CE and OE are tied to GND and WE is tied to Vcc assuring a permanent output of data. In "original mode" these lines are tied to the system in the usual way.
As only 64 bytes are needed, the SRAM's address lines A6..10 are tied to GND.

In MMU-mode the outputted data is fed to the address bus through four 74LS257A (U41-C5t, U42-D5o, U55-D5m, U56-D5t). Notice the "A" as this version of the 257 can be tristated, the 74LS257 can not! The schematic shows the 257 but UltiCaps database marked the outputs as "tristate outputs".
All 257A's become tristated when MASTER becomes (L). This is realized by a 04 (U51b-A3b) inverting the MASTER-signal. The two 257A's (U41, U42) which output A10..15 also are tristated when DMA is active. This is realized by ORring (U57a-C5m) the inverted MASTER-signal and the inverted HLDA-signal (see DMA).

The moment the MMU is active, the data busses need to be separated from the systems data bus. Two 245 bi-directional buffers (U27-D6o, U28-D7d) enable the user to access the SRAMs. They are enabled by the 139 mentioned above. But they must not be allowed to output anything the moment the MMU is active. So the select-signal is first NORred (U44c-C5l) with the "MMU is enabled"-signal. As the 139 hasn't been synchronised with PHI2 yet, the third input of this 27 NOR-gate is connected with PHI1.
The above means that we cannot update the MMU when in MMU-mode; to update the MMU, the system must be in "original mode".

The MMU can be enabled when the user wants to, and then only when the 65816 accesses the first 64K-segment. This is realized by NORring (U17b-C7m) the output of U32, the 682, with the output of the 6522 designated to turn the MMU on or off. The MMU is enabled anyway when in DMA-mode. This is done by ORring (U19c-C6m) the output of U17b with the HLDA-signal. The output of U19c steers the A/B-inputs of the 157s and 257s. This is also the "MMU is enabled"-signal mentioned above.
Why in DMA-mode? The 8237 can only access up to 64 KB, which simply means it, has no means to access any other segment. The idea is that in DMA-mode the addressbits A10..15 are delivered by a register plus R/W-line. The last means that the chosen address to outputs its data (= A16..23) depends on the fact whether it is a read- or write-operation. Port B of the 6522 output its five highest bits for the address towards a 541 buffer (U54-B7r) representing A11..15. MEMW is the sixth input representing A10. The moment the DMA becomes active, the 65818 outputting the original A10..15 is tristated and U54 becomes active.
Why different addresses for a read- or write-operation? In this way data can be DMA-ed from one segment to another one.
What MMU-register can be used? AFAIK any register. Just make sure the software doesn't access the region related to this register before or after the DMS-operation, as the result could be unpredictable.

As said, two 257A's (U41, U42) are tristated during a DMA for the simple reason the 8237's provide these address lines themselves.

Updating the SRAMs is a 16-bits I/O-operation. The meaning of this remark will be explained later.


The 6522

The original PC-Card project needed a control register for several reasons. Now I needed a bit for enabling the MMU. But in this case I had to be sure of the state of this bit after the reset. This is not guaranteed when using a 573. So I used a 273 8-bits latch with reset and a 541 to read it out again. Then the idea occurred to use the "register version" of the MMU to save I/O-space but which meant I needed another six bits. A 6522 provides all the needed bits and needs less soldering at the end :)

The 6522 provides the following bits:
* PA0..PA6 for addressing the SRAMs
* A11..15 for the MMU when in DMA-mode
* MM: this bit en/disables the MMU
* 8/16: this bit en/disables the 16-to-8 bit DMA (see later)
All other bits and features are unused and are available for the user.


The read- and write-signals

The PC is capable of addressing memory and I/O on a very low level: the Intel- CPUs have separate read- and write-lines to do that. The 6502 and compatible CPU's don't have this feature. Therefore I/O in a system with such a CPU is called "Memory mapped I/O".
As the 6502 doesn't have this feature, we have to create it. I could use the same two bits as used in PC-Card but as you already read above, I decided to reserve a 64K segment for this purpose. Why 64KB while the PC only uses $0400 bytes? For the simple reason the ISA-bus actually can address up to 64 KB but for a (IMHO stupid) reason IBM decided to use only $0400 bytes.
$0400 bytes don't seem much although it is twice as much as the C64's free space. I haven't seen any PC-cards using mirrors yet and mirroring is one of the biggest space-eaters some cartridges are "famous" for. A lot of PC-cards are configurable by using DIP-switches. I don't think you have to worry about not being able to attach PC-cards to your system due to busconflicts.

The 65816 uses the PHI2 signal to tell attached ICs when the data- and address bus is valid. The PC uses the read- and write-signals mentioned above to perform the same trick.
This means we have to transfer PHI2, R/W and the I/O-segment signal into MEMW, MEMR, IOWR and IORD. My idea is to use a 74LS156 (U49-A6d), a 3-to-8 demultiplexer with OC-outputs. Disable the 156 and it behaves like it was tristated which enable us to perform DMA-transfers as the 8237 must be able to control these lines as well. Pull-up resistors make sure of valid levels in all other situations (not drawn).
As you can see I only use the R/W- and I/O-segment-line to generate the four signals for the ISA-bus. Designing this schematic I figured out that PHI2 is not needed at all at this stage as the timing is corrected later any way.

The 65816 must be able to address the 8237's. Being Intel-ICs they need IORD and IOWR as input lines. This means that the 156 must perform its function during an access of one of the 8237's as well. To make sure that IORD or IOWR are activated, the I/O-segment signal is ANDed (U46b-A6c) with the two CS-lines. As mentioned before, updating the SRAMs is an I/O-operation as well so this line is ANDed as well.

The ISA-bus lines SMEMR and SMEMW are only activated if the address is under $100000. The reason for this is to prevent that an old 8-bit card, which only can decode 20 address lines, writes/reads data when in reality an address above $0FFFFF is outputted. This can be realized by decoding A20..A23 using three OR-gates, U18a..c-A3. The output of the last one is combined with the MEMx-signals using again two OR-gates, U18d-A3d and U19a-A3d. The result is fed to PMEMx.
Why PMEMx? This has something to do with UltiCap, just forget it.

The six generated signals are fed to a 244 buffer, U59-A3a, for several reasons:
* to make sure that the signals are strong enough to drive all the busses
* adapt the timing for DRAM's
* it enables us to disable these signals towards the ISA-bus when:
    * MASTER becomes (L)
    * performing a 16-to-8-bit DMA

The 244 is an IC containing two 4-bits buffers. One is used to buffer the IOxx-lines, the other the xMEMx-lines.
A 3-input NAND-gate (U10b-B4a) combines the output of U19b-B2a (16-bit DMA, see later), MASTER and the RAS-signal (U4a-C1c, see REFRESH) to enable the buffer for the I/O-lines. Another 3-input NAND-gate combines the output of U52e , MASTER and the RAS-signal to enable the buffer for the xMEMx-lines.
U52e tells the AND-gate that the first 256K-segment is accessed and thus the xMEMx-lines have to be disabled. The reason for this is to make sure that no PC-card outputs its data when a DMA-operation accesses this segment because the DMA expects to retrieve data from original system.


DMA

The 16-bit ISA-bus has seven DREQ/DACK lines and that's why we'll need two 8237's. Like a PC we'll use the second 8237 for 16-bit transfers only.

During a DMA-transfer, output HRQ of the first 8237, U2-B4c, becomes (H). This signal is clocked into a 74 using PH1. This clocking guarantees a synchronised halting and tristating of the 65816. The same reason accounts for starting the 65816 again.
The positive output of the 74 is fed to the HLDA-input, acknowledging the DMA-request is granted.

The 8237's run on a 4 MHz clock derived from the clock of the original system or a separate crystal module. If nothing is done, the read- and writesignals outputted by the 8237 use this speed as well (remember that the 8237 was meant for the 4.77 MHz 8088 in the first IBM-PC's). This means we need to synchronise the 8237 with PHI2 using the Ready-input.

To make sure that the 8237 covers the whole high part of PHI2, we need a mechanism that detects both edges of PHI2. First the mechanism has to be activated by either MEMR or MEMW during a DMA-transfer. An AND-gate, U26c-D5d, combines these two signals. The output of U26c is fed to a NOR-gate (U22d-C1) which output is fed to the READY-inputs of the 8237's.
The output of the AND-gate, U26c, is also fed to the data-input of a 74 flip-flop, U40a-D1. This 74 is clocked by PHI2. In this way U40a detects the rising edge of PHI2. The negative Q-output is fed to the data-input of the second half of this 74, U40b. This 74 is clocked by PHI1 to detect the falling edge of PHI2.
The Q-output of U40b is fed to the above NOR-gate, U22d, as well. At the falling edge of PHI2, the output of U22d becomes (L) allowing the 8237's to go on. The moment the 8237 ends the MEMW- or MEMR-action, the output of U22d becomes (H), clearing both the flip-flops through the inverter U32F-D1.

During a memory-to-memory transfer the 8237 first reads and then writes the byte using an internal temporary buffer. The problem will be reading from the 65816. The moment PHI2 goes (L) and releases the Ready-input, this will not be the moment the 8237 stores the info as well. So the data has to be buffered in some way. We'll see we need this buffer as well when transferring data from/to the ISA-bus. The solution is to place the 8237's BEHIND these buffers. This also means that the buffers have to be steered as if addressing an ISA-card.

The 8237 is able to transfer data in blocks of maximal 64 KB. This means it must be able to manipulate 16 address lines. It is capable of driving the first eight, A0..7, itself. For driving the other eight, A8..15, it needs the support of an extra 8-bit latch: the 74ALS573. As said we'll use two 8237's like in a PC: one will take care of 8-bit transfers, the other of 16-bit transfers. The last is archived by connecting the generated address lines A0..14 of the 8237 to A1..15 of the ISA-bus. A0 must be kept (L) during a 16-bit transfer. As U1-A4a, the 16-bit 8237, already provides A8, the used 573 ,U7-A3c, only has to provide A9..15. The 8th bit of this 573 is used to generate a low A0 during a 16-bit transfer.
This solution means that the second 8237 is only capable of transferring 32K words. I have the schematics of the IBM AT that I used as reference. But one page is missing: the one covering DMA. So I have no idea how IBM solved this.

The 573 is enabled by output AEN of the 8237. But this signal has to be inverted first. We use a NAND-gate, U6b-A3c. Negating one of the inputs of the NAND-gate tri-states the 573. One is AEN of course. The other input comes from a AND-gate, U37c-B3c, which ANDs PHI2 and the signal coming from the MASTER-input of the ISA-bus. Negating this last line means a card wants to control the bus. The use of PHI2 means that the 573 is only active during the positive half of PHI2. This is necessary for the refresh of DRAM's.

U5-B3c is the 573 A8..15 latch towards the ISA-bus for the 8-bit 8237. Another NAND-gate, U6c-B3c, provides the same function as U6b.

During a DMA transfer the 8237 has to take care of the R/W-line. The negative output of Uxx is fed to an 125, U43a-A6b, which buffers MEMW.


The data bus (1): 8-bit transfer registers

This sounds easy: the 65816 is a 8-bit processor so it must be able to handle 8-bit transfers. But unfortunately it isn't that simple. Let's have a look how a 16-bit card handles 8-bit operations:
SHBE A0 Transfer
 0   0  word
 0   1  byte on D8..15
 1   0  byte on D0..7
 1   1  will never occur 
The above means that we need a kind of T-junction which enables us to read/write from/to D0..7 or D8..15 depending on address line A0.

The SHBE-signal is a signal generated by the CPU of the PC. In that case you would say that a 80286+ cannot exchange data with an 8-bit only card. Indeed, it cannot. That a PC can is made possible by a 245 buffer that leads the data read from D0..7 to D8..15 or vica versa.
How does a PC know that a card can handle 16-bit transfers? This is signalled by the card by negating MEMCS16 or IOCS16 according the type of operation. I have thought about providing some means to detect the fact that a card used one of these lines. But IMHO the Eyeball MK 1 should be sufficient enough :)

The above means that choosing which eight data bits to use, not only depends on A0, but also depends on what type of card it is!

Remark: various info mentioned the fact that a card also can generate SBHE. For the moment I don't know of any card capable of doing so.


The data bus (2): 16-bit transfer registers

Real 16-bit transfers caused the trouble I ran into with my initial 1989 design. First I found out that some transfers MUST be 16 bits wide.
Example: an 16-bit IDE-interface only accepts 16-bit I/O transfers. In case of the IDE-hard disk drive there is an additional problem. Data can only be handled sectorwise: it has to be received/sent in portions of 256 words. And this data has to be read/written in a row from/to the SAME address. This means that after reading this address the next read will make the hard disk drive output the next WORD. A 65816 can only perform 8-bit transfers so we must provide a temporary 16-bit latch for storing the word.

Then there is another problem with 16-bit transfers. Let's have a look at the following program:
.eq WINDOW = $DF00
START   ldx  #$00
        lda  WINDOW,x
        sta  $2000,x
        inx
        bne  START
When A0=0 the WORD is read from the ISA-bus and stored in the buffer, the Accu is filled with the lower-byte. When A0=1, the only thing that should happen is that the Accu is filled with the contents of the register that stored the upper-byte.

In the above example register X is incremented. But I can imagine examples where it is preferred to decrement X during the loop. In that case the word must be read when A0 = 1.
This means that we need some means to tell the system that A) we want a 16-bit transfer and B) in what direction the addresscount goes.
To worsen the problem, writing is done in the opposite way: when incrementing X, the actual write has to be done when A0 = 1, when decrementing X, the actual write has to be done when A0 = 0.

Some experiments of my own made me draw the following conclusions:
* all memory related cards (videocards, the buffers of networkcards) are able to perform 8-bit operations
* the only 16-bit-only operations I know of are I/O operations
* 16-bit I/O operations can happen on odd addresses as well (??? no proof)

The last conclusion means that reading an odd 16-bit I/O address will give you an other register and not, as with reading on odd 16-bit memory address, the upperbyte of the even address. The only solution I have to read this upper-byte is to reserve an I/O-address just for reading the contents of the buffer that stored the data bits D8..15 during the initial read of the word. As the above is also valid for writing, another I/O-address must be reserved for writing the buffer towards D8..15 of the ISA-bus.

Two pairs of 573's, U12..15-D2, latch the data. How are they clocked or enabled?
+--------------------------------------- DMA               (0 = no)
| +------------------------------------- Original system   (0 = yes)
| | +----------------------------------- 8/16 bit          (0 = 8-bit)
| | | +--------------------------------- ReaD/Write        (0 = write)
| | | | +------------------------------- IO/MEM            (0 = MEM)
| | | | | +----------------------------- A0 CBM
| | | | | |
| | | | | |   +------------------------- 573 D0..7 to ISA Clock       U15
| | | | | |   | +----------------------- 573 D0..7 to ISA Output En.  U15
| | | | | |   | | +--------------------- 573 D0..7 to CBM Clock       U14
| | | | | |   | | | +------------------- 573 D0..7 to CBM Output En.  U14
| | | | | |   | | | | +----------------- 573 D8..15 to ISA Clock      U12
| | | | | |   | | | | | +--------------- 573 D8..15 to ISA Output En. U12
| | | | | |   | | | | | | +------------- 573 D8..15 to CBM Clock      U13
| | | | | |   | | | | | | | +----------- 573 D8..15 to CBM Output En. U13
| | | | | |   | | | | | | | | +--------- MEMR / IORD
| | | | | |   | | | | | | | | | +------- MEMW / IOWR 
| | | | | |   | | | | | | | | | | +----- SBHE
| | | | | |   | | | | | | | | | | | +--- A0 ISA
0 1 2 3 4 5   0 1 2 3 4 5 6 7 8 9 A B
------------+------------------------
0 0 - - - - | - - - 1 - - - 1 1 1 - -
0 1 0 0 - 0 | 1 0 - 1 - - - 1 1 0 - 0
0 1 0 0 - 1 | 1 0 - 1 - - - 1 1 0 - 1
0 1 0 1 - 0 | - 1 1 0 - - - 1 0 1 - 0
0 1 0 1 - 1 | - 1 1 0 - - - 1 0 1 - 1
0 1 1 0 0 0 | 1 0 - 1 - - - 1 1 0 1 0
0 1 1 0 0 1 | - - - 1 1 0 - 1 1 0 0 1
0 1 1 0 1 0 | 1 0 - 1 0 0 - 1 1 0 - 0
0 1 1 0 1 1 | 1 0 - 1 0 0 - 1 1 0 - 1
0 1 1 1 0 0 | - 1 1 0 - 1 - 1 0 1 - 0
0 1 1 1 0 1 | - 1 - 1 - 1 1 0 0 1 0 1
0 1 1 1 1 0 | - 1 1 0 - 1 1 1 0 1 - 0
0 1 1 1 1 1 | - 1 1 0 - 1 1 1 0 1 - 1
1 0 0 0 - 0 | - 1 1 0 - - - 1 * * - 0  * = depends on 8237
1 0 0 0 - 1 | - 1 1 0 - - - 1 * * - 1
1 0 0 1 - 0 | 1 0 - 1 - - - 1 * * - 0
1 0 0 1 - 1 | 1 0 - 1 - - - 1 * * - 1
1 0 1 0 - 0 | - 1 1 0 - - - 1 * * 1 0 
1 0 1 0 - 1 | - - - 1 - 1 1 0 * * 0 1
1 0 1 1 - 0 | 1 0 - 1 - - - 1 * * 1 0
1 0 1 1 - 1 | - - - 1 1 0 - 1 * * 0 1
1 1 - - - - | - 1 - 1 - 1 - 1 * * * -
Clocking any 573 is only valid during a valid read- or write-operation. For U12..15 this means they have to be clocked when PHI2 = (H) and one of the MEMx- or IOxx-lines = (L). This is realized by U39b-C4c and U20c-C3c. PHI2 is needed because the timing of the MEM/IO lines isn't guaranteed when generated by a 8237.
If you have a good look at the first two columns, you'll notice that enabling the output of a 573 is only possible during an EXOR-like function of DMA and accessing the original system. This is realized using a 86 (U....) fed by ... and ... I will refer to this signal with ENA.

In case of U12 we want to avoid that the latch is clocked during a 16-bit I/O operation. On the other hand it need to be clocked during a specific 65816 write.

U15 and U12 needs to be enabled during:
- (No DMA ) and (CBM write)
- (DMA) and (MEMR)
under the condition MASTER=(H).
An 86 EXOR-gate combines R/W and DMA. An OR-gate, U54A-C5b combines the output with ENA and the result is NANDed (U41c-C4a) with the signal coming from MASTER.

U13, D8..15 to C64, is enabled during: - (No DMA), (16-bit card), (MEMR) and (A0=1) U47a-D6d
- (DMA), (16-bit card), (MEMW) and (A0=1) U23a-D5b
* CBM I/O-read "3r"
A 86 EXOR combines MEMR and DMA. This is fed to a 5-input NOR-gate. Its output is inverted and ANDed with "3r" using U56a-C5b.

U14, D0..7 to C64, is enabled during: - (No DMA), (8-bit card) and (CBM read) U20b-D6d
- (No DMA), (16-bit card), (CBM read) and (I/O card) U33a-D6
- (No DMA), (16-bit card), (CBM read), (Memory card) and (A0=0) U23b-D6a
- (DMA), (8-bit card) and (MEMW) U33b-D6b
- (DMA), (16-bit card), (MEMW) and (A0=0) U55a-D5b
The last line means I am not able to DMA with 16-bit IO-cards (for the moment, see later).
All the above outputs are NORred using U47b-D5b.

Enabling U12..15 will cost us a lot of gates. A logical thought is using a PAL or a GAL, but unfortunately I cannot program them :( However, an other idea is using an EPROM as the Enable signals aren't that time critical. In the worst case, that is if the idea won't work, I can replace the EPROM with a little add-on card.

SBHE must be (L) during a 16-bit DMA transfer or the opposite of address line A0. This realized by NORring the AEN-signal of U1 with A0 using U53c-A2b. A 125 (U43c-B1d) takes care of tristating it.


16-bit I/O and DMA

I first thought that it was impossible to DMA from/to IDE but then I got the following idea: use the 8-bit 8237 and disable all certain features when address line A0=1:
* disable the IOxx-lines towards the ISA-bus
* A0=0 towards the ISA-bus during a read or write
* disable the clock input of U13 when reading its contents
* take care of what operation happens during a read or write.

This means we need an extra bit in the Control register to tell the circuit there is (or isn't) a 16-bit DMA transfer going on through the 8-bit 8237 (U2). This bit is fed (through the OR-gate U3c-C1d) to U39a-B3a for disabling the IOxx-lines (see later) and to U20c for disabling the clock inputs of U13 and U14.
U19b-C1d EXORs address line A0 and IOWR:
 A0  IOWR  |  result
-----------+---------
 0    0    |    0
 0    1    |    1
 1    0    |    1
 1    1    |    0
The output is fed to U3c, the OR-gate mentioned above, which causes that the bit only is effective during a I/O-read or -write when A0=1.
U37a-B1b ANDs the bit with A0 to guarantee A0=0 during the transfer. U43b makes sure that A0 can be tristated if needed.

Remark: the above means we "borrow" the odd address for our own purposes. This means that the above mechanism cannot be used for DMA transfers with an odd I/O-address. (Don't know any, to be honest. Soundcard, SCSI ???)


The REFRESH

This line is used to signal an ISA-card that there is a valid refresh address on the bus. The IBM-AT uses a 74LS590 to do the job. Unfortunately the 590 is difficult to get. But some 393-counters plus buffers will do as well.
AFAIK the PC only refreshes A0..A7 which is enough for the 41256 (256K*1) or equivalents. But this is not good enough for the 44256 (256K*4) and bigger. IMHO it won't hurt the bus to expand the addressrange up to A11 which even allows us to refresh 16 MB modules! Three 393's, UA35a, UA35b and UA36a, all in C2, provide A0..11. These lines are buffered through two 541's, U34 and U38, which are enabled by PHI2.

When do we have to execute a refresh? In a PC the CPU or a DMA-transfer is halted for a moment to allow a refresh-cycle. During any transfer where the C64 is involved, the CPU or 8237 cannot do anything the lower half of PHI2. So my idea is to use this lower halve of PHI2 as the moment to activate the refresh.

How to refresh the DRAM's? The keyword is timing. The 4164-12 64K*1 DRAM needs 120 ns RAS-time, read: access time. But before (or after) it needs an extra 90 ns recovery time. We can archive this by delaying the read/write-signals for the ISA bus by 125 ns. Why 125 ns? This is exactly one complete Dotclock-cycle. In 2 MHz-mode this will leave us with another 125 ns for the RAS.

But this also applies to an ordinary read- or writecycle. An extra condition is that the read- or writecycle ends at the falling edge of PHI2. This simply means that the recovery time has to be situated at any edge of PHI2.

Hardware solution: The Dotcclock is fed to an 393 4-bit counter, U36b-C4c, to generate a 4 MHz signal. This clock is fed to two 74's, D-flip-flops (U8b-C4d, U8a-C3c). PHI2 is fed to the Data- and Clear-input of the first 74, U8b. An inverted PHI2 is fed to the same inputs of the second 74, U8a.
The idea is that the 4 MHz signal clocks the state of (the inverted) PHI2 into the 74. The 74 is reset when needed by (the inverted) PHI2. Both signals will look like this:
             __    __    __    __    __    __    __    __    __    __ 
Dotclock:   |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
          __|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__

          _____       _____       _____       _____       _____       __
4 MHz:         |     |     |     |     |     |     |     |     |     |
               |_____|     |_____|     |_____|     |_____|     |_____|

          _____                         _______________________
PHI2:          |                       |                       |
               |_______________________|                       |________

          ___________                   _____________________________  
Output /Q:           |                 |                             |
(REFRESH)            |_________________|                             |__

                _____________________________                   ________
Output /Q:     |                             |                 |
(ACCESS)  _____|                             |_________________|
Remark:
* REFRESH is the negative output of the 74, U8a, fed by the inverted PHI2
* ACCESS is the negative output of the 74, U8b, fed by PHI2

In case CLK = 2 MHz, the result is:
             __    __    __    __    __    __    __    __    __    __ 
Dotclock:   |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
          __|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__

          _____       _____       _____       _____       _____       __
4 MHz:         |     |     |     |     |     |     |     |     |     |
               |_____|     |_____|     |_____|     |_____|     |_____|

          _____             ___________             ___________
PHI2:          |           |           |           |           |
               |___________|           |___________|           |________

          ___________       _________________       _________________     
Output /Q:           |     |                 |     |                 |    
(REFRESH)            |_____|                 |_____|                 |__

                _________________       _________________       ________
Output /Q:     |                 |     |                 |     |
(ACCESS)  _____|                 |_____|                 |_____|
The signal coming from output /Q named ACCESS is used in the first place to steer any memory-transfer where the ISA-bus is involved: this signal ensures us of enough recovery time after a refresh. This is realized by using this signal to steer U39a, the 541 that buffers the ISA-bus read- and write-lines.

Remark: older PC-cards can be equipped with 150 ns DRAM's. When in 1 MHz, you probably won't experience problems. But in the 2 MHz mode you only have 125 ns accesstime and that is not enough! So be warned.


The Interrupts

The ISA-bus outputs 11 active (H) IRQ-signals. The C64 can only handle one active (L) signal. The transformation is done by two 5-input NOR-gates, U50a-D3c and U50b-D4d, an inverter U32f-D3c and a 3-input NAND-gate, U46b-D4c. We also feed the IRQ's to two 541's, U48-D4d and U49-C4b, so the C64 can check which IRQ actually triggered the circus.
To make sure that unused lines aren't treated as an interrupts, we'll pull the inputs low using 3K3 resistors.
Remark for myself: what about using 74HCT541's? Maybe I then can increase the value of the resistors.

IRQ1
This register, U49, reads the state of the first eight available IRQ's: 3, 4, 5, 6, 7, 9, 10 and 11.
Output enable: I/O - read "4r"

IRQ2
This register, U48, reads the state of the last three available IRQ's: 12, 14 and 15. The other 5 bits are reserved for future use.
Output enable: I/O - read "5r"

Some friends suggested to use 8259's, Intels Programmable Interrupt Controller, but I couldn't see any real advantages. IMHO I even needed more hard- and software then with the above simple design.


The other lines

IOCHCK
The input IOCHCK is connected to the NMI-input.

IOCHRDY
This signal is connected to Uxx which ANDs all possible inputs for the RDY-input of the 65816.

0WS
The 65816 has no equivalent at all for this input. In fact it is running at "zero wait states" all the time. So we simply do nothing with this input.

CLK
I have no idea which cards use this input. For the moment I use PHI2. If needed one can use the DOT-clock.

BALE
This output tells the card when the address is valid. Therefore we'll feed this output with PHI2.

OSC
This signal is, AFAIK, only used by the CGA-card. We'll feed this output with a signal from a 14.318 MHz crystal-module.

RESET
This line will be fed by the CBMs RESET-signal through an inverter, U11b-B8a.

AEN
A (H) during an IORD or IOWR signals that not an I/O-operation but a DMA-transfer is going on. So when no DMA is in progress, this line remains (L). It is connected to the HLDA-output of the master-8237.

DRQx, DACKx
To be connected to the 8237's.

MASTER
Signal to gain complete control of the bus during a DMA, a card can pull this line (L). Used to disable all bussignals. For the moment I don't know of any card capable of using this line.





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