Path: ns-mx!hobbes.physics.uiowa.edu!zaphod.mps.ohio-state.edu!usc!elroy.jpl.nasa.gov!nntp-server.caltech.edu!toddpw From: toddpw@cco.caltech.edu (Todd P. Whitesel) Newsgroups: comp.sys.apple2 Subject: Re: Addenda : Technical Help on Memory (//c) Message-ID: <1992Mar4.092239.18270@cco.caltech.edu> Date: 4 Mar 92 09:22:39 GMT References: <1992Mar2.234257.13118@umiami.ir.miami.edu> Organization: California Institute of Technology, Pasadena Lines: 107 Don't bother. Use RAS as AX and Q3 as CAS. It's what the 80 column card does. BUT! I'm in a flicking mood tonight. If you really want to implement those signals exactly as you described them, here's how to do it with a single PAL. It's also the main technical innovation of the //e -- everything else was mainly repackaging. The //e timing controller was a awesome example of real hacking in action. jdeitch@umiami.ir.miami.edu writes: >Given the signals phase 0, RAS, Q3 from the MMU, I need to be able to >generate CAS and AX in order to multiplex DRAM addresses on a memory expansion >card I'm designing for my //c. I've fiddled with logic charts in every way I >can think of and I just can't figure out a way to get CAS and AX out of those >three signals. I know it is possible because the MMU itself does it. The last sentence is wrong, not because it isn't possible (it is), but because that is not how the MMU does it. The following explanation is based on my examination of the //e schematics, documentation, and some good ol' fashioned lab tests. It also gives a quick primer on PAL's for the benefit of youse out there who've always wondered what that meant. What the MMU does is utilize the signals generated by the timing PAL, which on both the //e and the original //c's is a PAL16R8. For those of you who haven't used PAL's before, the PAL16R8 has 8 inputs and 8 outputs, and each output is run through a 1 bit register, meaning the PAL can remember what its last output was. The logic inside can, for each output, compute a simple logic function of ALL its pins, including both the inputs and the outputs. This makes the PAL a teeny state machine, where the byte output is the state it's currently in, and each time you clock it, it uses the present state and the inputs to decide what the next state should be. Now you can't do _every_ possible such state machine with a PAL -- to do that you need a 64k byte ROM instead of the 8-term sum-of-products array the PAL uses. A ROM is like a 2^N term sum-of-products array (64K in this case), so the ROM is 8,000 times more complex than the PAL. For applications like timing controllers, however, a ROM-sized state machine is never necessary (unless you're an Intel processor or you're lazy like Bill Mensch, yuk yuk -- sorry). The PAL timing controller in the //e and //c is a one-chip version of what Wozniak needed about four chips of grunt TTL to do in the ][+. The center of Woz's clock generator was a shift register, and that is a good starting point for examining the //e timing PAL. I've reordered the signals to illustrate this. >Phase 0 : 111111100000001111111000000011111110000000 >RAS : 100000110000011000001100000110000011000001 >AX : 110001111000111100011110001111000111100011 >CAS : 111000111100011110001111000111100011110001 >Q3 : 111100011110001111000111100011110001111000 Notice the following remarkable facts (below, "after" means one time period, one column in the above diagram, after something else): 1. RAS always goes low after two clocks high. 2. AX always goes low after RAS goes low. 3. CAS always goes low after AX goes low. 4. Q3 always goes low after CAS goes low. This smacks of a shift register. But now things get interesting: 5. AX goes high after Q3 gooes low. 6. CAS and RAS both go high after AX goes high. 7. Q3 goes high after RAS goes high. Also, phase 0 inverts itself. This is not exactly what the original //e timing controller did (CAS went high with Q3 instead of RAS; both designs will work but it is safer to have CAS stay low the extra cycle. It takes a couple paragraphs to explain that properly, so I'll skip it unless someone wants to hear it; it's the same effect that lets old programs like Money Munchers read the last video data byte and synchronize to the screen on a ][+.) Anyway, back to the main discussion. The PAL's internal logic doesn't know when something has changed state (there's only one bit of memory for each output, so all it can remember is what the current state _is_). So the patterns I gave above can't be implemented directly. BUT, as it happens, you _can_ still figure out what each clock should be based on the previous state of the clocks. I'll spare you the icky derivation; I've reverse engineered the //e controller and here is the punch line, in "word logic notation": new RAS = AX and (not Q3) new AX = RAS or (not Q3) new CAS = (AX and Q3) or RAS new Q3 = RAS or CAS Some of these are simplified; the //e generator also handles the main video signals and it can also disable the CAS line entirely if the motherboard RAM isn't selected. To implement the "risky CAS" that rises with RAS, use new CAS = AX this also lets you simplify new Q3 to just CAS, but both do the same thing. Now, to your original problem: generating AX and CAS from RAS and Q3. You don't need phase 0. If you want to do it the way you originally specified, you need the 7M signal. Get a 74LS74 and clock both flip flops with 7M. Then run Q3 though an inverter and or that with RAS. Send the output of the OR gate to the D input of one of the flip flops; this generates new AX according to the equation above. To get your CAS, simply run the Q output of the AX flip flop to the D input of the second flip flop, to implement "new CAS = AX". Implementing a "safe" CAS uses one AND gate and one OR gate instead of simply delaying AX. Let me know if you have any questions, need something clarified, etc. Todd Whitesel toddpw @ tybalt.caltech.edu p.s. good luck on your project!