/// LSU EE 3755 -- Computer Organization

//

/// Verilog Notes 4 – Fall 2009 Delay, Descriptive Styles

/// Contents

/// Delays

/// The Event Queue and Verilog Simulation

//  Descriptive Styles

//  Implicit Structural Descriptive Style

//  Behavioral

///  Lexicographic Conventions

//

// :Sample:  A short example of Verilog, much less than a whole module.

// :Example: A long example of Verilog code, usually a module.

// [bar]:    Information that EE 3755 students are not yet responsible for

//            but is included here anyway.

/// References

// :P:   Palnitkar, "Verilog HDL"

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

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

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

/// Delays

// :P: 6.2, 6.2.2, 6.2.3

// A /delay/ is a specification of elapsed time, the amount of

// time the simulator is supposed to wait.

// The simulator keeps track of simulated time, measured in cycles.

// This is unlike conventional languages.

// The default delay is zero.

//

// If delays are not specified things happen instantly.

//

// The default delay for a gate is zero.

//

// The default delay for an assign is zero.

//

// The default delay for an assign with a really complex expression

// is zero.

//

// The default delay for a module containing a zillion gates is zero.

//

// Zero is NOT the same as one.

//

// Delays can be specified in a variety of ways.

//

//   The following will be covered in class:

//

//      Delays in wires and assigns (this set).

//      Delays in behavioral statements (later this semester).

//

//   See "delays" module, below, for further description.

// :Example:

//

// A module that just passes the signal through, like wire.  Suppose

// at t=5 input a changes from 0 to 1, when does x change?

module no_delays(x,a);

input a;

output x;

assign x = a;

wire   w = x;

endmodule

// Ans: x changes at 5 + 0 = 5.

// :Example:

//

// A module that just passes the signal through unchanged, though it

// passes through two inverters.  Suppose at t=5 input a changes from

// 0 to 1, when does x change?

module no_delays2(x,a);

input a;

output x;

wire   b;

not n1(b,a);

not n2(x,b);

endmodule

// Ans: x changes at 5.

// :Example:

//

// Illustration and explanation of delays in assigns and wires.

module delays(x,a);

input a;

output x;

// Delay (For nets.)

//

wire #7   w = a;

//

// w gets value of a 7 cycles after each change in a (a must hold

// steady for at least 7 cycles).

// Delay (For continuous assignments.)

//

assign #3 x = w;

//

// x gets value of "w" 3 cycles after each change in "w" (w must

// hold steady for at least 3 cycles).

endmodule

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

// :Example:

//

// The binary full adder presented earlier.  There are no delays here.

module bfa_implicit(sum,cout,a,b,cin);

input a,b,cin;

output sum,cout;

assign sum =

~a & ~b &  cin |

~a &  b & ~cin |

a & ~b & ~cin |

a &  b &  cin;

assign cout = a & b | b & cin | a & cin;

endmodule

// :Example:

//

// The same BFA with delays.

// Suppose "a" changes at t=5 and "b" changes at t=20.

// When do sum and cout change?

module bfa_implicit_d(sum,cout,a,b,cin);

input a,b,cin;

output sum,cout;

assign #3 sum =

~a & ~b &  cin |

~a &  b & ~cin |

a & ~b & ~cin |

a &  b &  cin;

assign #2 cout = a & b | b & cin | a & cin;

endmodule

// Ans: sum: t=8 and t=23;  cout t=7 and t=22.

// :Example:

//

// A 4-bit ripple adder constructed using the undelayed BFA.

// If a changes at t=5 when does sum change?

module ripple_4(sum,cout,a,b);

input [3:0] a, b;

output [3:0] sum;

output       cout;

wire         c0, c1, c2;

bfa_implicit bfa0(sum[0],c0,a[0],b[0],1'b0);

bfa_implicit bfa1(sum[1],c1,a[1],b[1],c0);

bfa_implicit bfa2(sum[2],c2,a[2],b[2],c1);

bfa_implicit bfa3(sum[3],cout,a[3],b[3],c2);

endmodule

// Ans: t = 5.

// :Example:

//

// A 4-bit ripple adder constructed using the BFA with delays.

// Suppose at t=0 a=0 and b=4'b1111

// If a changes to 1 at t=100 when does sum stop changing?

module ripple_4_d(sum,cout,a,b);

input [3:0] a, b;

output [3:0] sum;

output       cout;

wire         c0, c1, c2;

bfa_implicit_d bfa0(sum[0],c0,a[0],b[0],1'b0);//sum[0] changes at 103,

//c0 changes at 102.

bfa_implicit_d bfa1(sum[1],c1,a[1],b[1],c0);  //sum[1] changes at 105,

//c1 changes at 104.

bfa_implicit_d bfa2(sum[2],c2,a[2],b[2],c1);  //sum[2] changes at 107,

//c2 changes at 106.

bfa_implicit_d bfa3(sum[3],cout,a[3],b[3],c2);//sum[3] changes at 109,

//cout changes at 108.

endmodule

// Ans t=109

// :Example:

//

// A 4-bit adder using operators and no delays. This would be

// a better way of coding a 4-bit adder in Verilog, but it's

// not a good way to demonstrate the low speed of a ripple adder

// to a computer organization class.

// If no delay CLA and RCA will compute at the same time.

input [3:0] a, b;

output [3:0] sum;

output       cout;

wire [4:0]   sum_with_carry = a + b;

assign       sum = sum_with_carry[3:0];

assign       cout = sum_with_carry[4];

endmodule

// :Example:

//

// This is not really an example and students are not expected

// to understand it.  This is a testbench for the adder, it

// instantiates the adders, generates inputs for them, and checks

// for the correct output.

//

wire [4:0] sum1, sum2, sum3;

reg [3:0]  a, b;

integer    i;

input [4:0] s;

input [79:0] name;

if( s != shadow_sum ) begin

\$display("Wrong sum in %s: %d + %d = %d != %d\n",

\$stop;

end

initial begin

for(i=0; i<=255; i=i+1) begin

a = i[3:0];

b = i[7:4];

#10;

check_sum(sum1,"Ripple");

check_sum(sum2,"Ripple_d");

check_sum(sum3,"Operator");

end

\$display("Tests completed.");

end

endmodule

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

/// The Event Queue and Verilog Simulation

/// The Verilog Simulator Event Queue

//

// Simulator maintains a "to-do list" called an /event queue/.

//

// An entry in the event queue specifies something that the simulator

//  needs to do.  These include:

//

//   (A) Changing the value of a wire [or reg].

//

//   (B) Evaluating an expression appearing in an assign statement.

//

//   (C) Determining the output of a gate.

//

// (The letters above are used in the example below.)

//

// Each entry has a /timestamp/ which indicates when the action

//  specified by the entry is supposed to be done.

//

// Entries are sorted by timestamp.

//

// [Entries with the same timestamp are divided in to five layers.]

/// How Verilog Simulators Run

//

// Wires [and registers] are initialized to x.

//

// Initial entries are put in the event queue. (Covered later in the

//  semester.)

//

// WHILE there the event queue is non-empty:

//

//   Remove any entry with the smallest time stamp.

//

//   Set the time to that time stamp.

//

//   If the entry changes the value of a wire [or reg]:

//

//      Put entries in the event queue for all gates and expressions

//      [and event controls] affected by the wire [or reg].

//

//   Else If the entry is for an expression in an assign statement:

//

//      Evaluate the expression.  Put an entry in the event queue

//      to modify the wire that's assigned.  The entry's time stamp

//      is the current time plus the delay (plus zero if no delay).

//      [Delete other entries in the event queue corresponding to the

//      same assign.]

//

//   Else If the entry is for a gate:

//

//      Determine the output of the gate. Put an entry in the event

//      queue to modify the wire connected to the gate's output.  The

//      entry's time stamp is the current time plus the delay (plus

//      zero if no delay).  [Delete other entries in the event queue

//      corresponding to the same gate instance.]

//

//   Else If ... (Covered with procedural code.)

//

// End simulation (when while loop is done).

// :Example:

//

// Module illustrating timing and event queue.  The testbench (shown

// further below) sets a and b equal to 0 at t=0.

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

input a, b;

output x,y;

wire d, e;

not #2 n1(d,a);

not #3 n2(e,d);

assign x = b ^ d ^ e;

xor a1(y,b,d,e);

endmodule

/// Event Queue for Example

//

// The comments below show the contents of the event queue as the

// module above is simulated with the testbench way below.  Some

// events generated by the testbench have not been shown.

// Event Queue After Testbench Starts, t = 0

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 1  timestamp = 0;  A: Set a <- 0

// Entry 0  timestamp = 0;  A: Set b <- 0

// Entry 0 removed.

// Change b from x to 0.

// Event Queue at t = 0

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 4  timestamp = 0;  B: Evaluate:   xor a1(y,b,d,e);

// Entry 3  timestamp = 0;  B: Evaluate:   assign x = b ^ d ^ e;

// Entry 1  timestamp = 0;  A: Set a <- 0

// Entry 1 removed.

// Change a from x to 0.

// Event Queue at t = 0

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 5  timestamp = 0;  C: Evaluate:   not #2 n1(d,a);

// Entry 4  timestamp = 0;  C: Evaluate:   xor a1(y,b,d,e);

// Entry 3  timestamp = 0;  B: Evaluate:   assign x = b ^ d ^ e;

// Entry 3 removed.

// Compute b ^ d ^ e, result wire x does not change (was undefined, still is)

// Event Queue at t = 0

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 5  timestamp = 0;  C: Evaluate:   not #2 n1(d,a);

// Entry 4  timestamp = 0;  C: Evaluate:   xor a1(y,b,d,e);

// Entry 4 removed

// Compute xor a1(y,b,d,e).  Output y does not change (was x, still is).

// Event Queue at t = 0

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 5  timestamp = 0;  C: Evaluate:   not #2 n1(d,a);

// Entry 5 removed.

// Compute n1(d,a).  d is to change from x to 1.

// Insert change to d in event queue for 2 cycles later.

// Event Queue at t = 0

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 6  timestamp = 2;  Set d <- 1

// Remove entry 6.

// Change time to t = 2.

// Set d to 1.

// Add items affected by d.

// Event Queue at t = 2

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 9  timestamp = 2;  assign x = b ^ d ^ e;

// Entry 8  timestamp = 2;  xor a1(y,b,d,e);

// Entry 7  timestamp = 2;  not #3 n2(e,d);

// Remove entry 7.

// Compute n2(e,d).  e is to change from x to 0

// Insert change to e in event queue for 3 cycles later.

// Event Queue at t = 2

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 10 timestamp = 5;  Set e <- 0

// Entry 9  timestamp = 2;  assign x = b ^ d ^ e;

// Entry 8  timestamp = 2;  xor a1(y,b,d,e);

// Remove entry 8.

// Compute xor(y,b,d,e)

// No change in y. (Was x, still is.)

// Event Queue at t = 2

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 10 timestamp = 5;  Set e <- 0

// Entry 9  timestamp = 2;  assign x = b ^ d ^ e;

// Remove entry 9

// Compute b ^ d ^ e

// No change in x.

// Event Queue at t = 2

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 10 timestamp = 5;  Set e <- 0

// Remove entry 10.

// Change time to t = 5

// Set e to 0

// Event Queue at t = 5

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 12  timestamp = 5;  assign x = b ^ d ^ e;

// Entry 11  timestamp = 5;  xor a1(y,b,d,e);

// Remove entry 11.

// Evaluate xor(y,b,d,e)  y to change from x to 1.

// Event Queue at t = 5

//

// Entry 2  timestamp = 8;  Resume testbench procedural code.

// Entry 13  timestamp = 5;  Set x <- 1

// Entry 12  timestamp = 5;  assign x = b ^ d ^ e;

// Remove entry 12.

// Evaluate b ^ d ^ e.  wire x to change from x to 1.

// Event Queue at t = 5

//

// Entry 2   timestamp = 8;  Resume testbench procedural code.

// Entry 14  timestamp = 5;  Set y <- 1

// Entry 13  timestamp = 5;  Set x <- 1

// Remove entry 13.

// Set x to 1.

// Add affected items. (The affected item is in the testbench which isn't shown.)

// Event Queue at t = 5

//

// Entry 2   timestamp = 8;  Resume testbench procedural code.

// Entry 15  timestamp = 5;  Some procedural stuff.[always @( a or b or x or y )]

// Entry 14  timestamp = 5;  Set y <- 1

// Remove entry 14

// Set y to 1.

// Add affected items. (The affected item is already there, the always thing.)

// Event Queue at t = 5

//

// Entry 2   timestamp = 8;  Resume testbench procedural code.

// Entry 15  timestamp = 5;  Some procedural stuff.[always @( a or b or x or y )]

// Remove entry 15

// The procedural code prints a message.

// Event Queue at t = 5

//

// Entry 2   timestamp = 8;  Resume testbench procedural code.

// Remove entry 2 (finally).

// Change time to t = 8

// Continue running the procedural code until... something else

//  is put in the event queue.  More details will be provided when procedural

//  code covered.

// :Example:

//

// The testbench for the code above.  This module uses procedural

// code which has not been covered yet.  It can be ignored for now.

module demo_timing();

reg a, b;

wire x, y;

timing everyones_timing_module_instance(x,y,a,b);

integer i;

always @( a or b or x or y )

\$display(" a,b = %d, %d   x,y= %d, %d",a,b,x,y);

initial begin

for(i=0; i<4; i=i+1) begin

{a,b} = i[1:0];

#8;

end

end

endmodule

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

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

/// Descriptive Styles

///  Descriptive Style Definition

//

//   A set of rules for a Verilog description.

///  Three Major Styles

//

//    Explicit Structural:  Most restrictive.

//    Implicit Structural:  Still restrictive.

//    Behavioral:           Least restrictive. (Not yet covered.)

//

//  A Verilog description is called ``explicit structural'' if it

//   follows explicit structural design rules. (described below).

//   The same holds for the other styles.

/// Explicit Structural Descriptive Style

//

//  The Verilog specifies every component and how they are wired.

//

//  Tedious to write

//

//  Rules:

//   No operators (+,&,~, etc.)

//   No assign's (continuous assignments).

//   No initial/always blocks (covered later).

// :Example:

//

//  The module below is explicit structure and is neither implicit

//  structural nor behavioral.

module bfa_structural(sum,cout,a,b,cin);

input a,b,cin;

output sum,cout;

wire   term001, term010, term100,term111;

wire   ab, bc, ac;

wire   na, nb, nc;

or o1(sum,term001,term010,term100,term111);

or o2(cout,ab,bc,ac);

and a1(term001,na,nb,cin);

and a2(term010,na,b,nc);

and a3(term100,a,nb,nc);

and a4(term111,a,b,cin);

not n1(na,a);

not n2(nb,b);

not n3(nc,cin);

and a10(ab,a,b);

and a11(bc,b,cin);

and a12(ac,a,cin);

endmodule

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

/// Implicit Structural Descriptive Style

// Some components and wiring are specified using expressions.

// Less tedious to write

// Rules:

//  No initial/always blocks (covered later).

// :Example:

//

//  The module below is implicit structure and is neither explicit

//  structural nor behavioral.

module bfa_implicit(sum,cout,a,b,cin);

input a,b,cin;

output sum,cout;

assign sum =

~a & ~b &  cin |

~a &  b & ~cin |

a & ~b & ~cin |

a &  b &  cin;

assign cout = a & b | b & cin | a & cin;

// It can't be explicit structural because of the assign and operators.

endmodule

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

/// Behavioral

// Easiest to write.

// :Example:

//

//  The module below is behavioral and is neither explicit nor

//  implicit structural.

//

module bfa_behavioral(sum,cout,a,b,cin);

input a,b,cin;

output sum,cout;

// Material for this module will be covered later.

// It's here to show what behavioral code looks like.

// We aren’t going to explain behavioral code now.

reg    sum, cout;

always @( a or b or cin )

begin

sum = ~a & ~b &  cin |

~a &  b & ~cin |

a & ~b & ~cin |

a &  b &  cin;

cout = a & b | b & cin | a & cin;

end

endmodule

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