Shift register
Four flip-flops in a row that take one bit per edge and hold the last four side by side. Serial in, parallel out, and what the order of four lines decides.
- Level
- rtl
- Code
- shift-register
- Checked
- Verilator 5.052, Icarus Verilog 13.0, Yosys 0.66
- Published
- Authorship
- Drafted with AI assistance
- Status
- In progress — published so it can be reviewed, not finished.
A serial-in, parallel-out shift register turns a stream of bits on one wire into a word. At
every rising edge each stage takes the bit of the stage before it and the first stage takes the
bit on si, so after four edges the last four bits stand side by side on q. It is four D
flip-flops in a row, and one line of code each.
Run plays this scenario from the start; driving an input continues from here.
A circuit that runs: a schematic and its waveform on one time axis. Inputs: si. Outputs: q3, q2, q1, q0. clk runs at 8 ticks a period. It is built from 4 D flip-flops. The waveform shows clk, si, q3, q2, q1, q0.
Figure 1. Press Run. A bit enters at each rising edge and every stage moves one place right; after the fourth edge q3 q2 q1 q0 read 1011.
This page draws serial in, parallel out only. The other half of the usual pair, a parallel load for serial out, puts a multiplexer in front of every flop, and four flops and four multiplexers do not fit one drawing that can still be read on a phone.
How it works, edge by edge
The flops print no names. From left to right they are q3, q2, q1 and q0, and each prints
the bit it holds. Three lamps hang on the wires between two flops, each showing the left flop's
q, which the flop to its right takes at the next edge; the fourth, q0, hangs after the last
flop. Follow the rows of the waveform, which are in the same order.
From tick 0 to tick 3, before the first edge, all four rows are X. There is no reset, and nothing
has entered yet. si sends 1011 least significant bit first, one bit before each edge: 1, 1, 0 and
- At the first edge
q3takes the 1, and the other three stages take the X of the stage before them: an X moves along the register exactly as a bit does.
At the second edge q2 takes the 1 that q3 held, at the same edge at which q3 takes the next
bit, another 1, so its row stays high. The third edge, tick 20, shows it plainly: q3 falls to 0
as q1 rises to 1. Every stage moves at once, each from the value its neighbour had just before
the edge, which is why the bits walk down the rows one step per clock period. At the fourth edge,
tick 28, q0 leaves X for the first time, and q3 q2 q1 q0 read 1011: the word as it is written,
with the bit sent first in q0.
Two words sends 1011 and then 1100, back to back. q holds the first word whole for one clock
period after the fourth edge. After the fifth edge it holds three bits of the first word and one of
the second, after the sixth two of each, and after the seventh one of the first and three of the
second. It is the second word only at the eighth edge, tick 60. The register cannot tell a word
from a mixture; something that counts the bits has to, as the UART
receiver's bit counter does when it raises last.
Slow bits changes si every two clock periods: a 1, then a 0. The register shifts at every
edge whether a new bit has arrived or not, so each bit is taken twice and q reads 0011. A
serial line slower than the clock needs the shift enabled once a bit — the UART receiver's
shift is exactly that — and this drawing has no enable to show it.
The code
// A 4-bit shift register, serial in and parallel out. At each rising edge of
// clk every stage takes the bit of the stage before it and q3 takes si, so a
// word sent least significant bit first stands in q after four edges.
//
// Reset style for this module: none. A data register needs no reset: until
// four bits have arrived q is not a word whatever it holds, and whatever reads
// it has to wait for the fourth edge anyway.
module shift_register (
input logic clk,
input logic si,
output logic [3:0] q
);
// One flip-flop a bit, named as the drawing names them, q3 nearest si.
logic q3, q2, q1, q0;
// All four take their new value at the same edge, from the values before
// it: that is what <= means, and why the order of these lines does not
// matter.
always_ff @(posedge clk) begin
q3 <= si;
q2 <= q3;
q1 <= q2;
q0 <= q1;
end
// The parallel output: the four stages side by side, q3 the most
// significant bit.
assign q = {q3, q2, q1, q0};
endmoduleThe reset style is stated at the top of the file: none. This register carries data, and until
four bits have arrived its value is not a word whatever it holds, so a reset would only change
which meaningless value it starts with. The four lines in the always_ff are the four flops, in
the drawing's order, and each lights its own flop. They are <=, so every line reads the values
from before the edge and the order of the lines does not matter.
The same register is often written as one line on a vector, q <= {si, q[3:1]};. This page names
the four stages instead, so that each is a flop in the drawing and a row the replay below can
compare by name.
Synthesis result
Yosys's generic synthesis turns shift_register.sv into 4 cells, 4 of them flip-flops. The cells are Yosys's own gate library, not an FPGA's or a standard-cell library's: the count measures the logic, not the area of any chip.
| Cell | What it is | Count |
|---|---|---|
$_DFF_P_ | D flip-flop on the rising edge | 4 |
| Total | 4 | |
Lint by Verilator 5.052, the testbench by Icarus Verilog 13.0, synthesis by Yosys 0.66.
Icarus replayed this page's three scenarios on this code, and all 804 values the waveform draws match.
The netlist before synthesis
What Yosys's prep reads in shift_register.sv, before any gate is chosen, drawn by netlistsvg 1.0.2.
Pitfalls
Blocking assignments, and the order of the lines. Write the four lines with = in this order
and each reads what the line above it has just written: all four stages take si at the same edge,
and q is one bit four times. Yosys agrees with the simulation here, and keeps one flip-flop for
all four bits. Written bottom-up, from q0 = q1 to q3 = si, the same = code happens to shift
correctly inside this module — which is worse. It passes a simulation and this page's testbench,
anything reading q at the same edge still races with it, as the D
flip-flop page shows, and nothing but a linter says that it works only
because of the order of four lines. Verilator's -Wall and Verible flag both orders. With <= the
order of the lines never matters.
Reading q between words. Two words is the pitfall: q changes at every edge and is a
word at only one edge in four. A receiver that reads it without counting reads mixtures.
One bit per edge. Slow bits is the other: a shift register shifts at every clock edge, and a bit that lasts two clock periods is two bits to it. The shift has to be told when a bit is there.
No reset is a choice for data, not for control. This register's X lasts exactly until the fourth edge, and whatever reads it has to wait for that edge anyway. A register whose value decides something — a count, a state — cannot start as X, and needs the reset this one leaves out.
Check yourself
- Does the order of the four lines in the always_ff matter? And if they were written with = instead of <=?
- With <= it does not. Every line reads the values from before the edge, so the four stages take the same new values in any order. With = each line reads what the lines above it have already written at this edge, so the order decides what is built. Top-down, every stage takes si at once; bottom-up, it happens to shift, and the next edit that reorders the lines breaks it.
- In 1011, LSB first, why is q0 the last row to leave X?
- Because an X moves along the register like any other bit. Before the first edge every stage is X; each edge moves everything one place right and puts a known bit into q3, so the known bits reach q0 at the fourth edge, carrying the bit that was sent first.
- How does whatever reads q know when it holds a whole word?
- It does not, from q alone. q is a word at every fourth edge and a mixture of two words at the three in between, as Two words shows, so something has to count the bits and say when the fourth has arrived. In a UART receiver that is the bit counter, whose last tells the state machine the final bit is in.