2
\$\begingroup\$

The code I am using is the following. I am using five states as this is a Moore model, and non-overlapping sequence is assumed. The state logic is correct as far as I can tell. However, when I run it, there is one test case that it does not pass.

The fact that I have trouble understanding is that it passes all cases after that with 1100 as the input and leaves out just one. I don't have the testbench for this, and only the test cases are used to determine the validity of design. The test case that didn't pass had the sequence X=1,X=1,X=0,X=0.

module sequence_detector_fsm (
        input Clk,      
        input X,            
        output Y            
);

parameter A=0, B=1, C=2, D=3, E=4;
reg [2:0] PS, NS;

always @(posedge Clk) begin
    PS <= NS;
end 

always @(PS,NS,X) begin
    case (PS)
        A       : NS = X ? B : A;
        B       : NS = X ? C : A;
        C       : NS = X ? C : D;
        D       : NS = X ? B : E;
        E       : NS = X ? B : A;
        default : NS = A;
    endcase 
end

assign Y = (PS==E);

endmodule
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

The problem is that your next-state logic uses an incorrect sensitivity list:

always @(PS,NS,X) begin

Since you make assignments to NS inside the block, you should not trigger the always block when NS changes. This can lead to unexpected simulation results like what you are observing. You should only trigger the block when the "inputs" to the block (namely, PS and X) change. You can use the special syntax @* (the implicit sensitivity list) for this. This syntax is a good coding practice because it relieves you of the burden of maintaining a list of signals to monitor. Only the signals that are "read" inside the block are added to the sensitivity list. This is the code you should use:

always @* begin

Here is the design code plus a simple testbench to show how your problem is fixed:

module sequence_detector_fsm (
        input Clk,      
        input X,            
        output Y            
);

parameter A=0, B=1, C=2, D=3, E=4;
reg [2:0] PS, NS;

always @(posedge Clk) begin
    PS <= NS;
end 

always @* begin
    case (PS)
        A       : NS = X ? B : A;
        B       : NS = X ? C : A;
        C       : NS = X ? C : D;
        D       : NS = X ? B : E;
        E       : NS = X ? B : A;
        default : NS = A;
    endcase 
end

assign Y = (PS==E);

endmodule 


module tb;

bit Clk;
bit X;
wire Y;

sequence_detector_fsm dut (
    .Clk  (Clk),
    .X    (X),
    .Y    (Y)
);

always #5 Clk++;

initial begin
    repeat (2) begin
        @(posedge Clk); X <= 1;
        @(posedge Clk); X <= 1;
        @(posedge Clk); X <= 0;
        @(posedge Clk); X <= 0;
        repeat (3) @(posedge Clk);
    end
    $finish;
end

endmodule

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.