`define xSIX_MUX `define xMUX2 `define xMUX3 `define xRANGE `define xRANGEIF `define xSIX_MUX_IF_ELSE `define xSIX_MUX_IF `ifdef SIX_MUX module six_mux(x,sel,a,b,c,d,e,f); input sel, a, b, c, d, e, f; output x; wire [2:0] sel; // Values limited to 0-5. reg x; wire a, b, c, d, e, f; // Because the case items are constants and the case expression is // an integer, Leonardo can automatically detect the parallel case. // Leonardo has no way of knowing that sel cannot take on values of // 6 or 7, so it cannot detect the full_case and therefore that is // specified explicitly. If full_case were not present Leonardo // would insert latches to hold the value of x (updated the last // time sel was less than 6). always @( sel or a or b or c or d or e or f ) // exemplar full_case case( sel ) 0: x = a; 1: x = b; 2: x = c; 3: x = d; 4: x = e; 5: x = f; endcase endmodule // six_mux `endif `ifdef MUX2 module mux2(x,sel,a,b,c,d); input sel, a, b, c, d; output x; wire [2:0] sel; reg x; wire a, b, c, d; // A complete analysis of the cases below would show that the cases // are full and, if the case items are appropriately modified (see // mux3), parallel. Leonardo 1999.1f, however, cannot detect this // and so synthesizes logic that sequentially checks the case items // and uses latches in case none are true. // With a parallel_case directive incorrect hardware will be synthesized // since Leonardo will check the case items as given here, not as // specified in mux3, which would be correct. always @( sel or a or b or c or d ) casez( sel ) 3'b??1: x = a; // Odd case 3'b000: x = b; // Zero 3'b1??: x = c; // Even, nonzero, >= 4 3'b0??: x = d; // Even, nonzero, < 4; endcase // casez( sel ) endmodule // mux2 `endif // ifdef mux2 `ifdef MUX3 module mux3(x,sel,a,b,c,d); input sel, a, b, c, d; output x; wire [2:0] sel; reg x; wire a, b, c, d; // Here Leonardo can detect that the case items are parallel and // full and so will automatically detect the parallel and full // cases. always @( sel or a or b or c or d ) casez( sel ) 3'b??1: x = a; // Odd case 3'b000: x = b; // Zero 3'b1?0: x = c; // Even, nonzero, >= 4 3'b010: x = d; // Even, nonzero, < 4; endcase endmodule `endif `ifdef RANGE module range(x,v1,v2,v3,a1,a2,a3); input v1, v2, v3, a1, a2, a3; output x; reg x; wire [3:0] v1, v2, v3; wire a1, a2, a3; // One of v1, v2, v3 will be twelve. // At least one will be twelve and at most one will be twelve. // This module will be connected such that exactly one of the // inputs (v1,v2,v3) will be equal to 12 and therefore exactly one // of the case items below will be true. Leonardo has no way of // knowing this and so parallel and full case directives must be // used. always @( v1 or v2 or v3 ) // exemplar parallel_case // exemplar full_case case( 12 ) v1 : x = a1; v2 : x = a2; v3 : x = a3; endcase endmodule // range `endif // ifdef RANGE `define RANGEIF `ifdef RANGEIF module rangeif(x,v1,v2,v3,a1,a2,a3); input v1, v2, v3, a1, a2, a3; output x; reg x; wire [3:0] v1, v2, v3; wire a1, a2, a3; // Assumption: Exactly one v will be equal to twelve. // The code below is functionally equivalent to the code above, but // it uses if .. else if.. instead of a case statement. There is // no way to tell Leonardo that if/then/else chains are full or parallel // using a directive. // Synthesis directives full_case and parallel_case are ignored for if's. `ifdef RI1 always @( v1 or v2 or v3 ) if( v1 == 12 ) x = a1; else if( v2 == 12 ) x = a2; else if( v3 == 12 ) x = a3; else begin $display("Unexpected case."); $stop; end `endif `define RI2 `ifdef RI2 always @( v1 or v2 or v3 or a1 or a2 or a3 ) if( v1 == 12 ) x = a1; else if( v2 == 12 ) x = a2; else begin x = a3; // exemplar translate_off if( v3 != 12 ) begin $display("Ahhhh!!!!"); $stop; end // exemplar translate_on end `endif `ifdef RI3 always @( v1 or v2 or v3 ) begin if( v1 == 12 ) x = a1; if( v2 == 12 ) x = a2; if( v3 == 12 ) x = a3; end `endif endmodule `endif `ifdef SIX_MUX_IF_ELSE module six_mux_if_else(x,sel,a,b,c,d,e,f); input sel, a, b, c, d, e, f; output x; wire [2:0] sel; // Values limited to 0-5. reg x; wire a, b, c, d, e, f; // The code above is equivalent to six_mux above. Leonardo is able to // detect that the if conditions are parallel and so it does not, // for example, check that sel != 0 when assigning x = b for sel == // 1. // // Leonardo cannot detect that the cases are full and so it will // synthesize a latch. (That could avoided by adding a last else // condition and assigning some dummy value to x.) // // Leonardo cannot infer that a multiplexor with a binary input // would be appropriate. (It is able to do this for the case // statement.) This is not a problem because the optimization // steps, performed "between" the RTL and technology schematics, // replace the explicit comparators with much simpler logic. always @( sel or a or b or c or d or e or f ) begin if( sel === 0 ) x = a; else if( sel === 1 ) x = b; else if( sel === 2 ) x = c; else if( sel === 3 ) x = d; else if( sel === 4 ) x = e; else if( sel === 5 ) x = f; end endmodule // six_mux_if_else `endif `ifdef SIX_MUX_IF module six_mux_if(x,sel,a,b,c,d,e,f); input sel, a, b, c, d, e, f; output x; wire [2:0] sel; // Values limited to 0-5. reg x; wire a, b, c, d, e, f; // The code above is functionally equivalent to the code above. By // removing the else's we are making explicit that the conditions // are parallel, but Leonardo already knew that. (Simulation is // slightly less efficient here since every condition must always // be tested.) As with the code above, a latch will be synthesized, // which is a problem. always @( sel or a or b or c or d or e or f ) begin if( sel === 0 ) x = a; if( sel === 1 ) x = b; if( sel === 2 ) x = c; if( sel === 3 ) x = d; if( sel === 4 ) x = e; if( sel === 5 ) x = f; end endmodule // six_mux_if `endif `ifdef SIX_MUX_IF_ELSE_FULL module six_mux_if_else_full(x,sel,a,b,c,d,e,f); input sel, a, b, c, d, e, f; output x; wire [2:0] sel; // Values limited to 0-5. reg x; wire a, b, c, d, e, f; // In the code below a dummy assignment is added after the // last else. With this dummy assignment the synthesis program // will not synthesize a latch and so the synthesize module // will be correct, although with extra logic. always @( sel or a or b or c or d or e or f ) begin if( sel === 0 ) x = a; else if( sel === 1 ) x = b; else if( sel === 2 ) x = c; else if( sel === 3 ) x = d; else if( sel === 4 ) x = e; else if( sel === 5 ) x = f; else x = a; // Dummy case, added to synthesis program omits latch. end endmodule // six_mux_if_else_full `endif `ifdef FOUR_MUX_IF_ELSE module four_mux_if_else(x,sel,a,b,c,d); input sel, a, b, c, d; output x; wire [1:0] sel; reg x; wire a, b, c, d; // Though the synthesis program is documented as doing "full // coverage analysis" for if-then-else statements (synthesis // manual, page 6-28) it cannot detect that x will always be // assigned (full case) in the code below and so it will synthesize // a latch. The workaround is to add a dummy assignment. always @( sel or a or b or c or d ) if( sel === 0 ) x = a; else if( sel === 1 ) x = b; else if( sel === 2 ) x = c; else if( sel === 3 ) x = d; endmodule `endif