FPGA Development Board
Custom-designed PCB featuring the Lattice iCE40UP5K FPGA with various peripherals.
[CURRENTLY UNDER CONSTRUCTION!]
Introduction
In this project we take many of the digital logic design concepts from the 3-bit counter project, and supercharge it to explore the world of Field Programmable Gate Arrays (FPGAs).
The 3-bit Counter
A 3-bit counter is a simple digital circuit made up of three flip-flop circuits (one per bit) that steps through
every binary value from 000 to 111 (0–7 in decimal) and then wraps back around to 000. Each clock pulse advances the count
by one, with the least significant bit toggling every pulse and higher bits toggling only when the bit below rolls over. This
gives a neat, orderly binary sequence, which we will visualise via three LEDs for the binary output, and a seven-segment
display for decimal output.
Resistor Transistor Logic - Crossing from Digital to Analog
You are probably already familiar with the primitive logic functions, NOT, AND, OR, XOR and their negations. In the simplest case these logic functions transform two binary inputs A and B into a binary output, Y, corresponding to the given function. For example, Figure 3.1 shows the NAND gate alongside its truth table. The NAND gate is surprisingly versatile and will be of prime importance in the following digital design section.
\[ \begin{array}{cc|c} A & B & Y = \overline{A \,+\, B} \\ \hline 0 & 0 & 1 \\ 0 & 1 & 1 \\ 1 & 0 & 1 \\ 1 & 1 & 0 \end{array} \]
These logic gates are powerful in and of themselves and allow the construction of more complex digital building blocks, eventually all the way to a full CPU. However, how can we build logic gates in the real world? The symbol itself is a 'black-box', abstracting details away from the actual implementation. Surprisingly, logic gates can be implemented in various ways, for example, water valves, relays, Minecraft redstone and of course, transistors. There are many logic families available which use transistor logic. We have selected resistor–transistor logic (RTL) for this project due to its simplicty, from both an implementation and education standpoint.
Resistor–Transistor Logic (RTL) emerged in the early 1960s as one of the first practical digital families built from discrete components. By combining simple resistors for pull-up bias and NPN transistors for pull-down switching, RTL enabled the construction of basic logic. This lead to transistor counts far lower than earlier relay or vacuum-tube systems. Widely used in early computer prototypes and minicomputers, RTL laid the groundwork for more advanced families (DTL, TTL) by demonstrating how discrete components could reliably implement Boolean functions at kilohertz-scale clock rates. Interestingly, RTL was the logic family used in the guidance computers of the Apollo missions!
RTL is remarkably simple, the only components required are NPN bipolar junction transistors (BJTs) and resistors. In each gate, NPN transistors act as pull-down switches, while resistors provide pull-up bias. We use a 0-5 V logic voltage scale, with [0-1] V meaning '0' (LOW) and [3-5] V meaning a '1' (HIGH). In general, AND functions are implemented with BJTs in series, and OR functions with BJTs in parallel. In fact, the natural logic formed by these gates is NAND and NOR, respectively. To save on components (additional NOT gates), we restrict ourselves to these three logic functions. (Aside: one can actually show that any other logic function can be built purely from NAND gates). After experimentation with noise immunity, rise time and (critically) fan-out, 1 kΩ pull-ups were standardised for the collector resistance, whilst 10 kΩ would be used on the gate-inputs to isolate transistor bases and limit drive current. Fan-out refers to the phenomenon where the logical tolerances of a logic gate degrade as it drives an increasing number of inputs. For example, if we connect the output of an RTL NAND gate to the inputs of 6 later-stage gates, each will load some base current through the collector resistor of the previous stage. A voltage divider expression was used to derive a function for the loss in ability of driving a logic HIGH as fan-out increased. As 3V was deemed tolerable to push the BJTs into saturation for a logic HIGH, a rough fan-out limit of 6-8 was calculated and simulatied in JScircuit. Figure 3.1 shows a 2-input RTL NAND gate simulation in JScircuit. Based on the input switches, one can see that this behaviour is consistent with the NAND gate in Figure 3.1. Note that the output produces a clean 5 V when the inputs are LOW, however this voltage will sag when the output drives a gate downstream. Additionally, the output cannot reach a true 0 V due to the V_CE(sat) of the transistors.
Designing Digital Logic Blocks
At the heart of the 3-bit counter are three fundamental subsystems: the edge-triggered master–slave D flip-flops that store each bit, the next-state toggle logic that determines exactly when each flip-flop should change state, and the seven-segment decoder network that converts the binary count into signals for the decimal display. Each of these blocks must operate reliably using only discrete resistor–transistor logic (RTL) components, so we must carefully balance speed, noise margin, and component count while keeping the entire design simple enough for hand-assembly.
3.1 Flip‑Flop Implementation
The D flip‑flop (DFF) is implemented as two gated latches—master and slave—each constructed from cross‑coupled NAND gates and input‑gating transistors. On the falling edge of the clock, the master latch closes and the slave latch opens, capturing the input and securely storing it. We chose 10 kΩ pull‑up resistors and 4.7 kΩ interconnect resistors to optimise propagation delay and maintain robust noise immunity. SPICE simulations confirmed clean edge‑trigger behavior, with setup and hold times around 20 ns and negligible metastability.
3.2 Next‑State Logic Simplification
The combinational logic feeding each D‑FF toggles the stored bit precisely when its lower‑order bit rolls over from 1→0. By plotting Karnaugh maps for each toggle function, we derived minimal sum‑of‑products expressions. For example, the middle bit follows D1 = Q0 ⊕ Q1 = (Q0 & ¬Q1) + (¬Q0 & Q1). We then converted this into NAND‑only form: D1 = NAND( NAND(Q0, Q1), NAND(¬Q0, ¬Q1) ), which reduces transistor count and keeps the design within RTL paradigms.
3.3 Seven‑Segment Decoder Network
The final stage converts the three‑bit binary count into segment signals for the LED display. Each of the seven segments corresponds to a distinct combination of the three bits; we used Karnaugh‑map grouping to share common terms and minimise the total gate count. Each segment line uses two‑input NAND gates followed by current‑limiting resistors (2.2 kΩ) to protect the LEDs. In testing, this network toggled cleanly at up to 1 MHz clock rates without visible flicker.
Simulation
- Hand-soldered all SMD resistors & capacitors.
- Placed BJTs and LEDs, checked orientation.
- Debugged early fan-out issues by increasing pull-ups.
- Cleaned with IPA and fitted into 3D-printed enclosure.
PCB Design with KiCAD 8
- Logic Style: RTL NAND gates built from NPN transistors + pull-up resistors.
- Flip-Flops: D-type, edge-triggered on the falling edge of the clock.
- Counter: Three FFs in series → ripple counter.
- Clock: Manual push-button, hardware-debounced.
Finished Design
Building logic from scratch taught me:
- The real impact of fan-out limits on voltage levels.
- How timing skews arise in ripple counters.
- Why integrated logic is so pervasive—so many transistors cram into each IC!
Conclusion
Building logic from scratch taught me:
- The real impact of fan-out limits on voltage levels.
- How timing skews arise in ripple counters.
- Why integrated logic is so pervasive—so many transistors cram into each IC!