Close

A BCD to 7-segment decoder with a GAL

A project log for Adventures in programmable logic devices

Educating myself about GALs, CPLDs, FPGAs and similar devices

ken-yapKen Yap 04/02/2024 at 14:312 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.

GAL16V8
gal7seg

CLOCK I0    I1    I2    I3    NC    NC    NC    NC   GND
/OE   OA    OB    OC    OD    OE    OF    OG    NC   VCC

define(`B0',`/I0*/I1*/I2*/I3')dnl
define(`B1',`I0*/I1*/I2*/I3')dnl
define(`B2',`/I0*I1*/I2*/I3')dnl
define(`B3',`I0*I1*/I2*/I3')dnl
define(`B4',`/I0*/I1*I2*/I3')dnl
define(`B5',`I0*/I1*I2*/I3')dnl
define(`B6',`/I0*I1*I2*/I3')dnl
define(`B7',`I0*I1*I2*/I3')dnl
define(`B8',`/I0*/I1*/I2*I3')dnl
define(`B9',`I0*/I1*/I2*I3')dnl
define(`BA',`/I0*I1*/I2*I3')dnl
define(`BB',`I0*I1*/I2*I3')dnl
define(`BC',`/I0*/I1*I2*I3')dnl
define(`BD',`I0*/I1*I2*I3')dnl
define(`BE',`/I0*I1*I2*I3')dnl
define(`BF',`I0*I1*I2*I3')dnl

/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

DESCRIPTION

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:

GAL16V8
gal7seg

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

DESCRIPTION

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 inputs, I was in mode 3 and the outputs were registers. Since this is a combinatorial circuit, I actually want mode 2. So the revised specification is this:

GAL16V8
gal7seg

NC    I0    I1    I2    I3    NC    NC    NC    NC   GND
NC    OA    OB    OC    OD    OE    OF    OG    NC   VCC

define(`B0',`/I0*/I1*/I2*/I3')dnl
define(`B1',`I0*/I1*/I2*/I3')dnl
define(`B2',`/I0*I1*/I2*/I3')dnl
define(`B3',`I0*I1*/I2*/I3')dnl
define(`B4',`/I0*/I1*I2*/I3')dnl
define(`B5',`I0*/I1*I2*/I3')dnl
define(`B6',`/I0*I1*I2*/I3')dnl
define(`B7',`I0*I1*I2*/I3')dnl
define(`B8',`/I0*/I1*/I2*I3')dnl
define(`B9',`I0*/I1*/I2*I3')dnl
define(`BA',`/I0*I1*/I2*I3')dnl
define(`BB',`I0*I1*/I2*I3')dnl
define(`BC',`/I0*/I1*I2*I3')dnl
define(`BD',`I0*/I1*I2*I3')dnl
define(`BE',`/I0*I1*I2*I3')dnl
define(`BF',`I0*I1*I2*I3')dnl

/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

DESCRIPTION

A BCD to 7 segment decoder

I flashed the .jed file to the GAL and testing the chip on the breadboard showed that the specification was correct.

Discussions

Dave Henry wrote 04/04/2024 at 10:17 point

I have done quite a bit on ATF22V10 and the ATF16V8 so would be interested in your experiences. I use WinCupl (buggy, close project view seems to stop most crashes) and Xgpro/T56 programmer. I have been trying to get the 40 pin ATF2500C to work without much success so far.

Main issue with the ATF16V8 and ATF22V10 is that they can only have 1 clock for the D flip-flops, where as ATF2500C can have many clocks. For projects like video controllers having multiple clocks per PLD reduces the chip count.

  Are you sure? yes | no

Ken Yap wrote 04/04/2024 at 10:33 point

It may be a while before I get to the higher pin count GALs if at all.

  Are you sure? yes | no