The JK Flip-Flop, Fully Traced
A ground-up walkthrough of the most versatile 1-bit memory element in digital design — the logic behind it, its truth and excitation tables, a NAND-gate schematic, and working algorithms in pseudocode, Python, C, and Verilog.
01 · Foundations
What a Flip-Flop Actually Does
A flip-flop is a bistable circuit — it can sit in exactly one of two stable states, 0 or 1, and it holds that state until it's told to change. That "holding" behavior is what gives digital circuits memory. Chain enough flip-flops together and you get registers, counters, and eventually entire processors.
The JK flip-flop is often introduced as the "fixed" version of the SR (Set-Reset) latch. An SR latch has one dangerous blind spot: if both S and R are driven to 1 at the same time, the output becomes undefined. The JK flip-flop closes that gap — when both its inputs J and K are 1, instead of an invalid state, the output simply toggles. That one design decision is why the JK flip-flop shows up everywhere from counters to shift registers.
02 · Schematic
Logic Symbol & NAND-Gate Implementation
Below is a classic NAND-based JK flip-flop built from a cross-coupled latch with two feedback lines — Q and Q' are routed back into the input gates. This feedback is exactly what lets the circuit "remember" its last state and is the mechanism behind the toggle behavior.
03 · Behavior
Truth Table
Qâ‚™ is the present state (before the clock edge) and Qâ‚™₊₁ is the next state (after the clock edge).
| J | K | Qâ‚™ | Qâ‚™₊₁ | Action |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | HOLD |
| 0 | 0 | 1 | 1 | HOLD |
| 0 | 1 | 0 | 0 | RESET |
| 0 | 1 | 1 | 0 | RESET |
| 1 | 0 | 0 | 1 | SET |
| 1 | 0 | 1 | 1 | SET |
| 1 | 1 | 0 | 1 | TOGGLE |
| 1 | 1 | 1 | 0 | TOGGLE |
Characteristic Equation
The entire table above collapses into one Boolean expression, which is what you'd actually implement in code or use for state-machine analysis:
Excitation Table
Useful in reverse — when designing a sequential circuit, this tells you what J and K must be set to, to move from a known Qâ‚™ to a desired Qâ‚™₊₁.
| Qâ‚™ | Qâ‚™₊₁ | J | K |
|---|---|---|---|
| 0 | 0 | 0 | X |
| 0 | 1 | 1 | X |
| 1 | 0 | X | 1 |
| 1 | 1 | X | 0 |
X = don't care — either 0 or 1 works for that transition.
04 · Design Caveat
The Race-Around Condition
A plain level-triggered JK flip-flop has a flaw: if J = K = 1 and the clock stays high for longer than the gate propagation delay, the output can toggle repeatedly within a single clock pulse — an unpredictable oscillation called the race-around condition.
The standard fix is the master-slave JK flip-flop: two JK stages in series, with the master driven by the clock and the slave by its complement. The master captures the input while the clock is high; the slave only updates once the clock goes low, so the output changes at most once per clock cycle. Nearly every JK flip-flop used in real designs today is a master-slave or edge-triggered variant for exactly this reason.
05 · Algorithm
Generalized Algorithm
Whether you're modeling this in software, HDL, or a microcontroller-driven simulation, the logic reduces to a simple decision procedure evaluated on every active clock edge:
BEGIN JK_FlipFlop(J, K, Q_current) // Executes once per active clock edge IF J == 0 AND K == 0 THEN Q_next = Q_current // HOLD ELSE IF J == 0 AND K == 1 THEN Q_next = 0 // RESET ELSE IF J == 1 AND K == 0 THEN Q_next = 1 // SET ELSE IF J == 1 AND K == 1 THEN Q_next = NOT Q_current // TOGGLE END IF RETURN Q_next, NOT Q_next // Q, Q' END
06 · Implementation
Python Simulation
A small class-based simulator you can drop into a notebook to step through clock pulses and print state transitions:
class JKFlipFlop: def __init__(self, initial_state=0): self.Q = initial_state def clock_edge(self, J, K): """Evaluate one active clock edge and update state.""" if J == 0 and K == 0: pass # hold elif J == 0 and K == 1: self.Q = 0 # reset elif J == 1 and K == 0: self.Q = 1 # set elif J == 1 and K == 1: self.Q = 1 - self.Q # toggle return self.Q, 1 - self.Q # --- demo: step through a sequence of (J, K) inputs --- ff = JKFlipFlop() sequence = [(0,0), (1,0), (0,0), (1,1), (1,1), (0,1)] for i, (J, K) in enumerate(sequence): Q, Qn = ff.clock_edge(J, K) print(f"clk{i}: J={J} K={K} -> Q={Q} Q'={Qn}")
[(1,1)] * 5 through this class and watch Q alternate on every call — that's the toggle behavior driving binary counters in hardware.
C Implementation (Embedded / Firmware Style)
For microcontroller or bit-level simulation work, here's the same logic in C using bitwise operations:
#include <stdio.h> typedef struct { unsigned char Q; } JKFlipFlop; void clock_edge(JKFlipFlop *ff, unsigned char J, unsigned char K) { if (!J && !K) { /* hold: Q unchanged */ } else if (!J && K) { ff->Q = 0; /* reset */ } else if (J && !K) { ff->Q = 1; /* set */ } else { ff->Q = !ff->Q; /* toggle */ } } int main(void) { JKFlipFlop ff = { 0 }; unsigned char J_in[] = {0,1,0,1,1,0}; unsigned char K_in[] = {0,0,0,1,1,1}; for (int i = 0; i < 6; i++) { clock_edge(&ff, J_in[i], K_in[i]); printf("clk%d: J=%d K=%d -> Q=%d\n", i, J_in[i], K_in[i], ff.Q); } return 0; }
Verilog (Hardware Description)
And finally, the version you'd actually synthesize onto an FPGA — an edge-triggered, master-slave-equivalent JK flip-flop with asynchronous reset:
module jk_flip_flop ( input wire clk, input wire rst_n, // active-low async reset input wire J, input wire K, output reg Q, output wire Qn ); assign Qn = ~Q; always @(posedge clk or negedge rst_n) begin if (!rst_n) Q <= 1'b0; else case ({J, K}) 2'b00: Q <= Q; // hold 2'b01: Q <= 1'b0; // reset 2'b10: Q <= 1'b1; // set 2'b11: Q <= ~Q; // toggle endcase end endmodule
posedge clk: synthesizing to a real edge-triggered flip-flop (rather than a level-sensitive latch) is exactly what eliminates the race-around problem discussed above — the output can only change once, at the rising clock edge.
07 · Where It's Used
Real Applications
- Binary counters — tie J = K = 1 and every clock pulse toggles Q, producing a divide-by-2 frequency output; cascade stages for divide-by-N counters.
- Shift registers — chains of JK flip-flops move data one bit per clock cycle, used in serial-to-parallel conversion.
- Frequency dividers — the toggle mode alone is the simplest way to halve a clock frequency in hardware.
- Finite state machines — the excitation table above is the standard tool for deriving next-state logic when designing FSMs with JK flip-flops.

0 Comments