@* is an event control. It does not know anything about input/outputs, or combination logic for that matter. It simply builds an implicit sensitivity list by looking at the identifiers in the single statement that follows it. (that single statement could be a begin/end block). If you have
Code:
always begin
A = D;
F = G;
@* begin
A[B] = C;
D = A;
wait(E);
end
end
then @* is replaced with @(A or B or C).G is not included because it is not part of the statement that appears after the @*. D is not included because it only appears as an
lvalue (target of an assignment), and E is not included because it only appears in an event control.
Synthesis rules usually require that only one event control can appear in an
always construct and must be the first token in the construct, and no other event controls are allowed in the construct. That is why you always see
always @* together.
SystemVerilog replaced
always @* with
always_comb and
always_latch. This is preferable because there are many problems with @*.
First is if any of the identifiers are parameters or constants, the construct does not execute unless there is some other event. always_comb will always execute at time 0. Then the result will be correct from time 0.
parameter A=1;
always @* C = A | B;
This does not execute until there is a event on B.
The other problem with @* is that it ignores identifiers embedded in function, whereas always_comb expands the function.
always @* Z = func() && W;
function reg func;
func = X | Y;
endfunction
Only W is put on the sensitivity list.
If you use SystemVerilog's always_comb, W, Y and Y are put on the sensitivity list.
Dave