Sugihara
Sugihara

Reputation: 1101

Verilog Latch in always@(posedge clk)

If I understand latch correctly, it is created in combinational block in which not all possible conditions are declared when assigning a variable to a value. How am I getting a latch in my sequential block?

When I compiled my code via Quartus, it retured 2 Fmax, which indicates I have a latch.

   always@(posedge clk or negedge nreset) begin
      case(counter)
         0: begin
            if(state == IDLE) begin
               // DOES SOMETHING
            end
         end

         1: begin
           // DOES ASSIGNMENT
         end // PROLOG

         81: begin
           // DOES ASSIGNMENT
         end // EPILOG


         82: begin
            // DOES ASSIGNMENT
         end // POSTPROC

         default: begin
            // DOES ASSIGNMENT
         end // ROUNDS

      endcase  

I have checked each of the cases, and made sure all assignments are non-blocking. Any idea why I might be latching?

My code is computing SHA1

I have 2 always@(posedge clk), one computes the next Wt, and the above computes the next A,B,C,D,E value.

Upvotes: 0

Views: 1601

Answers (2)

RGD2
RGD2

Reputation: 469

More information needed for a short, specific answer: What reg type variables are you setting / writing to in that always block?

Any circumstances where you fail to ensure there is at least one assignment for each such variable, will infer a latch for that variable, because you have a circumstance where it would have to just stay unchanged.

If you want it to stay unchanged but be a proper clock-driven register and not be a latch, you can just have something like

myreg <= myreg;

Which can be at the top of the always block, because any subsequent non-blocking assignments within the same always block will safely override it.

There will be no glitchs from having more than one <= assignment to the same variable within the block, because while it is interpreted as sequential code, it's actual 'run time'/'as implemented' behaviour is instantaneous if combinational, or clock delayed if sequential, but either way dependent only on the last effective <= assignment. If there was no <= statement in some circumstance for a particular variable... well, that's how we get inferred latches.

Therefore all possible cases are covered in all possible circumstances, trivially.

You can even have just a one-liner like:

{reg1, reg2, reg3} <= {reg1, reg2, reg3};

Where the {,} list (identical on both sides!) has all the registers you intend to control in this always block, at the top of the always block (before your if statements or case statement) to categorically prevent any latch-inference of the mentioned variables.

This works because it ensures that in all possible circumstances, every reg type has a explicit value. It is this complete coverage which disables latch inference.

Otherwise you have to set all regs once in every case, either to the new value they will have, or to 'themselves' to express that they should not change.

If you have signals which are one-hot or flag outputs intended to be high in one state case only, it is better to just pre-set them to default to zero (rather than 'themselves' as above), and then set them to 1'b1 only in the specific cases before they are supposed to be high (if synchonous block), and this will work also. (It's more usual to have a combinational block always @* that does that but for cases where they are high, because it is easier to read - they will be high on the same state they are mentioned in, done that way. Setting them with <= in a posedge block really sets what they will be when the next clk posedge arrives: So it's generally better to make this explicit by setting outputs and a 'next_state' reg in an combinational case block, then just have a single posedge block that just sets state <= next_state;).

The other thing that can get you an inferred latch, is having a combinational block with a input variable missing from the sensitivity list. Avoid that by preferring always @* to make it always include all in-scope variables in the sensitivity list.

PS. There are two types of synthesizable variable: wire and reg. In verilog, reg just indicates it will be set in some kind of combinational block (initial or always), and wire is outside of those, either by connection, by a expression when defined, or with a single later assign wirevar = expr; line. A reg variable is only a register if it is assigned in a synchronous block AND it doesn't get inferred to be a latch.

Upvotes: -1

Peter Bayley
Peter Bayley

Reputation: 26

There is no else on your if statement.The synthesizer is confused as to what needs to happen next, thus inferring latches.

If that is not intended but instead simply what you wrote for the stack overflow example then the problem may be in your other always block.

A latch is simply a Flip Flop without a clock. The reason synthesizers think they are bad is because they can potentially cause timing errors. Latches are not always a problem either, in fact sometimes as you probably already know, they are intentional.

Check your assign statements, and see if you have any regs declared outside of an always block which is initialized to 0 or some value.

In that case you might like to try the initial block. Syntax:

 initial
 begin

 value = 0;
 input = 0; // or something

 end

Upvotes: 1

Related Questions