Skip to content

VHDL · Chapter 7.7 · Sequential Logic Design

Shift Registers

A shift register is a chain of flip-flops where, on every clock, each bit takes the value of its neighbour while a new bit enters one end. That simple sideways motion does a surprising amount of work: serialising a word onto a single wire, deserialising a serial stream back into a word, building delay lines, and, with feedback, generating pseudo-random sequences. This lesson models shifting cleanly with concatenation and covers the serial-in and parallel-in, serial-out and parallel-out variants. It maps each form to its underlying flip-flop chain and connects shifting back to the one-clock latency of a single flip-flop, since a length-N register is also an N-clock delay. It builds the intuition to reach for shift registers with confidence.

Foundation14 min readVHDLShift RegisterSerialiseDelay LineLFSRRTL

1. Engineering intuition — data marching down a chain

A shift register is a bucket brigade: a row of flip-flops, and on every clock each one passes its value to the next while a fresh value enters at the input end. After N clocks, a value that entered the front has marched to the back. Because each stage is a flip-flop (one clock of latency, lesson 7.3), a length-N shift register is also an N-clock delay line. The same structure, read at the end serially or across all stages in parallel, gives you serialisation, deserialisation, and delay — three of the most common jobs in digital design.

2. Formal explanation — shifting with concatenation

shift_forms.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library ieee; use ieee.std_logic_1164.all;
signal sreg : std_logic_vector(7 downto 0);
 
-- SHIFT LEFT: drop the top bit, bring 'din' in at the bottom (concatenation).
sl : process (clk)
begin
  if rising_edge(clk) then
    sreg <= sreg(6 downto 0) & din;        -- {old bits 6..0, new din} → shifts toward the MSB
  end if;
end process;
-- SHIFT RIGHT would be:  sreg <= din & sreg(7 downto 1);
serial_out <= sreg(7);                       -- the bit that has shifted all the way through

A shift register is a vector whose next value is the old vector concatenated with the incoming bit: sreg <= sreg(n-2 downto 0) & din shifts toward the MSB (left), dropping the top bit and inserting din at the LSB. Reading one end (sreg(7)) gives the serial output; reading the whole vector gives the parallel output. The concatenation & is the clean, idiomatic way to express the shift.

3. Production RTL — serialiser (PISO) and deserialiser (SIPO)

piso_sipo.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library ieee; use ieee.std_logic_1164.all;
-- PISO: parallel-load a word, then shift it out one bit per clock.
piso : process (clk)
begin
  if rising_edge(clk) then
    if load = '1' then sreg <= parallel_in;       -- load all 8 bits
    else               sreg <= sreg(6 downto 0) & '0';  -- shift out MSB-first
    end if;
  end if;
end process;
ser_out <= sreg(7);
 
-- SIPO: shift a serial stream in; read the assembled word in parallel.
sipo : process (clk)
begin
  if rising_edge(clk) then
    rxreg <= rxreg(6 downto 0) & ser_in;          -- assemble 8 bits over 8 clocks
  end if;
end process;
word_out <= rxreg;

What hardware does this become? Two flip-flop chains. The PISO has a load mux on each stage (parallel load vs shift) and reads the top bit serially — a serialiser (UART transmit, SPI shift-out). The SIPO shifts the serial input through and reads all stages in parallel — a deserialiser (UART receive, SPI shift-in). Both are the same shift chain with different input/output ports.

4. Hardware interpretation — a chain of flip-flops

chain of flip-flops shifting data with serial and parallel accessshift / clkshift / clkserial innew bit enters hereFF0stage 0FF1stage 1FFnserial out / delayed by Nparallel outread all stages12
A shift register is a chain of flip-flops; each clock, every stage captures its neighbour's value and a new bit enters one end. Reading the far end gives the SERIAL output (and an N-stage chain is an N-clock delay line); reading all stages gives the PARALLEL output. Serial-in/parallel-out (SIPO) deserialises; parallel-in/serial-out (PISO, with a load mux per stage) serialises. The structure is identical — only which ports you use changes.

5. Simulation interpretation — a bit marches through

A single '1' shifts left through an 8-bit register, one stage per clock

8 cycles
A single '1' shifts left through an 8-bit register, one stage per clockdin=1 enters at the LSB → sreg=0x01din=1 enters at the LS…the '1' has shifted to bit 2 → sreg=0x04 (moves one stage per clock)the '1' has shifted to…clkdin10000000sreg0001020408102040t0t1t2t3t4t5t6t7
A single '1' entering din marches one bit-position per clock (0x01, 0x02, 0x04, ...), reaching the MSB after 8 clocks. That one-stage-per-clock motion is the shift register, and it is why a length-N chain delays a serial stream by exactly N clocks — each stage is one flip-flop of latency.

6. Debugging example — wrong shift direction or off-by-one length

Expected: a serial stream serialised/deserialised correctly. Observed: the bits come out reversed, or one bit short/extra, or misaligned with a framing signal. Root cause: the concatenation order shifted the wrong way (MSB-first vs LSB-first) relative to the protocol, or the register length did not match the word size (off-by-one), or the load/shift control was timed one clock off. Fix: match the concatenation direction to the protocol's bit order (sreg(n-2 downto 0) & din for MSB-first out, or the reverse), size the register to the word, and align the load/shift enable with the framing. Engineering takeaway: a shift register's correctness is direction + length + timing — pin down bit order, word length, and exactly when load versus shift happens.

shift_direction.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- MSB-first serial OUT (shift left, read the top bit):
sreg    <= sreg(6 downto 0) & '0';   ser_out <= sreg(7);
-- LSB-first serial OUT (shift right, read the bottom bit):
-- sreg <= '0' & sreg(7 downto 1);   ser_out <= sreg(0);

7. Common mistakes & what to watch for

  • Wrong shift direction / bit order. Match & concatenation to the protocol (MSB-first vs LSB- first); getting it backwards reverses the bits.
  • Length mismatch. Size the register to the word; an off-by-one length drops or adds a bit.
  • Load/shift timing. Align the load (parallel-in) and shift enable with the framing/valid signals; one-cycle slips misalign the data.
  • Forgetting the N-clock latency. A length-N shift register delays by N clocks; account for it in surrounding logic.
  • Unintended feedback. Feeding the output back into the input with XOR taps makes an LFSR — powerful, but only when intended; otherwise keep the input a real data source.

8. Engineering insight & continuity

The shift register is motion through flip-flops: one stage per clock, which simultaneously serialises, deserialises, and delays depending on which ports you read. Express it with concatenation, size it to the word, and get the direction and timing right, and it underlies every serial interface (UART, SPI), every delay line, and — with feedback taps — LFSRs for pseudo-random sequences and CRCs. With registers, enables, counters, and shift registers covered, the module's core structures are complete. The remaining two lessons address pitfalls and subtleties: Gated Clocks and Why to Avoid Them (why clock-enables, not clock gating, are the right tool) and Signals versus Variables in Clocked Processes (how the two behave when registered).