/// LSU EE 3755 -- Fall 2013 -- Computer Organization
//
/// Verilog Notes 6 -- Procedural Code & Behavioral Modeling

/// Under Construction, Mostly Complete
//  Time-stamp: <20 September 2013, 15:12:47 CDT, koppel@sky.ece.lsu.edu>
//
// Possible Changes and Additions
//
//   Testbench for population count modules.


/// Contents
//
// Procedural Code Overview
// Procedural Code Basics (initial,always,begin,end,#,$display)
// More Procedural Code Basics  (always)

// Variables (reg, integer, etc)

// Conditional Statement (if)
// Looping Statements (for,while,repeat,forever)
// Case Statements

// Event Control (@)


/// References
//
// See http://www.ece.lsu.edu/ee3755/ref.html
//
// :BV3: Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed.
// :C:   Cadence Verilog-XL Reference V 10.2
// :Q:   Qualis, "Verilog HDL Quick Reference Card Revision 1.0"
// :H:   Hyde, "Handbook on Verilog HDL"


////////////////////////////////////////////////////////////////////////////////
/// Procedural Code Overview

// :C: Chapter 8 first page. Easy to follow.
// :BV3: A.11

 /// Structural Model
//
// A description of hardware in terms of an interconnection of simpler
// components.  The Verilog examples presented in class up to this
// point have been structural models.

 /// Behavioral Model
//
// A description of what hardware does.  That is, a description of
// what the outputs should be given some input.
//
// Written using procedural code.

 /// Procedural Verilog Code
//
// Used for writing behavioral models.
//
// Like a Simple C Program:
//   Statements executed in program order.
//
// Unlike a Simple C Program
//   Multiple pieces of code can run concurrently.
//   Need to think about how code starts and pauses.
//   Time (simulated) part of language.

 /// Activity Flow (within procedural code)
//
// The place execution has reached at a particular time.
//
// A Verilog description can have many activity flows.
//   Each "initial" and "always" (see below) block has
//   its own activity flow.

// How Code Starts in an ordinary C Program
//   Starts with call to "main."
//
// How Procedural Code Starts in Verilog
//   Code in all "initial" and "always" blocks (see below)
//   starts at t=0.

 /// Reminder
//
// Pay attention to how simulated time is handled.
//
// Remember that several pieces of procedural code can execute
// concurrently, and so several activity flows are concurrently
// advancing.


////////////////////////////////////////////////////////////////////////////////
/// Procedural Code Basics
///  (initial,always,begin,end,#,$display)

// :BV3: A.11.1
// :C: Chapter 8, up to section on Non-Blocking Procedural Assignments.
// :C: Page 333, $display;  page 346, $time;  page 347, $stop
// :C: p182 Delays (#).


// :Keywords: initial, always, begin, end, #, $display, $stop

// Procedural Code
//
// Starts with either "initial" or "always"...
// ... followed by a single statement ...
// ... or a begin / end block [or a fork/join block].
//
// Details follow example.

// :Example:
//
// A module using procedural code to print simple messages.

module my_first_procedural_module();

   // It's what it looks like.  Integers will be covered soon.
   integer i;

   initial    // Indicate start of procedural code.
              // Activity flow (execution) starts at t=0.
     begin    // begin/end used to bracket code.

        // Lines below execute sequentially, like an ordinary program.

        i = 0;

        $display("Hello, EDA World!!  BTW, i=%d t=%t", i, $time);

        i = 1;

        $display("Hello, EDA World!!  BTW, i=%d t=%t",i,$time);

     end

endmodule


 /// Specifying Procedural Code: initial, always
//
// :Syntax: initial STATEMENT;
//
// Start activity flow (start executing) with STATEMENT at t=0.
// STATEMENT may finish at t=0 or later (depending on what it is).
//
// Note: STATEMENT may be a single statement, a begin/end block, [or a
// fork/join block].
//
//
// :Syntax: always STATEMENT;
//
// Start activity flow (start executing) with STATEMENT at t=0.
// STATEMENT may finish at t=0 or later (depending on what it is).
// When STATEMENT finishes start it again. (Loop infinitely.)


 /// Procedural [Sequential] Block: begin, end
//
// :Syntax: begin STATEMENT1; STATEMENT2; ... end
//
// Used to bracket statements.  begin, end, and statements between
// treated as a statement.
//
// The entire begin/end block below is treated as a single statement.
// :Sample: begin a=0; b=2; end
//
// :Sample: initial begin clk = 0; x = 3; end


 /// System Task: $display
//
// :Syntax: $display(FORMAT,EXPR1,EXPR2,...);
//
// Used to display messages on simulator console.  Similar to C
// printf.  FORMAT specifies what text to print and, using /escape
// sequences/, how expressions should be formatted.  EXPR1, EXPR2, etc
// are evaluated and their values printed.
//
// Format Escape Sequences
//
// Start with a % and are followed by a format character.
// Format characters: %d (decimal), %h (hex), %o (octal), %b (binary)
//                    %c (character), %s(string), %t(time), ...
//
// See module for examples.


 /// System Task: $stop
//
// :Syntax: $stop;
//
// Stop simulator.  Typically used at the end of a testbench or where
// the testbench discovers an error.


 /// Procedural Delay
//
// :Syntax: # NUM;
//
// Delay execution NUM time units.  See behavioral_2 example.
//
// :Syntax: # ( EXPR );
//
// Delay by value of EXPR;
//
// :Syntax: # NUM  STATEMENT;
//
// Delay execution NUM time units then execute STATEMENT. This is
// equivalent to:  begin # NUM; STATEMENT; end
//
// :Syntax: # ( EXPR ) STATEMENT;
//
// Delay by value of EXPR then execute STATEMENT. This is equivalent
// to: begin # (EXPR); STATEMENT; end


// :Example:
//
// Procedural code using initial.  Code below starts at t=0, and
// because there are no delays, finishes at t=0.
//
// Question: Reg x can be viewed using the wave window and the console
// (where the display messages appear).  With respect to x below
// there's an important difference between the two.  What is it?

module behavioral_1(x);
   output x;

   reg [7:0]  x;

   initial
     // Activity flow starts here at t=0.
     // Procedural Code Starts Here
     begin

        x = 1;
        $display("Hello, x=%d, t=%t",x,$time);

        x = 2;
        $display("Hello, x=%d, t=%t",x,$time);

        x = 3;
        $display("Hello, x=%d, t=%t",x,$time);

     end

endmodule

// Simulator Output
//
// # Hello, x=  1, t=                   0
// # Hello, x=  2, t=                   0
// # Hello, x=  3, t=                   0


// :Example:
//
// An example of behavioral code using delays.  The initial block
// starts at t=0 and finishes at t=3.

module behavioral_2(x);
   output x;

   reg [7:0]  x;

   always
     begin

        x = 1;
        $display("Hello, x=%d, t=%t",x,$time);
        #1;

        x = 2;
        $display("Hello, x=%d, t=%t",x,$time);
        #1;

        x = 3;
        $display("Hello, x=%d, t=%t",x,$time);
        #1;

     end

endmodule

// Simulator Output
//
// # Hello, x=  1, t=                   0
// # Hello, x=  2, t=                   1
// # Hello, x=  3, t=                   2

// :Example:
//
// Use of two initials in a module.  Both start execution at t=0.

module behavioral_3(x);
   output x;

   reg [7:0] x;

   // Initial block A
   initial
     // Activity flow starts here at t=0.
     begin

        x = 1;
        $display("Hello, x=%d, t=%t",x,$time);
        #10;

        x = 2;
        $display("Hello, x=%d, t=%t",x,$time);
        #10;

        // The two statements below and in the next initial block
        // execute at t=20.  There is no way to tell for sure whether
        // the final value of x will be 3 or 30.

        x = 3;
        $display("Hello, x=%d, t=%t",x,$time);
        #10;

     end

   // Initial block B
   initial
     // Activity flow starts here at t=0.
     begin
        #5;

        x = 10;
        $display("Hello, x=%d, t=%t",x,$time);
        #10;

        x = 20;
        $display("Hello, x=%d, t=%t",x,$time);
        #5;

        // The two statements below and the two in the previous
        // initial block execute at t=20.  There is no way to tell for
        // sure whether the final value of x will be 3 or 30.

        x = 30;
        $display("Hello, x=%d, t=%t",x,$time);
        #10;

     end

endmodule

//  t   0    5    10   15   20
//  A   x=1       x=2       x=3
//  B        x=10      x=20 x=30
//
//  Both blocks execute at t=20.  One of them will execute before the
//  other but there is not way to predict which one. (The Verilog
//  language does not specify which should execute first; though a
//  particular implementation of Verilog may be consistent one way the
//  behavior of other implementations can be different.)
//
// Simulator Output:
//
// # Hello, x=  1, t=                   0
// # Hello, x= 10, t=                   5
// # Hello, x=  2, t=                  10
// # Hello, x= 20, t=                  15
// # Hello, x=  3, t=                  20
// # Hello, x= 30, t=                  20


// :Example:
//
// The module below is a behavioral description of an xor gate that
// doesn't work.  Why not?

module this_xor_gate_doesnt_work(x,a,b);
   input a, b;
   output x;

   reg    x;

   initial
     begin
        x = a ^ b;
     end

endmodule

module this_xor_might_work(x,a,b);
   input a, b;
   output x;

   reg    x;

   always @ ( a )
     begin
        x = a ^ b;
     end

endmodule

// Because it sets the output to a xor b only once, at t=0.  Inputs a
// and b might change after t=0, but x won't.


// :Example:
//
// Testbench for the xor gate above.

module demo_xor();

   reg a, b;
   wire x;

   this_xor_gate_doesnt_work x0(x,a,b);

   integer i;

   initial
     for (i=0; i<4; i=i+1)
       begin
          a = i[0];
          b = i[1];
          #1;
       end

endmodule


////////////////////////////////////////////////////////////////////////////////
/// More Procedural Code Basics  (always)

// :BV3: A.11.1
// :C: Chapter 8, up to section on Non-Blocking Procedural Assignments.


// :Keyword: always
//
// :Syntax: always STATEMENT;
//
// Execute STATEMENT at t=0.
// When it completes execute it again. And again, and again,...

 /// Use of initial and always
//
// Use of initial
//   Testbench code.
//   Initializing modules for simulation, NOT for synthesis.


// :Example:
//
// A simple always demo.  Message will be printed endlessly
// as simulated time advances.

module shouldnt_do_this();

   always
     begin
        $display("This is an infinite loop.");
        #10;
     end

endmodule


// :Example:
//
// An example of how NOT to use always.  It starts at t=0 and loops
// endlessly without advancing time.  Therefore the code in the
// initial block never gets past the #1 delay.

module never_do_this();

   always
     begin
        $display("This is an infinite loop too.");
     end

   initial
     begin
        #1;
        $display("The simulator will never get this far.");
     end

endmodule


// :Example:
//
// An example of how to use always.  The code in the initial block
// initializes the clock to 0.  The code in the always block inverts
// it every ten cycles.  This sort of code is used by testbenches, not
// modules to be synthesized.

module clock_generator(clk);
   output clk;
   reg    clk;

   initial clk = 0;

   always
     begin
        #5;
        clk = ~clk;
     end

endmodule


// :Example:
//
// Another proper use of always.  This generates a clock that is high
// for 90% of the time. (The clock above was a square wave.)

module another_clock_generator(clk);
   output clk;
   reg    clk;

   always
     begin
        clk = 0;
        #1;
        clk = 1;
        #9;
     end

endmodule


////////////////////////////////////////////////////////////////////////////////
/// Variables (reg, integer, etc)

// :BV3: A.6.2
// :C: Page 32-  (Covers in greater detail than needed here.)


// :Keywords: reg, integer, real, time

 /// Variable Types
//
// Hold values, unlike wires (nets)

// Variable Types
//
// reg:     Holds physical values. (Vector of 0, 1, x, z)
//          Declared with a specific number of bits.
//          Unsigned integer (or x or z).
//
// integer: Signed integer.
//          Usually 32 bits (based on host machine).
//
// real:    Floating-point number. Usually IEEE 754 double.
//
// time:    At least a 64-bit integer.
//          For holding simulated time.

module var_usage();

   reg [7:0] r;
   integer   i;
   real      f;
   time      t;

   initial
     begin
        r = -5;  // Value in reg interpreted as unsigned ...
        i = r;   // ... so i gets a positive value even though ints are signed..
        f = 1.0 / i;  // Take reciprocal of i.
        t = $time; // Get current time.

        // Display values in appropriate formats.
        $display(" r = %h,  i = %d,  f = %f,  t = %t",r,i,f,t);
     end

endmodule


 /// Variable and Net Assignment Rules
//
// Nets and variables are not interchangeable.  Here is how they can be used:
// Letters refer to example below.
//
// Note: net types: wire, [others not covered].
//       variable types: reg, integer, real, time, [others not covered].
//
// A:Procedural Code
//   Can assign to variables.
//   Cannot assign to nets.
//
// B:Continuous Assignment (assign)
//   Left-hand side must be a net.
//   Cannot be used to assign variables.
//
// C:Instantiation Input Connection
//   Can use net, variable, or expression.
//
// D:Instantiation Output Connection
//   Must use net. (Cannot use variable.)
//
// E:Module Input Port
//   Must use net.  (Cannot use variable.)
//
// F:Module Output Port
//   Can use net or variable.


// :Example:
//
// Examples of how nets and registers used.

module reg_v_net();

   reg [7:0] x, y;
   wire [7:0] a, b;

   // B: Continuous assignment to a net.
   assign     a = x;
   // B: The commented-out line below would be an error because reg's cannot
   //    be assigned using assign.
   // assign     y = x;   /// Error

   initial
     begin
        // A: Assignment to a variable.
        x = 1;
        // A: The commented-out line below would be an error because
        //    net's cannot be assigned in procedural code.
        // b = 1;
     end

endmodule


// :Example:
//
// Examples of how nets and registers used for ports and connections.

module port_example_1();
   wire s, co;

   // D: Commented-out line below would be an error because variables
   //    (including reg's) cannot connect to instantiation output
   //    connections, in this case sum and carry out.
   // reg s, co;

   // C: Instantiation input connections (inputs to an instantiated
   //    module, bfa_implicit.b1 below) can be either reg's or net's.
   reg  a, b;

   wire bee;

   not n1(bee,b);

   // C: Input connections to instantiated module are regs (a,b) and
   //    an expression (1'b0).
   // D: Output connections are nets (s,co), and cannot be variables (regs).
   bfa_implicit b1(s, co, a, bee, 1'b0);   // A module instantiation.

   initial
     begin

        #1; a = 0;  b = 0;
        #1; a = 0;  b = 1;
        #1; a = 1;  b = 0;
        #1; a = 1;  b = 1;
        #1;

     end

endmodule


// :Example:
//
// Additional examples of how to use variables and nets.

module port_example_2(x,s,a);
   // E: Module inputs must be wires. (The default.)
   input a;
   // F: Module outputs can be either variables or nets.
   //    Here x is a variable (reg) and s is a net (wire, by default).
   output x, s;
   reg    x;

   // E: The commented out line below would be an error since module inputs
   //    cannot be variables.
   // reg a;

   wire co;
   // D: Commented-out line below is an error because variables
   //    (including reg's) cannot connect to output ports, in this case
   //    sum and carry out.
   // reg co;

   // C: Input connections to an instantiated module (bfa_implicit.b1
   //    below) can be either reg's or net's.  Here, net type wire is
   //    used.
   wire  b, ci;

   integer i;

   assign b = i[0];
   assign ci = i[1];

   bfa_implicit b1(s,co,a,b,ci);

   initial
     begin

        x = 1; // x is not a very useful output.

        #1; i = 0;
        #1; i = 1;
        #1; i = 2;
        #1; i = 3;
        #1;

     end

endmodule


////////////////////////////////////////////////////////////////////////////////
/// Conditional Statement (if)

// :BV3: A.11.2
// :C: Pages 174-176

// :Keywords: if, else

//  :Syntax: if ( CONDITION ) IF_TRUE_STATEMENT
//  :Syntax: 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;


// :Example:
//
// Examples demonstrating if.

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

// :BV3: A.11.6
// :C: Pages 179-182

// :Keywords: for, while, repeat, forever

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

//  Some 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 it is in C.
      // while ( i = i - 1 ) x = x + 1;   // Syntax error.


      /// Three Ways to Iterate Ten Times:

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


////////////////////////////////////////////////////////////////////////////////
/// Case Statement

// :BV3: A.11.4
// :C: Page 176-179

// :Keywords: case, casex, casez, default, endcase

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

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



////////////////////////////////////////////////////////////////////////////////
/// Event Control (@)

// :C: Page 182-185 Would be easier to follow with more
//     examples. Includes discussion of delays as well as event control)
// :BV3: A.11.1 (look for description of sensitivity list)


// An /event control/ statement pauses the execution of the procedural
// code in which it appears until the specified event occurs.  Other
// procedural code and simulation activities are not affected.

// The general use of event control statements will be briefly
// described here.  Specific uses (for Form 1 and Form 2) will be
// described in later sections.  The general uses will not be used
// much in this class.

// :Syntax: @( EXPR ) STATEMENT;
//
// Evaluate EXPR and resume execution starting with STATEMENT when
// value of EXPR changes.


// :Syntax: @( EXPR1 or EXPR2 or... ) STATEMENT;
//   or
// :Syntax: @( EXPR1, EXPR2, ... ) STATEMENT;
//
// Evaluate EXPR1, EXPR2, ... and resume execution starting with
// STATEMENT when the value of any of the EXPR change. The two forms
// are equivalent (the one with " or " or the one with ", ").


// :Syntax: @( posedge EXPR ) STATEMENT;
//
// Resume execution starting with STATEMENT when EXPR changes from 0
// to anything or from anything to 1.


// :Syntax: @( negedge EXPR ) STATEMENT;
//
// Resume execution starting with STATEMENT when EXPR changes from
// anything to 0 or from 1 to anything.


// :Syntax: @( EDGE1 EXPR1 or EDGE1 EXPR2 or ... ) STATEMENT;
//
// EDGE1 can be posedge, negedge, or nothing.
// Resume execution at STATEMENT when any of the EXPR change to
// the specified value (nothing, which means just EXPRx, means any change).

 /// How Event Controls Used
//
// The event controls can be used anywhere a statement can go.  In
// practice they are almost always used right after "always," which is
// the way they will be covered in the following sections.  The more
// general use will not be covered any further in class, those who are
// curious can visit http://www.ece.lsu.edu/v/2001/l060.html