PALWIZ ====== Palwiz is an open-source program to generate JEDEC programming files for simple GAL chips. I wrote it because there was no open-source alternative out there, just a few old programs that only ran under MS-DOS such as PALASM and ABEL. Admittedly, they do a lot more than palwiz, but that's at the price of not being able to use them on your favorite UNIX-like operating system, which may not even use the same CPU. What you lose in features you gain in freedom. The basic design came about after looking at the ancient open source Fortran version of PALASM and seeing how it worked. That was when I realized that I didn't need anything to optimize equations or expand XORs or do pin fitting, I just needed something which would work with the three standard GAL chips (16V8, 20V8, 22V10) in their various architecture modes. Yes, it's quick and dirty, and the code is a bit ugly, but it works, and it's easier than editing the JEDEC programming files by hand, which is what I was doing at first. I even found some boo-boos in my first attempts at hand-programming when writing palwiz. Palwiz is no substitute for having the GAL data sheets. You will need to have the data sheets and know how to read them. You will also have to assign input and output pins yourself, and be aware of when an output will need more input terms than it has. You just won't have to care what the specific fuse numbers are or have to carefully count the right column in a line of '1's. WHAT'S A GAL CHIP? ================== (Note: this assumes you have some basic familarity with digital circuit design. If not, there are many books and web sites which can tell you all about Boolean algebra and TTL chips.) A GAL chip is a kind of programmable logic chip. First there were PLAs (Programmable Logic Array), which had a whole bunch of terms went into lots of AND gates, the output of which were fed into a whole bunch of OR gates. The inputs to the AND and OR gates are selected by a matrix of "fuses". These were really fuses, and a programmer would send enough power through the chip in a certain way to burn each fuse. The next evolution from PLAs was PAL chips (Programmable Array Logic), in which each AND gate fed into a single OR gate, with each OR gate receiving the output of a fixed number of AND gates, usually 8 or so. This was a good thing because while you were limited to less inputs for each OR gate, the larger number of AND gates made it possible to simply duplicate the common terms for multiple OR gates, and the resulting chip was simpler to program. PAL chips came in many different configurations, some with active-low outputs, some with active-high outputs, some with registered outputs, etc. There were a _lot_ of different types of PAL chips. The names of PAL chips indicated the number of inputs, the type of output, and the maximum number of outputs. For example, a "16R6" had 16 inputs, and 6 registered outputs. The final evolution was the GAL chip (Generic Array Logic), which made the old PAL chips obsolete. First of all, the old-fashioned PROM fuse array was replaced with an EEPROM. This meant that chips could be reprogrammed if you found a bug or didn't need them any more. The second improvement was having only three different types of chips, instead of dozens. This was accomplished by making the output stages (called "macrocells") configurable in multiple ways. Conversion programs were available to migrate existing programming from all the old PAL chip types. The namimg was changed slightly because some outputs could be used as inputs instead, so the first number now referred to the number of input pairs to the fuse matrix. This was shown by using a "V" (which probably means "versatile") as the output type in the chip name. 16V8 has up to 16 inputs and up to 8 outputs in 20 pins; 20V8 has up to 20 inputs and up to 8 outputs in 24 pins; and 22V10 has up to 22 inputs and up to 10 outputs in 24 pins. Note that some of these configurations existed in PALs as well, notably from TI. If the chip type doesn't start with "GAL" or "PALCE" (AMD's name for GAL), it's probably not reprogrammable like a GAL chip. There were a few other chip types which have since been osboleted. These include the 24V10, 26V12, 20RA10 (RA=registered asynchronous), the PALCE610 (which was effectively a 20V16, but with very configurable output stages), and the 29M16 (the M is for macrocell?). The programming for the chips is specified in what is called a "JEDEC" file, after the name of the standards group for IC chips. (Specifically, it is JEDEC Standard Number 3A.) It specifies the state of each fuse, and a few other things like test information. However, each chip type has its fuse numbers assigned differently, so a given JEDEC file works with only one chip type and needs a specialized conversion program to translate for another chip type. This is where higher-level specification languages come in. Palwiz is the next level up, where you can specify the pins by name and create a JEDEC file based on on a description using simple equations. Above that are hardware specification languages which can automatically expand and optimize equations, can automatically generate counters and state machines, and can automatically assign pins based on a best fit. Beyond that are languages which can specify the contents of more complex FPGAs (field programmable gate arrays) and other high-density generic logic chips. HOW TO USE IT ============= To build it from source, just type "gcc palwiz.c -o palwiz". From the command line, it's just "palwiz ", where (without the angle brackets) is your PAL description file. The JEDEC file is sent to standard output, so you will want to use the ">" redirection to save it to an output file. The PAL description file consists of multiple statements ending in semicolons. There are four types of statements: "chip", "pin", "test", and equations. CHIP ---- chip ; Example: chip 20V8R; This must be the first statement. It specifies the type of chip being programmed. Since 16V8 and 20V8 have "architecture fuses" which change the way the chip works, each of these gets a separate subtype. The supported chip types are: 16V8S - 16V8 in "simple" mode 16V8C - 16V8 in "complex" mode 16V8R - 16V8 in "registered" mode 20V8S - 20V8 in "simple" mode 20V8C - 20V8 in "complex" mode 20V8R - 20V8 in "registered" mode 22V10 - 22V10/22CV10 (the 22V10 has no architecture fuses) 26V12 - 26V12/26CV12 (the 26V12 has no architecture fuses) For each of these chip types, you will want to download the chip's data sheet to understand how the inputs and outputs work, and what they can do in each mode. PIN --- pin [!]; Example: pin 20 !ROMCS; This specifies the name of each pin, and whether it is active low or not. If a pin is active low, the "!" will automatically invert an equation on an output pin or select the inverted term from an input pin. Beware of using the "!" both in the PIN statement and an equation! This will double- invert the pin, and you will probably get the wrong result! The 22V10 has two "phantom" pins for equations that don't go to output pins. The global reset is phantom pin 25, and the global preset is phantom pin 26. TEST ---- There are three forms of this: 1) test ; Example: test N00N00NNNNNN NNNNNNNNNHNN; This adds a raw test vector to the JEDEC output file. Spaces in the test vector are removed automatically. The test vector is a list of states for each pin of the device. For a full description of what states are used in the test vectors, you will need to look elsewhere, but here is a simple list: 0,1 - set input to 0 or 1 L,H - test input for being high or low N - don't test this pin (N is always used on the power and ground pins) Z - test this pin for being three-state disabled C,K - clock input pin: C = low, high, low; K = high, low, high 2) test '[' [!][=state] ... '->' [!][=state] ']' ; Example: test [ CLK=C !D0 D1 !D2 OE -> !BA14 BA15 !BA16 ]; One or more input pins are specified, optionally inverted, and one or more output pins are specified, optionally inverted. The inverted state of the pin in the pin declaration is also taken into account. A test vector is built using the correct pin positions for the named pins. Custom pin states can be defined with the '=' sign, and 0/1/H/L/C/K states are checked for validity and inverted per the pin declaration. 3) test pin [pin ...] ; Example: test OEO ROMCS RAMCS LCO; Generates test vectors for every possible combination of inputs used by the listed pins. There are some limitations to this. Registered outputs can not be used, feedback inputs can not be used, output enables are not included, and more than six or seven inputs will generate a lot of test vectors. Equations --------- [!][.OE] [:] = 0; [!][.OE] [:] = 1; [!][.OE] [:] = [!] [ [!] ...]; operator is one of "&", "|" The simple case sets a term to 0 or 1. The more complicated equations are a bunch of AND equations separated by ORs. Using the "!" on an input pin selects the inverted input (or the non-inverted input if the pin was declared with a "!"), and likewise, using a "!" on the output pin inverts the output (or un-inverts if the pin was declared with a "!"). When too many OR terms have been specified, an error is reported. The AND "&" operator has higher precedence than the OR "|" operator. Because you'll see it this way everywhere else, "/" is accepted everwhere instead of "!", "*" is accepted instead of "&", and "+" is accepted instead of "|". If the output is registered, use ":=" instead of "=". If the output has an Output Enable from the pin matrix, adding a ".OE" to the output pin name will select the pin's Output Enable term. Clock and OE inputs which are not defined with the fuse matrix are implied and not declared. EXAMPLE ======= This example is for an Atari 7800 cartridge bank select. RAM is located at $4000-$7FFF, bank switched ROM is located at $8000-$BFFF, the bank is selected by writing anywhere in $8000-$BFFF, and the last bank of ROM appears at $C000-$FFFF by using OE to disable the bank select address in favor of pull-up resistors. Pins 1 and 22 are connected together, pins 13 and 15 are connected together, and pins 17-19 need a pull-up resistor. Some pins are named (for future expansion) but not used. // Atari 7800 supercart 128K ROM + 8/16K RAM or 128K ROM + 16K ROM chip 20V8R; // 20V8 registered mode pin 1 CLK; pin 24 VCC; pin 2 CLK2; pin 23 P_23; pin 3 RW; pin 22 LCO; pin 4 P_4; pin 21 !RAMCS; pin 5 A15; pin 20 !ROMCS; pin 6 A14; pin 19 BA14; pin 7 P_7; pin 18 BA15; pin 8 D4; pin 17 BA16; pin 9 D0; pin 16 BA17; pin 10 D1; pin 15 !OEO; pin 11 D2; pin 14 D3; pin 12 GND; pin 13 !OE; BA16 := D2; BA15 := D1; BA14 := D0; ROMCS = A15 & RW; RAMCS = !A15 & A14 & CLK2; !LCO = A15 & !A14 & !RW & CLK2; OEO = !A14; // 20V8R needs OE term for non-registered pins ROMCS.OE = 1; LCO.OE = 1; OEO.OE = 1; RAMCS.OE = 1; BA17.OE = 1; // generate automatic test vectors test OEO ROMCS RAMCS LCO; // latch test vectors test [ CLK=C !D0 D1 !D2 OE -> !BA14 BA15 !BA16 ]; // load test [ !CLK D0 !D1 D2 OE -> !BA14 BA15 !BA16 ]; // latched test [ CLK=C D0 !D1 D2 OE -> BA14 !BA15 BA16 ]; // load test [ !CLK !D0 D1 !D2 OE -> BA14 !BA15 BA16 ]; // latched test [ CLK=C !D0 D1 !D2 !OE -> BA14=Z BA15=Z BA16=Z ]; // load+disable test [ !CLK D0 !D1 D2 OE -> !BA14 BA15 !BA16 ]; // latched CAVEATS ======= Well, of course this program isn't guaranteed to do anything but take up space on your hard drive. If a guaranteed correct program is important to you, you should be paying people money for a program. TO DO ===== I'd really rather start all over and make something with a syntax that is a subset of either PALASM or ABEL than make major changes, but here are some things that could still be useful: Checksum generation for output text. It would be nice if test vector generation could see common AND terms and generate a single negative case for each input. Version 1.1 changes (2007-05-08) ================================ * Using the ".OE" term on a registered 16V8/20V8 output pin would silently force the pin to be non-registered. An error is now reported. * Test vector generation now correctly identifies feedback pins, and should no longer report an error when an input-only I/O pin is an input term for the output pin being tested. * Registered feedback terms are now inverted before dumping the fusemap. Version 1.2 changes (2007-05-25) ================================ * Command-line parameter errors would not abort the program * Removed hard tabs from the source code * added 26V12 support - it may be obsolete, but I have three 26CV12 chips, and it's basically a 20V10 with more pins (and VCC/GND moved) (This has not been tested with an actual chip, but should work.) Version 1.2.1 changes (2013-10-01) ================================ * Uncommented u_int, etc. so it would compile. * Cleaned up makefile Version 1.2.2 changes (2020-01-05) ================================== * Changed MAXPINS to 28. 26V12 has 28 pins, but apparently I typed in the wrong number, and didn't notice because complier warnings weren't so great back then. * Updated makefile, including adding -Werror and C99 compiler options. * Reformatted code to K&R style formatting with mandatory braces. * Code now makes extensive use of in-block decalarations, and uses stdbool.h for bool type. Version 1.3 changes (2020-01- ) ================================ - Chip specs are now stored as constant arrays - The 26V12 data still had some errors, but more importantly, the 26CV12 and 26V12 chips, despite the similar name are not the same chip! The 26V12 has more option fuses and would require a lot of work to support its second clock and buried macrocell modes. - FIXME break up code into more .c modules?