We assume that you understand case (casez, casex) statement as well as if-else statement. So, the focus is on full_case and parallel_case directives.
The synthesis directives are added as a comment immediately after the case expression and before any of the case items as shown below.
case (case_expression) // synopsys full_case parallel_case
case_item1 : statement1;
case_item2 : statement2;
default : statement3;
endcase
Full case statement
In a full case statement, all possible values of case_expression can be matched to a case_item or to a case default. If case_expression does not match any of the case_item and case statement does not include case default, it’s not full case statement.
Consider the following examples 1(a) & 1(b). Both examples do not tell what happens to “dout” when sel = 2’b11.
For both examples, when sel = 2’b11, simulation will hold the last assigned value to “dout” i.e. the simulation results will be same but synthesis will produce different results.
Explanation:
For simulation, “// synopsys …” directive is merely a verilog comment and will be ignored. So, simulation results will remain same i.e. last assigned “dout” value.
Since case statement in example 1(a) is not full, synthesis will infer a latch as shown below.
So, synthesis output will be last assigned “dout” value for sel = 2’b11 and hence there will be no simulation-synthesis mismatch.
In example 1(b), “synopsys …” directives are understood by synthesis tools. Tools like Synplicity and Precision interprets full_case directive to mean that if a case statement is not full, outputs are don’t cares for all unspecified case_items. So, dout = 1’bx for sel = 2’b11. This causes a functional mismatch between simulation and synthesis.
Parallel case
In a parallel case statement, case_expression matches to one and only one case_item. If the case_expression matches to more than one case_item, it’s not parallel case statement.
Consider the following examples 2(a) & 2(b). Here, multiple case_items match sel = 3’b011/3’b101/3’b110/3’b111.
Example 2(a) will simulate like a priority encoder where sel[2] has priority over sel[1] which has priority over sel[0]. Synthesis will also infer a priority encoder.
So, there will be no mismatch between simulation and synthesis.
Please note that sel[2] is MSB and sel[1] is LSB.
Example 2(b) will also simulate like a priority encoder because “// synopsys …” directive will be ignored. But synthesis tools recognize parallel_case directive and non-priority logic will be synthesized. This will cause functional mismatch between simulation and synthesis.
Please note that both full_case and parallel_case directives can also be used together.