courtesy: http://invionics.com/systemverilog-insights-always-and-always_comb-are-not-the-same/
Always_comb is one of a number of new process types added to SystemVerilog to give developers more control and improve code readability. On the surface always_comb seems like a convenient short-hand for always @*, but, surprisingly, that’s not actually the case. always_comb is actually quite different than always @*, and you should be aware of how if you plan on using it!
Before we dig too deeply into the details there is one thing about always_comb that I would like to point out. Much to my dismay,always_comb does not prevent accidental latch inference (something I’m sure we’ve all done with the Verilog always procedure). The SystemVerilog LRM does not declare latch inference within always_comb procedures as illegal. All that is suggested, but not required, of your SystemVerilog parser is to warn the user in the case of latch inference within an always_comb procedure. It’s an interesting choice, especially given that SystemVerilog brought in the always_latch and always_ff procedures too!
With that detail out of the way, let’s take a look at the differences between always @* and always_comb. In generally, these fall into four areas — time, sensitivity, content, and exclusivity of variables.
Time
When looking at the always_comb‘s execution time keep in mind the procedures intent — to model combinational logic. As such, the always_comb procedure, unlike always @*, executes at time zero. This makes sense as the outputs of a combinational logic model should have an initial value that depends on the values of the input signals. This is not possible with the always @*procedure as it’s outputs values are slave to the sensitivity list and thus require a delta on a sensitivity list signal to get updated.
When looking at the always_comb‘s execution time keep in mind the procedures intent — to model combinational logic. As such, the always_comb procedure, unlike always @*, executes at time zero. This makes sense as the outputs of a combinational logic model should have an initial value that depends on the values of the input signals. This is not possible with the always @*procedure as it’s outputs values are slave to the sensitivity list and thus require a delta on a sensitivity list signal to get updated.
Sensitivity
Both always_comb and always @* have inferred sensitivity lists. The inference, however, is different between the two procedures.always_comb‘s sensitivity goes a little deeper than always @*. always_comb is sensitive to changes inside a function as well as expressions in immediate assertions within functions. always @* is not sensitive to either. Both procedures are sensitive to changes to the inputs of functions and to expressions in assertions used directly within the procedures. For example:
Both always_comb and always @* have inferred sensitivity lists. The inference, however, is different between the two procedures.always_comb‘s sensitivity goes a little deeper than always @*. always_comb is sensitive to changes inside a function as well as expressions in immediate assertions within functions. always @* is not sensitive to either. Both procedures are sensitive to changes to the inputs of functions and to expressions in assertions used directly within the procedures. For example:
always_comb begin
comb_out <= comb_in0 && comb_func(comb_in1, comb_in2);
Assert00: assert (comb_in0 == comb_sensitive) else if (comb_ignored) $exit();
end
function comb_func;
input in0, in1;
begin
Assert01: assert (in0 == func_sensitive) $exit();
return in0 && in1;
end
endfunction
In the above code the always_comb procedure is sensitive to comb_in0, comb_in1, comb_in2, comb_sensitive and func_sensitive. The always_comb is not sensitive to comb_ignored because it is not in the immediate assertion statement but rather in the action block of the assertion. If the above always_comb procedure was changed to always @* then the procedure’s implicit sensitivity list would only include comb_in0, comb_in1, comb_in2 and comb_sensitive.
Content
The SystemVerilog LRM restricts the type of statements allowed within an always_comb procedure. This also makes sense in the context of a model for combinational logic. Blocking statements, fork-join statements, and statements with blocking timing or event controls are forbidden within an always_comb procedure.
The SystemVerilog LRM restricts the type of statements allowed within an always_comb procedure. This also makes sense in the context of a model for combinational logic. Blocking statements, fork-join statements, and statements with blocking timing or event controls are forbidden within an always_comb procedure.
Exclusivity
One very interesting aspect of always_comb is that the procedure owns the variables assigned with itself. That is, no other process is allowed to assign to a variable that an always_comb procedure assigns to. always @* has no such exclusivity. With that said, always_comb does not own assignment to the complete variable, only the portions it assigns to. So, the following is legal:
One very interesting aspect of always_comb is that the procedure owns the variables assigned with itself. That is, no other process is allowed to assign to a variable that an always_comb procedure assigns to. always @* has no such exclusivity. With that said, always_comb does not own assignment to the complete variable, only the portions it assigns to. So, the following is legal:
reg [1:0] a;
always_comb
a[1] = 1'b0;
always_comb
a[0] = 1'b1;
In the end, the always @* and always_comb are more like close siblings than identical twins. They both have similar abilities but are forced to live under close, but not identical, rules. It’s important to be aware of these differences, especially with respect to procedure sensitivity and execution time, as they can have surprising impacts on your simulations!
No comments:
Post a Comment