Complete overlapping FSM design for 1101 — after each detection, the FSM reuses the longest suffix of the detected sequence that can start a new match, enabling back-to-back detections in streams like 11011011101.
The only difference between overlapping and non-overlapping detectors is what happens after a detection. In a non-overlapping detector, the FSM resets to S0 and discards all consumed bits. In an overlapping detector, the FSM transitions to the state representing the longest suffix of the detected sequence that is also a valid prefix of the target — allowing the very bits just detected to contribute to the next match.
Input: 1 1 0 1 1 1 0 1 └──────┘ └──────┘ Detect: ↑ ↑ After detect: go to S0 (last bit '1' is discarded) Count = 2 detections
Input: 1 1 0 1 1 0 1 └──────┘ └──────┘ Detect: ↑ ↑ After detect: go to S1 (last bit '1' reused!) Count = 2 detections in 7 bits!
To determine the post-detection state, we apply the KMP failure function to the pattern “1101”. This finds the longest proper suffix of the pattern that is also a prefix of the pattern.
Pattern: 1 1 0 1 Index: 0 1 2 3 For the complete pattern "1101", examine all proper suffixes: Suffix "1" → is it a prefix of "1101"? YES ("1...") → length 1 Suffix "01" → is it a prefix of "1101"? NO Suffix "101" → is it a prefix of "1101"? NO Longest proper suffix that is also a prefix: "1" (length 1) Therefore: after detecting "1101", the last bit '1' is REUSED and the FSM transitions to S1 (= "matched prefix '1'") Overlapping example: Input: 1 1 0 1 1 0 1 ↑ ↑ detect here detect here (reused '1' from first detect) First match: bits 0-3 = 1101 → detect, go to S1 (keep '1') Second match: bits 3-6 = 1101 → detect, go to S1 (keep '1')
Non-Overlapping (Module 25)
S3 + in=1 → S0, out=1
Reset to initial — no reuse
Overlapping (This Module)
S3 + in=1 → S1, out=1
Go to S1 — reuse the last ‘1’
★ = detection events. Bits t=4 and t=7 are shared between two consecutive matches (the ‘1’ at end of first 1101 starts the next). 3 detections in 12 bits.
Identical to non-overlapping except the detection transition from S3 (on input=1) goes to S1 instead of S0. The ‘1’ that completes 1101 is immediately reused as the start of the next potential 1101 sequence.
| Current State | Matched prefix | Input = 0 | Input = 1 | ||
|---|---|---|---|---|---|
| Next State | Output | Next State | Output | ||
| S0 | “” | S0 | 0 | S1 | 0 |
| S1 | “1” | S0 | 0 | S2 | 0 |
| S2 | “11” | S3 | 0 | S2 | 0 |
| S3 | “110” | S0 | 0 | S1 ★ | 1 ← DETECT |
★ The ONLY change from non-overlapping: detection returns to S1 instead of S0, reusing the last ‘1’ as the first bit of the next potential match.
// ============================================================ // Module : seq_det_mealy_ovlp // Type : Mealy FSM — Overlapping 1101 detector // Key diff : After detection, go to S1 (not S0) — reuse last '1' // States : S0=init, S1=got"1", S2=got"11", S3=got"110" // ============================================================ `timescale 1ns/1ps `default_nettype none module seq_det_mealy_ovlp ( input clk, input rst_n, input in, output reg detected ); localparam [1:0] S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11; reg [1:0] state, next_state; // ── Sequential: state register ──────────────────────────── always @(posedge clk) begin if (!rst_n) state <= S0; else state <= next_state; end // ── Combinational: next state + Mealy output ────────────── always @(*) begin next_state = S0; detected = 1'b0; case (state) S0: next_state = in ? S1 : S0; S1: next_state = in ? S2 : S0; S2: next_state = in ? S2 : S3; // "111"→stay S2, "110"→S3 S3: begin if (in) begin // ★ OVERLAPPING: reuse last '1' → go to S1, not S0 next_state = S1; // 1101 → last '1' starts next match detected = 1'b1; // 1101 detected! end else begin next_state = S0; // 1100 → reset end end default: next_state = S0; endcase end endmodule `default_nettype wire
next_state = S0 became next_state = S1 inside the S3, in=1 branch. Every other line is byte-for-byte identical. This tiny change enables overlapping detection.The Moore overlapping detector uses 5 states (S0–S4), same as non-overlapping. The only change: from S4 (detection state), input=1 transitions to S1 instead of S0, reusing the bit received during S4 as the start of the next match.
| Current State | Output | Matched prefix | Next State | |
|---|---|---|---|---|
| Input = 0 | Input = 1 | |||
| S0 | 0 | “” | S0 | S1 |
| S1 | 0 | “1” | S0 | S2 |
| S2 | 0 | “11” | S3 | S2 |
| S3 | 0 | “110” | S0 | S4 |
| S4 | 1 ← DETECT | “1101” | S0 | S1 ★ |
★ Moore overlapping: from S4 (detection state), input=1 goes to S1 — the ‘1’ received while in S4 becomes the start of the next match. Input=0 from S4 still goes to S0.
// ============================================================ // Module : seq_det_moore_ovlp // Type : Moore FSM — Overlapping 1101 detector // Key diff : S4 + input=1 → S1 (not S0) — reuse bit during detect state // States : S0=init, S1="1", S2="11", S3="110", S4=DETECT // ============================================================ `timescale 1ns/1ps `default_nettype none module seq_det_moore_ovlp ( input clk, input rst_n, input in, output detected ); localparam [2:0] S0 = 3'b000, S1 = 3'b001, S2 = 3'b010, S3 = 3'b011, S4 = 3'b100; reg [2:0] state, next_state; // ── Sequential: state register ──────────────────────────── always @(posedge clk) begin if (!rst_n) state <= S0; else state <= next_state; end // ── Combinational: next state ───────────────────────────── always @(*) begin next_state = S0; case (state) S0: next_state = in ? S1 : S0; S1: next_state = in ? S2 : S0; S2: next_state = in ? S2 : S3; S3: next_state = in ? S4 : S0; S4: begin // ★ OVERLAPPING: input=1 during detect state → S1, not S0 next_state = in ? S1 : S0; end default: next_state = S0; endcase end // ── Output: purely state-dependent (Moore) ──────────────── assign detected = (state == S4); endmodule `default_nettype wire
next_state = S0 (non-overlapping) became next_state = in ? S1 : S0 (overlapping). The output line assign detected = (state == S4) is unchanged — Moore output logic never changes regardless of overlapping/non-overlapping.| Property | Non-Overlapping (Module 25) | Overlapping (This Module) |
|---|---|---|
| Post-detection state (Mealy) | S3 + in=1 → S0 (reset) | S3 + in=1 → S1 (reuse ‘1’) |
| Post-detection state (Moore) | S4 → S0 always | S4 + in=1 → S1, S4 + in=0 → S0 |
| Lines changed (Mealy) | — | 1 line: S0 → S1 in S3 branch |
| Lines changed (Moore) | — | 1 line: S0 → in ? S1 : S0 in S4 case |
| State count | Mealy: 4, Moore: 5 | Identical — Mealy: 4, Moore: 5 |
| Example: input 11011101 | Detects at t=4, resets. Detects at t=8. Count=2 | Detects at t=4, goes to S1. Detects at t=7. Count=2 in fewer bits |
| Example: input 11011011101 | Detects at t=4 and t=11. Count=2 | Detects at t=4, t=7, t=11. Count=3 |
S3: begin if (in) begin next_state = S0; ← discards '1' detected = 1'b1; end else next_state = S0; end
S3: begin if (in) begin next_state = S1; ← reuses '1' detected = 1'b1; end else next_state = S0; end
The testbench specifically exercises overlapping detection scenarios — streams where non-overlapping would miss detections but overlapping finds them. It runs both FSMs simultaneously and checks that extra detections occur at the correct cycles.
// ============================================================ // Testbench : seq_det_ovlp_tb // DUT 1 : seq_det_mealy_ovlp // DUT 2 : seq_det_moore_ovlp // Focus : Overlapping detection — consecutive 1101 patterns // where last bit of one match is first bit of next // ============================================================ `timescale 1ns/1ps `default_nettype none module seq_det_ovlp_tb; reg clk=0, rst_n=1, in=0; wire mealy_det, moore_det; seq_det_mealy_ovlp dut_m(.clk(clk),.rst_n(rst_n),.in(in),.detected(mealy_det)); seq_det_moore_ovlp dut_r(.clk(clk),.rst_n(rst_n),.in(in),.detected(moore_det)); always #5 clk = ~clk; initial begin $dumpfile("seq_det_ovlp.vcd"); $dumpvars(0, seq_det_ovlp_tb); end integer pass_cnt=0, fail_cnt=0, test_num=0; task apply_bit; input b; begin in=b; @(posedge clk); #1; end endtask task chk; input exp_m, exp_r; input [255:0] msg; begin test_num++; if(mealy_det===exp_m && moore_det===exp_r) begin $display(" PASS [%2d] %s | M=%b R=%b",test_num,msg,mealy_det,moore_det); pass_cnt++; end else begin $display(" FAIL [%2d] %s | got M=%b R=%b exp M=%b R=%b", test_num,msg,mealy_det,moore_det,exp_m,exp_r); fail_cnt++; end end endtask initial begin $display("\n======================================================="); $display(" 1101 OVERLAPPING Detector — Mealy & Moore"); $display("======================================================="); rst_n=0; @(posedge clk); #1; rst_n=1; // ── Test 1: Single clean 1101 ────────────────────────── $display("\n --- Test 1: Single 1101 ---"); apply_bit(1); chk(0,0, "bit1=1: no detect"); apply_bit(1); chk(0,0, "bit2=1: no detect"); apply_bit(0); chk(0,0, "bit3=0: no detect"); apply_bit(1); chk(1,0, "bit4=1: Mealy DETECT, Moore not yet"); apply_bit(0); chk(0,1, "idle: Moore DETECT (from S4)"); // ── Test 2: Overlapping — 1101101 (2 detections in 7 bits) $display("\n --- Test 2: Overlapping 1101101 (2 detections) ---"); rst_n=0; @(posedge clk); #1; rst_n=1; apply_bit(1); apply_bit(1); apply_bit(0); apply_bit(1); chk(1,0, "1st 1101: Mealy DETECT (same cycle)"); // After detection, Mealy goes to S1 (overlapping!) // Next bits: 1 0 1 = complete second 1101 starting from last '1' apply_bit(1); chk(0,1, "bit5=1: Moore 1st DETECT, Mealy in S2"); apply_bit(0); chk(0,0, "bit6=0: in S3 now"); apply_bit(1); chk(1,0, "bit7=1: Mealy 2nd DETECT! (overlapping!)"); apply_bit(0); chk(0,1, "Moore 2nd DETECT"); // ── Test 3: 11011101 — prove reuse works correctly ───── $display("\n --- Test 3: 11011101 overlapping ---"); rst_n=0; @(posedge clk); #1; rst_n=1; apply_bit(1); apply_bit(1); apply_bit(0); apply_bit(1); chk(1,0, "1st detect at bit4"); apply_bit(1); apply_bit(1); apply_bit(0); apply_bit(1); chk(1,0, "2nd detect at bit8"); apply_bit(0); chk(0,1, "Moore 2nd detect confirmed"); // ── Test 4: No detection stream ──────────────────────── $display("\n --- Test 4: 1100111 — no detection ---"); rst_n=0; @(posedge clk); #1; rst_n=1; apply_bit(1);apply_bit(1);apply_bit(0);apply_bit(0); apply_bit(1);apply_bit(1);apply_bit(1); chk(0,0, "1100111 = no detect"); // ── Test 5: Three back-to-back in 11011011101 ────────── $display("\n --- Test 5: 11011011101 (3 Mealy detections) ---"); rst_n=0; @(posedge clk); #1; rst_n=1; // bits: 1 1 0 1 1 0 1 1 1 0 1 apply_bit(1);apply_bit(1);apply_bit(0);apply_bit(1); chk(1,0, "1st detect t4"); // 1101↑ → S1 apply_bit(1);apply_bit(0);apply_bit(1); chk(1,0, "2nd detect t7 (overlapping)"); // 1101↑ → S1 apply_bit(1);apply_bit(1);apply_bit(0);apply_bit(1); chk(1,0, "3rd detect t11 (overlapping)"); // ── Summary ──────────────────────────────────────────── $display("\n======================================================="); $display(" RESULTS: %0d / %0d PASS | %0d FAIL", pass_cnt,test_num,fail_cnt); $display("======================================================="); if(fail_cnt==0) $display(" ✅ ALL TESTS PASSED\n"); else $fatal(1," ❌ %0d FAILURE(S)\n",fail_cnt); #20; $finish; end initial $monitor(" @%0t in=%b | mealy=%b moore=%b", $time,in,mealy_det,moore_det); endmodule `default_nettype wire
The waveform shows the overlapping stream 1101101 — two detections in 7 bits. The last ‘1’ of the first detection immediately becomes the first ‘1’ of the second match, demonstrating the state reuse.
# ── Icarus Verilog ──────────────────────────────────────────── iverilog -o ovlp_sim \ seq_det_mealy_ovlp.v \ seq_det_moore_ovlp.v \ seq_det_ovlp_tb.v vvp ovlp_sim gtkwave seq_det_ovlp.vcd # ── ModelSim ────────────────────────────────────────────────── vlog seq_det_mealy_ovlp.v seq_det_moore_ovlp.v seq_det_ovlp_tb.v vsim -c seq_det_ovlp_tb -do "run -all; quit -f"
| Property | Mealy Non-OL (M25) | Moore Non-OL (M25) | Mealy Overlapping | Moore Overlapping |
|---|---|---|---|---|
| States | 4 (S0–S3) | 5 (S0–S4) | 4 (S0–S3) | 5 (S0–S4) |
| Post-detect state (in=1) | S0 | S0 | S1 | S1 |
| Post-detect state (in=0) | S0 | S0 | S0 | S0 |
| Detections in 1101101 | 1 | 1 | 2 | 2 |
| Detections in 11011011101 | 2 | 2 | 3 | 3 |
| Lines changed vs non-OL | — | — | 1 line | 1 line |
| Detection latency | Same cycle as last bit | +1 cycle | Same cycle as last bit | +1 cycle |