/// LSU EE 3755 -- -- Computer Organization

//

/// Verilog Notes 3 -- Fall 2009-- Expressions

/// Contents

// Operators: Equality, Comparison

// Operator:  Conditional

// Operators: Shift, Cat

// Operator Precedence and Association

// ALU Example

/// References

// :P:   Palnitkar, "Verilog HDL"

// :Q:   Qualis, "Verilog HDL Quick Reference Card Revision 1.0"

// :PH:  Patterson & Hennessy, "Computer Organization & Design"

////////////////////////////////////////////////////////////////////////////////

/// Operators:   Equality, Comparison

// :P: 6.4.3, 6.4.4

// There are two equality operators, == and ===, and two inequality

// operators, != and !==.

//

// There are also comparison operators.

//

// See the example.

// :Example:

//

// Examples and description of the equality operators.

module equality(x1,x2,x3,x4,a,b);

input [2:0] a, b;   // Both a and b are 3 bits.

output x1, x2, x3, x4;

// Logical Equality

//

assign       x1 = a == b;

//

// If a and b consist only of 0's and 1's:

//   If a and b are identical, x1 is set to 1,

//   if a and b differ, x1 is set to 0.

// If a or b has an x or z, x1 is set to x.

//

// Examples:

//

// a    b    |  a == b

// """"""""""""""""""

// 000  000  |  1

// 000  001  |  0

// 001  001  |  1

// x01  001  |  x

// x01  x01  |  x       // Note: x is not a don't care.

// Logical Inequality

//

assign       x2 = a != b;

//

// Analogous to logical equality.

//

// Examples:

//

// a    b    |  a != b

// """"""""""""""""""

// 000  000  |  0

// 000  001  |  1

// 001  001  |  0

// x01  001  |  x

// x01  x01  |  x

// Case Equality

//

assign       x3 = a === b;

//

// If a and b are identical (including x's and z's) x3 is 1 otherwise

// x3 is set to zero.

//

// Examples:

//

// a    b    |  a === b

// """"""""""""""""""""

// 000  000  |  1

// 000  001  |  0

// 001  001  |  1

// x01  001  |  0

// x01  x01  |  1

// Case Inequality

//

assign       x4 = a !== b;

//

// If a and b are identical (including x's and z's) x4 is set to 0 otherwise

// x4 is set to one.

//

// Examples:

//

// a    b    |  a !== b

// """"""""""""""""""""

// 000  000  |  0

// 000  001  |  1

// 001  001  |  0

// x01  001  |  1

// x01  x01  |  0

endmodule

// :Example:

//

// Illustration and explanation of the comparison operators.

module compare(x1,x2,x3,x4,a,b);

input [7:0] a, b;   // Both a and b are 8 bits.

output x1, x2, x3, x4;

// Take note: Comparison (and other) operators interpret contents of a

// vector (e.g., a and b) as unsigned.

// Greater Than

//

assign       x1 = a > b;

//

//

// Examples:

//

// a    b    |  a > b

// """"""""""""""""""

// 3    1    |  1

// 1    3    |  0

// 4    4    |  0

// x    4    |  x

// -1   3    |  1   See note below.

//

// The 8-bit 2's complement representation of -1 is 8'b11111111

// which is identical to the 8-bit representation of 255, 8'b11111111.

// The comparison operand will always interpret contents of a vector

// as an unsigned integer.

// Greater Than or Equal To

//

assign       x2 = a >= b;

//

//

// Examples:

//

// a    b    |  a >= b

// """"""""""""""""""

// 3    1    |  1

// 1    3    |  0

// 4    4    |  1

// x    4    |  x

// -1   3    |  1   See note above.

// Less Than

//

assign       x3 = a < b;

//

//

// Examples:

//

// a    b    |  a < b

// """"""""""""""""""

// 3    1    |  0

// 1    3    |  1

// 4    4    |  0

// x    4    |  x

// -1   3    |  0   See note above

// Less Than or Equal To

//

assign       x4 = a <= b;

//

//

// Examples:

//

// a    b    |  a <= b

// """"""""""""""""""

// 3    1    |  0

// 1    3    |  1

// 4    4    |  1

// x    4    |  x

// -1   3    |  0   See note above.

endmodule

////////////////////////////////////////////////////////////////////////////////

/// Operator: Conditional

// :P: 6.4.10

//

// :Sample: assign v =  x ? y : z

//

//   If x is 1 assign y to v, if x is 0 assign z to v.

//

// :Sample: assign v =  x < 3 ? y + 1 : z - x;

//

//   If x < 3 assign y+1 to v; if x >= 3 assign z-x to v.

// :Example:

//

// A simple illustration of the conditional operator.

module conditional(x,a,b,s);

input [31:0] a, b;

input        s;

output [31:0] x;

// The Conditional Operator

//

//

assign        x = s ? a : b;

//

// Examples:

//

// a  b  s  | s ? a : b

// """"""""""""""""""""

// 11 22 0  | 22   (b selected if s == 0)

// 11 22 1  | 11   (b selected if s != 0 and not unknown)

// 11 22 x  | x

endmodule

// :Example:

//

// Use of the conditional operator to implement a four-input

// multiplexor.

//

// With procedural code, to be covered later, there are many

// ways to code multiplexors.

module mux4(x,a,b,c,d,select);

input [31:0] a, b, c, d;

input [1:0]  select;

output [31:0] x;

assign        x =

select == 0 ? a :

select == 1 ? b :

select == 2 ? c : d;

// Notes on example above:

//

// "select == 0" evaluates to Logic 0 (if select isn't value 0)

//  or to Logic 1 (if select is value 0).

//

//

endmodule

// :Example:

//

// Another use of the conditional operator.  In this one parenthesis

// are necessary.

output [15:0] x;

input [15:0]  a, b;

assign        x = ( adjust_a ? a + 5 : a ) + ( adjust_b ? b + 5 : b );

// In example above parentheses are needed, otherwise the middle "+"

// would grab the "a" away from the first conditional.

//   x =  adjust_a      ? a + 5 :

//        a + adjust_b ? b + 5 : b ;

endmodule

////////////////////////////////////////////////////////////////////////////////

/// Operators: Shift, Concatenate

// :P: 6.4.7, 6.4.8

// The shift operators, << and >>, perform left and right shifts.

//

//   Zeros are shifted in to the vacated positions.

//

// The concatenation operator, {}, makes a large vector out of

// its arguments.

//

// See examples for further description.

// :Example:

//

// Illustration and description of shift operators.

module shifts(x1,x2,a,s);

input [15:0] a;

input [2:0]  s;

output [15:0] x1, x2;

// The Left Shift Operator

//

assign        x1 = a << s;

//

// Examples:

//

// a    s    |  a << s

// """""""""""""""""""

// 01011 0   | 01011    // Note: shown in binary

// 01011 1   | 10110

// 01011 2   | 01100

// 01011 7   | 00000

// The Right Shift Operator

//

assign        x2 = a >> s;

//

// Examples:

//

// a    s    |  a >> s

// """""""""""""""""""

// 11011 0   | 11011    // Note: shown in binary

// 11011 1   | 01101

// 01011 2   | 00010

// 01011 7   | 00000

endmodule

// :Example:

//

// Use of the shift operator to multiply by four.

module a_times_4_plus_b(x,a,b);

input [7:0] a, b;

output [10:0] x;

assign        x = ( a << 2 ) + b;

endmodule

// :Example:

//

// Illustration and description of the concatenate operator.

module cat(x,y,a,b);

input [3:0] a, b;

output [7:0] x;

output [7:0] y;

// The Concatenation Operator

//

assign      x = { a, b };

//

// Examples:

//

// a    b    |  { a, b }

// """""""""""""""""""

// 0000 1111 | 00001111

// 1010 1111 | 10101111

// Note: Constants within the concatenation operator must be sized,

// for example, 3'd5 is okay but 5 is not.

assign      y = { a, 3'd5, b };

endmodule

////////////////////////////////////////////////////////////////////////////////

/// Operator Precedence and Association

// :P: 6.4.11

// Precedence and association specify for which operator an operand is used.

// See Examples.

///  Operator Precedence

//  + - ! ~ (unary)            highest precedence

//  *  /  %

//  +  - (binary)

//  <<  >>

//  <  <=  >  >=

//  ==  !=  ===  !==

//  &  ~&

//  ^  ^~

//  |  ~|

//  &&

//  ||

//  ?: (conditional operator)  lowest precedence

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

// :Example:

//

// Examples illustrating precedence and association.  This example

// uses behavioral code which has not been covered yet but should

// be easy enough to figure out.

module precedence_and_association_examples();

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

integer i_am_a_condition_for_operator_to_the_right;

integer i_am_the_else_part_of_the_operator_to_the_left;

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

// All operators associate left-to-right except ?:.

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

x =   a ? b : i_am_a_condition_for_operator_to_the_right       ? d : e;

//    x=    a                                              ? b :

//          i_am_a_condition_for_operator_to_the_right       ? d : e;

x = ( a ? b : i_am_the_else_part_of_the_operator_to_the_left ) ? d : e;

//    x will be  assigned with d or e.

// if a is true, the  condition for next statement will be “b”.

// which looks like x= b ? d : e;

//

// if a is false, the  condition for next statement will be

//” i_am_the_else_part_of_the_operator_to_the_left “

// which looks like x= i_am_the_else_part_of_the_operator_to_the_left ? d :e ;

// The three lines below do the same things.

x = a < 10 ? 10 : a < 20 ? 20 : 30;

// When a = 9, 19, 29:

//  a  =9:

//  x = 9 < 10 ? 10 : 9 < 20 ? 20 : 30;

//  x = 10;

//  a  = 19:

//  x = 19 < 10 ? 10 : 19 < 20 ? 20 : 30;

//  x = 19 < 20 ? 20 : 30;

//  x = 20;

//  a  = 29:

//  x =  29 < 10 ? 10 : 29 < 20 ? 20 : 30;

//  x =  29 < 20 ? 20 : 30;

//  x =  30;

//With parentheses

x = a < 10 ? 10 : ( a < 20 ? 20 : 30 );

// When a = 9, 19, 29:

//  a =9 .

//  x = a < 10 ? 10 : ( 9 < 20 ? 20 : 30 );

//  x = 9 < 10 ? 10 : 20;

//  x = 10;

//

//  a = 19 .

//  x = a < 10 ? 10 : ( 19 < 20 ? 20 : 30 );

//  x = 19 < 10 ? 10 : 20;

//  x = 20;

//

//  a = 29 .

//  x = a < 10 ? 10 : ( 29 < 20 ? 20 : 30 );

//  x = 29 < 10 ? 10 : 30;

//  x = 30;

if( a < 10 ) x = 10; else begin if ( a < 20 ) x = 20; else x = 30; end

x = ( a < 10 ? 10 : a < 20 ) ? 20 : 30;

//   When a = 9 , 19,  29..

// a = 9.

//   x = ( 9 < 10 ? 10 : 9 < 20 ) ? 20 : 30 ;

//   x =  10 ? 20 : 30 ;

//   Since 10 means true,

//   x =  10 ? 20 : 30 ;

//   x =  20;

// a = 19.

//   x = ( 19 < 10 ? 10 : 19 < 20 ) ? 20 : 30 ;

//   x = 19 < 20 ? 20 : 30 ;

//   x = 20;

// a = 29.

//   x = ( 29 < 10 ? 10 : 29 < 20 ) ? 20 : 30 ;

//   x = 29 < 20 ? 20 : 30 ;

//   x = 30;

end

endmodule // precedence_examples

/// Note on Style

//

// Avoid unnecessary parenthesis for common operators.

// For example use:

//   x = a + b * c;

// Do not use:

//   x = a + ( b * c );

// The second assignment does exactly the same thing as the first but

// the parenthesis add clutter which can become cumbersome in complex

// expressions.

//

// Note that the Palnitkar text specifies the opposite style,

// and so would prefer the second assignment.

////////////////////////////////////////////////////////////////////////////////

/// ALU Example

// :PH: An example of a different ALU.

// An example of a CPU arithmetic and logical unit (ALU).

// An ALU typically has two operand inputs (a and b below),

// a control input (op below), and a result output.  It

// can perform several arithmetic and logical operations,

// the operation to perform is specified by the op input.

// There are two ALU modules below, one uses the conditional

// operator, the other uses a multiplexor module, which

// is also defined.

// :Example:

//

// ALU using the conditional operator.

module alu(result,a,b,op);

input [31:0] a, b;

input [3:0]  op;

output [31:0] result;

parameter     op_sub = 1;

parameter     op_or  = 2;

parameter     op_a   = 3;  // Result is a (unmodified).

parameter     op_b   = 4;  // Result is b (unmodified).

parameter     op_srl = 5;  // Shift a right logical (no sign extension).

parameter     op_sra = 6;  // Shift a right arithmetic (sign extension).

parameter     op_rr  = 7;  // Rotate a right.

assign result =

op == op_add ? a + b            :

op == op_sub ? a - b            :

op == op_or  ? a | b            :

op == op_a   ? a                :

op == op_b   ? b                :

op == op_srl ? a >> 1           :

op == op_sra ? {a[31], a[31:1] }:

op == op_rr  ? {a[0],  a[31:1] } : 0;

endmodule

// :Example:

//

// A multiplexor with eight 32-bit inputs.  To be used in the

// ALU below.

module mux8x32(o,s,i0,i1,i2,i3,i4,i5,i6,i7);

input [31:0] i0,i1,i2,i3,i4,i5,i6,i7;

input [2:0]  s;

output [31:0] o;

assign o =

s == 0 ? i0 :

s == 1 ? i1 :

s == 2 ? i2 :

s == 3 ? i3 :

s == 4 ? i4 :

s == 5 ? i5 :

s == 6 ? i6 : i7;

endmodule

// :Example:

//

// An ALU using the multiplexor.  Note that the constants are not used

// and that it is much harder to tell if a particular operation is in

// the correct multiplexor input.

module alu2(result,a,b,op);

input [31:0] a, b;

input [2:0]  op;

output [31:0] result;

// Parameters not used here.

parameter     op_sub = 1;

parameter     op_or  = 2;

parameter     op_a   = 3;  // Result is a (unmodified).

parameter     op_b   = 4;  // Result is b (unmodified).

parameter     op_srl = 5;  // Shift a right logical (no sign extension).

parameter     op_sra = 6;  // Shift a right arithmetic (sign extension).

parameter     op_rr  = 7;  // Rotate a right.

mux8x32 m1(result, op,

a + b,

a - b,

a | b,

a,

b,

a >> 1,

{a[31], a[31:1] },

{a[0], a[31:1] }

);

endmodule