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?
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.