1

when we write FSM in verilog there are two ways to write FSM first is using 3 always block(1 for next-state combinational logic + 1 for presene->next state sequential logic + 1 for output logic) and second way is to use only one always block for all 3 operation but my output wave for both cases is different..why is it so?

for example i have coded simple fsm in both ways and my out is shifted by 20 timeunit

first way :

//using one alwys block
module moore_20_1(x_in,y_out,clk,reset);
input wire clk,reset,x_in;
output reg y_out;

reg [1:0] state;

parameter start=2'b00,s0=2'b01,s1=2'b10,s2=2'b11;

always @ (posedge clk)//next state logic + ps->ns logic + output logic
begin
  if(reset==1'b1) begin
    state<=start;
    y_out<=0;
  end
else begin
  case(state)
    start: begin if(x_in) state<=s0;
          else state<=s0;
            y_out<=0;
          end
    s0: begin if(x_in) state<=s1;
      else state<=s0;
      y_out<=0;
    end
    s1: begin if(x_in) state<=s2;
      else state<=s1 ;         
      y_out<=0;
    end
    s2: begin if(x_in) state<=s0;
      else state<=s2;
      y_out<=1;
    end
    endcase


end
end
endmodule

second way

    //moore machine using 3 always block(ps->ns+output logic+next-sate logic)
module moore_5_20_2(x_in,y_out,clk,reset);
input wire clk,reset,x_in;
output reg y_out;

reg [1:0] state;
reg [1:0] next_state; 

parameter start=2'b00,s0=2'b01,s1=2'b10,s2=2'b11;

//ps->ns logic
always@ (posedge(clk))
if(reset==1'b1) 
  next_state<= #1 start;
else
  next_state<= #1 state;


//next-stae logic  
always @(next_state,x_in)
case(next_state)
  start: begin if(x_in) state<=s0;
          else state=s0;
          end
    s0: begin if(x_in) state<=s1;
      else state=s0;
    end
    s1: begin if(x_in) state<=s2;
      else state=s1 ;         
    end
    s2: begin if(x_in) state<=s0;
      else state=s2;
    end
    endcase

//OUTPUT LOGIc

always@(next_state)
if (reset==1'b1) y_out<= 0;
else begin 
    case(next_state)
      start:y_out<= 0;
      s0: y_out<=   0;
      s1: y_out<=0;
      s2: y_out<=#1 1;

    endcase
  end
endmodule

why the output is shifted by 20 timeunit..?

user3091069
  • 111
  • 1
  • 3
  • Why you are assigning `next_state <= state` on the posedge? Usually it is the other way around, next_state is combinatorially driven by the state and inputs, and then on posedge `state <= next_state`. – Tim Jul 22 '14 at 19:33
  • its just the reg names...for sake of convenience i use it..but my whole logic is built on these reg name only..!:) – user3091069 Jul 22 '14 at 19:58
  • Yeah it's probably not the source of the problem, but just looking at that code will probably confuse most people who have experience with state machines, since the names are sort of backwards. Have you looked at waveforms of your two FSMs? It would be helpful to show wave comparisons in your question of the state and outputs. – Tim Jul 22 '14 at 20:02

1 Answers1

2

I am going to make a few assumptions about how you are testing both of these, namely that you have something like this in your testbench:

initial begin 
  clk = 0; 
  forever #10 clk = ~clk; 
end

And I am also assuming the second way is 20 (or maybe 19?) time units ahead of the first way, based on what I think is going wrong.

Basically, the first way is buffering the output y_out in a register while the second way is setting y_out combinationally.

As this is a Moore machine (which both of those implementations are), the output is dependent only on the current state. In the first way, on the clock edge, y_out is being set to a value based on the "current" state (ie, what the state is the moment right before the clock edge). While the state might also change at the clock edge, this will not happen until after the next value of y_out has been determined for this clock cycle. This means in a single clock cycle, y_out will be set based on what the state was in the previous cycle and stay that way until the next clock edge.

In the second way, y_out is set combinationally rather than on a clock edge. In this case, the next state logic will determine state and when a clock edge comes along, next_state will become state (after 1 time unit for some reason....). Thus, now the combinational block that determines the output y_out will wake up and set y_out to whatever value for that state. Therefore, y_out will take on the output for the current state, the state for this clock cycle and not that of the previous clock cycle as in the first way.

For example, say we're in state s1 and x_in is asserted. Thus, in the second way state is all ready at s2 in preparation for the transition. A clock edge comes.

In the first way, the always block wakes up. reset isn't asserted so on to the case statement. We're in s1 and x_in is asserted so state will become s2 and y_out is set to 0. Done until the next clock edge. So it will look like we are in s2 and y_out is 0, until the next clock edge, at which time y_out will become 1.

In the second way, the state register always block wakes up and next_state becomes s2 after 1 time unit. Once next_state becomes s2, the output logic always block for y_out will wake up and now next_state is s2 so y_out will become 1 now (or again after 1 time unit?). So it will look like we are in s2 and y_out is 1 (roughly), which is about 20 time units ahead.

NOTE: Much of the confusion involved in this (partially as Tim mentioned) is not particularly good style. I prefer the second way more, but the way you implemented it is somewhat non-ideal. Heres a suggested rewrite for future reference (though I did take some simplification liberties as well):

module nice_moore_machine(
  input wire clock, reset, x_in,
  output reg y_out);

reg [1:0] state, next_state;

parameter start = 2'b00, s0 = 2'b01, s1 = 2'b10, s2 = 2'b11;

/* State register (synchronous reset) */
always @(posedge clk) begin
  if (reset) begin
    state <= start;
  end
  else begin
    state <= next_state;
  end
end

/* Next state logic */
always @(*) begin
  case (state)
    start: begin
      next_state = s0;
    end
    s0: begin
      next_state = (x_in) ? s1 : s0;
    end
    s1: begin
      next_state = (x_in) ? s2 : s1;
    end
    s2: begin
      next_state = (x_in) ? s0 : s2;
    end
  endcase
end

/* Output logic */
always @(*) begin
  y_out = (state == s2); /* Note that y_out could be a net and use an assign in this case */
end

endmodule

Hope this helps you understand better!

Unn
  • 4,775
  • 18
  • 30