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:
Shift in (load low): {q[6:0], din} — the vector slides left,
the new serial bit enters at the bottom. Eight clocks turn a serial
bitstream into a parallel byte. This concatenation idiom is one of the
most-used lines in all of Verilog.
Parallel load (load high): the whole register is written at once
— the starting point for shifting a byte out serially (watch dout,
the MSB, as it plays the loaded byte one bit per clock).
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.