`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