Lecture 06 – Events Timing and Basic Testbenches
Ryan Robucci
1. References
- (Cummings 2000) Some examples are borrowed: Cummings, Clifford E. "Nonblocking assignments in verilog synthesis, coding styles that kill!." SNUG (Synopsys Users Group) 2000 User Papers (2000). http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
- (IEEE Std 1364-2005) IEEE Standard for Verilog Hardware Description Language," in IEEE Std 1364-2005 (Revision of IEEE Std 1364-2001) , vol., no., pp.1-590, 7 April 2006 doi: 10.1109/IEEESTD.2006.99495 Abstract: The Verilog hardware description language (HDL) is defined in this standard. Verilog HDL is a formal notation intended for use in all phases of the creation of electronic systems. Because it is both machine-readable and human-readable, it supports the development, verification, synthesis, and testing of hardware designs; the communication of hardware design data; and the maintenance, modification, and procurement of hardware. The primary audiences for this standard are the implementers of tools supporting the language and advanced users of the language. URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=1620780&isnumber=33945
- Reference material for timing examples: (Cummings 1999) Cummings, Clifford E. "Correct Methods for Adding Delays to Verilog Behavioral Models !." HDLCON 1999. http://www.sunburst-design.com/papers/CummingsHDLCON1999_BehavioralDelays_Rev1_1.pdf
2. An Event Driven Language also used for Synthesis
- We emphasize use of Verilog as a hardware description language for synthesis, but it is a general event-driven simulation language
- Verilog is event driven, events are triggered to cause evaluation events to be queued which cause updates to be queued which may in turn serve as triggers for other events to be queued.
- Events are entered into a priority queue for processing. Event elements in the priority queue are removed and processed according to two rules
- earliest time first
- then first come first serve stack behavior
- Nondeterminism of concurrent statements: By default, individual assignment statements and blocks in a module are considered to be concurrent. This means that there evaluation may be queued in any order if triggered.
- Certain coding guidelines constrain the use of the language to ensure deterministic behavior in simulation and are known to map to hardware with the same behavior
- Most of these issues relate to concurrency
3. Verilog Language
- Being a hardware description and modeling language, Verilog supports modeling of concurrency as well as time.
all of the following should be considered as equivalent since concurrent processes are described
not I1(b_n,x); and I2(b_n,x); assign w = (a|b); assign y = (w|u);
and I2(b_n,x); assign w = (a|b); assign y = (w|u); not I1(b_n,x);
assign y = (w|u); and I2(b_n,x); assign w = (a|b); not I1(b_n,x);
- In-class: discuss flow of value propagation and events: \(\boxed{{a,b,c,d}={1,1,1,1}} \rightarrow \boxed{{a,b,c,d}={1,1,1,0}}\)
- Event-Driven: update events cause evaluation events, which case update events
- selective, as-needed processing of expressions and code
- massive simulation time savings for large circuits with few value changes (low activation)
- selective, as-needed processing of expressions and code
4. Timing
- Timing and delay are intrinsic aspects of physical circuits and are important concepts for hardware modeling
- Delay in a logic path might be a parasitic effect, and must be analyzed to ensure the circuit can operate fast enough.
- Delay in the logic path also helps prevent race conditions if the clk arival at the downpath register is slightly delayed
5. Timing (Example: Pulse Circuit)
Other times, delay is fundamental to how a circuit works.
- In the circuit below delay is necessary for the circuit to generate a pulse.
Structural Example with delays indicated with #:
module pulser(y, x); input x; output y; wire x_n; and #5 (y,x,x_n) not #3 (x_n,x); endmodule
6. Concurrent Operation
- Describing concurrency (usually to model parallelism) is another key feature of an HDL
- The following code attempts to model a swap of y1 and y2, as in
- y1 = old y2 , concurrently with
- y2 = old y1
Concurrent Assignment (Cummings 2000):
module fbosc2 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; always @(posedge clk or posedge rst) if (rst) y1 <= 0; // reset else y1 <= y2; always @(posedge clk or posedge rst) if (rst) y2 <= 1; // preset else y2 <= y1; endmodule
This is a case where handing of concurrency, is critical as two interdependent updates are at once
7. Verilog Execution Model
- A Verilog Simulation involves processing events from different queues that have different priorities
- Most events in the queues can be describe as evaluation or update events
- Evaluation events involve processing or execution. These events can enable other events to enter the active queue, often it enters value assignment events into the queue.
- Update events involve making a value assignment to a variable. These in turn may implicitly enable evaluation events that are sensitive to the changed variable
8. The stratified event queue
The IEEE standard identifies 5 regions for events to live:
- Active events: in queue ready for execution in current simulation time. The Nondeterminism property states that the order that they are removed is not specified. One effect is that concurrent statements and blocks are not guaranteed execution in any order. Furthermore, blocks of behavioral statements may be returned to the active queue at any point even if only partially completed. This allows interleaving of process execution but also unpredictable behavior for concurrent processes with miscoded communication paths between them.
- Inactive events: to be processed at the end of the current simulation time after any active events in the queue. An explicit zero delay (#0) is a way to force an event to be transferred to the inactive event queue.
- Nonblocking assign update events: to be processed at the end of the current simulation time after active and inactive events in the queue. They are processed in the order they are added to the queue.
- Monitor events: to be processed if no active, inactive, or nonblocking assign update events are in the queue. These events do no create any other events. `$monitor` and `$strobe` system tasks generate monitor events.
- Future events: active, inactive and nonblocking assign update events scheduled with a future time
9. IEEE Specification of Event Handling
(Quoted from IEEE Std 1364-2005 with colors added)
while (there are events){ if (no active events){ if (there are inactive events){ activate all inactive events; } else if(there are nonblocking assign update events){ activate all nonblocking assign update events; } else if(there are monitor events){ activate all monitor events; } else{ advance T to the next event time; activate all inactive events for time T; } } E = any active event; if (E is an update event){ update the modified object; add evaluation events for sensitive processes to event queue; }else { /* shall be an evaluation event */ evaluate the process; add update events to the event queue; } }
10. Bad Parallel Blocks
Bad Concurrent Assignment (Cummings 2000):
module fbosc1 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; always @(posedge clk or posedge rst) if (rst) y1 = 0; // reset else y1 = y2; always @(posedge clk or posedge rst) if (rst) y2 = 1; // preset else y2 = y1; endmodule
- This code attempts to model a swap of y1 and y2
- Timing of execution of parallel always blocks is not guaranteed in simulation — though synthesis will probably work since synthesis approaches each always blocks somewhat independently at first
11. Simulation of parallel blocks
12. Good Parallel Blocks
Will not only synthesize correctly, but also simulate correctly:
Good Concurrent Assignment (Cummings 2000):
module fbosc2 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; always @(posedge clk or posedge rst) if (rst) y1 <= 0; // reset else y1 <= y2; always @(posedge clk or posedge rst) if (rst) y2 <= 1; // preset else y2 <= y1; endmodule
13. Sim Example
module amb_parallel_swap(); reg clk, rst; reg y1, y2; reg z1, z2; initial clk = 0; always #50 clk = ~clk; initial begin rst = 1; #10; rst = 0; end initial begin #1000 $finish; end
always @(posedge clk , posedge rst) if (rst) y1 = 0; // reset else y1 = y2; always @(posedge clk , posedge rst) if (rst) y2 = 1; // preset else y2 = y1;
always @(posedge clk , posedge rst) if (rst) z1 <= 0; // reset else z1 <= z2; always @(posedge clk , posedge rst) if (rst) z2 <= 1; // preset else z2 <= z1; endmodule
14. Continuous Assignment
Continuous assignment statements enable (a.k.a. schedule or trigger) an evaluation event when any source element of the RHS expression changes. Upon any expression's resulting value change, an update event for the LHS is added to the active queue.
assign {cout,b} = d+a;
- Left-hand-side (LHS) expression:
{cout,b}
- Right-hand-side (RHS) expression:
d+a
- Left-hand-side (LHS) expression:
At the start of each simulation, an initial evaluation of continuous assignments occurs at time zero to propagate constant values. The various cascades of dependanceis cause other expresssions and procedural code in the HDL models to be evaluated at time zero as a result. In the the following, an initial evaluation and assignment will occur, but no other update to a will happen in the simulation.
assign a=1;
15. Procedural continuous assignment
- Consider this topic not covered until future notice
- Involves keywords assign, force, deassign, release when specifically used inside procedural code
16. Switch (transistor) processing
- Not covered until future notice: switch modeling keywords such as tran, tranif0, tranif1,rtran, rtranif0, rtranif1
17. Blocking and Nonblocking Procedural Assignment with Delays
Blocking assignments cause an immediate evaluation of the right hand side. If delay is provide, then the assignment to the left-hand-expression is scheduled for a future time unless the delay is 0 and in which case the assignment event is entered into the inactive queue. If no delay is specified the statement performs the assignment and returns immediately. Once the assignment is performed, any change will enable any events dependent on the value.
a = #D b+c;
delay D before blocking assignment
Nonblocking assignments schedule an evaluation and assignment using the values of the inputs at the time of the scheduling. The event is placed in the nonblocking assignment update event queue for the current time or, if a delay is provided, a future time.
a <= #D b + c;
assignment delay D
Delays are only used when modeling for simulation. They should not be used to describe characteristics to a hardware synthesis tool. Typically, all # delays are stripped from code before synthesis.
18. Procedural Blocking and Procedural Assignment Delay
- In the delay before evaluation form (statement delay or evaluation delay), the delay essentially βsleepsβ the process until another time before the following code is evaluated.
so call statement delay because delay is essentially before entire statement
#D a = b + c;
#D; a = b + c;
#D a <= b + c;
#D; a <= b + c;
- Assignment delay schedules an assignment for a future time, though the RHS expression evaluation is not delay and may use the variable values at the time of the scheduling rather than the future.
- for delayed blocking assignments, no progression in procedural code until update event is handled (code does not pass control)
- control is not passed out of the block (particularly, always block control triggers may be missed)
- for delayed non-blocking assignments, the update is delayed yet execution control is passed immediately
- for delayed blocking assignments, no progression in procedural code until update event is handled (code does not pass control)
#D a = b + c;
- delay>evaluate>assign>progress
- future values of b,c used
- passes control after assignment
#D a <= b + c;
- delay>evaluate>progress>assign
- future values of b,c used
- passes control after evaluation
Assignment Delay (delay before assignment)
a = #D b + c;
- evaluate>delay>assign>progress
- current values of b,c used
- control passed after blocking assignment
a <= #D b + c;
- evaluate>delay>progress>assign
- current values of b,c used
- control passed after blocking assignment
Code example
initial #0 $display($time," a b y z"); initial begin $monitor($time,u8a,u8b,u8y,u8z); u8a=0; u8b=0; #5; #5 u8a = 1; #5 u8b = 1; end always@* begin $display($time,u8a,u8b," enter nonblocking"); u8y <= #20 u8a+u8b; $display($time,u8a,u8b," leave nonblocking"); end always@* begin $display($time,u8a,u8b," enter blocking"); u8z = #20 u8a+u8b; $display($time,u8a,u8b," leave blocking"); end initial #100 $finish;
Result
Simulator is doing circuit initialization process. 0 0 0 enter nonblocking 0 0 0 leave nonblocking 0 0 0 enter blocking *** Finished circuit initialization process. 0 a b y z 0 0 0 x x 10 1 0 enter nonblocking 10 1 0 leave nonblocking 10 1 0 x x 15 1 1 enter nonblocking 15 1 1 leave nonblocking 15 1 1 x x 20 1 1 leave blocking *** 20 1 1 0 0 30 1 1 1 0 35 1 1 2 0 Stopped at time : 100 ns : File "β¦/delay_tests.v" Line 56
Delayed Blocking assignment prevented multiple calls.
19. Inertial and Transport Delay
- Transport Delay maintains all transitions and delays them by a specified amount. Models a delay like an ideal transmission line.
- Transport delay does not model pulse rejection described below.
- Inertial Delay also delays transitions, but it only maintains transitions to new states that are held for as long as the specified delay. Approximates models charging and pulse rejection.
- Inertial Delay Pulse Rejection: pulses of a duration less than the specified inertial delay are rejected.
20. Inertial Delay Using Continuous Assignment (wire and SystemVerilog reg/logic)
The following are all examples of inertial delay on a wire.
- delay in the continuous assignment
Verilog/SystemVerilog
wire x_n; assign #5 x_n = ~n;
wire #5 x_n; assign x_n = ~n;
wire #5 x_n = ~n;
SystemVerilog
logic x_n; assign #5 x_n = ~n;
delay in the wire declaration
wire #5 x; assign x = ~x;
delay in the declaration of a wire with implicit assignment
wire #5 x_n = ~n;
β οΈ invalid
logic #5 x_n = ~n;
reg #5 x_n = ~n;
- Additive inertial delay: delay in declaration is added to any in the assignment
in this example, the inertial delay to `a` is from `x` is 3:
wire #2 a; assign #1 a = x;
in this example, the inertial delay to `a` is `4` and for `b` is `3`:
wire #3 a; wire #2 b; assign #1 {a,b} = {x,x};
21. Primitive Delay is Inertial Delay
Inertial delay may be provide to primitives using the simplist form of the delay operator.
wire y; and #3 I1(y,a,b);
In this next example, the inertial delay to y is 4 since delay provide in the declaration is added.
wire #1 y; and #3 I1(y,a,b);
22. Pulse Rejection is Based on the Result/Output (not input pulse-width)
The pulse rejection behavior is based on the result, not the inputs. The result of an expression to be assigned must maintain a new value for the specified time.
wire y; assign #2 y = a&b;
wire y; and #2 I1(y,a,b);
wire y; assign #3 y = |{a,b,c};
wire y; or #3 I1(y,a,b,c);
23. Rising and Falling Delay Can Be Different
wire y; and #(3,2) I1(y,a,b); //#(rising delay,falling delay)
Transitions | Edge Type |
---|---|
0 β 1, Xβ1 Zβ1 | Rising Edge |
1 β 0, Xβ0, Zβ0 | Falling Edge |
Other output edges (e.g.Β XβZ , 1βZ ) assume the minimum value between the of the rising and falling delays (2 in the example above)
Good Reference:http://verilog.renerta.com/source/vrg00011.htm
Min:Typical:Max
You can also specify Min:Typ:Max delays which are selected by the simulator:
assign #(1:2:3) y = a & b; assign #(2:3:4,1:2:3) y = a & b;
Good Reference: http://verilog.renerta.com/source/vrg00025.htm
24. Inertial Delay for "reg"
For a reg
, to model inertial delay it is recommend to create a delayed wire copy. Direct modeling of inertial delay is difficult otherwise.
Augmenting reg with Inertial Delay:
wire c; reg c_nodelay assign #5 c = c_nodelay; always @(b,d) c_nodelay = ~b|d; end
25. Modeling of Delay for Sequential Logic
- Study these examples one-by-one as practice to understand Verilog; and reference when trying to model delay (no need to memorize)
- Note that
always_ff
oralways_comb
are not used since this a modeling exercise and not for synthesis
parameter TC2Q; reg q; always @(posedge clk) q <= #TC2Q ~b;
- Evaluate now, assign later
- Models Clk-to-Q delay
β
parameter TC2Q; reg q; always @(posedge clk) q = #TC2Q ~b;
- Evaluate now, assign later
- Bad: Nondeterminism of assignment at later time
β (delay the clock)
parameter TC2Q; reg q; always @(posedge clk) #TC2Q q <= ~b;
- Evaluate after delay then assign
- Models a delay in the clock signal. Not recommended, better to create and use a delayed clock using other delay methods
β
parameter TC2Q; reg q; always @(posedge clk) #TC2Q q = ~b;
- Evaluate after delay then assign
- Bad: Nondeterminism of assignment at later time
26. Modeling of Transport Delay
- transmission lines
- transport delay models transmission line delay, for which the digital signal at a far destination is a delayed copy of the source end signal
- combinational logic blocks
- inertial delay captures the idea that the "switches" of digital logic must be held in a state for some time to affect the capacitors involve
- useful for modeling switches driving capacitors
- transport delay models a slowed propagation of change through a cascade of gates
- does not represent that an input must be held, only that there is a delay between a change in an input and a resulting in an output
- inertial delay captures the idea that the "switches" of digital logic must be held in a state for some time to affect the capacitors involve
inertial delay | transport delay |
---|---|
- modeling a gate driving a capacitor load at the output of a circuit | - modeling delays through several combinational logic gates, e.g. combinatorial path delay |
βοΈ Trasport Delay for combinational logic
parameter D; reg y; always @(a,b) y <= #D a&b;
always @(y) y_delayed <= #D y;
- Evaluate now, assign later
- Can be use to model transport delay for combinatorial logic or a delayed signal such a from a transmission line
- Note that non-blocking assignment is required to to prevent blocking of re-evaluation
parameter D; reg y; always @(a,b) y = #D a&b;
- Evaluate now, assign later
- Bad: Blocks reevaluation (ignores input update events)
parameter D; reg y; always @(a,b) #D y <= a&b;
- Evaluate later and assign
- Bad: Blocks reevaluation
parameter D; reg y; always @(a,b) #D y = a&b;
- Evaluate later and assign
- Bad: Blocks reevaluation
27. Simulation Use of RHS non-blocking assignment delay
- RHS non-blocking delays may be conveniently used in testbenches to schedule several delayed assignments (not something I use)
Example 1:
initial begin a <= 0; a <= #10 255; a <= #20 22; a <= #30 10; b <= 'bx; b <= #1 1193; b <= #10 122; c <= #10 92; c <= #15 93; end
Example 2: delays relative to rst signal change
initial begin a = 0; b = 0; c = 0; wait (rst==0); a <= #10 255; a <= #20 22; a <= #30 10; b <= #1 1193; b <= #10 122; c <= #10 92; c <= #15 93; end
28. Procedural Timing Controls
- Delay control: delay between encountering the expression and when it executes.
- Introduced by simple
#
- Introduced by simple
Event control: delay until event
- Explicit Events are named events that allow triggering from other procedures
- A named event may be declared using the keyword
event
- The event control operator @ can be used to hold procedural code execution operator
->
triggers the event
- A named event may be declared using the keyword
- Implicit events are responses to changes in variables
- The event control operator @ can be provided a sensitivity list with variables and on optional event selectivity using keywords
posedge
andnegedge
- The event control operator @ can be provided a sensitivity list with variables and on optional event selectivity using keywords
event triggerName;
@(triggerName);
-> triggerName;
- Explicit Events are named events that allow triggering from other procedures
29. Event Control Operator
- The event control operator may be provided with variables
multiple variables using comma separation. (older syntax is to use or)
@(a,b,c)
π Old Syntax
@(a or b or c)
Edge selective:
negedge
andposedge
restrict sensitivity to the following transitions@(posedge clk or negedge en)
- Negedge Bit Transitions:
- 1β 0
- 1β x or z
- x or z β 0
- Posedge Bit Transitions:
- 0 β 1
- x or z β1
- 0 β x or z
- Multibit: When posedge and negedge modify a multi-bit operand , only the lsb is used to detect the edge.
- Negedge Bit Transitions:
1010 -> 0001 posedge 1011 -> 1110 negedge
30. Level-sensitive event control using wait
- The wait statement suspends execution until a condition is true.
- It can be considered as a level-sensitive control since it doesn't wait for a transition edge.
Comparison of wait to posedge:
@(posedge clk)
even if clk is already true, wait for next rising edge
wait (clk);
if clk is already true, produce without delay
Example to change data on the falling clock edge that follows a variable exceeding the value 10:
wait(a>10); @ (negedge clk); data<=data+1;
31. Repeat Construct
Repeat keyword can be used to create repetition of statements or delay operations
Repeat "Loop"
repeat (3) begin count = count +1; $display ("Count" : count); end
Repeat timing control
Any timing control may be modified so as to be repeated/multiplied, by using the keyword repeat
Dynamic Repeat (simulation run-time variable)
repeat (count) @ (event expression) /*empty statement*/;
If count is positive, repeat the timing control that number of time. If count is equal or less than 0, skip
Cycle Delay
Wait fot 10 clk rising edges before proceeding execution:
repeat (10) @ (posedge clk); do_stuff
Delay an assignment by 5 clk edges
a <= repeat(5) @(posedge clk) data;
Delay Multiplicity
Delay an assignment by 5 inverter delays:
parameter INV_DELAY = 4.5; a <= repeat(5) #INV_DELAY data;
32. initial and always
The initial construct is used to denote code to be executed once at the beginning of the simulation.
The always construct causes code to run repeatedly in an infinite loop. It is only useful with a delay or control construct, otherwise will create a zero delay infinite loop that can block time progression in simulation
This would run infinitely and stall the simulation time:
always x=a&b;
This prints endlessly in the beginning of the simulation:
always begin $display(“hello %0t”); end
0 : hello 0 : hello 0 : hello 0 : hello 0 : hello ...
33. Sequential and Parallel Blocks
- Sequential procedural blocks are wrapped with begin...end
- Parallel procedural blocks are wrapped with fork...join
- Statement Delay control is relative to entering the block
- Control passes out of the block when the last statement, which may be delayed in time, is completed
- Here is a mix, waiting for two three events before performing assignment
a=b
:
begin x=y; fork @event ... ; @event ... ; @event ... ; join a = b; end
- Don't confuse the term sequential code to mean coding a procedural block for sequential hardware
- sequential code refers to control flow of code which defines its functional interpretation, but it can describe the functionality of combinatorial hardware and/or sequential hardware
- sequential hardware would refers to inferred hardware
34. Sim Using Test Bench
DUT:
module Nand_Latch_1 (q,qbar,preset,clear); output q, qbar; input preset,clear; nand #1 G1 (q,preset,bar); nand #1 G2 (qbar,clear,q); endmodule
Testbench:
module Nand_Latch_1_TB; // Design Unit Testbench reg preset, clear; wire q, qbar; Nand_Latch_1 M1 (q, qbar, preset, clear);// Instantiate DUT initial // Create DUTB response monitor begin $monitor ($time, "|preset = %b clear = %b q = %b 1 qbar = %b", preset, clear, q, qbar); end initial begin // Create DUTB stimulus generator #10 preset =0; clear =1; #10 preset =1; $stop; #10 clear =0; #10 clear =1; #10 preset =0; end initial begin #60 $finish ; end endmodule
Results:
xcelium> run 0|preset = x clear = x q = x 1 qbar = x 10|preset = 0 clear = 1 q = x 1 qbar = x 11|preset = 0 clear = 1 q = 1 1 qbar = x 12|preset = 0 clear = 1 q = 1 1 qbar = 0 Simulation stopped via $stop(1) at time 20 NS + 0 ./test_nand_tb.sv:25 #10 preset =1; $stop; xcelium> run 20|preset = 1 clear = 1 q = 1 1 qbar = 0 21|preset = 1 clear = 1 q = x 1 qbar = 0 22|preset = 1 clear = 1 q = x 1 qbar = x 30|preset = 1 clear = 0 q = x 1 qbar = x 31|preset = 1 clear = 0 q = x 1 qbar = 1 40|preset = 1 clear = 1 q = x 1 qbar = 1 41|preset = 1 clear = 1 q = x 1 qbar = x 50|preset = 0 clear = 1 q = x 1 qbar = x 51|preset = 0 clear = 1 q = 1 1 qbar = x 52|preset = 0 clear = 1 q = 1 1 qbar = 0 Simulation complete via $finish(1) at time 60 NS + 0 ./test_nand_tb.sv:31 #60 $finish ; // Stop watch
35. Time Unit and Resolution Directive
clocks can be set to realistic frequencies for timing simulation
parameter PERIOD=4; initial clock = 1’b0; always #(PERIOD/2) clock = ~clock;
unit and precision for the time quantity is defined by a derective at the top of a Verilog file
`timescale unit/resolution
- time unit: what unit the delays should be interpreted as
- precision: what the precision is used for each timing event
Examples:
example :
`timescale 1ns/1ps
Then `#17.0402` represents 17.040 ns
example
`timescale 1.0ns/100ps ... #(10/3.0) clock = 1'b1;
10/3.0 = 3.33…ns = 3333.3333….ps, but delay in simulation is rounded to 3300 ps because resolution is 100ps
errors can accumulate over time:
`timescale 1.0ns/100ps ... #(10/3.0) clock = 1'b1; #(10/3.0) clock = 1'b0; #(10/3.0) clock = 1'b1;
36. Generating a clock in a testbench
50% duty cycle:
initial begin clk = 0; end always begin #5 clk = 0; #5 clk = 1; end
initial begin clk = 0; end always begin #5 clk = ~clk; end
The procedural construct forever can be used the create an infinite loop:
initial begin clk = 0; forever begin #5 clk = ~clk; end end
37. Generating an irregular clock in a testbench
initial begin clk = 0; forever begin repeat (16) begin #5 clk = ~clk; end #20; end end
The procedural construct repeat can be used to create a limited loop
38. Testing all combinatorial inputs using a counter
Here, the first input, a
, is changed every 5 time units, cycling every 10
Each subsequent input at half the rate of the previous
reg a,b,c,d; initial begin a <= 0; b <= 0; c <= 0; d <= 0; end always begin #5 a <= ~a; end always begin #10 b <= ~b; end always begin #20 c <= ~c; end always begin #40 d <= ~d; end
The same can be achieved using a counter:
wire a,b,c,d; reg [3:0] count; initial begin count = 0; end assign {a,b,c,d}=count; always begin #5 count = count+1; end
39. Application of Stimulus in Testbench
- recommended: non-blocking updates to drive primary inputs of a DUT
- assumes DUT is a synchronous circuit
emulates FFs driving inputs, providing deterministic simulation
always @(posedge clk) begin a <= seqA; b <= seqB; c <= seqC; end
- test bench that applies stimuli to design's primary inputs
β
always @(posedge clk) begin a = pattern_memory[i][0]; // non-determinism b = pattern_memory[i][1]; // non-determinism c = pattern_memory[i][2]; // non-determinism i=i+1; end
βοΈ
always @(posedge clk) begin a <= pattern_memory[i][0]; // good b <= pattern_memory[i][1]; // good c <= pattern_memory[i][2]; // good i=i+1; end
- test bench that applies stimuli to design's primary inputs
- Input Driver Stage Modeling in Testbench using non-blocking assignments to primary inputs :
DUT with primary inputs a,b,c:
example testbench
- inline driver
module tb ; ... logic [7:0] a,b,c,clk,u,v,v_q,w_q; ... my_module dut(.*); ... initial begin a='0; b='0; c='0; end always @ (posdge clk) begin : driver //DRIVER automatic logic [7:0] gen_a, gen_b, gen_c; //automatic implies no memory between invocations of block gen_a = a + 1; gen_b = gen_a + 1; gen_c = gen_b + 1; a<=gen_a; b<=gen_b; c<=gen_c; end ... ...
to freestyle input generation, use more timing controls based on clock
module DUT(w_q, v_q,a,b,c,clk,u,v); input logic [7:0] a,b,c; output logic [7:0] v_q,w_q; input logic clk; output logic [7:0] u,v; always_comb begin u=a|b; v=u|c; end always_ff @ (posedge clk) begin v_q<=v; w_q<=v_q; end endmodule // DUT module tb; logic [7:0] w_q, v_q,a,b,c,u,v; logic clk; DUT dut(.*); initial begin #0 $display("%5s ","time","%3s %3s %3s %3s %3s %3s %3s ","a","b","c","u","v","v_q","w_q"); /**/ $monitor("%5t ",$time,"%3d %3d %3d %3d %3d %3d %3d " , a, b, c, u, v , v_q, w_q); end initial begin: CLK clk = 0; #5; forever #5 clk = ~ clk; end initial begin a='0; b='0; c='0; @ (posedge clk); a<=2; b<=3; c<=4; repeat (2) @ (posedge clk); //2-cycle stall @ (posedge clk); $display("%5t-",$time,"%60s","d:(set a,b,c to 0):"); //consistently before monitor a<=0; //set with rising edge concluding cycle in which w_q==7 b<=0; c<=0; repeat (10) @ (posedge clk); //$display("%5t-",$time,"%60s","d:(set a,b,c to 255):"); a<=255; b<=255; c<=255; repeat (10) @ (posedge clk); $finish; end // initial begin endmodule
xcelium> run time a b c u v v_q w_q 0 0 0 0 0 0 x x 10 2 3 4 3 7 0 x 20 2 3 4 3 7 7 0 30 2 3 4 3 7 7 7 40- d:(set a,b,c to 0): 40 0 0 0 0 0 7 7 50 0 0 0 0 0 0 7 60 0 0 0 0 0 0 0 140 255 255 255 255 255 0 0 150 255 255 255 255 255 255 0 160 255 255 255 255 255 255 255 Simulation complete via $finish(1) at time 240 NS + 0 ./test.sv:60 $finish;
Timing Simulation (sub-cycle timing)
- a timing simulation with circuit delays displays transitions with sub-cycle timing accuracy
Zero-Delay Simulation, a.k.a. functional/behavioral
- Sometimes called a behavioral / functional simulation since it is checking the digital functionality on a cycle-accurate basis.
40. Use $display
for debugging procedural code
$display
statements are best used for observing sequential procedural code blocks, which have multiple statements processes for one instant of time
always_comb begin // (dep. on a,b,c) automatic logic [7:0] _u; //for RTL code use automatic for internal combinatorial variables // (akin to VHDL variable) $display("a(0)=",a); $display("b(0)=",b); _u = a * 2; //u is twice a $display("u(0)=",u); _u = _u>b ? b:_u; //u is limited/clipped to threshold b $display("u(1)=",_u); v = _u + c; //v is min(a*2,b) + c $display("v(0)=",v); end
41. $final
(System Verilog )
- complementary to
initial
like initial procedures, but instead are called at the end of a simulation instead of at the begining keyword use:
final begin $display("Simulation Ended"); end
42. Differentiate "Use of Loops for Simulation Testbenches" vs "Loops in RTL for Synthesis"
- In the previous slides you were taught
for
,forever
andrepeat
in the context of simulation behavioral code for a testbench - going forward you are expected to know such use
- However you should NOT yet start using loops for synthesis.
- Rules for using loops in synthesis will be taught in a later lecture