Designing and Building a Hexadecimal Display for Small Computer and Logic Projects.
I do digital design regularly, and it’s occasionally real handy to take a group of signals (e.g. an address bus) and display them. I don’t have a lot of great tools to do that though.
Ordinarily I’d hook up my logic analyzer. That would do the job, yes. But the logic analyzer is a complex instrument, that requires a lot of setup. It’s not a tool to just pull out for every little task. Just setting up the display takes forever.
Logic probes can be used for individual signals. A simple logic probe is easy to build, cheap to buy, and limited in capability. You only get one bit, and maybe a clock indicator. Better than the logic analyzer for small jobs, but not suitable for displaying a lot of bits together.
A small display, capable of showing 16 bits in hexadecimal format would be ideal. These can be directly matched against assembler output or ROM images and the like. It would also work as a simple output device for a digital system under development.
Building such a display isn’t that complicated. All you need are some standard logic parts and a little electronics know-how. It only took me a few hours to get this display working. Well worth the time!
Inspiration partly taken from Hex Out, partly from my own previous designs.
Hexadecimal Display Design
In order to display binary input as hexadecimal, three things must happen:
- Divide the input into 4 bit segments
- Convert each 4 bit segment to hexadecimal output compatible with the display
- Display the numbers 0-9, and letters A-F in an unambiguous way
Each of these tasks can be done in multiple ways, from brute force to Wozniak level logic knots. I simply chose methods that fit the parts I had to hand. Where I had a choice, I prioritized keeping the logic simple and part counts low.
7 Segment LED Displays
LEDs are the go-to choice for small displays: self luminous, easy to drive, relatively low power. Every gadget has at least one LED on it, if only to tell you it’s “ON”.
Many displays are simply bare LEDs, but there exist special displays to display numbers or letters. Of these “alphanumeric” displays, 7 segment displays are the most common.
Seven segments turns out to be the practical minimum to display numbers. Letters can be displayed too, but there are some… limitations.
Displays with more segments do a better job of displaying letters, but it’s irrelevant since the basic 7 segment version can do ABCDEF without too much trouble.
So-called “7” segment displays are actually 8 segment displays. Each digit typically includes a free decimal point. I don’t have any use for decimal points here, but I might have some application that needs them later on. Might as well point it out.
Hexadecimal to 7 Segment Decoder
Being a common type of display, there are a lot of ICs designed to drive 7 segments. BCD decoders are common; many ASICs have decoding logic built right in. What is conspicuously missing is hexadecimal decoders. A handful of parts supported hexadecimal display, none of which seem to be in production for the past few decade3s. It’ll have to be a custom job.
Making a hex to 7 segment display decoder is a first year logic project. Literally, we made one halfway through Digital Logic class. Gate level design is pretty simple, but why bother? GAL16V8s exist; they are more than powerful enough to do this job. Any other PLD, or even just a ROM makes for a single chip solution.
What would be a tedious gate level design process becomes a fast “type a few lines” process. My only challenge is not poking WinCUPL hard enough to crash it. Which it does. All the time.
Multiplexing Logic
By far the easiest way to make a four digit display is to buy four displays, four decoders, four drivers, and just plug them together as separate units.
Without multiplexing, every digit in the display is it’s own self-contained system. Simple, but that’s a lot of redundant parts.
There is no problem with doing things this way- many devices do. What is problematic is that decoders, displays, and drivers can be expensive. Not just in terms of money; physical space is always a concern. Pins and wires take up way more space than you think they should.
Multiplexing the display allows common components to be re-used. In this case, the display driver and decoder can be shared for each digit. These are the most expensive parts of the display (other than the display itself), so it’s a good design choice.
Multiplexing reduces the driver and decoder to just one unit. We had to add the logic to section up the input and select the corresponding digit though.
Obviously this requires some extra logic to switch between the active digit. This extra overhead must be balanced against adding those extra drivers/decoders. For more than one or two digits, multiplexing is usually a worthwhile trade-off.
Since the simple design would take up way too much resources, I designed around multiplexing from the start.
Building the Hexadecimal Display
Most of the complexity came in the design stage. Actually building the display mostly consists of plugging standard parts together.
For now I’ll settle for a breadboarded prototype. I have most of the required logic in DIP packages, what I don’t have to hand can be easily built from discrete parts.
Display
Let’s start with the display. To save pins all the connections on one side of the LEDs are grouped together. My particular module has common cathodes, one per digit. Segments are grouped together too. To light a particular segment on a particular digit, you simply connect the segment line to positive voltage and the digit line to ground.
Segments might need up to 30mA each. All segment current passes through the common cathode. A fully lit display therefore requires up to 250mA, depending on the chosen segment current.
Driving this current is not trivial. Logic ICs are usually not intended to drive heavy loads- 10mA alone is a lot for HC logic. Clearly a power amplifier is needed.
One important gotcha is that datasheets list per-pin current limits separately from the total supply current limit. While the pin limit might be 25mA, the supply total might be limited to 50mA. If you have more than two outputs, you can’t run them all to 25mA.
Output might not be symmetric either- TTL can sink 10x or more than it can source.
After considering some one-chip solutions, I decided to just use discrete transistors. A PNP 2N3906 works as a high side switch, so long as you can pull the base up to the emitter. Seven PNP transistors make up the segment drivers.
Simple drivers work when the display voltage is close to the logic voltage. Otherwise the level shifter must be used.
Open collector outputs can replace the NPN in the shifted driver, if the OC output can withstand Vdisplay.
Without multiplexing, you’d just slap one driver on each display and be done with it. Multiplexing demands you put drivers on the other side too, so each digit can be individually addressed.
On the low side, a simple NPN switch will work. A 2N3904 in TO-92 can handle 200mA continuously. Multiplexing means the average current is lower, so they can handle the 250mA design load. A 2N2222 would work up to about 1A. More than that and you’ll need a proper power transistor. Possibly a heatsink too. Watch out for that base current!
Much simpler on the bottom. Notice the HC04 inverters- NPN transistors need the opposite polarity of the input buffer enables.
Whew. That’s a lot of circuit just to light some LEDs up! It’s a necessary complication, well worth a thorough consideration.
Decoder
Not much to say here- using a GAL cuts out most of the work. Decoding is just a simple truth table assignment, so a CUPL TABLE does all of the heavy lifting:
Name HexDisplay ;
PartNo 00 ;
Date 23-Aug-22 ;
Revision 01 ;
Designer ;
Company SDR ;
Assembly None ;
Location ;
Device g16v8;
/* *************** INPUT PINS ******************** */
PIN 2 = D3; /* MSB */
PIN 3 = D2;
PIN 4 = D1;
PIN 5 = D0;
/* *************** OUTPUT PINS *********************/
PIN 19 = seg0; /*Segment G*/
PIN 18 = seg1;
PIN 17 = seg2;
PIN 16 = seg3;
PIN 15 = seg4;
PIN 14 = seg5;
PIN 13 = seg6; /*Segment A*/
FIELD input = [D0..3];
FIELD output = [O0..6]; /*Decouples segments to simplify inverted output*/
FIELD segments = [seg0..6];
segments = !output;
TABLE input => output {
0=>3F; 1=>06; 2=>5B; 3=>4F;
4=>66; 5=>6D; 6=>7D; 7=>07;
8=>7F; 9=>6F; A=>77; B=>7C;
C=>39; D=>5E; E=>79; F=>71;
}
I spent more time picking which pins to use than thinking about the logic. The only catch is sometimes you want postive-true outputs, and sometimes you need negative-true ones. Using a pin to swap polarity was thwarted by product term limits.
Multiplexer
The final subsystem is the multiplexing logic. This divides the input and output into four discrete sections. We save an expensive decoder, but multiplexing is not free and it requires it’s own overhead.
Displays are multiplexed by turning them on and off in sequence. Do this fast enough and the display looks static. Anything over 50Hz is good, a common range is 100-200Hz.
Clearly we need a counter of some sort. I’ll stop you right there- none of the standard counter ICs will work. They’re too much for such a small counter. I chose to build a small Johnson counter out of some flipflops and NAND gates. I could use another GAL, but it would barely be filled.
This simple counter lights each digit sequentially. Each digit is on for 25% of the time, so the oscillator actually runs at about 400Hz to get the 100Hz nominal refresh rate.
An oversight with this design is that the ‘244s need a LOW input, but the driver transistors might need either polarity. Common cathode displays need HIGH outputs for their drivers, which is why those HC04 inverters are there.
Retrospectively, an HC4017 or HC4022 would have worked a little better. You still have to deal with output inversion though.
Completed Hexadecimal Display
Even with some omissions, this is about what you can fit on one sheet of A4.
Fully assembled and functional.
I could squeeze the input buffers onto the top breadboard, but that would be far less convenient to wire up.
As far as projects go, most of the challenge is getting everything to fit together on one sheet. Same for the breadboard. Component layout could be tighter, but it’s good enough.
Testing the Hexadecimal Display
As always, I test things as I build them. This time around there weren’t too many problems, just some oversights.
One of the inverters on the HC04 was stuck at high, but swapping in one of the spare inverters in fixed that.
At first the GAL output was inverted. Input bits were transposed too. A quick trip back to WinCUPL fixed that in less than a minute. Ah, the wonders of programmable logic!
Unfortunately I made a rather foolish error by confusing the 74×541 with the 74×244. The former is an 8 bit buffer with it’s enable inputs gated together. It’s the latter, with independent 4 bit buffers that I wanted. I found a few ‘244s, but only in TLL. GAL inputs are TLL compatible, so no issues there. Swapping them out was not trivial, but pretty quick nonetheless.
When it was all put together, I handwired some simple test patterns.
I’m running each segment at a dim 6mA or so. Multiplexing means each digit is only about 1/4 as bright as a static one. Bumping that up would require some lower value resistors, but I don’t have any suitable ones right now. Getting the camera to see it is tricky, but it’s easy to see by eye if you don’t shine light directly on the display.
A fun thing to do is driving the multiplexer with a variable speed clock. Just turn it up, and watch the digits fuse together into a static display:
Cool.
Also cool are the odd flickering patterns the digits make. That’s due to the multiplexing aliasing with the camera shutter. The effect is similar to a strobe light, where some things appear to be standing still or even moving backwards. Getting good video of a multiplexed display can be tricky!
All looks good to me. I’ll stop development here for now.
Finishing Up
Much of August was spent not working on cool projects, but sorting out back-end website issues. Turns out having your server implode negatively impacts productivity- who knew? Google is taking forever to re-index everything, and I just haven’t been my best these past weeks. Being able to finish a project, more or less in one shot, is a real pick-me-up.
Designing the hexadecimal display is a nice exercise in digital logic. As a project it sits on that boundary of being complex enough to require some serious thought, but simple enough to complete quickly. The product is useful in itself too; it’s not just a learning exercise.
While I needed a hexadecimal display, there’s no reason other output formats couldn’t be used. BCD is the obvious one; in that case you can replace the GAL with a 4511 or similar. I suppose you could display octal or some other base, but you’d have to rewire the input to work with different numbers of bits.
I would like to build a more permanent display. That requires some extra work; some new parts too. It’ll have to be a separate article, since it’s turning out way more complicated than I expected.
LEDs have a good mix of affordability, flexibility, and ease of use- but they’re not the only way to display stuff. With an appropriate driver, the same logic can be used with neon tubes, light bulbs, mechanical shutters, and plenty more.
14 or 16 segment displays could be used, but the GAL16V8 isn’t powerful enough to decode that many segments. Maybe you could do it with some clever output logic- there’s food for thought.
Four hex digits is enough to display a 16 bit value, which is plenty enough for small computers. Expanding the display is easy, you just add more input buffers, more digits, and use a slightly bigger counter. Eight digits seems like the practical limit. More and you run into multiplexing problems. Going the other way is easier. 8 bits requires just one counter bit with no decoding; 4 bits is just a direct connection.
Digital design is probably the closest thing I have to an “expertise”. I always found it enjoyable, and I have spent plenty of time drawing up truth tables and gate diagrams. Tumultuous life events aside, I have been working towards getting back into 6502 projects as well as far more advanced computer design. I also have some interesting digital side-projects in the works. All of them can benefit from a good plug-and-play display.
That will all happen next time. I still have plenty of back-end stuff to work on, so timing might have to be a bit… flexible for the foreseeable future.
Have a question? Comment? Insight? Post below!