/// 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