Wednesday, April 9, 2025

Entry 24: Program counter and T-flip-flop

Now that we have a memory system, registers, and a simple ALU, Grok suggested adding a program counter.

Program Counter

Adding a Program Counter (PC) is a fantastic next step, bringing you even closer to a full CPU-like architecture. Let’s dive into what a program counter is, how it fits into your 4-bit address and data bus system, and how you can implement it with your existing components.


What Is a Program Counter?

  • Definition: The Program Counter (PC) is a special-purpose register in a CPU that holds the address of the next instruction to be fetched from memory (RAM in your case). It’s like a pointer that tells the system where to look next in the program sequence.
  • Purpose:
    • Keeps track of the current position in a program stored in memory.
    • Increments automatically after each instruction fetch to point to the next instruction.
    • Can be loaded with a new address for jumps or branches (e.g., in subroutines or loops).

Key Features

  • Size: Matches your address bus—4 bits in your system, addressing 16 locations (0000 to 1111).
  • Operations:
    • Increment: PC = PC + 1 after each fetch.
    • Load: Set PC to a new value (e.g., from data bus or switches).
    • Output: Drives the address bus to select RAM locations.
  • Output Control: Typically uses tri-state outputs to share the address bus with other devices (e.g., MAR).

How It Fits Your Setup

  • Your System:
    • 4-bit address bus (A0–A3) feeding MAR, MUXed with DIP switches to RAM A0–A3.
    • 4-bit data bus (D0–D3) with MDR, RAM, two registers, and ALU (74LS283).
  • PC Role:
    • Adds a sequential address source to your address bus, letting you fetch data or instructions from RAM in order (e.g., a program stored at 0000, 0001, etc.).
    • Works alongside MAR (MAR for specific addresses, PC for program flow).
  • Integration: PC outputs connect to the address bus via tri-state buffers, so it can drive the bus when needed without clashing with MAR or DIP switches.

-end-

That is a lot of information. To break this down, I will start with a 1 bit counter. It will have the following features:

  • It holds the value Q which is 0 or 1. Incrementing the value will take it back to 0.
  • It has a Count pin and a Clock pin.
    • When Count = 1 and clock goes high, Q increments.
    • When Count = 0 and clock goes high, nothing happens.
  • It has a Clear pin. When Clear = 1, Q goes to 0 (independent of Clock).
  • It has a Preset pin. When Preset = 1, Q goes to 1 (independent of Clock).
First, let's focus on the Count, ignoring Clear and Preset for the moment.

1 bit counter

"Lets consider the simplest one bit version that can only count up from 0."

Let’s design the simplest 1-bit up-counter that can only count up from 0, mimicking a basic program counter for a single bit, focusing solely on incrementing from 0 to 1 and wrapping back to 0, using basic gates and a flip-flop. Since it’s a 1-bit counter, it’ll toggle between 0 and 1 with each clock pulse, giving you a minimal yet functional starting point that you can later scale to 4 bits for your full program counter. Here’s how to build it step-by-step.


What It Does

  • Function: Counts up from 0 to 1, then wraps back to 0 on the next clock pulse.
  • Inputs:
    • CLK: Clock signal (e.g., button press) to increment.
  • Output:
    • Q: Current count (0 or 1).
  • Behavior:
    • Starts at 0.
    • Each CLK pulse toggles Q (0 → 1 → 0 → …).
  • Simplifications:
    • No preset (no set to 1).
    • No clear (no reset to 0).
    • No down-counting 

Truth Table

CLK EdgeQ (Current)Q (Next)
Rising01
Rising10

Design Requirements

  • Single Bit: Uses one flip-flop to store Q.
  • Toggle: Q flips (0 to 1, 1 to 0) on each clock pulse.
  • Up Only: No decrement logic needed.

The simplest way to do this is with a T flip-flop (toggle flip-flop).

T flip-flop

T flip-flop changes state on each clock edge. Since T flip-flops aren’t common as standalone ICs (unlike D or JK), we’ll build one using a gated D flip-flop by feeding back the inverted output (Q̅) to the D input.

-tbc-

Remember the gated D flip-flop, see entry 14 (ignoring preset and clear):

It has the following truth table (again, ignoring preset and clear):

So we simply connect Q̅ to D, and rename L to T. We now have a T flip-flop:

  • When T = 0 (gate closed), nothing happens when the clock goes high.
  • When T = 1 and Q = 0, then Q̅ = 1 and D = 1. Now when the clock goes high, Q becomes 1. It only "flip once" since when Q = 1 and Q̅ = 0, the clock is 1 and not rising.
  • When T = 1 and Q = 1, then Q̅ = 0 and D = 0. When the clock goes high, Q becomes 0.

The T flip flop is precisely a 1 bit counter. I designed a T flip-flop called "TFlipFlop" from the gated D flip-flop by connecting Q̅ to D (it also has a Preset (setting Q to 1) and a Clear (setting Q to 0):

Try it out on Wokwi, project "T flip-flop". When T = 1, Q goes on and off on each clock signal.

There is another type of flip-flop, that I have not yet looked at, the JK flip-flop. Compared to the T flip-flop, the JK flip-flop has two input pins, "J" and "K", instead of the input pin "T". If the pins J and K are connected, then it is equivalent to a T flip-flop where T = J = K. 

Let's extend this to a four bit counter,.. in the next entry.






No comments:

Post a Comment