Module 4 VHDL
Module 4 VHDL
•Module 4
• Verilog provides designers the ability to describe design
functionality in an algorithmic manner.
• All other behavioral statements can appear only inside these structured
procedure statements.
Blocking Assignments
• The statement count = count + 1 is executed last. The simulation times at which the
statements are executed are as follows:
All statements x = 0 through reg_b = reg_a are executed at time 0
Statement reg_a[2] = 0 at time = 15
Statement reg_b[15:13] = {x, y, z} at time = 25
Statement count = count + 1 at time = 25
Since there is a delay of 15 and 10 in the preceding statements, count = count + 1 will be
executed at time = 25 units
• Note that for procedural assignments to registers, if the right-hand side has more bits
than the register variable, the right-hand side is truncated to match the width of the
register variable. The least significant bits are selected and the most significant bits
are discarded. If the right-hand side has fewer bits, zeros are filled in the most
significant bits of the register variable.
Nonblocking Assignments
• Nonblocking assignments allow scheduling of assignments
without blocking execution of the statements that follow in a
sequential block.
• reg_b[15:13] = {x, y, z} is scheduled to execute after 10 time units (i.e., time = 10)
• nonblocking assignment statements are executed last in the time step in which they are
scheduled, that is, after all the blocking assignments in that time step are executed.
• it is recommended that blocking and nonblocking assignments not be mixed in the same
always block.
Application of nonblocking
assignments
• They are used as a method to model several concurrent data
transfers that take place after a common event.
• At each positive edge of clock, the following sequence takes place for the nonblocking
assignments.
• A read operation is performed on each right-hand-side variable, in1, in2, in3, and reg1, at
the positive edge of clock. The right-hand-side expressions are evaluated, and the results
are stored internally in the simulator.
• The write operations to the left-hand-side variables are scheduled to be executed at the
time specified by the intra-assignment delay in each assignment, that is, schedule "write"
to reg1 after 1 time unit, to reg2 at the next negative edge of clock, and to reg3 after 1
time unit.
• The write operations are executed at the scheduled time steps. The order in which the
write operations are executed is not important because the internally stored right-hand-
side expression values are used to assign to the left-hand-side values. For example, note
that reg3 is assigned the old value of reg1 that was stored after the read operation, even if
the write operation wrote a new value to reg1 before the write operation to reg3 was
executed.
• Thus, the final values of reg1, reg2, and reg3 are not dependent on the order in which the
assignments are processed.
• In Illustration 1, there is a race condition when blocking statements are used.
• Instead, both registers will get the same value (previous value of a or b), based on
the Verilog simulator implementation.
• At the positive edge of clock, the values of all right-hand-side variables are "read,"
and the right-hand-side expressions are evaluated and stored in temporary variables.
• During the write operation, the values stored in the temporary variables are
assigned to the left-handside variables. Separating the read and write operations
ensures that the values of registers a and b are swapped correctly, regardless of the
order in which the write operations are performed.
Implementing Nonblocking Assignments using Blocking
Assignments
• For digital design, use of nonblocking assignments in place of blocking
assignments is highly recommended in places where concurrent data
transfers take place after a common event.
• If there are multiple zero delay statements, the order between them is
nondeterministic.
• In Example, four statements x = 0, y = 0, x = 1, y = 1 are to be executed at simulation
time 0.
• However, since x = 1 and y = 1 have #0, they will be executed last. Thus, at the end of
time 0, x will have value 1 and y will have value 1.
• The order in which x = 1 and y = 1 are executed is not deterministic.
• using #0 is not a recommended practice.
Event-Based Timing Control
• An event is the change in the value on a register or a net.
event OR control
• These conditions are used to decide whether or not a statement should be executed.
• The nested if-else-if can become unwieldy if there are too many
alternatives. A shortcut to achieve the same result is to use the case
statement.
• Each of statement1, statement2 , default_statement can be a single
statement or a block of multiple statements.
• casex treats all x and z values in the case item or the case expression
as don't cares.
• An initial condition
• The initialization condition and the incrementing procedural assignment are included
in the for loop and do not need to be specified separately. Thus, the for loop provides a
more compact loop structure than the while loop.
• the while loop is more general-purpose than the for loop. The for loop cannot be used
in place of the while loop in all situations.
• for loops are generally used when there is a fixed beginning and end to the loop. If the
loop is simply looping on a certain condition, it is better to use the while loop.
Repeat Loop
• The keyword repeat is used for this loop.
• The loop does not contain any expression and executes forever until the
$finish task is encountered.
• If timing control constructs are not used, the Verilog simulator would execute
this statement infinitely without advancing simulation time and the rest of the
design would never be executed.
Sequential and Parallel Blocks
• Block statements are used to group multiple statements to act
together as one.
• If delay or event control is specified, it is relative to the time the block was entered.
• All statements in a parallel block start at the time when the block was entered. Thus, the
order in which the statements are written in the block is not important.
• The keyword fork can be viewed as splitting a single flow into independent flows. The
keyword join can be seen as joining the independent flows back into a single flow.
Independent flows operate concurrently.
Special Features of Blocks
• three special features available with block statements: nested blocks,
named blocks, and disabling of named blocks.
Nested blocks
• All generate instantiations are coded with a module scope and require the
keywords generate - endgenerate.
• Generated instantiations can be one or more of the following
types:
• Modules
• Continuous assignments
• net, reg
• event .
• Generated data types have unique identifier names and can be referenced
hierarchically.
• Parameter redefinition using ordered or named assignment or a
defparam statement can be declared with the generate scope.
• Generate loop
• Generate conditional
• Generate case
Generate Loop
• A generate loop permits one or more of the following to be
instantiated multiple times using a for loop:
• Variable declarations
• Modules
• Continuous assignments
• Prior to the beginning of the simulation, the simulator elaborates (unrolls) the code in the
generate blocks to create a flat representation without the generate blocks. The unrolled code is
then simulated. Thus, generate blocks are simply a convenient way of replacing multiple
repetitive Verilog statements with a single statement inside a loop.
• genvar is a keyword used to declare variables that are used only in the evaluation of generate
block. Genvars do not exist during simulation of the design.
• Generate loops can be nested. However, two generate loops using the same genvar as an index
variable cannot be nested.
• The name xor_loop assigned to the generate loop is used for hierarchical name referencing of
the variables inside the generate loop. Therefore, the relative hierarchical names of the xor gates
will be xor_loop[0].g1, xor_loop[1].g1, ......., xor_loop[31].g1.
• Generate loops are fairly flexible. Various Verilog constructs can be used inside the generate
loops.
Generate Conditional
• A generate conditional is like an if-else-if generate construct that
permits the following Verilog constructs to be conditionally
instantiated into another module based on an expression that is
deterministic at the time the design is elaborated:
• Modules
• Continuous assignments
• Modules
• Continuous assignments
Consider a controller for traffic at the intersection of a main highway and a country
road.
• The traffic signal for the main highway gets highest priority because cars are continuously
present on the main highway. Thus, the main highway signal remains green by default.
• Occasionally, cars from the country road arrive at the traffic signal. The traffic signal for the
country road must turn green only long enough to let the cars on the country road go.
• As soon as there are no cars on the country road, the country road traffic signal turns yellow
and then red and the traffic signal on the main highway turns green again.
• There is a sensor to detect cars waiting on the country road. The sensor sends a signal X as
input to the controller. X = 1 if there are cars on the country road; otherwise, X= 0.
• There are delays on transitions from S1 to S2, from S2 to S3, and from S4 to S0.
• Tasks are used for common Verilog code that contains delays, timing, event
constructs, or multiple output arguments.
• Functions are used when common Verilog code is purely combinational, executes in
zero simulation time, and provides exactly one output.
• Functions are typically used for conversions and commonly used calculations.
• Tasks can have input, output, and inout arguments; functions can have input
arguments. In addition, they can have local variables, registers, time variables,
integers, real, or events.
• Tasks and functions do not contain always or initial statements but are called from
always blocks, initial blocks, or other tasks and functions.
Tasks
• Tasks are declared with the keywords task and endtask. Tasks must be used if any one of the following
conditions is true for the procedure:
• Output and inout argument values are passed back to the variables in the task
invocation statement when the task is completed.
• Although the keywords input, inout, and output used for I/O arguments in a task are
the same as the keywords used to declare ports in modules, there is a difference.
• I/O arguments in a task are used to pass values to and from the task.
Consider a task called bitwise_oper, which computes the bitwise and, bitwise
or, and bitwise ex-or of two 16-bit numbers. The two 16-bit numbers a and b
are inputs and the three outputs are 16bit numbers ab_and, ab_or, ab_xor. A
parameter delay is also used in the task.
• In the above task, the input values passed to the task are A and B.
• Hence, when the task is entered, a = A and b = B. The three output values are
computed after a delay.
• This delay is specified by the parameter delay, which is 10 units for this example.
• When the task is completed, the output values are passed back to the calling output
arguments.
• Therefore, AB_AND = ab_and, AB_OR = ab_or, and AB_XOR = ab_xor when the
task is completed.
Asymmetric Sequence
Generator
• All declared items are statically allocated and they are shared across all uses of the task executing
concurrently.
• Therefore, if a task is called concurrently from two places in the code, these task calls will operate
on the same task variables.
• To avoid this problem, a keyword automatic is added in front of the task keyword to make the tasks
re-entrant. Such tasks are called automatic tasks.
• All items declared inside automatic tasks are allocated dynamically for each invocation.
• Each task call operates in an independent space. Thus, the task calls operate on independent copies
of the task variables.
• This results in correct operation. It is recommended that automatic tasks be used if there is a chance
that a task might be called concurrently from two locations in the code.
Functions
• Functions are declared with the keywords function and endfunction.
• Functions are used if all of the following conditions are true for the
procedure:
• The output of a function is passed back by setting the value of the register
function_identifer appropriately.
• At the end of function execution, the return value is placed where the function was
invoked.
• The optional range_or_type specifies the width of the internal register. If no range or
type is specified, the default bit width is 1.
• Notice that at least one input argument must be defined for a function.
• There are no output arguments for functions because the implicit register
function_identifer contains the output value.
• Also, functions cannot invoke other tasks. They can invoke only other functions.
Function Examples-Parity calculation
• Let us discuss a function that calculates the parity of a 32-bit address and returns the value. We assume even parity.
• Note that in the first invocation of calc_parity, the returned value was used to set the reg parity. In the second invocation, the
value returned was directly used inside the $display task. Thus, the returned value is placed wherever the function was invoked.
Automatic (Recursive)
Functions
• Functions are normally used non-recursively .
• If a function is called concurrently from two locations, the results are non-
deterministic because both calls operate on the same variable space.
• Automatic functions can be invoked through the use of their hierarchical name.
Constant Functions
• A constant function is a regular Verilog HDL function, but with certain restrictions.
• These functions can be used to reference complex values and can be used instead of constants.
• Example 8-11 shows how a constant function can be used to compute the width of the address bus in
a module.
Signed Functions
• Signed functions allow signed operations to be performed on the
function return values.