Program counter circuit: count, jump and reset, live
A program counter (PC) is the register that holds the address of the next instruction. On each clock edge this 4-bit PC does one of four things: RST = 1 sets it to 0, JMP = 1 loads the jump target J3 to J0, INC = 1 adds 1, and otherwise it holds. Reset wins over jump, and jump wins over counting.
Every instruction a processor runs comes from the address in its program counter. Normally the PC just counts: after fetching the instruction at address 5, it moves on to 6. A jump or branch instruction breaks the sequence by loading a new address, which is how loops and if statements work, and reset sends the processor back to the start of its program. The circuit is a 4-bit register with three choices in front of each flip-flop. An incrementer adds 1 the way a synchronous counter does (each bit flips when INC is 1 and every lower bit is 1, so 1111 wraps to 0000); a 2-to-1 multiplexer picks the jump target instead when JMP is 1; and an AND with NOT RST forces 0 for a synchronous reset. With INC at 0 and JMP at 0 the incrementer passes the old value through, so the PC holds, which a CPU uses to wait while a slow instruction finishes. A conditional jump, like JZ in digiwleea's instruction set, is the same circuit with JMP driven by the zero flag. Flip-flops start in an unknown state, so the live circuit opens held in reset: turn RST off and the PC starts counting.
Open this circuit in the lab →
What you need
- 4× D flip-flop: the PC bits, all on one clock
- 4× XOR: incrementer sums: PC_k XOR carry_k
- 3× AND: incrementer carries: INC AND PC0, then AND PC1, then AND PC2
- 8× AND: jump mux: J_k AND JMP, and sum_k AND NOT JMP
- 4× OR: jump mux outputs
- 4× AND: synchronous reset: next_k AND NOT RST
- 2× NOT: NOT JMP and NOT RST
Step by step
- Place a clock
CLK, inputsRST,INC,JMPandJ3toJ0, four D flip-flops on CLK, and probesPC3toPC0. - Incrementer: carry into bit 0 is INC; each bit's sum is PC_k XOR carry_k, and the carry into the next bit is carry_k AND PC_k.
- Jump: for each bit, a 2-to-1 multiplexer chooses J_k when JMP is 1 and the incrementer's sum when JMP is 0.
- Reset: AND each multiplexer output with NOT RST and feed it to the flip-flop's D. Pulse RST, then let it count, hold with INC at 0, and jump by setting J and JMP.
Count, hold, jump and reset
| Clock edge | RST | INC | JMP | J3..J0 | Action | PC3..PC0 | PC |
|---|---|---|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 0000 | reset | 0000 | 0 |
| 2 | 0 | 1 | 0 | 1001 | count | 0001 | 1 |
| 3 | 0 | 1 | 0 | 1001 | count | 0010 | 2 |
| 4 | 0 | 1 | 0 | 1001 | count | 0011 | 3 |
| 5 | 0 | 1 | 0 | 1001 | count | 0100 | 4 |
| 6 | 0 | 1 | 0 | 1001 | count | 0101 | 5 |
| 7 | 0 | 0 | 0 | 0111 | hold | 0101 | 5 |
| 8 | 0 | 0 | 0 | 0111 | hold | 0101 | 5 |
| 9 | 0 | 0 | 1 | 1100 | jump | 1100 | 12 |
| 10 | 0 | 1 | 0 | 0000 | count | 1101 | 13 |
| 11 | 0 | 1 | 0 | 0000 | count | 1110 | 14 |
| 12 | 0 | 1 | 0 | 0000 | count | 1111 | 15 |
| 13 | 0 | 1 | 0 | 0000 | count | 0000 | 0 |
| 14 | 0 | 1 | 1 | 0011 | jump | 0011 | 3 |
| 15 | 0 | 1 | 0 | 0000 | count | 0100 | 4 |
| 16 | 1 | 1 | 0 | 0000 | reset | 0000 | 0 |
This is the exact run checked before the page is built, on all four PC bits after each of the 16 clocks: a reset, five counts, a two-cycle hold (the J inputs change but are ignored), a jump to 12, counting through 15 and wrapping to 0, a jump to 3 while INC is also 1 (the jump wins), one more count and a final reset. A processor core like this sits at the heart of both a microprocessor and a microcontroller; see microprocessor vs microcontroller.
You can also read the full theory in the lesson on the program counter. Prefer to build it yourself from scratch? Open the digiwleea lab and place the gates on the canvas, or start from the logic gate simulator.
More builds: Registers and counters
All 246 build guides, by topic
Each of these is one step from a transistor to a working CPU. Build every gate from CMOS transistors and work all the way up in the free digiwleea lab, with the free theory reference alongside.
Open the 4-bit program counter in the lab →Frequently asked
What is a program counter?
The register in a CPU that holds the memory address of the next instruction to fetch. It normally counts up by one after each fetch, and jumps, branches and calls load it with a new address.
How is a program counter built?
From flip-flops, one per address bit, with logic in front of each: an incrementer that adds 1, a multiplexer that can load a jump address instead, and a reset that clears it. This 4-bit one uses 4 D flip-flops and 25 gates.
What happens to the program counter on a jump?
The jump target is loaded into it on the next clock edge instead of the incremented value, so the next instruction is fetched from the new address. A conditional jump loads it only when a condition, such as the zero flag, is true.
Why does the program counter wrap around?
A 4-bit counter can only hold 0 to 15, so adding 1 to 15 gives 10000, and the fifth bit is lost: the PC becomes 0. Real CPUs have wider program counters, 16, 32 or 64 bits, so programs rarely reach the end.
What is the difference between the program counter and the instruction register?
The program counter holds where the next instruction is (an address); the instruction register holds the instruction itself after it has been fetched from that address.