Could someone explain to me why a latch would be inferred instead of a flip-flop?
always_ff @ (posedge clk, negedge rst)
begin
if (!rst)
a <= '0;
end
Shouldn't the fact that the always block is sensitive to a signal edge be enough to infer a flip-flop. In this case when a negative edge of reset is triggered a gets 0, else it keeps former value.
This question comes from the selected best answer from this stackoverflow question:
System Verilog always_latch vs. always_ff
===========================================================================
I will share here what I found out so far. The reason why this synthesizes to a latch, instead of a flip-flop is because on the right side of the assignment is a CONSTANT. When this is the case the behavior of a latch and a flip-flop are EQUIVALENT, because it does not matter whether it catches the input value on a signal edge (flip-flop) or while input latching is enabled (latch) as the input does not change. So the synthesis tool chooses the element that takes less resources, i.e. the latch.
On the other hand, if on the right side of the assignment there was a VARIABLE, the synthesis would have to infer a flip-flop, because it would matter whether the input is sampled on an edge (flip-flop) or during input latching is enabled (latch), meaning the two logic elements are NOT EQUIVALENT.
Here is an example. First two always blocks will synthesize to a latch (in Quartus 14), which is OK, as they are equivalent, because of a constant. But, the 3. and the 4. always block will also be synthesized into a latch, which is not the intended behavior and these blocks are not equivalent! The 3. block will give a warning, while the 4. one won't.
module ff_latch(
input logic clk,
input logic nrst,
input logic a,
output logic t, x, y, z
);
always_ff @(posedge clk, negedge nrst)
begin
if (!nrst)
t <= 0;
end
always_latch
begin
if (!nrst)
x <= 0;
end
always_ff @(posedge clk, negedge nrst)
begin
if (!nrst)
y <= a;
end
always_latch
begin
if (!nrst)
z <= a;
end
endmodule: ff_latch
To me this behavior is not correct, as I specifically said I want a flip-flop (with edge triggering). It's not even that the coding is ambiguous, always blocks 3. and 4. are clearly different, as can be seen in this waveform from the above simulation:
Block 3. (tb_y) behaves like a asynchronous flip-flop and block 4. (tb_z) behaves like a latch. But the synthesis tool infers a latch in both cases.
If someone can shed some light on this or comment the code or the waveform, it would be much appreciated.