Week7 Module7
Week7 Module7
COURSE INTENDED On the completion of the course, student is expected to be able to do the
LEARNING OUTCOMES: following:
II. OBJECTIVES: By the end of this module you should be able to:
III. INTRODUCTION:
The purpose of this module is to understand the reasons behind the
guidelines, one needs to have a full understanding of the functionality and
scheduling of Verilog blocking and nonblocking assignments.
IV. CONTENTS:
Lesson Coverage:
INTRODUCTION
Guideline: Use blocking assignments in always blocks that are written to generate combinational logic.
Guideline: Use nonblocking assignments in always blocks that are written to generate sequential logic.
A Verilog race condition occurs when two or more statements that are scheduled to execute in the same simulation
time-step, would give different results when the order of statement execution is changed, as permitted by the
IEEE Verilog Standard. To avoid race conditions, it is important to understand the scheduling of Verilog blocking
and nonblocking assignments.
Blocking assignments
The blocking assignment operator is an equal sign ("="). A blocking assignment gets its name because a blocking
assignment must evaluate the RHS arguments and complete the assignment without interruption from any other
Verilog statement. The assignment is said to "block" other assignments until the current assignment has
completed. The one exception is a blocking assignment with timing delays on the RHS of the blocking operator,
which is considered to be a poor coding style.
1. Evaluate the RHS (right-hand side equation) and update the LHS (left-hand side expression)
of the blocking assignment without interruption from any other Verilog statement.
A blocking assignment "blocks" trailing assignments in the same always block from occurring until after the
current assignment has been completed.
A problem with blocking assignments occurs when the RHS variable of one assignment in one procedural block
is also the LHS variable of another assignment in another procedural block and both equations are scheduled to
execute in the same simulation time step, such as on the same clock edge. If blocking assignments are not properly
ordered, a race condition can occur. When blocking assignments are scheduled to execute in the same time step,
the order execution is unknown.
According to the IEEE Verilog Standard, the two always blocks can be scheduled in any order. If the first always
block executes first after a reset, both y1 and y2 will take on the value of 1. If the second always block executes
first after a reset, both y1 and y2 will take on the value 0. This clearly represents a Verilog race condition.
Nonblocking assignments
The nonblocking assignment operator is the same as the less-than-or-equal-to operator ("<="). A nonblocking
assignment gets its name because the assignment evaluates the RHS expression of a nonblocking statement at the
beginning of a time step and schedules the LHS update to take place at the end of the time step. Between
evaluation of the RHS expression and update of the LHS expression, other Verilog statements can be evaluated
and updated and the RHS expression of other Verilog nonblocking assignments can also be evaluated and LHS
updates scheduled.
The nonblocking assignment does not block other Verilog statements from being evaluated.
1. Evaluate the RHS of nonblocking statements at the beginning of the time step.
2. Update the LHS of nonblocking statements at the end of the time step.
Nonblocking assignments are only made to register data types and are therefore only permitted inside of
procedural blocks, such as initial blocks and always blocks. Nonblocking assignments are not permitted in
continuous assignments.
Again, according to the IEEE Verilog Standard, the two always blocks can be scheduled in any order. No matter
which always block starts first after a reset, both nonblocking RHS expressions will be evaluated at the beginning
of the time step and then both nonblocking LHS variables will be updated at the end of the same time step. From
a users perspective, the execution of these two nonblocking statements happen in parallel.
Before giving further explanation and examples of both blocking and nonblocking assignments, it would be useful
to outline eight guidelines that help to accurately simulate hardware, modeled using Verilog. Adherence to these
guidelines will also remove 90-100% of the Verilog race conditions encountered by most Verilog designers.
Guideline #3: When modeling combinational logic with an always block, use blocking assignments.
Guideline #4: When modeling both sequential and combinational logic within the same always block, use
nonblocking assignments.
Guideline #5: Do not mix blocking and nonblocking assignments in the same always block.
Guideline #6: Do not make assignments to the same variable from more than one always block.
Guideline #7: Use $strobe to display values that have been assigned using nonblocking assignments.
Designers new to Verilog are encouraged to memorize and use these guidelines until their underlying functionality
is fully understood.
In general, a Verilog always block cannot trigger itself. Consider the oscillator example in Example 3. This
oscillator uses blocking assignments. Blocking assignments evaluate their RHS expression and update their LHS
value without interruption.
The blocking assignment must complete before the @(clk) edge-trigger event can be scheduled. By the time the
trigger event has been scheduled, the blocking clk assignment has completed; therefore, there is no trigger
event from within the always block to trigger the @(clk) trigger.
In contrast, the oscillator in Example 4 uses nonblocking assignments. After the first @(clk) trigger, the RHS
expression of the nonblocking assignment is evaluated and the LHS value scheduled into the nonblocking assign
updates event queue.
Before the nonblocking assign updates event queue is "activated," the @(clk) trigger statement is encountered
and the always block again becomes sensitive to changes on the clk signal. When the nonblocking LHS value is
updated later in the same time step, the @(clk) is again triggered. The osc2 example is selftriggering (which is
not necessarily a recommended coding style).
Condition Statements
Condition statements are important since you have learned programming, it evaluates and gives primary solutions
as written by the developer.
The if - else statement controls the execution of other statements. In programming language like c, if - else controls
the flow of program. When more than one statement needs to be executed for an if condition, then we need to use
begin and end.
Syntax : if
if (condition)
statements;
Syntax : if-else
if (condition)
statements;
else
statements;
if (condition)
statements;
else if (condition)
statements;
................
................
else
statements;
if-else Statements
if statements allows the tool to decide a statement is to be executed or not, depending on the conditions specified.
General syntax is as follows:
if( condition )
statement;
If the condition or conditional expression is true, then statement will be executed, otherwise not.
if( hold == 0 )
counter = counter + 1;
else statement can be used with if optionally. If condition specified in if statement is false, statement after else
will be executed. See this example, if reset is nonzero counter will become zero, othewise it will be incremented.
if( reset )
counter = 0;
else
counter = counter + 1;
If there are more than one statements within an if block, we can combine them using begin -- end. We can also
nest if-else statements as in these examples.
if( reset )
begin
counter <= 0;
over_flow <= 0;
end
else if ( counter == 15 )
begin
counter <= 0;
over_flow <= 1;
end
else
begin
counter <= counter + 1;
over_flow <= 0;
end
if-else statements should be used inside initial or always blocks. Generally if-else statements generates
multiplexers while synthesizing.
Variable declaration
It is a fundamental rule of the Verilog HDL that any object that is assigned a value in an always statement must
be declared as a variable. Hence,
The term variable was introduced in the verilog-2001 standard. Previously, the term used was register. This was
confusing, because a Verilog variable (register) does not necessarily imply that a hardware register would be
synthesized, hence the change of terminology.
If statement
The if statement in Verilog is a sequential statement that conditionally executes other sequential statements,
depending upon the value of some condition. An if statement may optionally contain an else part, executed if the
condition is false.
Although the else part is optional, for the time being, we will code up if statements with a corresponding else
rather than simple if statements. In order to have more than one sequential statement executed in an if statement,
multiple statements are bracketed together using the begin..end keywords,
always @(sel or a or b)
begin
if (sel == 1)
begin
f = a;
g = ~a;
end
else
begin
f = b;
g = a & b;
end
end
reg f, g;
always @(sel or sel_2 or a or b)
if (sel == 1)
begin
f = a;
if (sel_2 == 1)
g = ~a;
else
g = ~b;
end
else
begin
f = b;
if (sel_2 == 1)
g = a & b;
else
g = a | b;
end
Notice that the code is beginning to look a little bit confusing! In the code above, begin..end blocks have only
been used where they must be used, that is, where we have multiple statements. It is probably a good idea to use
begin..end blocks throughout your Verilog code - you end up typing in a bit more Verilog but it's easier to read.
Also, if you have to add more functionality to an always block later on (more sequential statement), at least the
begin..end block is already in place. So,
h = a & b;
end
end
else
begin
if (sel_2 == 1)
begin
g = a & b;
h = ~(a & b);
end
else
begin
h = ~(a | b);
g = a | b;
end
f = b; // here's f!
end
end
Note that the order of assignments to f, g and h has been played around with
V. REFERENCES: Roth, C.H. Jr. And John, L. K. (2018). Digital Systems Design Using VHDL (3rd
ed.). Texas, USA: Cengage Unlimited