How we check whether all of the variables assigned to in an always block are, indeed, assigned to in all paths. In other words: how we know that we don't need to infer a latch.
This is a basic criteria for whether we can treat an always block as combinational. Some examples of what we want to accept and reject:
always @(*) <---- OK, combinational block because if (c1) lhs = rhs1; LHS is assigned in every branch. else lhs = rhs2; always @(*) <---- NOT OK, need to infer a latch if (c1) lhs = rhs; because LHS must hold its value when C1 is false. always @(*) <---- OK, combinational block because lhs = rhs1; LHS is assigned in every branch. if (c1) lhs = rhs2;
Our implementation is brain-dead simple: we write a function that checks whether a particular LHS is assigned in every branch. Then we'll apply that function to every LHS that is used anywhere in the block.
This approach fails to identify "arguably" combinational always blocks such as:
always @(*) if (c1) lhs = rhs1; if (!c1) lhs = rhs2;
because our path exploration function stupidly does not consider the possible relationships between the conditions.
Well, it's not clear that we should try to do anything smarter than this. After all, synthesis tools might not do hard work here, either.