Monday, October 10, 2022

Part 1d: GAL equations and memory decoding

Memory decoding can be done with discrete logic chips wired so that a certain memory chip (RAM or ROM) is selected whenever the address bus contains a memory address within the range where you want to place memory. You also have to consider whether the memory is being Read or Written and also respect the CPU clock phase and any other relevant control bus signal.

While discrete logic can do the job adequately and sometimes efficiently, it does not have the flexibility to be altered once a circuit is built. On the other hand, using Programmable Logic Device (PLD) like a GAL allows flexibility in allowing the system designer to alter the memory decoding scheme by simply reprogramming the PLD. Some PLDs can only be programmed once and others can be reprogrammed multiple times. I have chosen to use a GAL so that I can experiment with different memory mapping schemes in case I change my mind later on.

For example, if I want to map 16KB of RAM from $0000..$3FFF I could start with the following simple logic equation:

    /CS = A15 OR A14 OR VMAo2

where /CS is Chip Select (active low) and A15 and A14 are address lines and VMAo2 is Valid Memory Address AND Phase2 clock (active low). We don't need to use the R/W line, since this is RAM which has a separate R/W pin and we want to select that memory for reading or writing. For ROM we would need to include the R/W signal as well.

In the above equation, the only time /CS will be low is when A15 = 0, A14 = 0 and VMAo2 = 0, and this would select the memory chip only when the CPU is addressing memory in the range $0000..$3FFF. For any other combination, /CS will be high. Most memory devices use an active low signal to select the chip.

The above circuit could be built with a single 74LS32 quad 2-input OR gate as follows:

Less readable but this equation can also be written as:

    /CS = NOT( NOT(A15) AND NOT(A14) AND NOT(VMAo2) )

This is how the GAL would internally represent the same logic equation.

It gets more complicated if you want to exclude a range of memory. For my mapping plan I want to exclude the lower 512 bytes. Now we need to use A15, A14, A13, A12, A11, A10 and A9 and VMAo2 so we can include the lower 512 bytes in an equation to ignore addresses in the range $0000..$01FF, but still select RAM above that.

The equation now grows to:

/CS = VMAo2 OR A15 OR A14 OR NOT(A13 OR A12 OR A11 OR A10 OR A9)

Now the only time /CS will be low is when A15 and A14 is low, AND also when any of the address lines from A13..A9 are high. If A13, A12, A11, A10 and A9 are all low then /CS will be high, thus excluding the memory from $0000..$01FF.

Suddenly with this simple change the circuit has grown to 3 chips (two 74LS32's and a 74LS04), and instead of 2 gates we now have 8 gates. If I want to include RAM between $4000 and $BFFF the logic circuit would need to change again.

This is where the flexibility of a GAL comes into play. We can wire all those address lines as inputs into the GAL and depending on the logic equations programmed into the chip we can select specific memory decoding schemes without rearranging the physical circuit or adding additional gates. There is a limit to how big the equations can be inside each GAL, and also which pins are used.

WINCUPL is a free program for Windows that can compile your equations for a specific GAL and produce an output .jed file ready for your device programmer. WINCUPL uses specific ASCII characters to represent certain boolean logic symbols that are not normally readily accessible in 7 or 8 bit encoding. These are as follows:

( ) parenthesis can also be used to group the order of operation.

WINCUPL has some features that make writing complicated equations easier and memory mapping using the FIELD statement is one such feature. So instead of having a long equation with all the address lines in the equation it can be written as a range of memory and WINCUPL will do the rest when it compiles.

For example:
Instead of the long equation we used last to map memory between $0200 and $3FFF we can simply use these statements which is much easier to comprehend:

PIN 18  = !RAMCS
FIELD MEMADR = [A15..A8];
RAMCS = VMA02 & MEMADR :[0200..3FFF];

pin 18 is defined as an active low output using the ! symbol. the FIELD statement defines MEMADR as a list consisting of A15..A8. RAMCS is assigned to the logic equation listed and WINCUPL knows it's an output pin automatically.

This is only a brief description of how some of the equations are written in WINCUPL. You don't need to understand all of the language in order to use it. I only learned enough to get the equations written that I needed. A more thorough description is included in the WINCUPL user manual here:

https://ww1.microchip.com/downloads/en/DeviceDoc/doc0737.pdf

The equations I eventually determined for my memory mapping scheme is as followings:
filename: ETA3400X.PLD

Name     ETA3400X ;
Device   G22V10 ;
Partno   x ;
Date     04-Jul-22 ;
Revision 01 ;
Designer Mark C ;
Company  Rev3ng ;
Assembly None ;
Location None ;

/****************************************************************/
/*                                                              */
/* Heathkit ET3400 Memory Expansion                             */
/*                                                              */
/* Maps additional RAM avoiding existing expansion options      */
/* provided within the ETA-3400 Memory I/O Accessory            */
/* Avoids the following memory space:                           */
/*      $FC00 - $FFFF 1K Monitor ROM                            */
/*    * $E800 - $EFFF 2K Fantom II ROM alternate location       */
/*    * $E000 - $E7FF 2K Tiny BASIC ROM alternate location      */
/*      $C400 - $C7FF I/O Expansion space                       */
/*      $C200 - $C2FF PIA0 (6820) alternate location            */
/*      $C100 - $C1FF 7-Seg Display I/O space                   */
/*      $C000 - $C0FF Keypad I/O space                          */
/*    * $1C00 - $23FF 2K Tiny BASIC ROM primary location        */
/*    * $1400 - $1BFF 2K Fantom II ROM primary location         */
/*    * $1000 - $13FF PIA0 (6820) primary location              */
/*      $0000 - $01FF 512 Bytes on-board RAM                    */
/*    * NOTE: mapped as RAM space depending on setting of       */
/*            ALT config input pin.                             */
/*                                                              */
/* Provides separate /CE outputs for the following locations    */
/*      $D000 - $FBFF 4K Fantom II Monitor and Tiny BASIC ROM   */
/*                    and 7K for ROM expansion                  */
/*      $C700 - $C7FF I/O Expansion                             */
/*      $C600 - $C6FF I/O Expansion                             */
/*      $C500 - $C5FF I/O Expansion                             */
/*      $C400 - $C4FF I/O Expansion                             */
/*      $C200 - $C2FF PIA0 alternate location                   */
/*      $1400 - $23FF 4K Fantom II Monitor and Tiny BASIC ROM   */
/*      $1000 - $13FF PIA0 primary location                     */
/*                                                              */
/****************************************************************/

/**************** INPUT PINS *********************/
PIN 24   = VCC       ;
PIN 1    = o2        ; /* PHASE 2 CLOCK                         */
PIN 2    = A9        ;
PIN 3    = A8        ;
PIN 4    = A10       ;
PIN 5    = A11       ;
PIN 6    = A14       ;
PIN 7    = A13       ;
PIN 8    = A12       ;
PIN 9    = !RW       ; /* R/W from CPU Bus                      */
PIN 10   = A15       ;
PIN 11   = !VMA02    ; /* Valid Memory Address & Phase 2 Clock  */
PIN 12   = GND       ;
PIN 13   = !ALT      ; /* Alternate Memory Map Select           */
 
FIELD MEMADR = [A15..A8];

/**************** OUTPUT PINS *********************/
/* PIN 23  = !IO7 ; /* $C700 - $C7FF I/O Expansion              */
/* PIN 22  = !IO6 ; /* $C600 - $C6FF I/O Expansion              */

PIN 21  = A16 ;  /* Output to RAM A16 to select 2nd 64K bank   */
PIN 18  = !RAMCS ; /* $0200 - $BFFF RAM select depending on ALT input */
PIN 20  = !ROMCS ; /* $1400 - $23FF 4K Fantom II Monitor and Tiny BASIC ROM */
  /* or $D000 - $FBFF 11K Fantom II Monitor and Tiny BASIC ROM */
PIN 19  = !PIACS  ; /* $C200 - $C2FF PIA0 (alternate location)  */
/* or $1000 - $13FF PIA0 (primary location) */
PIN 17  = !RE ; /* Push Data from RAM/ROM/PIA onto CPU Data Bus */
PIN 15  = !OE ; /* Output Enable to RAM and ROM                 */
PIN 16  = !WE ; /* Write Enable to RAM and PIA                  */

/* PIN 21  = !IO5 ; /*    $C500 - $C5FF I/O Expansion           */
/* PIN 22  = !IO4 ; /*    $C400 - $C4FF I/O Expansion           */

/***************** LOGIC EQUATIONS *****************/
RAMSEL = (VMA02 & MEMADR :[0200..0FFF]) #  /* either RAM config */
         (ALT & VMA02 & MEMADR :[1000..3FFF]) # /* ALT RAM config */
         (!ALT & VMA02 & MEMADR :[2400..3FFF]) # /* extended RAM config */
         (VMA02 & MEMADR :[4000..BFFF]) ; /* either RAM config  */
                                          /* beat that WINCUPL !*/

ROMSEL = (!ALT & VMA02 & MEMADR :[1400..23FF]) # /* standard $1400..$23FF */
         (ALT & VMA02 & MEMADR :[D000..FBFF]) ; /* ALT ROM $D000..$FBFF */

/* IO7   = VMA02 & MEMADR :[C700..C7FF] ; /* $C7xx */
/* IO6   = VMA02 & MEMADR :[C600..C6FF] ; /* $C6xx */
/* IO5   = VMA02 & MEMADR :[C500..C5FF] ; /* $C5xx */
/* IO4   = VMA02 & MEMADR :[C400..C4FF] ; /* $C4xx */

PIASEL = (!ALT & VMA02 & MEMADR :[1000..13FF]) # /* standard PIA $1000..$13FF */
         (ALT & VMA02 & MEMADR :[C200..C2FF]) ; /* ALT PIA $C200..$C2FF */  

RAMCS = RAMSEL;
ROMCS = ROMSEL;
PIACS = PIASEL;

WE = VMA02 & RW;
OE = VMA02 & !RW;
RE = VMA02 & (ROMSEL # RAMSEL # PIASEL) & !RW;

A16 = 'b'0 ; /* A16 set Low. later will be used to access another 48K bank in RAM*/

It's a bit hard to follow everything in the above formulas at first glance. I started off with simpler equations and worked up from there. This is where reprogramming of the GAL came in handy. I also have an ALT input pin which is used in the equations to give me two completely different memory maps.

I'd hate to think what a discrete logic circuit for this set of equations would look like. WINCUPL creates a discrete set of compiled logic equations in one of it's ouput files (.doc) that you can view. This is a snapshot of two of the larger equations:

Imagine how complicated a discrete circuit to perform the above equations would look. It would be huge compared to a single GAL chip that can hold the equivalent circuit or more if required.

This is how I assigned the pin out for the GAL:

The seemingly random sequence of input signals on pins 1..11 was simply to help in the pcb layout and not how I had programmed it originally. Also the three output CS pins on pin 18, 19 and 20 are because the GAL can handle larger equations on those pins and I was almost at the limit for some of the equations at one stage.

I'll go into the circuit diagram next, then move to prototyping...

No comments:

Post a Comment

Part 2o: The future of the ETA-3400X

You can find all the work I've done on the ETA-3400X and 8K ALTAIR 680 BASIC, except for the ETA-3400X Gerber files, on the ET-3400 grou...