Electronic – ‘1011’ Overlapping (Mealy) Sequence Detector in Verilog

digital-logicrtlstate-machinesverilog

I'm designing a "1011" overlapping sequence detector,using Mealy Model in Verilog.

The FSM that I'm trying to implement is as shown below :-

enter image description here

Verilog Module :-

`timescale 1ns / 1ps

module seq_detector(
input x,clk,reset,
output reg z
);

parameter S0 = 0 , S1 = 1 , S2 = 2 , S3 = 3 ;
reg [1:0] PS,NS ;

    always@(posedge clk or posedge reset)
        begin
            if(reset)
                PS <= S0;   
            else    
                PS <= NS ;
        end             

    always@(PS or x)
        begin 
            
            case(PS)
                S0 : begin 
                            z = 0 ;
                            NS = x ? S1 : S0 ;
                            $display(PS);
                        end
                S1 : begin 
                            z = 0 ;
                            NS = x ? S1 : S2 ;
                            $display(PS);
                        end
                S2 : begin 
                            z = 0 ;
                            NS = x ? S3 : S0 ;
                            $display(PS);
                        end 
                S3 : begin 
                            z = x ? 1 : 0 ; 
                            NS = x ? S1 : S2 ;
                            $display(PS);
                        end

            endcase
        end
endmodule

Testbench :-

`timescale 1ns / 1ps

module testbench;
    // Inputs
    reg x;
    reg clk;
    reg reset;
    // Outputs
    wire z;
    // Instantiate the Unit Under Test (UUT)
    seq_detector uut (
        .x(x), 
        .clk(clk), 
        .reset(reset), 
        .z(z)
    );
    
initial
    begin
        clk = 1'b0;
        reset = 1'b1;
        #15 reset = 1'b0;
    end

always #5 clk = ~ clk;  

initial begin
        #12 x = 0;#10 x = 0 ; #10 x = 1 ; #10 x = 0 ;
        #12 x = 1;#10 x = 1 ; #10 x = 0 ; #10 x = 1 ;
        #12 x = 1;#10 x = 0 ; #10 x = 0 ; #10 x = 1 ;
        #12 x = 0;#10 x = 1 ; #10 x = 1 ; #10 x = 0 ;
        #10 $finish;
    end
      
    
endmodule

Simulation Output :-

enter image description here

The issue is that, I'm getting the number of '1011' detected to be correct (i.e. 3 according to the testbench). But the timing where the output is going high is wrong. The output 'z' is going high when '101' is being detected, when it's expected to go high when '1011' occurs. What's the possible modification that I'd have to do, so as to eliminate this error ?

Best Answer

The error is caused by mixing the combinational State assignment block with the sequential output block. The combinational state assignment block and the sequential output block have different sensitivity lists.

Following these guidelines helped me design glitch-gree FSMs.

  1. Sequential blocks use nonblocking assignments.
  2. Combinational blocks use blocking assignments.
  3. It's better to use registered outputs.
  4. Use combinational logic for the state assignment block

Link to the design on EDA Playground

Design:

`timescale 1ns / 1ps

 module seq_detector(
 input x,clk,reset,
 output reg z
 );

 parameter S0 = 0 , S1 = 1 , S2 = 2 , S3 = 3 ;
 reg [1:0] PS,NS ;

 //sequential state register block
 always @ (posedge clk or posedge reset)
   if (reset)
     PS <= S0;  
   else
     PS <= NS;
   
 //sequential output block
 always @ (posedge clk or posedge reset)
   if (reset)
     z <= 1'b0;
   else
     z <= (PS == S3) && x;
 
 //combinational state assignment block  
 always @ (*)
  begin
    case(PS)
        S0 : NS = x ? S1 : S0 ;
        S1 : NS = x ? S1 : S2 ;
        S2 : NS = x ? S3 : S0 ;
        S3 : NS = x ? S1 : S2 ;
    endcase
  $monitor(PS);
  end
  
 endmodule

Testbench:

`timescale 1ns / 1ps

 module testbench;
 // Inputs
 reg x;
 reg clk;
 reg reset;
 // Outputs
 wire z;
 // Instantiate the Unit Under Test (UUT)
 seq_detector uut (
    .x(x), 
    .clk(clk), 
    .reset(reset), 
    .z(z)
);



always #5 clk = ~ clk;  

initial begin
$dumpfile("dump.vcd");
$dumpvars(1, testbench);
fork 
    clk = 1'b0;
    reset = 1'b1;
    #15 reset = 1'b0;
begin  
    #12 x = 0;#10 x = 0 ; #10 x = 1 ; #10 x = 0 ;
    #12 x = 1;#10 x = 1 ; #10 x = 0 ; #10 x = 1 ;
    #12 x = 1;#10 x = 0 ; #10 x = 0 ; #10 x = 1 ;
    #12 x = 0;#10 x = 1 ; #10 x = 1 ; #10 x = 0 ;
    #10 $finish;
end
join   
end  
endmodule

Waveform: https://www.edaplayground.com/w/x/3Pj waveform