/// LSU EE 3755 Fall 2009 Computer Organization

//

/// Verilog Notes 7 -- Procedural Code & Behavioral Modeling

 

// 

//

 

 

/// Contents

//

// Procedural Code Overview

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

// More Procedural Code Basics  (always)

// Variables (reg, integer, etc)

 

/// References

//

// :P:   Palnitkar, "Verilog HDL"

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

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

 

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

/// Procedural Code Overview

 

// :P: 7, 7.1, 7.1.1

 

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

//

 

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

//   Time (simulated) part of language(think about delay).

//   when we have /delay/, the /delay/ is unit time

// (simulated time).

 

//This example is NOT a completed code

//This  shows 3 blocks are running concurrently

// at time 3, each block generates output of and-gate

//each block has its own activity flow(what it does).

 

//module activity_flow( )

/*

initial

   begin

        #3

       and a1(a1,b1,c1);

   end

 

initial

   begin

       #3

      and a2(a2,b2,c2);

   end

 

initial

   begin

       #3

       and a3(a3,b3,c3);

  end

 

 

endmodule

 

*/

 

 

/// Activity Flow (within procedural code)

//

 

//

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

 

// :P: 7.1, 7.1.1, 7.1.2  initial, always

// :P: 7.7, 7.7.1 begin/end.

// :P: 7.3, 7.3.1 Delay (#)

// :P: 3.3.1 System tasks, including $display.

 

// :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();

 

  

   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,World!, i=%d t=%t", i, $time); //time t = 0;

 

 

      i = 1;

       

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

    

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

// block of codes inside initial begin-end  will be

// executed ONLY once.

// 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: initial 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  NUM time units.  See behavioral_2 example.

//

// :Syntax: # ( EXPR );// # (a+b);

                       // for example ,when a =1, b =3,

                       // # 4;

//

// Delay by value of EXPR;

//

// :Syntax: # NUM STATEMENT;

//          # 5 and a1(a,b,c);

// Delay  NUM time units then execute STATEMENT. This is

// equivalent to:  begin # NUM; STATEMENT; end

                  //begin #5; and a1(a,b,c); 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.

//

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;

  

   initial

     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.

//

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

 

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

// execution starts at t = 0, and executes only once.

 

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

 

// :P: 7.1.2  always

 

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

// Two blocks always and initial running concurrently

// because there is job to finish at time t = 0

//( which never finishes..always block).

// simulated time clock never reaches time t = 1;

// so the initial block's $display will never enter

//(it will be executed at time t =1.)

 

module never_do_this();

 

   always

     begin

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

     end

 

   initial

     begin

        #1;

        $display("The simulator will never print this one.");

     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.

 

module clock_generator(clk);

   output clk;

   reg    clk;

 

   initial clk = 0;

 

   always

     begin

        #10;

        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)

 

// :P: 4.2.3 Port connection rules.

// :P: 3.2.3, 3.2.5 Registers (Variables), variable types.

 

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

//

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

        i = r;  

        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.

//       variable types: reg, integer, real, time.

//

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

// : bfa bfa1(sum,carryout,a,b)

// : a, b can be net or variable.

//

// D:Instantiation Output Connection

//   Must use net. (Cannot use variable.)

// : bfa bfa1(sum,carryout,a,b)

// : sum, carryout should be net.

//

 

// E:Module Input Port

//   Must use net.  (Cannot use variable.)

// : module bfa (sum,carryout,a,b)

// : a, b should be net.

 

// F:Module Output Ports

//   Can use nets or variables.

 

 

// When make a module, inputs should be wires.

// When instantiate a module, outputs should be wires.

 

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

 

   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;

 

   // 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,b,1'b0);

 

   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.

// focus on usage of nets and variables,

// not to focus on module's functionality...

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.

   //  below we intantiate BFA.

   // When intantiate a module, outputs should be nets

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