0
\$\begingroup\$

Trying to implementing a Moore state machine using three always blocks. The Moore state machine has two inputs (ain[1:0]) and one output (yout). The output yout begins as 0 and remains a constant value unless one of the following input sequences occurs:

(i) The input sequence ain[1:0] = 01, 00 causes the output to become 0
(ii) The input sequence ain[1:0] = 11, 00 causes the output to become 1
(iii) The input sequence ain[1:0] = 10, 00 causes the output to toggle.

module moore_sequence_detector_3_blocks(
input clk,
input reset,
input [1:0] ain,
output reg yout
);
reg[2:0] state, nextstate;
parameter S0=0, S1=1, S2=2, S3=3, S1_To_S0=4, S2_To_S0=5, S3_To_S0=6;

always @(posedge clk or posedge reset) // always block to update state
    if(reset)
    begin
        state <= S0;
    end
    else
    begin
        state <= nextstate;
    end

always @(state or ain) // always block to compute nextstate
begin
    case (ain)
        2'b00:
            if(state == S1)
                nextstate = S1_To_S0;
            else if(state == S2)
                nextstate = S2_To_S0;
            else if(state == S3)
                nextstate = S3_To_S0;
            else
                nextstate = state;
        2'b01: nextstate = S1;
        2'b10: nextstate = S2;
        2'b11: nextstate = S3;
        default: nextstate = S0;
    endcase
end

always @(state) // always block to compute output
    begin
        case(state)
            S0: yout = 0;
            S1_To_S0: yout = 0;
            S2_To_S0: yout = ~yout;
            S3_To_S0: yout = 1;
            default:
                yout = yout;
        endcase
    end endmodule

I cant seem to figure out what is wrong. The states should work as follows enter image description here

sout0 yout = 0 sout1 yout = 1

swait1 yout = 0 swait2 yout = 0 swaitInv0 yout = 0

swait3 yout = 1 swait4 yout = 1 swaitInv1 yout = 1

swaitInv0 -> sout1

\$\endgroup\$
1
\$\begingroup\$

You state machine coding is rather weird.

You normally start with looking which state you are in and then respond to the input to go to a new state. Also you should give your states better names.

case (state)
SEEN_00: 
    case (ain)
    2'b00 : next_state = SEEN_00;
    2'b01 : next_state = SEEN_01;
    2'b10 : next_state = ..
    2'b11 : next_state = ..
    endcase
SEEN_01 : 
    case (ain)
    2'b00 : next_state = ..
    2'b01 : next_state = ..
    2'b10 : next_state = ..
    2'b11 : next_state = ..
    endcase
SEEN_10 :
    ...
SEEN_11 :
    ...
endcase

Now here is a nice trick if you need to react to state transitions. You look at the current state and the next state:

if (state==SEEN_01 && next_state==SEEN_00) 
   yout <= ...
else
   if (state==SEEN_10 && next_state==SEEN_00) 

This is an example where the coding using a state and next_state gives you a huge advantage against just writing state <= SEEN_..;

With this the state machine code becomes regular and thus trivial.

Now here is a nice GOTCHA:

Note that the output yout is registered and is not combinatorial depending on an input.

Thus this is NOT a Mealy machine.

At the same time the output is NOT dependent on the state as in state SEEN_00 the yout can be 0 or 1 depending on the previous state. Thus if you take the definition of a Moore machine literally "a Moore machine is a finite-state machine whose output values are determined only by its current state. "

This is NOT a Moore machine either.

\$\endgroup\$
0
\$\begingroup\$
always @(state) // always block to compute output
    begin
        case(state)
            S0: yout = 0;
            S1_To_S0: yout = 0;
            **S2_To_S0: yout = ~yout;**
            S3_To_S0: yout = 1;
            default:
                **yout = yout;**
        endcase
    end endmodule

In the above code i am seeing latch formation usually which is not preferred in the synthesizable codes, and the FSM you have written is kind of new style which i haven't seen till now, from the state transition diagram you have provided i have written the FSM for the same in system verilog , please go through it if needed:

module sequence_detector (
    input        clk,reset
   ,input [1:0]  ain
   ,output logic yout
);

logic nyout;
enum logic [3:0] {   START
                    ,SWAIT_1,SWAIT_2,SWAIT_3,SWAIT_4
                    ,SWAITINV_0,SWAITINV_1
                    ,SOUT_0,SOUT_1
                    ,XXX = 'x
                 } state,next;

always_ff @(posedge clk or posedge reset)
    if(reset) state <= #1 START;
    else      state <= #1 next;

always_comb begin 
        next = 'x;
   casez(state)
    START      :case(ain)
                    2'b01 : next = SWAIT_2   ;
                    2'b10 : next = SWAITINV_0;
                    2'b11 : next = SWAIT_1   ;
                endcase
    SWAIT_1   :case(ain)
                    2'b00 : next = SOUT_1    ;
                    2'b01 : next = SWAIT_2   ;
                    2'b10 : next = SWAITINV_0;
                endcase
    SWAIT_2   :case(ain)
                    2'b00 : next = SOUT_0    ;
                    2'b01 : next = SWAITINV_0;
                    2'b11 : next = SWAIT_1   ;
                endcase
    SWAIT_3   :case(ain)
                    2'b00 : next = SOUT_1    ;
                    2'b01 : next = SWAIT_4   ;
                    2'b10 : next = SWAITINV_1;
                endcase
    SWAIT_4   :case(ain)
                    2'b00 : next = SOUT_0    ;
                    2'b10 : next = SWAITINV_1;
                    2'b11 : next = SWAIT_3   ;
                endcase
    SWAITINV_0:case(ain)
                    2'b00 : next = SOUT_0 ;
                    2'b01 : next = SWAIT_2;
                    2'b11 : next = SWAIT_1;
                endcase
    SWAITINV_1:case(ain)
                    2'b01 : next = SWAIT_4;
                    2'b10 : next = SOUT_0 ;
                    2'b11 : next = SWAIT_3;
                endcase
    SOUT_0    :case(ain)
                    2'b01 : next = SWAIT_2   ;
                    2'b10 : next = SWAITINV_0;
                    2'b11 : next = SWAIT_1   ;
                endcase
    SOUT_1    :case(ain)
                    2'b00 : next = SWAITINV_1;
                    2'b01 : next = SWAIT_4   ;
                    2'b11 : next = SWAIT_3   ;
                endcase
   endcase
end

always_ff @(posedge clk or posedge reset)
    if(reset) yout <= #1 1'b0;
    else      yout <= #1 nyout;

always_comb begin
        nyout = 'x;
  case(state)
    SOUT_0,SWAITINV_0,
    SWAIT_1,SWAIT_2     : nyout = 1'b0;
    SOUT_1,SWAITINV_1,
    SWAIT_3,SWAIT_4     : nyout = 1'b1;
  endcase
end

endmodule

in the similar lines from the @oldfart answer use the FSM state names as sequence detected which will be helpful for reading code and understanding it easily, u can see the code below:

module moore_sequence_detector (
    input        clk,reset
   ,input [1:0]  ain
   ,output logic yout
);

logic nyout;
enum logic [2:0] {   START
                    ,SEEN_01,SEEN_0100
                    ,SEEN_11,SEEN_1100
                    ,SEEN_10,SEEN_1000
                    ,XXX = 'x
                 } state,next;

always_ff @(posedge clk or posedge reset)
    if(reset) state <= #1 START;
    else      state <= #1 next;

always_comb begin 
        next = 'x;
   casez(state)
    START    :case(ain)
               2'b01 : next = SEEN_01;
               2'b10 : next = SEEN_10;
               2'b11 : next = SEEN_11;
              endcase
    SEEN_01  :         next = (ain == 2'b00) ? SEEN_0100 : START;
    SEEN_10  :         next = (ain == 2'b00) ? SEEN_1000 : START;
    SEEN_11  :         next = (ain == 2'b00) ? SEEN_1100 : START;
    SEEN_0100:         next = START;
    SEEN_1100:         next = START;
    SEEN_1000:         next = START;
   endcase
end

always_ff @(posedge clk or posedge reset)
    if(reset) yout <= #1 1'b0;
    else      yout <= #1 nyout;

always_comb begin
        nyout = yout;
  casez(state)
   SEEN_0100 : nyout =  1'b0;
   SEEN_1000 : nyout =  1'b1;
   SEEN_1100 : nyout = ~yout;
  endcase
end

endmodule
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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