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