ipunished
ipunished

Reputation: 694

What to do when a latch cannot be avoided?

I know that latches are frowned upon in hardware and in Verilog coding. But, I sometimes come across cases where I cannot avoid a latch. For example, in these two cases:

always @ (*)
begin
    random_next = random; //default state stays the same
    count_next_r = count_r;
        
        random_next = {random[28:0], feedback}; //**shift left the xor'd every posedge clock
        

    if (count_r == 30) //if all 30 bits are shifted into register
    begin
        count_next_r = 0;
        random_done = random; //assign the random number to output after 13 shifts
    end
    else
    
        count_next_r = count_r + 1;

Here the random_done is a latch. I cannot see any other way of writing this. I only want the random_done to have data after 30 shifts of random. If I implement it this way, I am warned of a latch and it does not work properly.

Similarly, in the code below:

always @ (*)
begin
    state_next = state_reg; //default state stays the same
    count_next = count_reg;
    sel_next = sel;
    case(state_reg)
        idle:
            begin
                //DISPLAY HI HERE
                sel_next = 2'b00;
                if(start)
                begin
                    count_next = random_done; //get the random number from LFSR module
                    state_next = starting;
                end
            end
        starting:
            begin
                if(count_next == 750000000) // **750M equals a delay of 15 seconds. 8191 for simulation
                begin                           //and starting from 'rand' ensures a random delay
                    outled = 1'b1; //turn on the led 
                    state_next = time_it; //go to next state
                end
                
                else
                begin
                    count_next = count_reg + 1; 
                    outled = 1'b0;
                end
            end     
        time_it:
            begin
                    sel_next = 2'b01; //start the timer
                    state_next = done;                  
            end
                
        done:
            begin
                if(stop)
                    begin
                        sel_next = 2'b10; //stop the timer
                        outled = 1'b0;
                    end
                
            end
            
        endcase
        

From the above code the problematic section is this:

done:
    begin
        if(stop)
            begin
                sel_next = 2'b10; //stop the timer
                outled = 1'b0;
            end

Here outled is detected as a latch and during implementation I am warned of this. I simply want the led to go low when the stop bit is pressed.

How can I avoid these latches?

Upvotes: 3

Views: 298

Answers (3)

Martin Thompson
Martin Thompson

Reputation: 16832

If you make all your code synchronous (sensitive to posedge clk) you will not get latches. And you will get an easier time writing timing constraints (in the best case, you only need a single constraint for the clock period!)

Upvotes: 1

toolic
toolic

Reputation: 62236

You should be able to factor the outled logic out. Something like this.

always @(posedge clk or negedge nreset) begin
    if (!nreset) begin
        outled <= 0;
    end else if (state_reg == starting) begin
        if (count_next == 750000000) begin
            outled <= 1'b1; //turn on the led 
        end else begin
            outled <= 1'b0;
        end
    end else if ((state_reg == done) && stop) begin
            outled <= 1'b0;
    end
end

Upvotes: 2

AxelOmega
AxelOmega

Reputation: 972

Why not assign random_done to a register.

Create a counter and have it count down from thirty, then if it is zero assign the register random_done the new random value.

reg [4:0] counter; 

always@(posedge clk) begin
  if(rst) begin
    counter <= 5'd30;
  end
  else begin
    if(counter == 0) begin
      counter <= 5'd30;
    else begin
      counter <= counter - 1;
    end
end

wire count_done;

assign count_done = (counter == 0);

reg [size-1:0] random_done

always@(posedge clk) begin
  ...
  if(count_done) random_done <= random;
  ...
end

To me this code looks a bit jumbled up, it does not look like you are describing hardware. Remember that Verilog ia an HDL Hardware Description Language. When emphasis on description.

Split the logic for each register in its own always block.

However first draw an RTL schematic of what you are trying to do. If you can not draw an RTL schematic of what you want to design, your design will most likely not be good hardware.

Upvotes: 2

Related Questions