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

 

module more_conditional(x,a,b,adjust_a,adjust_b);

   output [15:0] x;

   input [15:0]  a, b;

   input         adjust_b, adjust_a;

 

   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_add = 0;

   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_add = 0;

   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