iff
is an event qualifier. It doesn't matter what the event left of the iff
(edge or value change).
IEEE Std 1800-2012 § 9.4.2.3 Conditional event controls:
The @ event control can have an iff qualifier.
module latch (output logic [31:0] y, input [31:0] a, input enable);
always @(a iff enable == 1)
y <= a; //latch is in transparent mode
endmodule
The event expression only triggers if the expression after the iff
is true (as defined in 12.4), in this case when enable
is equal to 1. This type of expression is evaluated when a changes and not when enable
changes. Also, in similar event expressions of this type, iff
has precedence over or. This can be made clearer by the use of parentheses.
IEEE Std 1800-2012 suggests that iff
could be synthesizable 9.2.2.4 Sequential logic always_ff procedure, however it is currently uncommon for a synthesizer to support iff
. Therefore, it is not recommended to use iff
in coded intended to be synthesized. There an semi-exception I mention below using `ifdef
/`ifndef
.
If it becomes synthesizable, iff
could be used for clock, but it sill may not be the recommenced approach. Clock gating should be used for gating the clock of a large module that need to be dynamically suspended or turned off/on; not for handful of flops. Clock gating is rarely beneficial for small edge trigger designs. Typically using an enable pin or Q to D feedback is sufficient power/area savings.
A place where iff
is helpful in RTL is with the classic scheduling issue with overlapping asynchronous set/reset. When rst_n
and set_n
are both low, reset (in the below example) has priority. If rst_n
were to go high with set_n
renaming low (no transition), a real flop would asynchronous set, but RTL will do nothing.
alway_ff @(posedge clk, negedge rst_n, negedge set_n) begin
if (!rst_n) begin
// ...
end
else if (!set_n) begin
// ...
end
else begin
// ...
end
end
Adding posedge rst_n iff !set_n
to the sensitivity list allows the corner case condition to function property. Since iff
is not [currently] synthesizable, an `ifndef `endif
needs to be warped around it
alway_ff @(posedge clk, negedge rst_n,
`ifndef SYNTHESIS
posedge rst_n iff !set_n,
`endif
negedge set_n) begin
// ...
end