A pattern detector is a finite state machine that monitors a serial bit stream and raises its output whenever a specific multi-bit pattern has been received. The Verilog Sequence Detector article built a detector for a short pattern. This article applies the same method to a longer pattern, 110101, where choosing the right state after a mismatch becomes more important.
12 min read | Intermediate Level
What You'll Learn
- Derive every state transition of a pattern detector with the longest-suffix rule
- Write an overlapping 110101 detector as a Moore FSM in Verilog
- Compare an FSM detector with a shift register and comparator
- Choose test stimulus that actually exposes transition bugs
Deriving the Transitions
The detector has one state for each prefix of the pattern that has been matched: IDLE (nothing), S1, S11, S110, S1101, S11010 and S110101 (full match). When the next bit continues the pattern, the FSM moves forward one state. When it does not, the FSM moves to the state for the longest ending of the received bits that is also a start of the pattern. This is the longest-suffix rule.
| Current state | in = 1 | in = 0 | Reasoning for the mismatch case |
|---|---|---|---|
| IDLE | S1 | IDLE | "0" does not start the pattern |
| S1 | S11 | IDLE | "10" ends in nothing useful |
| S11 | S11 | S110 | "111" still ends in "11" |
| S110 | S1101 | IDLE | "1100" ends in nothing useful |
| S1101 | S11 | S11010 | "11011" ends in "11" |
| S11010 | S110101 | IDLE | "110100" ends in nothing useful |
| S110101 | S11 | IDLE | "1101011" ends in "11"; "1101010" in nothing useful |
The two transitions in bold are easy to get wrong. In S1101, a 1 breaks the pattern, but the last two bits received are "11", which is the start of a new "110101", so the FSM goes to S11, not IDLE. In S110101, a 1 again leaves "11" at the end of the stream. Taking that transition makes this an overlapping detector: a pattern that begins with the last bit of the previous match is still detected.
Quick Check
Q: The stream is 110110101. Where does the pattern 110101 end, and which transition must be correct to detect it?
Show Answer
It occupies bits 4 to 9 and ends at the last bit. After "1101" (bits 1 to 4), bit 5 is a 1, so the FSM must go from S1101 to S11. Bits 4 and 5 form the "11" that starts the match. Going to IDLE instead would lose bit 4, and the pattern would never be detected.
Design
module det_110101 ( input clk,
input rstn,
input in,
output out );
// 7 states need a 3-bit state register
localparam IDLE = 0,
S1 = 1,
S11 = 2,
S110 = 3,
S1101 = 4,
S11010 = 5,
S110101 = 6;
reg [2:0] cur_state, next_state;
// Moore output: high only in the state where the full pattern has been received
assign out = cur_state == S110101 ? 1 : 0;
// State register
always @ (posedge clk) begin
if (!rstn)
cur_state <= IDLE;
else
cur_state <= next_state;
end
// Next-state logic, following the transition table
always @ (cur_state or in) begin
case (cur_state)
IDLE : begin
if (in) next_state = S1;
else next_state = IDLE;
end
S1: begin
if (in) next_state = S11;
else next_state = IDLE;
end
S11: begin
if (!in) next_state = S110;
else next_state = S11; // "111": stay, still have "11"
end
S110 : begin
if (in) next_state = S1101;
else next_state = IDLE;
end
S1101 : begin
if (!in) next_state = S11010;
else next_state = S11; // "11011": keep the trailing "11"
end
S11010: begin
if (in) next_state = S110101;
else next_state = IDLE;
end
S110101: begin
if (in) next_state = S11; // "1101011": keep the trailing "11" (overlap)
else next_state = IDLE;
end
default : next_state = IDLE; // Code 7 is unused
endcase
end
endmodule
Synthesis result: The tool builds a 3-bit state register with synchronous reset, next-state logic for the 14 transitions, and a decoder for state 6 (3'b110) that drives out. Synthesis tools usually recognize this as an FSM and may re-encode it, for example as one-hot with 7 flip-flops, if that meets timing better.
Where are Pattern Detectors Used?
Wired network frames begin with a preamble of alternating bits followed by a start-of-frame delimiter, a byte whose last two bits break the alternating pattern. The receiver runs a pattern detector on the incoming bits to find that delimiter, which tells it exactly where the frame's first data bit begins.
Testbench
The testbench holds reset for five clock edges, then drives the pattern twice, back to back. A $strobe at each rising edge prints in and out after all updates for that edge.
module tb;
reg clk, in, rstn;
wire out;
integer l_dly;
always #10 clk = ~clk;
det_110101 u0 ( .clk(clk), .rstn(rstn), .in(in), .out(out) );
// Print the values at the end of each rising-edge time step
always @ (posedge clk)
$strobe ("T=%0t in=%0b out=%0b", $time, in, out);
initial begin
clk <= 0;
rstn <= 0;
in <= 0;
repeat (5) @ (posedge clk);
rstn <= 1;
@(posedge clk) in <= 1;
@(posedge clk) in <= 1;
@(posedge clk) in <= 0;
@(posedge clk) in <= 1;
@(posedge clk) in <= 0;
@(posedge clk) in <= 1; // First 110101 complete
@(posedge clk) in <= 1;
@(posedge clk) in <= 1;
@(posedge clk) in <= 0;
@(posedge clk) in <= 1;
@(posedge clk) in <= 0;
@(posedge clk) in <= 1; // Second 110101 complete
#100 $finish;
end
endmodule
ncsim> run T=10 in=0 out=0 T=30 in=0 out=0 T=50 in=0 out=0 T=70 in=0 out=0 T=90 in=0 out=0 T=110 in=1 out=0 T=130 in=1 out=0 T=150 in=0 out=0 T=170 in=1 out=0 T=190 in=0 out=0 T=210 in=1 out=0 T=230 in=1 out=1 T=250 in=1 out=0 T=270 in=0 out=0 T=290 in=1 out=0 T=310 in=0 out=0 T=330 in=1 out=0 T=350 in=1 out=1 T=370 in=1 out=0 T=390 in=1 out=0 T=410 in=1 out=0 Simulation complete via $finish(1) at time 430 NS + 0
The first pattern is driven from 110 to 210 ns, and out is 1 at 230 ns, one clock after the last bit, as expected for a Moore output. The second pattern is driven from 230 to 330 ns and detected at 350 ns. Each detection lasts exactly one clock cycle.
This stimulus does not test the difficult transitions.
The two patterns in this testbench are separate and never trigger S1101 with a 1 or S110101 with a 1. A design that sends both of those transitions to the wrong state produces exactly the same log. To catch such bugs, the stimulus must include streams such as 110110101 and 11010110101, or a long random stream checked against a reference model, as in the practice exercise below.
Debug and Test Mode Entry
Many chips enter a test or debug mode only after a specific sequence of values is applied to certain pins or written to a register. A pattern detector watches for that sequence, so the mode cannot be entered by accident during normal operation, for example from noise on a pin during power-up.
FSM vs Shift Register Implementation
The same detector can be built without an FSM: shift each incoming bit into a 6-bit register and compare the register with the pattern.
reg [5:0] sh;
always @(posedge clk)
if (!rstn) sh <= 6'b0;
else sh <= {sh[4:0], in}; // Last 6 bits, newest at bit 0
assign out = (sh == 6'b110101);
| FSM | Shift register + comparator | |
|---|---|---|
| Flip-flops | $clog2(states), 3 here | Pattern length, 6 here |
| Logic | Next-state logic derived from the transition table | One 6-input comparison |
| Design effort | Every transition must be worked out correctly | Almost none, and always overlapping |
| Long patterns (e.g. 32 bits) | Fewer flip-flops, but many states | 32 flip-flops and a 32-bit comparator |
| Changing the pattern | New states and transitions | Change one constant, or make it a register input |
For short fixed patterns, or patterns that must be programmable, the shift register is often simpler and less error-prone. The FSM approach saves flip-flops for long patterns and extends naturally to detectors whose behavior depends on more than the last N bits, such as patterns with variable gaps.
Quick Check
Q: If both versions are reset and then receive the same stream, will their out signals always match?
Show Answer
Yes. In the FSM, each state stands for the longest ending of the received bits that starts the pattern, so the FSM reaches S110101 exactly when the last six bits are 110101. That is the same condition the comparator checks. Both outputs follow registers updated on the same edge, so they match cycle for cycle. This is why the shift register version is a good reference model for testing the FSM.
Infrared Remote Control Receivers
Infrared remote controls send each command as a burst of pulses that starts with a fixed header and device address. The receiver chip in a television or set-top box decodes the pulses into bits and uses a pattern detector to recognize its own address before it accepts the command that follows.
Common Beginner Mistakes
Mistake #1: Sending every mismatch back to IDLE
Wrong: S1101: if (!in) next_state = S11010; else next_state = IDLE;
Right: else next_state = S11;
Why? After "11011", the last two bits are "11", which can start a new match. Going to IDLE throws them away, so the stream 110110101 is never detected. Apply the longest-suffix rule to every mismatch, using a table like the one at the start of this article.
Mistake #2: Restarting from S1 after a full match
Wrong: S110101: if (in) next_state = S1;
Right: S110101: if (in) next_state = S11;
Why? The last bit of the match is a 1, and the new bit is also a 1, so the stream ends in "11". Going to S1 keeps only one of them. In 11010110101, the second pattern shares its first bit with the end of the first, and the S1 version misses it.
Mistake #3: No default for unused state codes
Wrong: A case with only the seven state items for a 3-bit register
Right: Add default: next_state = IDLE;
Why? Code 7 is not assigned to any state. Without a default, next_state is unassigned in that case, so synthesis infers a latch, and an FSM that reaches code 7 through an upset has no defined way out.
Mistake #4: Testing only clean, separated patterns
Wrong: A testbench that sends the pattern a few times with no near-misses or overlaps
Right: Add streams that exercise every mismatch transition, plus long random streams compared against a reference model
Why? As the log in this article shows, a clean directed test passes even when two transitions are wrong. Each wrong transition only shows up with a specific bit history, which random stimulus finds much more reliably than hand-written patterns.
Practice Exercise
Challenge: Self-Checking Random Testbench
Write a testbench tb_check that drives 500 random bits into det_110101, one per clock, and checks out on every clock against a shift register reference model. Print an error for every mismatch and a pass or fail summary at the end.
Hint
Inside the testbench, keep reg [5:0] sh updated with sh <= {sh[4:0], in} on the same clock edge as the design. The expected output is then (sh == 6'b110101). Compare it with out on the falling edge, when both have settled.
Solution
module tb_check;
reg clk = 0, rstn = 0, in = 0;
wire out;
reg [5:0] sh; // Reference model: last 6 sampled bits
integer i, errors = 0;
always #10 clk = ~clk;
det_110101 u0 ( .clk(clk), .rstn(rstn), .in(in), .out(out) );
// Reference model, clocked exactly like the design
always @(posedge clk)
if (!rstn) sh <= 6'b0;
else sh <= {sh[4:0], in};
// Compare on the falling edge, away from the rising edge updates
always @(negedge clk)
if (rstn && (out !== (sh == 6'b110101))) begin
$display("[%0t] ERROR: out=%b expected=%b", $time, out, (sh == 6'b110101));
errors = errors + 1;
end
initial begin
repeat (3) @(posedge clk);
rstn <= 1;
for (i = 0; i < 500; i = i + 1)
@(posedge clk) in <= $random; // Bit 0 of a random number
@(posedge clk);
if (errors == 0) $display("PASS: 500 random bits, no mismatches");
else $display("FAIL: %0d mismatches", errors);
$finish;
end
endmodule
With the corrected design, every check passes. If you change the S1101 or S110101 transition back to the wrong state from the mistakes above, 500 random bits almost always produce a stream that exposes it, and the testbench reports the exact time of the first error.
Summary
In this tutorial, you learned:
- A pattern detector has one state per matched prefix of the pattern, plus IDLE
- On a mismatch, the FSM goes to the state for the longest ending of the received bits that starts the pattern
- For 110101, both S1101 and S110101 must go to S11 on a 1, which also makes the detector overlapping
- The Moore output rises one clock after the last bit of the pattern is sampled and lasts one cycle
- A shift register with a comparator gives the same result and makes an excellent reference model
- Directed tests with clean patterns can miss transition bugs; random stimulus with a reference model finds them