1
\$\begingroup\$

If you are trying to make a pure combinational logic using always @(*) , it seems the practice is to use a blocking statement:

always @ ( * ) begin
   x = a & b;
   y = c | d;
end

Using the blocking statement seems to infer y=c|d happens AFTER x=a&b, so how will this be synthesized? What if I want to make combinational logic where x=a&b and y=c|d are two independent gates? Should I do <= instead?

always @ ( * ) begin
   x <= a & b;
   y <= c | d;
end
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Yes, using blocking assignments in a procedural always block is a recommended good practice to infer combinational logic in synthesis.

In your code, since the signals are all independent of each other, the order of assignments is irrelevant. You will infer an AND gate for x and an OR gate for y. You can swap the order of the assignments and still get the same synthesized gates:

always @ ( * ) begin
   y = c | d;
   x = a & b;
end

Since they are independent, you could choose to separate them into their own always blocks and still get the same results:

always @ ( * ) y = c | d;
always @ ( * ) x = a & b;

Separating them might better convey the intent of the logic, but it is purely a matter of coding style.

Another style which results in the same gates is to use continuous assignments where you declare the x and y signals as wire types:

assign y = c | d;
assign x = a & b;

Using nonblocking assignments (<=) should infer the same gates for your code, but it is not recommended for combinational logic.


Using the blocking statement seems to infer y=c|d happens AFTER x=a&b

Simulation software will execute the y assignment after the x assignment, but since they are independent, it is irrelevant.

\$\endgroup\$
1
\$\begingroup\$

You should avoid using non-blocking assignments in combinational logic for a number of reasons.

You are correct for variables with no dependencies, it makes no difference for that synthesized logic in the ordering or which kind of assignment statements you use. But it could impact simulation in other parts of your design. It could have other consequences when you later introduce dependancies in that code.

Verilog RTL simulation assumes that sequential logic is synchronous to a clock edge in a single region, and all variables updated by the logic gets updated in a region after that clock edge using non-blocking assignments. But if any combinational logic gets inserted into the clock path, that synchronization is lost.

always @(*)
   y <= c & g; // incorrect use of non-blocking assignment 
always @(posedge c);
   a <= b + d;
always @(posedge y);
   e <= a + f;

Now the value of a when the third always block executes is no longer its old value.

Now lets go back to your first always block and make a slight modification

always @ ( * ) begin
   x = a & b;
   y = c | d & x;
end

Now the order matters because you must write to a variable before reading it in the same combinatorial block. If you change the assignments to nonblocking, the order no longer matters, but then the code block has to execute twice to let the values settle. Given a much larger piece of code, this will introduce a bigger rippling effect, plus introduce the possible de-synchronization mentioned above.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.