Adventures in programmable logic devices

Educating myself about GALs, CPLDs, FPGAs and similar devices

Similar projects worth following
I have wanted to learn about programmable logic devices but in the past for me they were too expensive and too exotic compared to logic and CPU chips. But now they are accessible to me.

I have been interested in programmable logic devices for a while. They are less well-known compared to logic chips and CPUs, but can do tasks that would require combinatorial and/or sequential logic with fast processing. They process in hardware instead of being driven by a program but they are customisable by programming.

This project will log my personal progress in exploring such devices from scratch. I will start with GAL (Generic Array Logic) and work my way up to CPLDs and FPGAs.

  • A BCD to 7-segment decoder with a GAL

    Ken Yap04/02/2024 at 14:31 2 comments

    GAL (Generic Array Logic) is descended from PAL (Programmable Array Logic). At the beginning these were fused, then UV erasable, and then flash programmable.

    A common use for PALs was to replace a lot of small scale logic in products like computer motherboards. GALs have displaced PALs so we won't discuss those any more. Current GALs are electrically reprogrammable.

    My first well-defined task is to write a configuration for a BCD to 7-segment output decoder. I'm using the ATF16V8B.  This has up to 16 inputs, 8 I/Os, and runs off 5V. Most of the programmable logic devices have moved to 3.3V. But this one is still in production and useful.

    A GAL assembler is needed to take a specification of the logic and turn it into a JEDEC file which is a standard format for GAL programmers like the TL866. In the Windows world WinCUPL is well-known. In the *nix world, there is GALasm. More recently, Galette, a rewrite of GALasm in Rust has appeared. I'll be using this.

    The specification language for GALasm and Galette is shown on this example page. The combinatorial logic for output terms is expressed as the sum of products of input terms. By De Morgan's rule this is equivalent to product of sums. Inversion is also available. This can generate any result from a combination of inputs. Let's jump straight into 7-segment logic.

    CLOCK I0    I1    I2    I3    NC    NC    NC    NC   GND
    /OE   OA    OB    OC    OD    OE    OF    OG    NC   VCC
    /OA = B1 + B4 + BB + BD
    /OB = B5 + B6 + BB + BC + BE + BF
    /OC = B2 + BC + BE + BF
    /OD = B1 + B4 + B7 + BA + BF
    /OE = B1 + B3 + B4 + B5 + B7 + B9
    /OF = B1 + B2 + B3 + B7 + BD
    /OG = B0 + B1 + B7 + BC
    A BCD to 7 segment decoder

    You can see that it's shorter to express the output terms as the inverse of the sum of input terms, i.e. list the digits for which a particular segment is off.

    I used the minipro software to flash this to the chip, as this Makefile shows:

    # Uses GNU make for pattern substitution
    default:        7segment.jed
    %.jed:          %.pld
                    galette $<
    %.pld:          %.pldm
                    m4 $< > $(<:.pldm=.pld)
    %.flash:        %.jed
                    minipro -p "ATF16V8B" -P -w $<

    Galette takes .pld files so why the .pldm files? If you look at the specification, the input terms representing the 16 BCD combinations are repeated. So I used the m4 macro processor on *nix to save typing and reduce the chance of errors, the Don't Repeat Yourself principle. Here is the result of the preprocessing:

    CLOCK I0    I1    I2    I3    NC    NC    NC    NC   GND
    /OE   OA    OB    OC    OD    OE    OF    OG    NC   VCC
    /OA = I0*/I1*/I2*/I3 + /I0*/I1*I2*/I3 + I0*I1*/I2*I3 + I0*/I1*I2*I3
    /OB = I0*/I1*I2*/I3 + /I0*I1*I2*/I3 + I0*I1*/I2*I3 + /I0*/I1*I2*I3 + /I0*I1*I2*I3 + I0*I1*I2*I3
    /OC = /I0*I1*/I2*/I3 + /I0*/I1*I2*I3 + /I0*I1*I2*I3 + I0*I1*I2*I3
    /OD = I0*/I1*/I2*/I3 + /I0*/I1*I2*/I3 + I0*I1*I2*/I3 + /I0*I1*/I2*I3 + I0*I1*I2*I3
    /OE = I0*/I1*/I2*/I3 + I0*I1*/I2*/I3 + /I0*/I1*I2*/I3 + I0*/I1*I2*/I3 + I0*I1*I2*/I3 + I0*/I1*/I2*I3
    /OF = I0*/I1*/I2*/I3 + /I0*I1*/I2*/I3 + I0*I1*/I2*/I3 + I0*I1*I2*/I3 + I0*/I1*I2*I3
    /OG = /I0*/I1*/I2*/I3 + I0*/I1*/I2*/I3 + I0*I1*I2*/I3 + /I0*/I1*I2*I3
    A BCD to 7 segment decoder

    I tried this on the breadboard shown. The output for BCD 0 was correct but nothing changed when I changed the input. Digging deeper shows that there are actually 3 modes of operation. How to select between these modes? There is nothing in the language that states the mode. Ah, it must depend on the labels of the pins. Since I had specified the CLOCK and /OE...

    Read more »

View project log

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates