0

I don't understand how to avoid inferred latches in my design of ASM Here's my code.

module ASM (
input[7:0] SW,
input Start, Reset, Clock,
output reg Led,
output reg[3:0] result);

reg[2:0] state, next_state;
reg[7:0] A;
wire Done;

parameter S1 = 3'd1;
parameter S2 = 3'd2;
parameter S3 = 3'd3;
parameter S4 = 3'd4;
parameter S5 = 3'd5;
parameter S6 = 3'd6;

always @(posedge Clock)
begin
    if (!Reset)
        state <= next_state;
    else
        state <= S1;
end

always @(state, Start, A)
begin

    case(state)
    S1: begin
        if (Start)
            next_state = S2;
        else
            next_state = S1;
    end
    S2: begin //check A == 0
        if (A == 8'd0)
            next_state = S6; //done
        else
            next_state = S3;//check A0
    end
    S3: begin //check A0
        if (A[0])
            next_state = S4; //result++
        else
            next_state = S5; //A>>1
    end
    S4: begin //result++
        next_state = S5;
    end
    S5: begin //A>>1
        next_state = S2;
    end     
    S6: begin //done
        if (Start)
            next_state = S6;
        else
            next_state = S1;
    end
    default: begin
        next_state = S1;
    end     
    endcase
end

always @(state, SW)
begin
    //result = 4'b0;
    //A = 8'd0;
    //Led = 1'b0;   
    case (state)
    S1: begin
        A = SW;
        result = 4'b0;
        Led = 1'b0; 
    end
    S2: begin

    end
    S3: begin

    end
    S4: begin
        result <= result + 4'd1;
    end
    S5: begin
        A = A >> 1;
    end     
    S6: begin
        Led = 1'b1;
    end     
    default: begin
        result = 4'b0;
        Led = 1'b0;     
    end 
    endcase
end
endmodule

I understand that i should initialize variables "A", "result" and "led" before "case" statement in second "always" block. But if do this every time when "always" block is active I loose my previous results of variables and assign them again to initial values and thus whole design is wrong. So that I can't avoid latches and simply shouldn't initialize these variables. But latches is bad practice. So can you explain how i should change code to avoid this?

Vlad Timofeev
  • 71
  • 1
  • 1
  • 9

3 Answers3

0

Well, the behaviour you want to get (only change for certain inputs and keep it's value otherwise) is that of a latch. If you want to avoid latches and have variables with memory use a synchronous always block.

always @(posedge Clock)
begin 
    case (next_state)
    S1: begin
        A <= SW;
        result <= 4'b0;
        Led <= 1'b0; 
    end
    S2, S3: begin

    end
    S4: begin
        result <= result + 4'd1;
    end
    S5: begin
        A <= A >> 1;
    end     
    S6: begin
        Led <= 1'b1;
    end     
    default: begin
        result <= 4'b0;
        Led <= 1'b0;     
    end 
    endcase
end
Hans Lehnert
  • 444
  • 3
  • 10
0

A synthesizer only cares about your sensitivity list for synchronous logic. @(state, SW) only triggers on specific variables in simulation. The synthesizer essentially sees @(state, SW, result). This is way @* (and the synonymous @(*)) is preferred for combination logic and intentional latches.

For detail about inferred latches read: What is inferred latch and how it is created when it is missing else statement in if condition.can anybody explain briefly?

For your case you should make the block synchronous. Change @(state, SW) to @(posedge Clock). To reduce the timing delay, change case (state) to case (next_state) in the same always block. You should use non-blocking to assign A, result, and Led. You may want to add a reset condtion.

Greg
  • 18,111
  • 5
  • 46
  • 68
  • Thanks for the answer. But why should i use non-blocking assignment in this particular case? I see no difference in desing when I use blocking assignment. – Vlad Timofeev Feb 01 '18 at 06:30
  • It is a good coding practice. Synchronous logic and intentional latches should be assigned with non-blocking to reduce the risk of race conditions in simulations. Synthesis doesn't care. http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf – Greg Feb 01 '18 at 06:38
0

The latches are inferred from the second case statement in your example. The reason is that all 3 variables are assigned in under some conditions (S1) and not assigned under others (S2,S3,...), meaning that they keep their old values in such cases. This is a typical latch behavior. Therefore you have inferred latches.

I do not think that this statement is good for fixing in any case. You have a bunch of error in it, using operations which should be done in synchronous blocks only, like A = A >> 1 or mixing blocking and non-blocking assignments. It is not a way to design a state machine. So, look at @Hans's Lehnert answer to get an idea.

Serge
  • 11,616
  • 3
  • 18
  • 28