/// LSU EE 4755 -- Fall 2018 -- Digital Design / HDL /// /// Rudiments of Behavioral Code /// Contents // Behavior Code and Structured Procedures // The initial Structured Procedure // Basics of Delay (#) and Event (@) Controls // The always Structured Procedure // The $display system task, and a testbench example. /// References // :SV12: IEEE 1800-2017 -- The SystemVerilog Standard // https://ieeexplore.ieee.org/document/8299595/ // This is for those already familiar with Verilog. // // :BV3: Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed. // The text used in LSU EE 2740. //////////////////////////////////////////////////////////////////////////////// /// Behavioral Code // Behavioral code is used to specify what hardware does rather than // describe it as an interconnection of simpler components (as does // structural code). Behavioral code looks like a program in a // conventional programming language but there are major // differences. One difference is in when a piece of code starts // running. In C, execution starts with the "main" routine, other // procedures start execution when they are called. In Verilog, // behavioral code is invoked in a variety of ways, some times in a // way similar to a procedure call, other times in response to a // change in a signal. // Details on behavioral code will be presented later. Here the // rudiments are presented here so that behavioral code can be used // Verilog examples. // :SV09: Section 9.2 // :BV3: Section A.11.1 /// Specifying Behavioral Code // // Behavioral code is placed in a /structured procedure/. // When and how many times the behavioral code executes depends // on the particular structured procedure. /// Structured Procedures // // :Keyword: initial STATEMENT // Start statement at t=0. // // :Keyword: always STATEMENT // Execute statement repeatedly, statement MUST have // a timing or event control (unless your goal is to // hang the simulator). // // :Keyword: always_comb STATEMENT // Execute statement at t=0 and whenever live-in objects change. // Use this when STATEMENT describes combinational logic. // // There are two additional always_FOO statements, they // will be covered later. // // :Keyword: final STATEMENT // Execute statement before simulator exits. // // STATEMENT is usually a block, e.g., begin a=1; etc.... ; end //////////////////////////////////////////////////////////////////////////////// /// Initial Blocks // :SV09: Section 9.2.1 // :BV3: Section A.11.1 /// Placement // // Appear in modules and programs (programs not yet covered). // There can be any number of initial blocks in each module and program. /// Execution Timing // // All initial blocks start at t=0. // /// Typical Uses // // Initialization. // // Testbench. /// NOT USED FOR // // Describing synthesizable hardware. // :Example: // // Simple example. module mymod1(input myport, output alsomyport); logic a, b; // Starts running at t=0. initial begin a = 1; b = myport; end endmodule //////////////////////////////////////////////////////////////////////////////// /// Delays and Event Controls // :SV09: Section 9.4 up to and including 9.4.2.1 /// Description // // Delay and event controls are used to pause the execution of // behavioral code. With a delay, execution of the piece of behavioral // code is paused for the specified amount of time. With an event // control, execution of the piece of behavioral code is paused until // something happens. The pause only affects the behavioral code in // which the delay or event control appears. During the pause the // simulator will do something else. // Here only a basic description is given. Later, more advanced // treatment will be given, including non-blocking delays and // the simulator event queue. /// Delay Control // // :Keyword: # AMT STATEMENT // Wait AMT time units, then execute STATEMENT. // In many cases STATEMENT is blank. /// Event Control // // :Keyword: @* STATEMENT // Wait until any source (live-in) object in STATEMENT changes. // The "*" is called an implicit event expression list. // :Keyword: @ ( A or B or ... ) STATEMENT // Wait for A or B to change, then execute statement. // Sensitivity List: the "A or B or ..." part. // // :Example: // // Simple delay and event control examples. // module delay_and_event_demo(input uwire b); int a; initial begin a = 1; // Assignment occurs at t = 0; // Below, a changes at t = 5. // #5 a = 2; // AMT -> 5, STATEMENT -> "a = 2;" // At this point t = 5; #7; // AMT -> 7, STATEMENT -> "" (Statement is empty.) // a is assigned at t = 12. a = 3; @ ( b ); // Wait until b changes. // Assume that b next changes at t=20. a = 4; // a assigned at t = 20. // Wait until b changes. (b is used as a source in STATEMENT.) // @* a = b; // STATEMENT -> "a = b;" end endmodule //////////////////////////////////////////////////////////////////////////////// /// Always Blocks // :SV09: Section 9.2.2 // :BV3: Section A.11.1 /// Description // // :Keyword: always STATEMENT // // - STATEMENT starts at t=0; // - The amount of time STATEMENT takes depends on its contents. // Assume that STATEMENT always takes 5 units. // - Then STATEMENT will finish at t=5 ... // - ... and then will start again at t=5 (hence always) ... // - ... and will finish at t=10 ... // - ... and start again at t=10 ... // // Note: There will be an infinite loop (deadlock) if STATEMENT // does not contain some kind of delay or event control. // // :Keyword: always_comb STATEMENT // // Restriction: STATEMENT cannot have timing (e.g, #3;) // nor event controls (@(a or b);). // // - STATEMENT executes at t=0. // - STATEMENT executes whenever an object used in STATEMENT changes. /// Common Use of Always -- Describe Combinational Logic // // :Sample: always @* STATEMENT // :Sample: always_comb STATEMENT // :Example: // // Use of always to generate a clock signal. module myclockgen(output logic clock); initial clock = 0; always #5 clock = !clock; endmodule // :Example: // // Good use of always, once upon a time. /// Now it's bad! // module mymod2good(output logic x,y, input uwire a,b,c); // Runs each time a or b or c changes. // always @( a or b or c ) begin /// FOOLISH! Use always @* instead. x = a + 1; y = b + c; end endmodule // :Example: // // Unusual use of always. Probably an error. // module mymod2bad(output logic x,y,z, input uwire a,b,c); // Runs each time a or b changes. Won't run if only c changes. // always @( a or b ) begin /// Note: c intentionally omitted. x = a + 1; y = b + c; end endmodule // :Example: // // Use of implicit event expression. always_comb // module mymod21(x,y,z,a,b,c); input uwire a, b, c; output logic x, y, z; // Runs at t=0 and each time any right-hand-side object changes. // always_comb begin x = a + 1; y = b + c; end endmodule /// Multiple initial And always Blocks // A module can have any number of initial and always constructs. // Timing and other details will be discussed later. module mymod3(output logic x,y,z, input uwire a,b,c); // Runs at initialization. initial begin x = 1; end // Runs at initialization .. // .. either before or after the block above. initial begin y = 1; end // Runs each time x changes. // always @( * ) begin y = 2 + x; end endmodule //////////////////////////////////////////////////////////////////////////////// /// Simple Testbench, and the $Display System Task // :SV09: Section 21.2 // The following are useful in procedures. They are covered briefly // below and will be covered in detail later. // :Keyword: $display // :Keyword: $write // // The $display system task. // Used in procedures to print messages in the transcript. // Similar to the C printf library function. // :Syntax: $display(FORMAT,ARG1,ARG2,...) // FORMAT is a string that can contain escape sequences. // ARG1, ARG2 are the values to be printed. // Format escape sequences start with a % and followed by a format character. // Format characters: %d (decimal), %h (hex), %o (octal), %b (binary) // %c (character), %s(string), %t(time), ... // // Examples: // $display("The values are: i=%0d or %h (hex) time=%t\n", i, i, $time); // This is one of many system tasks. // :Example: // // Use of behavioral code to write a testbench for a simple "imply" // module. The testbench is in module demo_the_tedious_way. module imply( output uwire x, input uwire a, b ); assign x = ~a | b; endmodule module demo_the_tedious_way(); logic a, b; uwire x; imply imp1(x, a, b); initial begin // Here t = 0 (units discussed later). a = 0; b = 0; $display("At the very beginning, t=%t, x= %d\n",$time,x); // This delays execution for one unit. #1; $display("A little later, t=%d, x= %d\n",$time,x); #1; a = 0; b = 1; $display(" t = %t, x = %d\n",$time,x); #1; $display(" t = %t, x = %t\n",$time,x); #1; a = 1; b = 0; #1; $display(" t = %t, x = %d\n",$time,x); #1; a = 1; b = 1; #1; $display(" t = %t, x = %d\n",$time,x); $stop; end endmodule // :Example: // // Same testbench as code above, but using a for loop to simplify // things. module demo_the_better_way(); int i; uwire a = i[0]; uwire b = i[1]; uwire x; imply imp1(x, a, b); initial begin for ( i=0; i<4; i++ ) begin $display("At the beginning of an iteration. t=%t, x=%d.\n", $time,x); #1; $display("In the middle of an iteration. t=%t, x=%d.\n", $time,x); #1; end $stop; end endmodule