/// Notes  and Demos for LSU EE 4702-1 Spring 2001

//  Material from LRM 4.1

/// Contents

//  Operator Overview
//  Handling of x and z by Logic Operators (Missing but should be here.)
//  Reduction Operators
//  Equality Operators
//  Concatenation (Not started.)
//  Conditional Operator
//  Operator Precedence and Association

/// Operator Overview

//  LRM 4.1

//  Many are identical to C counterparts.
//  Some C operators not present.
//  Some new ones specific to Verilog.
//  Precedence similar to C.

/// Reduction Operators

//  A Reduction Operation is one that converts many operands to one.
//  In Verilog, the operands are the bits of a vector, the result
//   is a single bit.

//  Verilog Reduction Operators
//   &   and
//   |   or
//   ^   exclusive or
//   ~&  not and
//   ~|   not or
//   ~^   xnor (not exclusive or)

/// WARNING: Table 4-19 in the "Experimental" LRM 4.1 is wrong (or mislabeled).
/// Correct Tables:   (Generated by test_reduction_xnor module, below.)

//    Reduction Exclusive Or
//    ^zz = x    ^zx = x    ^z1 = x    ^z0 = x
//    ^xz = x    ^xx = x    ^x1 = x    ^x0 = x
//    ^1z = x    ^1x = x    ^11 = 0    ^10 = 1
//    ^0z = x    ^0x = x    ^01 = 1    ^00 = 0

//    Reduction Exclusive Nor
//    ~^zz = x    ~^zx = x    ~^z1 = x    ~^z0 = x
//    ~^xz = x    ~^xx = x    ~^x1 = x    ~^x0 = x
//    ~^1z = x    ~^1x = x    ~^11 = 1    ~^10 = 0
//    ~^0z = x    ~^0x = x    ~^01 = 0    ~^00 = 1

module reduction_examples();

reg [3:0] a, b, a_xor_b;
integer   rand1, rand2, rnand1, rnand2, ror1, ror2, rxor1, rxor2;

initial begin

a = 8'b0110;

/// Reduction And
//  The two lines below do the same thing.
rand1 = & a;
rand2 = a[0] & a[1] & a[2] & a[3];
if( rand1 ) \$display("Reg a is 15.");

/// Reduction Nand
//  The two lines below do the same thing.
rnand1 = ~& a;
rnand2 = ! ( a[0] & a[1] & a[2] & a[3] );
if( rnand1 ) \$display("Reg a is not 15.");

/// Reduction Or
//  The two lines below do the same thing.
ror1 = | a;
ror2 = a[0] | a[1] | a[2] | a[3];
if( ror1 ) \$display("Reg a is not zero.");

/// Reduction Xor
//  The two lines below do the same thing.
rxor1 = ^ a;
rxor2 = a[0] ^ a[1] ^ a[2] ^ a[3];
if( rxor1 )
\$display("Reg a's binary representation has an odd number of 1s.");

/// Testing for Equality Using Reduction Xor
b = 8'b0111;
a_xor_b = a ^ b;  // Bitwise xor.
if( & a_xor_b ) \$display("The contents of a and b are the same.");
// The same thing without the temporary variable, a_xor_b.
if( & ( a ^ b ) ) \$display("The contents of a and b are the same.");

end
endmodule // reduction_examples

module text_reduction_xnor();
// Print the result of the reduction xnor (~^) on all possible
// two-bit values.

reg [3:0] vals;   // Used as a constant, holds the four logic values.
integer   a, b;
reg [1:0] ab;

initial begin

vals = 4'b01xz;

for(a=0; a<4; a=a+1)
for(b=0; b<4; b=b+1)
begin
ab = { vals[a], vals[b] };
\$display("~^%b = %b", ab, ~^ab);
end
end

endmodule

/// Equality Operators

//  Special handling needed for x's and z's.

//  ==  Logical equality.   Result unknown if operand has x or z.
//  !=  Logical inequality. Result unknown if operand has x or z.
//  === Case equality.      Compares x's and z's.
//  !== Case inequality.    Compares x's and z's.

//  LHS == RHS
//  Evaluates to x if there is an x or z in LHS or RHS
//  Evaluates to 1 if LHS and RHS are the same numbers.
//  Evaluates to 0 if LHS and RHS are different numbers.

//  LHS === RHS
//  Evaluates to 1 if LHS and RHS are bitwise identical (0's, 1's, x's, and z's).
//  Otherwise evaluates to 0.

//  Operands are made the same size by padding the left-hand side
//  of the smaller operand with zeros.  (Signs are NOT extended.)

//  N.B. neither x nor z act as a wildcard (don't care).

module equality_examples();

reg [3:0] four_bit_register;
reg [7:0] eight_bit_register;
integer   an_integer;

initial begin

/// Some obvious examples.
// Since numbers below do not contain x's or z's logical and
// case equivalence do the same thing.
if( 3 == 4 ) \$display("Something is VERY wrong.");
if( 3 === 4 ) \$display("Something is VERY wrong.");
if( 3 != 4 ) \$display("For this I need Verilog?");
if( 3 !== 4 ) \$display("For this I need Verilog?");

// Four-bit number is extended to 8 bits.
if( 8'd3 == 4'd3 ) \$display("They're equal.");
if( 8'd3 === 4'd3 ) \$display("They're equal.");

four_bit_register = 3;
eight_bit_register = 3;
if( four_bit_register == eight_bit_register ) \$display("Still equal.");
if( four_bit_register === eight_bit_register ) \$display("Still equal.");

/// Example of Zero Padding and Negative Number Handling
// Regs and wires are treated as unsigned values.  The assignment
// of a negative value works correctly.  However if it's converted
// to a longer form (as with the equality operators) the lhs will
// be padded with zeros, rather than sign extended and so the
// result will no longer be a negative integer.

four_bit_register  = -3;  // Value in register: 4'b1101
eight_bit_register = -3;  // Value in register: 8'b11111101
\$display("Four-bit reg: %d", four_bit_register);
if( four_bit_register != eight_bit_register )
\$display("They are not equal because the sign was not extended.");
if( four_bit_register == eight_bit_register[3:0] )
\$display("The low four bits are equal.");

/// Examples Using x and z
if( 4'b100x == 4'b100x )
\$display("This won't print because of x's, they may not be equal.");
if( 4'b100x != 4'b100x )
\$display("This won't print because of x's, they may be equal.");
if( 4'b10zx === 4'b10zx )
\$display("The two constants are bitwise identical.");
if( 4'b10zx !== 4'b10zx )
\$display("This won't print because they are bitwise identical.");
if( 4'b100x === 4'b1000 )
\$display("This won't print, x is not the same as 0.");

end

endmodule

/// Concatenation

//  {foo,bar,foobar}

/// Conditional

//  CONDITION ? IFTRUE : IFFALSE

//  The conditional operator (?:) takes three (yes, three) operands.
//  If CONDITION is zero evaluates to IFFALSE.
//  If CONDITION is non-zero and does not contain x or z bits, evaluates
//    to IFTRUE.
//  If CONDITION contains an x or z evaluates to a bitwise combination of
//    IFTRUE and IFFALSE:
//    Combined bit is 0 iff corresponding bits are 0 in IFTRUE and IFFALSE.
//    Combined bit is 1 iff corresponding bits are 1 in IFTRUE and IFFALSE.
//    Otherwise combined bit is x.

module conditional_example(x,y,a,b);
input a,b;
output x,y;
wire [3:0] a,b;

// Suppose b = 4'b1100;
// If a = 4'd5    then x = 4'b1100;
// If a = 4'd10   then x = 4'b1010;
// If a = 4'b01xz then x = 4'b1xx0;
wire [15:0] x = a < 10 ? b : 4'b1010;

// If a < 10 then y = 10
// else if a < 20 then y = 20
// else if a < 30 then y = 30
// else y = 40;
wire [15:0] y =
a < 10 ? 10 :
a < 20 ? 20 :
a < 30 ? 30 : 40;

endmodule // conditional_example

/// Operator Precedence and Association

//  LRM 4.1 Table 4-4.

//  Operator Precedence
//  + - ! ~ (unary)            highest precedence (Strongest Binding)
//  *  /  %
//  +  - (binary)
//  <<  >>
//  <  <=  >  >=
//  ==  !=  ===  !==
//  &  ~&
//  ^  ^~
//  |  ~|
//  &&
//  ||
//  ?: (conditional operator)  lowest precedence  (Weakest Binding)

//  Association is from left to right except conditional (?:).

module precedence_and_association_examples();

integer x, a, b, c, d, temp;

initial begin

/// Precedence Examples

// Multiplication has higher precedence than addition so multiply first.
x = a + b * c;  // Multiply then add.
x = ( a + b ) * c;  // Add then multiply.

// Comparison (<,>) has higher precedence than logical or (||),
// so compare first, then or the results.
if( a < b || c > d ) \$display("Condition true.");

// Logical equality (==) has higher precedence than bitwise xor (^).
if( a ^ b == c ) \$display("This is probably an error.");
if( ( a ^ b ) == c ) \$display("This is probably okay.");

// Unary negation (!) has higher precedence than logical or (||).
if( !a || b ) \$display("(Not a) or b.");
if( !(a || b) ) \$display("Not (a or b)");

// The conditional operator has the lowest precedence, lower than addition.
// if ( a < 10 ) x = b; else x = c + 1;
x = a < 10 ? b : c + 1;
// if ( a < 10 ) x = b + 1; else x = c + 1;
x = ( a < 10 ? b : c ) + 1;

/// Association Examples

// Addition and subtraction have the same precedence, so the
// leftmost operation is performed first.
x = a + b - c; // Add then subtract.
x = a - b + c; // Subtract then add.

// The conditional operator has right-to-left association. (All
// other operators associate left to right.)
// The three lines below do the same things.
x = a < 10 ? 10 : a < 20 ? 20 : 30;
x = a < 10 ? 10 : ( a < 20 ? 20 : 30 );
if( a < 10 ) x = 10; else begin if ( a < 20 ) x = 20; else x = 30; end

// The first line below and the next two lines do the same
// probably-not-too-useful thing. (Which is why conditionals associate
// right to left.)
x = ( a < 10 ? 10 : a < 20 ) ? 20 : 30;
if( a < 10 ) temp = 10; else temp = a < 20;
if ( temp ) x = 20; else x = 30;

end

endmodule // precedence_examples