Topic 09 · Digital Electronics

Shift Registers

SISO, SIPO, PISO, PIPO — all four types with an interactive simulator, universal shift register, bidirectional operation, and real VLSI applications including scan chains and SPI.

Four Types of Shift Registers

A shift register is a chain of D flip-flops where each flip-flop's output feeds the next one's input. Data shifts one position on every clock edge. The four types differ in how data enters and exits.

SISO
Serial-In, Serial-Out
Data enters one bit at a time from one end and exits one bit at a time from the other. Acts as a programmable delay line — N flip-flops = N-clock delay.
Delay line · Synchronizer
SIPO
Serial-In, Parallel-Out
Data enters serially. After N clocks all bits appear simultaneously on parallel outputs. The core of SPI receiver and serial-to-parallel conversion.
SPI RX · UART · Display driver
PISO
Parallel-In, Serial-Out
All N bits are loaded simultaneously on a LOAD pulse, then shifted out one bit per clock. The core of SPI transmitter and parallel-to-serial conversion.
SPI TX · CRC engine · Data compression
PIPO
Parallel-In, Parallel-Out
Data is loaded in parallel and read in parallel — essentially a register bank with a clock enable. Shifting is still possible but less common.
Register file · Data latch

Interactive 8-bit Shift Register

8-bit Shift Register Simulator Interactive
SISO
SIPO
PISO
Bidirectional
Serial output (Q0):

— Click Clock Pulse to begin —

How Shift Registers Work

Internal Structure

Each stage is a D flip-flop. The Q output of flip-flop n feeds directly into the D input of flip-flop n+1. On the rising clock edge, every flip-flop captures its D input simultaneously — so the entire register shifts by one position in one clock cycle. There is no ripple propagation like in asynchronous counters.

Key insight: Because all flip-flops are clocked together, an 8-bit shift register shifts all 8 bits in exactly 1 clock cycle. Loading it serially takes 8 clock cycles.

Shift Right Operation (4-bit example)

Suppose register holds 1010 and serial input is 1:

Initial:
1
0
1
0
← Q3..Q0
CLK↑, Sin=1:
1
1
0
1
Q0 shifted out (was 0)
CLK↑, Sin=0:
0
1
1
0
Q0 shifted out (was 1)

Verilog Implementations

SISO — Serial-In Serial-Out (N-bit delay line)

module siso #(parameter N = 8) (
  input  wire clk, rst_n,
  input  wire serial_in,
  output wire serial_out
);
  reg [N-1:0] sr;
  always @(posedge clk or negedge rst_n)
    if (!rst_n) sr <= 0;
    else        sr <= {serial_in, sr[N-1:1]};  // shift right

  assign serial_out = sr[0];
endmodule

SIPO — Serial-In Parallel-Out

module sipo #(parameter N = 8) (
  input  wire       clk, rst_n, serial_in,
  output reg  [N-1:0] parallel_out
);
  always @(posedge clk or negedge rst_n)
    if (!rst_n) parallel_out <= 0;
    else        parallel_out <= {serial_in, parallel_out[N-1:1]};
    // MSB comes in first; after N clocks, parallel_out holds the word
endmodule

PISO — Parallel-In Serial-Out

module piso #(parameter N = 8) (
  input  wire       clk, rst_n,
  input  wire       load,           // 1 = parallel load, 0 = shift
  input  wire [N-1:0] parallel_in,
  output wire       serial_out
);
  reg [N-1:0] sr;
  always @(posedge clk or negedge rst_n)
    if (!rst_n)  sr <= 0;
    else if (load) sr <= parallel_in;
    else           sr <= {1'b0, sr[N-1:1]};   // shift right, MSB out first

  assign serial_out = sr[N-1];
endmodule

Universal Shift Register (4-bit)

module universal_sr #(parameter N = 4) (
  input  wire       clk, rst_n,
  input  wire [1:0] mode,     // 00=hold, 01=shift-R, 10=shift-L, 11=load
  input  wire       r_in,     // right serial input
  input  wire       l_in,     // left  serial input
  input  wire [N-1:0] d,      // parallel data
  output reg  [N-1:0] q
);
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) q <= 0;
    else case (mode)
      2'b00: q <= q;                               // hold
      2'b01: q <= {r_in,  q[N-1:1]};              // shift right
      2'b10: q <= {q[N-2:0], l_in};               // shift left
      2'b11: q <= d;                               // parallel load
    endcase
  end
endmodule

Universal Shift Register

A universal shift register combines all modes using a 2-bit select and a 4:1 multiplexer at each flip-flop's D input. This is the most versatile building block — a single cell covers hold, shift-right, shift-left, and parallel load. The 74HC194 IC is the classic 4-bit universal shift register.

S1S0ModeOperationUse case
00HoldQ stays unchangedData storage, clock gating
01Shift RightMSB ← r_in, each bit → nextSerial TX (MSB first)
10Shift LeftLSB ← l_in, each bit → prevSerial TX (LSB first)
11Parallel LoadAll bits loaded at oncePISO initialization

Ring Counter & Johnson Counter

Both are shift registers with feedback — no external clock counter logic needed.

Ring Counter

Feedback: Q_last → D_first (direct). An N-bit ring counter circulates a single 1 bit through N states. State sequence for 4-bit: 1000 → 0100 → 0010 → 0001 → 1000…. Produces one-hot encoded states — perfect for one-hot FSMs with no decoder logic needed.

Johnson Counter (Twisted-Ring)

Feedback: Q̄_last → D_first (inverted). An N-bit Johnson counter has 2N states with glitch-free transitions (adjacent states differ by only 1 bit). 4-bit Johnson: 0000 → 1000 → 1100 → 1110 → 1111 → 0111 → 0011 → 0001 → 0000… — 8 states from 4 flip-flops.

FeatureRing CounterJohnson Counter
States from N flip-flopsN2N
FeedbackQ (direct)Q̄ (inverted)
Bit transitions per clock2 bits change1 bit changes (glitch-free)
Decoder neededNo (one-hot)Simple 2-input AND/OR
Self-startingNo (needs init)No (needs init)
VLSI useOne-hot FSM statePhase generation, clock divider

VLSI Applications

1. Scan Chain (DFT)

The most important VLSI application. During manufacturing test, every flip-flop in the design is re-wired into a giant shift register called the scan chain. A test pattern is shifted in serially (scan-in), the chip is clocked once in normal mode to capture the response, and the result is shifted out serially (scan-out) for comparison. This gives observability and controllability to every flip-flop in the design without needing a physical probe on each one.

2. SPI (Serial Peripheral Interface)

SPI uses a PISO in the transmitter and a SIPO in the receiver. On each SCLK edge, one bit shifts out of the master's PISO and into the slave's SIPO (and vice versa). After 8 clocks, a full byte has been exchanged. SPI is used in flash memory, ADCs, DACs, and display drivers.

3. LFSR (Linear Feedback Shift Register)

An LFSR is a SISO shift register with XOR feedback taps. It generates maximal-length pseudo-random sequences (2ⁿ−1 states) — used in BIST pattern generation, CRC calculation, and PRBS test patterns for SerDes links. See the LFSR deep dive →

4. CDC Synchronizer

A 2-flop synchronizer is literally a 2-stage SISO shift register. The signal crosses into the destination clock domain through two back-to-back flip-flops, reducing the probability of metastability propagation to near zero.

Shift Register vs Counter vs LFSR

PropertyShift RegisterCounterLFSR
FeedbackNone (linear chain)Carry/borrow logicXOR taps
SequenceShifts data in/outBinary count up/downPseudo-random
StatesNo fixed cycle2ⁿ (or Mod-N)2ⁿ − 1
Clock complexitySingle clockRipple or syncSingle clock
Primary useData movementTiming, countingRandomness, CRC

Related Topics