Shift Registers

A shift register is a chain of flip-flops where each one feeds the next: every clock, the whole pattern moves one position. It's the workhorse behind serializers (UART, SPI), deserializers, delay lines and — in a pinch — the classic dev-board LED chaser.

The design shows the two fundamental operations on one 8-bit register:

In the waveform: after the load of 8'hA5 you can read the byte marching out of dout MSB-first — 1,0,1,0,0,1,0,1 — while zeros (from din) fill in behind it.

Experiment: wire din = dout to make a ring that rotates forever, or tap two bits into an XOR feeding din — congratulations, you've built the LFSR from our generator.

The design

Verilog — design.v
// 8-bit shift register with parallel load and serial in/out.
module shifter (
    input  wire       clk,
    input  wire       rst,
    input  wire       load,     // 1: parallel load, 0: shift
    input  wire [7:0] pdata,    // parallel load value
    input  wire       din,      // serial in (enters at bit 0)
    output wire       dout,     // serial out (MSB first)
    output reg  [7:0] q
);
    always @(posedge clk) begin
        if (rst)
            q <= 8'd0;
        else if (load)
            q <= pdata;
        else
            q <= {q[6:0], din};   // shift left, din enters LSB
    end

    assign dout = q[7];
endmodule
Show the VHDL version
VHDL — design.vhd
-- 8-bit shift register with parallel load and serial in/out.
library ieee;
use ieee.std_logic_1164.all;

entity shifter is
    port (
        clk   : in  std_logic;
        rst   : in  std_logic;
        load  : in  std_logic;
        pdata : in  std_logic_vector(7 downto 0);
        din   : in  std_logic;
        dout  : out std_logic;
        q     : out std_logic_vector(7 downto 0)
    );
end entity;

architecture rtl of shifter is
    signal r : std_logic_vector(7 downto 0) := (others => '0');
begin
    process (clk) begin
        if rising_edge(clk) then
            if rst = '1' then
                r <= (others => '0');
            elsif load = '1' then
                r <= pdata;
            else
                r <= r(6 downto 0) & din;
            end if;
        end if;
    end process;
    q    <= r;
    dout <= r(7);
end architecture;

The testbench

Verilog — tb.v
`timescale 1ns/1ns
module tb;
    reg clk = 0, rst = 1, load = 0, din = 0;
    reg [7:0] pdata = 8'hA5;
    wire dout;
    wire [7:0] q;

    shifter dut (.clk(clk), .rst(rst), .load(load), .pdata(pdata),
                 .din(din), .dout(dout), .q(q));

    always #5 clk = ~clk;

    initial begin
        $dumpfile("wave.vcd"); $dumpvars(0, tb);
        #12 rst = 0;
        #10 load = 1;      // load 0xA5
        #10 load = 0;      // now shift it out MSB-first on dout
        #80                // 8 shifts: dout plays 1,0,1,0,0,1,0,1
        din = 1;           // then shift ones in for contrast
        #40 $finish;
    end
endmodule

Simulated waveform

This trace was produced by actually simulating the code above with Icarus Verilog.

15 30 45 60 75 90 105 120 135 150 t (ns) q[7:0] x 0 A5 4A 94 28 50 A0 40 80 0 1 3 7 F dout clk din load pdata[7:0] A5 rst

Open this lesson in the playground →