`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