Serial-In Serial-Out, Serial-In Parallel-Out, Parallel-In Serial-Out, Parallel-In Parallel-Out — with diagrams, truth tables, and Verilog RTL code.
| Type | Full Name | Input | Output | Clocks to Output | Main Use |
|---|---|---|---|---|---|
| SISO | Serial In Serial Out | 1 bit/clk | 1 bit/clk | N clocks (delay) | Delay line, LFSR, serial buffer |
| SIPO | Serial In Parallel Out | 1 bit/clk | N bits at once | N clocks to fill | Deserializer, UART RX, SPI RX |
| PISO | Parallel In Serial Out | N bits at once | 1 bit/clk | 1 load + N shifts | Serializer, UART TX, SPI TX |
| PIPO | Parallel In Parallel Out | N bits at once | N bits at once | 1 clock | Pipeline latch, data register |
A SISO shift register accepts one bit per clock on its input and produces one bit per clock on its output. Data shifts through a chain of D flip-flops. An N-bit SISO delays the input signal by exactly N clock cycles.
module siso_shift_reg #(parameter N=8) ( input clk, rst_n, si, // serial input output so // serial output (N-cycle delayed) ); reg [N-1:0] shift_reg; always @(posedge clk or negedge rst_n) begin if (!rst_n) shift_reg <= '0; else shift_reg <= {shift_reg[N-2:0], si}; // shift left end assign so = shift_reg[N-1]; // MSB is output after N clocks endmodule
Applications: Pipeline delay element, LFSR (with XOR feedback), CRC generation, serial communication buffer, waveform stretching.
A SIPO shift register shifts in bits serially and presents all N bits simultaneously at parallel outputs. After N clock cycles, the full N-bit word is available. This is the basis of every deserializer — UART, SPI, I2C receiver.
module sipo_shift_reg #(parameter N=8) ( input clk, rst_n, si, output [N-1:0] parallel_out // all N bits visible at all times ); reg [N-1:0] shift_reg; always @(posedge clk or negedge rst_n) begin if (!rst_n) shift_reg <= '0; else shift_reg <= {shift_reg[N-2:0], si}; end assign parallel_out = shift_reg; // all bits exposed endmodule
SIPO in UART: UART RX samples the line once per bit period and shifts each bit into a SIPO register. After 8 bits, the parallel output is the received byte. A valid flag is raised on bit count = 8.
A PISO shift register loads all N bits in parallel on a load pulse, then shifts them out one bit at a time over N clock cycles. This is the serializer — used in UART TX, SPI TX, and any parallel-to-serial conversion.
module piso_shift_reg #(parameter N=8) ( input clk, rst_n, input load, // 1 = load parallel data input [N-1:0] parallel_in, output so // serial output ); reg [N-1:0] shift_reg; always @(posedge clk or negedge rst_n) begin if (!rst_n) shift_reg <= '0; else if (load) shift_reg <= parallel_in; // parallel load else shift_reg <= {1'b0, shift_reg[N-1:1]}; // shift right end assign so = shift_reg[0]; // LSB out first (LSB-first protocol) endmodule
A PIPO shift register loads all N bits simultaneously and outputs all N bits simultaneously on the next clock edge. This is functionally equivalent to a D flip-flop register — the fundamental building block of every CPU pipeline stage.
module pipo_register #(parameter N=8) ( input clk, rst_n, en, input [N-1:0] d, output reg [N-1:0] q ); always @(posedge clk or negedge rst_n) begin if (!rst_n) q <= '0; else if (en) q <= d; // load on enable end endmodule
A Universal Shift Register combines all 4 modes — selected by a 2-bit mode control. The 74194 IC is the classic example.
| S1 S0 | Mode | Operation |
|---|---|---|
| 0 0 | Hold | No change — register holds current value |
| 0 1 | Shift Right | SISO/SIPO mode — shift right, SI from left |
| 1 0 | Shift Left | SISO/SIPO mode — shift left, SI from right |
| 1 1 | Parallel Load | PISO/PIPO mode — load all bits in parallel |
module universal_shift_reg #(parameter N=8) ( input clk, rst_n, input [1:0] mode, // 00=hold 01=shr 10=shl 11=load input si_right, si_left, input [N-1:0] d, 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 <= {si_right, q[N-1:1]}; // shift right 2'b10: q <= {q[N-2:0], si_left}; // shift left 2'b11: q <= d; // parallel load endcase end endmodule
An LFSR (Linear Feedback Shift Register) is a SISO shift register where the input bit is computed as XOR of specific "tap" positions. It generates a maximal-length pseudo-random sequence used in BIST, CRC, scrambling, and PRBS testing.
// 8-bit LFSR — taps at positions 8,6,5,4 (maximal length = 255) module lfsr_8bit ( input clk, rst_n, output reg [7:0] prbs ); always @(posedge clk or negedge rst_n) begin if (!rst_n) prbs <= 8'hFF; // non-zero seed else prbs <= {prbs[6:0], prbs[7] ^ prbs[5] ^ prbs[4] ^ prbs[3]}; end endmodule
SISO (Serial In Serial Out), SIPO (Serial In Parallel Out), PISO (Parallel In Serial Out), PIPO (Parallel In Parallel Out). Each differs in how data enters and exits the register.
SIPO = Deserializer: takes in bits one at a time, outputs all at once (UART RX). PISO = Serializer: loads all bits at once, outputs one bit at a time (UART TX). They are complementary and form a serial communication pair.
PIPO is used as a pipeline register, data latch, or general-purpose storage register. It loads N bits in one clock and outputs them in the same clock. Every CPU register file and pipeline stage uses PIPO-style registers.
LFSR (Linear Feedback Shift Register) is a SISO register where the input is an XOR of specific bit positions (taps). It generates pseudo-random sequences used in BIST (Built-In Self Test), CRC calculation, and PRBS testing in VLSI chips.
Basic shift: always @(posedge clk) shift_reg <= {shift_reg[N-2:0], serial_in}; — this shifts left each clock. For PISO with load: if (load) shift_reg <= parallel_in; else shift_reg <= {1'b0, shift_reg[N-1:1]};