Lesson 1. BCD → 7-segment decoder

In pictures

Four switches set a digit 0–9 in binary; a circuit of gates lights the right bars of that digit on a segment LCD. This is the first building block of the watch / Game & Watch: time is stored inside as binary numbers, but the screen needs digits made of bars. Between them sits a decoder — a circuit without memory that decides, from 4 bits, which of the 7 segments to light.

Result: chip DEC4x1, 150 transistors, all 10 digits correct.


0. What you need to know

BCD — every decimal digit is stored in 4 bits: D3 D2 D1 D0 (D3 is the most significant). 5 = 0101, 9 = 1001. The combinations 1010…1111 (10–15) never occur in BCD.

Segments are named by letters — a on top, then clockwise, g in the middle:

abcdefg
The seven segments of a digit and their names: a on top, then clockwise, g in the middle

1. The screen

  1. Place a Segment LCD (palette, the read-out icon next to the dot display).
  2. ⚙ → Size field: 24 × 30 (click the number, type, Enter).
  3. Right panel Stamps → size L 21 → section Digits → first tile (the eight without a point) → click in the middle of the field → Esc.
  4. S (select) → magic-wand click on the top segment → Enter (New pin) → name a → Enter. Clockwise the same way: top-right b, bottom-right c, bottom d, bottom-left e, top-left f, middle g.
  5. Close the editor. The body now has 7 pins a…g → hang labels a b c d e f g on them.

2. Inputs

Four Input switches → labels D0 D1 D2 D3. For convenience add a Display (bus) on D0..D3 to see the number.


0D31D20D11D0switchesDEC4x1no memoryabcdefgLCD shows "5"0101 = 5
The whole of lesson 1: four bits 0101 (= 5) enter the decoder, which lights segments a, c, d, f, g — the LCD shows a five. The decoder outputs reach the LCD pins through labels with the same letters.

3. Method: truth table → formula

Step 1. A table row = one AND of all inputs. An input that is 1 in that row is taken as is; an input that is 0 goes through NOT (a label with the prefix n: nD0 = NOT D0). Such an AND is 1 in exactly that row.

Step 2. OR all those ANDs together. The formula is already correct, just long.

Step 3. Simplify.

  • Strike out an input: the struck-out position "flips" → a row gets added. If the added row is a free one (10–15) — striking out is allowed. If it is a real digit with a different value of the segment — not allowed. ⚠ The test is exactly "which row gets added", not "this input is the same in all my rows". Digits 8 and 9 are real.
  • Merge two rows: if they differ in exactly one input, the pair = one AND without that input (X·B + X·¬B = X). One row may be used in several merges.
  • Factor out a common term: nD0·nD2 + nD0·D1 = nD0·(nD2 + D1).

If there are fewer zeros than ones — it is easier to describe when the segment is off and invert at the end. "OR, then NOT" = one NOR gate; "AND, then NOT" = one NAND — fewer transistors (in CMOS the native gates are exactly NAND and NOR; AND = NAND + NOT).

⚠ Trap: you can't chain NAND or NOR to get "more inputs" — each one adds its own NOT. NAND(NAND(A,B),C) is not NAND3 (on 111 it gives 1). Correct: NAND(AND(A,B), C). AND and OR can be chained: AND(AND(A,B),C) is an honest AND3.

Reuse. The same "digit detector" (for example, the AND for one) is needed by several segments — build it once, put a label on it, refer to the label.


4. Truth table

DigitD3 D2 D1 D0abcdefg
00 0 0 01111110
10 0 0 10110000
20 0 1 01101101
30 0 1 11111001
40 1 0 00110011
50 1 0 11011011
60 1 1 01011111
70 1 1 11110000
81 0 0 01111111
91 0 0 11111011
10-15freeanything — may be used when simplifying

5. Deriving each segment

Segment a — off on 1, 4

RowANDStrike out → addsResult
1 = 0001nD3·nD2·nD1·D0nD3 → 1001 = 9 (a=1) ✗
the others are digits too ✗
nD3·nD2·nD1·D0
4 = 0100nD3·D2·nD1·nD0nD3 → 1100 = 12, free ✓D2·nD1·nD0
example: digit 4 = 0100nD3=1nD2=0nD1=1D0=0AND4: "it is 1"D2=1nD1=1nD0=1AND3: "it is 4"01NORa = 0segment off
Segment a = NOR("it is 1", "it is 4"). On digit 4 the "it is 4" detector fires and the NOR turns segment a off — a four has no top bar.

a = NOR( nD3·nD2·nD1·D0 , D2·nD1·nD0 )

Segment b — off on 5, 6

Observation: when D2 = 0 it is always on → term nD2. When D2 = 1 it is on for 4 (00) and 7 (11) — when D1 and D0 are equal → nD1·nD0 + D1·D0.

b = nD2 + nD1·nD0 + D1·D0 (shorter: b = NAND( D2, XOR(D1, D0) ) — 2 gates)

Segment c — off on 2

RowANDStrike out → addsResult
2 = 0010nD3·nD2·D1·nD0nD3 → 1010 = 10, free ✓
nD2 → 0110 = 6 ✗
D1 → 0000 = 0 ✗
nD0 → 0011 = 3 ✗
nD2·D1·nD0

c = NAND3( nD2, D1, nD0 ) — built as NAND + NOT + NAND = 10 transistors (the first try, AND4 + NOT, would be 20: AND4 = three ANDs of 6). An honest CMOS NAND3 from transistors is 6 (see section 7).

Segment d — off on 1, 4, 7

RowANDStrike out → addsResult
1 = 0001nD3·nD2·nD1·D0every one gives a digit (9,5,3,0) ✗nD3·nD2·nD1·D0 (=1)
4 = 0100nD3·D2·nD1·nD0nD3 → 1100 = 12 ✓D2·nD1·nD0 (=4)
7 = 0111nD3·D2·D1·D0nD3 → 1111 = 15 ✓D2·D1·D0 (=7)

d = NOT( 1 + 4 + 7 ) — the "1" and "4" detectors are already built for a, reuse them.

Segment e — on for 0, 2, 6, 8 (fewer ones — take them, no NOT at the end)

Merges (pairs differing in one input; 10 and 14 are free):

RowsDiffer inGives
0, 2, 8, 10D3, D1nD2·nD0
2, 6, 10, 14D3, D2D1·nD0

e = nD2·nD0 + D1·nD0 → factor out nD0: e = nD0 · (nD2 + D1) — 2 gates.

Segment f — off on 1, 2, 3, 7

WhatHowGives
1 = 0001can't drop nD3: adds 9 (f=1) ✗nD3·nD2·nD1·D0
2 and 3 (+10, 11)differ in D0nD2·D1
3 and 7 (+11, 15)differ in D2D1·D0

f = NOT( 1 + nD2·D1 + D1·D0 ) — reuse "1"; D1·D0 is shared with b.

Segment g — off on 0, 1, 7

WhatHowGives
0 and 1differ in D0; can't drop nD3 (8, 9)nD3·nD2·nD1
7 = 0111nD3 → 1111 = 15 ✓D2·D1·D0 (=7)

g = NOR( nD3·nD2·nD1 , 7 )


6. Assembly

Helper gates with 3–4 inputs

Built as chains of two-input gates and folded with Ctrl+G into chips (input ports A B C [D], output Y):

ElementInputsOutput (→)
AND3
ANDA, Bab
ANDab, CY
AND4
ANDA, Bab
ANDab, Cabc
ANDabc, DY
OR3
ORA, Bab
ORab, CY
NAND3
NANDA, Bnab
NOTnabab
NANDab, CY

The decoder DEC4x1

INPUT PORTS: D0 D1 D2 D3 · OUTPUT PORTS: a b c d e f g

ElementInputsOutput (→)
NOTD0nD0
NOTD1nD1
NOTD2nD2
NOTD3nD3
AND4nD3, nD2, nD1, D0nD3nD2nD1D0← digit 1
AND3D2, nD1, nD0D2nD1nD0← digit 4
AND3D2, D1, D0D2D1D0← digit 7
ANDD0, D1D0D1
NORnD3nD2nD1D0, D2nD1nD0a
ANDnD0, nD1nD1nD0
ORnD1nD0, D0D1b_low
ORnD2, b_lowb
NAND3nD2, D1, nD0c
OR3nD3nD2nD1D0, D2nD1nD0, D2D1D0d_off
NOTd_offd
ORnD2, D1e_or
ANDe_or, nD0e
ANDnD2, D1nD2D1
OR3nD3nD2nD1D0, nD2D1, D0D1f_off
NOTf_offf
AND3nD3, nD2, nD1nD3nD2nD1
NORnD3nD2nD1, D2D1D0g

(Nets like b_low, d_off, e_or, f_off, nD2D1, nD3nD2nD1 can be plain wires without a name — the names are only there so the table reads clearly.)

Fold into a chip: select everything and Ctrl+G → chip DEC4x1, input ports D0 D1 D2 D3, output ports a b c d e f g. On the canvas: switches D0..D3 → DEC4x1 → labels a..g → LCD pins.

Test: click the switches through 0000…1001 — every digit looks like a real one.

What it shows for 10–15: the digits 2, 3, 4, 5, 6, 7 — because we dropped D3 almost everywhere. That's the price of simplifying: on numbers that never occur the screen draws whatever (the real 7447 chip does the same).


7. Even cheaper (for later)

SegmentAs builtShorter
bAND + OR + ORXOR(D1,D0) + NAND(D2, ·)
cNAND3 from NAND+NOT+NAND (10)NAND3 from transistors (6)
dOR3 + NOTNOR3 (6 transistors)
fOR3 + NOTNOR3
gAND3(nD3,nD2,nD1)same formula; 7 is already D2D1D0 ✓

NAND3 from transistors: 3 pmos in parallel (VCC ↔ Y), 3 nmos in series (Y → … → GND). NOR3 is the opposite: 3 pmos in series, 3 nmos in parallel.


8. The whole lesson as one paste (Cmd+I)

Creates AND3 AND4 OR3 NAND3 DEC4x1 in the library and places power, 4 switches D0..D3 and DEC4x1 with labels a..g on the canvas.

  • Paste into a project where these chips don't exist yet (otherwise the library gets two with the same name).
  • The netlist language does not describe the Segment LCD — place it by hand following section 1 and hang the labels a..g on its pins.
chip AND3 {  portIn(A)  portIn(B)  portIn(C)  portOut(Y)  AND(A, B, ab)  AND(ab, C, Y)} chip AND4 {  portIn(A)  portIn(B)  portIn(C)  portIn(D)  portOut(Y)  AND(A, B, ab)  AND(ab, C, abc)  AND(abc, D, Y)} chip OR3 {  portIn(A)  portIn(B)  portIn(C)  portOut(Y)  OR(A, B, ab)  OR(ab, C, Y)} chip NAND3 {  portIn(A)  portIn(B)  portIn(C)  portOut(Y)  NAND(A, B, nab)  NOT(nab, ab)  NAND(ab, C, Y)} chip DEC4x1 {  portIn(D0)  portIn(D1)  portIn(D2)  portIn(D3)  portOut(a)  portOut(b)  portOut(c)  portOut(d)  portOut(e)  portOut(f)  portOut(g)  NOT(D0, nD0)  NOT(D1, nD1)  NOT(D2, nD2)  NOT(D3, nD3)  AND4(nD3, nD2, nD1, D0, nD3nD2nD1D0)  AND3(D2, nD1, nD0, D2nD1nD0)  AND3(D2, D1, D0, D2D1D0)  AND(D0, D1, D0D1)  NOR(nD3nD2nD1D0, D2nD1nD0, a)  AND(nD0, nD1, nD1nD0)  OR(nD1nD0, D0D1, b_low)  OR(nD2, b_low, b)  NAND3(nD2, D1, nD0, c)  OR3(nD3nD2nD1D0, D2nD1nD0, D2D1D0, d_off)  NOT(d_off, d)  OR(nD2, D1, e_or)  AND(e_or, nD0, e)  AND(nD2, D1, nD2D1)  OR3(nD3nD2nD1D0, nD2D1, D0D1, f_off)  NOT(f_off, f)  AND3(nD3, nD2, nD1, nD3nD2nD1)  NOR(nD3nD2nD1, D2D1D0, g)} power(VCC)ground(GND)input(D0)input(D1)input(D2)input(D3)DEC4x1(D0, D1, D2, D3, a, b, c, d, e, f, g)

¿No te sale? Algo no funciona →