//
// Code adapted from http://electrosofts.com/verilog/fsm.html
//

module fsm_test;

reg  clk, rst, inp;
wire outp;
reg[15:0] sequence;
integer i;

detector d1( clk, rst, inp, outp);

initial
begin
    sequence = 16'b0101_0111_0111_0010;
    clk = 0;
    rst = 1;
    #5 rst = 0;

    $display("initial state = ", d1.state);
    // first test using above sequence
    for( i = 0; i <= 15; i = i + 1)
    begin
        inp = sequence[i];
        #2 clk = 1;
        #2 clk = 0;
        $display("test 1: Input = ", inp, " State = ", d1.state, "  Output = ", outp);
    end

    // second test using a random sequence
    for( i = 0; i <= 15; i = i + 1)
    begin
        inp = $random % 2;
        #2 clk = 1;
        #2 clk = 0;
        $display("test 2: Input = ", inp, " State = ", d1.state, "  Output = ", outp);
    end
end

endmodule

///////////////////////////////////////////////////////
// detector 
// Detects two consecutive 0's or two consecutive 1's in 
//   input inx; outy becomes 1 for a clock cycle when a 
//   detection occurs. No overlapping.
//
///////////////////////////////////////////////////////
module detector ( clk, reset, inx, outy);

input clk, reset, inx;
output outy;

reg [1:0] state;
reg [1:0] nextstate;
reg outy;

// state coding
parameter s0 = 2'b00, s1 = 2'b01, s2 = 2'b10, s3 = 2'b11;

always @( posedge clk )
    case( state )
       s0:
           if( inx ) nextstate <= s1;
           else nextstate <= s2;
       s1:
           if( inx ) nextstate <= s3;
           else nextstate <= s2;
       s2:
           if( inx ) nextstate <= s1;
           else nextstate <= s3;
       s3:
           if( inx ) nextstate <= s1;
           else nextstate <= s2;
    endcase

always @(posedge reset) // reset is active high
    nextstate = s0;

always @(nextstate)
    begin 
        state = nextstate ;
        if (state == s3 ) outy <= 1 ;
        else outy <= 0;
    end       
        

endmodule