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



//  Sources: Ci:  Ciletti, Modeling, synthesis, and rapid prototyping
//                         with the Verilog HDL
//           LRM: IEEE,    Verilog Language Reference Manual

/// Contents

// Conditional Statement (if) 
// Looping Statements (for,while,repeat,forever)
// disable. Used for exiting loops, etc.
// Case Statements 

/// Conditional Statement (if) 

//  Ci 7.12.3,  LRM 9.4

//  if( CONDITION ) IF_TRUE_STATEMENT
//  if( CONDITION ) IF_TRUE_STATEMENT else IF_FALSE_STATEMENT

//  If CONDITION is a non-zero number, execute IF_TRUE_STATEMENT;
//  If CONDITION is zero               execute IF_FALSE_STATEMENT;
//  If CONDITION contains an x or z,   execute IF_FALSE_STATEMENT;

module if_example();

   integer a, b, x, y, the_answer, the_right_answer;

   initial begin

      if( 123 ) $display("This should print.");

      if( 123 ) 
        $display("This should print."); 
      else
        $display("This should NOT print."); 

      if( 0 ) 
        $display("This should NOT print."); 
      else
        $display("This should print.");


      /// if/else/if Chains
      // A common way of using if. 

      if( a < 10 ) b = 1;
      else if( a < 20 ) b = 2;
      else if( a < 30 ) b = 3;
      else b = 4;

      /// Multiple Statements in if
      
      // The if only affects the statement immediately following,
      // so y is always assigned.
      if( a < 10 ) x = 1; y = 2;  // Looks like a bug.
      // If it is a bug, here is the correct way:
      if( a < 10 ) begin x = 1; y = 2; end
      // If the intent was to always assign y, then don't be misleading:
      if( a < 10 ) x = 1; 
      y = 2;

      // Note: begin foo; bar; foobar;... end is a single statement,
      // consisting of a sequential (begin/end) block.


      /// If and x's and z's.
      
      if( 1'bx ) 
        $display("This should NOT print."); 
      else
        $display("This should.");

      if( 1'bx === 1'bx ) 
        $display("This should print."); 
      else
        $display("But not this.");

      if( 1'bx == 1'bx ) 
        $display("This won't print."); 
      else
        $display("This will.");


   end

endmodule 


/// Looping Statements

//  Ci 7.12.4,  LRM 9.6

//  for( INIT_ASSIGN; CONDITION; STEP_ASSIGN ) STATEMENT
//  while( CONDITION ) STATEMENT
//  repeat( COUNT ) STATEMENT
//  forever STATEMENT

//  for C programmers might find the for loop disappointing:
//    INIT_ASSIGN must be an assignment, not an arbitrary statement.
//    STEP_ASSIGN must be an assignment, not an arbitrary statement.
//    CONDITION is an expression that evaluates to an integer.
//
//    1. Execute INIT_ASSIGN.
//    2. Evaluate CONDITION, if true go to next step, else done.
//    3. Execute STATEMENT
//    4. Execute STEP_ASSIGN;
//    5. Go to step 2.

//  while
//
//    1. Evaluate CONDITION, if false done, else go to next step.
//    2. Execute STATEMENT.
//    3. Go to step 1.

//  repeat
//    COUNT is an expression that evaluates to an integer.
//
//    1. Evaluate COUNT, call result the_count.
//    2. Execute STATEMENT the_count times.

//  forever
//
//    1. Execute STATEMENT.
//    2. Go to step 1.

//  There is a mechanism for breaking out of these loops, but
//  it's not as convenient as C's break.

module looping_examples();

   integer a, b, c;
   integer i, pop, x;
   reg     clock, clock2;

   initial begin

      /// for
      
      // Basic for loop.
      for(i=0; i<3; i=i+1) $display("yada");

      // There is no postincrement operator. :-(
      // for(i=0; i<3; i++) $display("yada");  // Syntax error.

      // Can only have a single initialization assignment. :-(
      // for(i=0, j=0; i<3; i=i+1) $display("yada");  // Syntax error.

      /// while

      // Basic while loop.
      while( x < 10 ) x = x + 1;

      // Sorry, assignment (=) is not an operator as in C.
      // while( i = i - 1 ) x = x + 1;   // Syntax error.


      /// Three Ways to Iterate Ten Times:
      
      //  This simplest way is the best. (repeat).
      for(i=0; i<10; i=i+1) x = x + 1;
      repeat( 10 ) x = x + 1;
      i = 10; while( i ) begin i = i - 1; x = x + 1; end

      // while example, count the 1's in b.
      pop = 0;
      while( b )
        begin
           pop = pop + b[0];
           b = b >> 1;
        end
      
   end

   /// forever,  The Right Way
   initial begin
      //  forever is normally used with a delay control.
      //  Example below implements a clock with a period of 2 cycles.
      clock = 0;
      forever begin #1 clock = ~clock; end
      // If there was a statement here it would never be executed.
      // This doesn't affect code in other initials.
   end
   
   /// forever, The Wrong Way.
   initial begin
      clock2 = 0;
      // Example below implements a clock with a period of 1 / infinity.
      // Because there is no delay the simulator will never advance
      //  time.
      // As a result the simulation will be frozen at t=0.
      // (Assuming the line below were uncommented.)
       forever begin clock2 = ~clock2; end  // Freezes simulator.
   end
        
endmodule


/// Named Blocks and the Disable Statement

//  LRM 11

 ///  Naming Blocks
 ///
 ///  begin:NAME ... end
//
//  Block named NAME.  NAME can be any valid identifier, by convention
//  block names are all upper case.
//
//  Variables can be declared within a named block. (See examples.)
//  Execution can be "thrown" out of block. (See example.)
//

 /// Disabling Blocks (Throwing Execution)
 ///
 /// disable BLOCKNAME
//
//  Force activity (execution of code) within BLOCKNAME to continue
//  at the first statement outside of BLOCKNAME.

 /// Uses for Disable

//  Can be used to exit from loops, to jump to the beginning of an
//  iteration, etc.

module disable_example(a,b);
   input a, b;

   integer i;

   initial begin:INITIAL_BLOCK
     // Declarations allowed here because this is a named block.
     integer x; 

      /// Disable used to exit from a for loop. (Like C's break.)

      begin:BLOCK1  // Note: BLOCK1 is outside of for loop.
         for(i=1; i<10; i=i+1) begin
            x = x * i;
            // Early exit if x > 100.
            if( x > 100 ) disable BLOCK1;
         end
      end

      /// Disable used to exit from a forever loop. (Like C's break.) 
      x = 1; i = 1;
      begin:BLOCK2
         forever begin
            x = x * i;  i = i + 1;
            // Exit exit if x > 100.
            if( x > 100 ) disable BLOCK2;
         end
      end
      
      /// Disable used to exit from or continue a for loop. (Like C's break and continue.)

      begin:BLOCK3_THE_OUTSIDE_BLOCK
        for(i=1; i<10; i=i+1)
          begin:BLOCK4_THE_INSIDE_BLOCK
            x = x * i;
             // Early exit if x > 100.
            if( x > 100 ) disable BLOCK3_THE_OUTSIDE_BLOCK;
            // Start next iteration if x > 50
            if( x > 50 ) disable BLOCK4_THE_INSIDE_BLOCK;
            x = x + 2; // Only executed if x <= 50.
        end
      end
   end

   /// Using disable on a non-enclosing block.

   // When a changes start printing a message every cycle.
   always @( a ) begin:BLOCK_X
      forever begin
         $display("Greetings from block x.");
         #1;
      end
   end

   // When b changes stop the messages from the code above.
   always @( b ) begin
      disable BLOCK_X;
   end
   
endmodule


/// Case Statement

//  LRM 9.5

//  Something like C's switch statement.
//  Three kinds: case, casex, casez.

//  case ( EXPR )
//    CASE_EXPR00, CASE_EXPR01, .. : STATEMENT0;
//    CASE_EXPR10, CASE_EXPR11, .. : STATEMENT1;
//    ...
//    [default: STATEMENTD;]
//  endcase
//

//  1. Evaluate EXPR, call result expr.
//  2. Compare expr to CASE_EXPR00, CASE_EXPR01, ..., CASE_EXPR10,
//     until a match is found. Comparison is the same as case equality.
//  3. If a match is found execute the corresponding STATEMENT.
//     If no match is found and default is present, execute STATEMENTD.

//  CASE_EXPR can be any expression, not just a constant.


//  casex ( EXPR )
//    CASE_EXPR00, CASE_EXPR01, .. : STATEMENT0;
//    CASE_EXPR10, CASE_EXPR11, .. : STATEMENT1;
//    ...
//    [default: STATEMENTD;]
//  endcase
//
//  Same as case except x acts as a wildcard (don't care).

//  casez ( EXPR )
//    CASE_EXPR00, CASE_EXPR01, .. : STATEMENT0;
//    CASE_EXPR10, CASE_EXPR11, .. : STATEMENT1;
//    ...
//    [default: STATEMENTD;]
//  endcase
//
//  Same as case except z acts as a wildcard (don't care).


module Case_examples();
   integer a, b, c, d;
   reg     cin, bita, bitb, cout, sum;
   integer the_answer, the_correct_answer;
   integer foo, bar, foobar;
   reg [7:0] input_1, input_2, input_3, key;
   reg       match;

   initial begin

      /// Case examples.
      //
      case( a )
        1       : $display("a is 1.");
        2,3     : $display("a is 2 or maybe 3.");
        b       : $display("a is equal to b.");
        b+c     : $display("a is equal to b+c");
        default : $display("a is something else.");
      endcase

      case( input_1 )
        8'bxxxxxxxx : $display("Input_1 is unknown.");
        8'bzzzzzzzz : $display("Input_1 is high impedance.");
        0           : $display("Input_1 is zero.");
        255         : $display("Input_1 is 255.");
      endcase
      

      case( key )
        input_1: match = 1;
        input_2: match = 2;
        input_3: match = 3;
        default: match = 0;
      endcase
      
      
      case( the_answer == the_correct_answer )
        1       : $display("Correct.");
        default : $display("Wrong.");
      endcase

      /// Binary Full Adder using Case
      //
      case( {cin, bita, bitb } )
        3'b000                 : begin cout = 0; sum = 0; end
        3'b001, 3'b010, 3'b100 : begin cout = 0; sum = 1; end
        3'b110, 3'b101, 3'b011 : begin cout = 1; sum = 0; end
        3'b111                 : begin cout = 1; sum = 1; end
      endcase

      /// Lots of Opportunity for Fun
      //
      case( { a > b + 1, 1'b1, c[2:0] } )
        {cin, cout, 3'b101 } : foo    = foo + 1;
        d[10:6]              : bar    = bar + 1;
        {1'b1,a[4:0]}        : foobar = foo + bar;
        default              : $display("None of the above.");
      endcase
      
   end
endmodule

module Casex_examples();

   reg [3:0] a, pri;

   initial begin

      casex( a )
        4'bxxx0: $display("a is even.");
        default: $display("a is odd.");
      endcase

      // 2001 Homework 1,2-style Priority Encoder

      casex( a )
        4'bxxx1: pri = 4'b0001;
        4'bxx11: $display("This can't happen.");
        4'bxx10: pri = 4'b0010;
        4'bx110: $display("This can't happen either.");
        4'bx100: pri = 4'b0100;
        4'b1000: pri = 4'b1000;
        default: pri = 4'b0000;
      endcase
      
   end
   
endmodule