Verilog: Continuous & Procedural Assignments

Verilog: Continuous & Procedural Assignments

Continuous Assignment

Continuous assignment is used to drive a value on to a net in dataflow modeling. The net can be a vector or scalar, indexed part select, constant bit or part select of a vector. Concatenation is also supported with scalar vector types.

module Conti_Assignment (addr1,addr2,wr,din,valid1,valid2,dout); input [31:0] addr1,addr2; input [31:0] din; output [31:0] dout; input valid1,valid2,wr;

wire valid; wire [31:0] addr;

//Net (scalar) continuous assignment assign valid = valid1 | valid2;

//Vector continuous assignment assign addr[31:0] = addr1[31:0] ^ addr2[31:0];

//Part select & Concatenation in Continuous assignment assign dout[31:0] = (valid & wr) ? {din[31:2],2'b11} : 32'd0;

Regular & Implicit Assignment

Regular continuous assignment means, the declaration of a net and its continuous assignments are done in two different statements. But in implicit assignment, continuous assignment can be done on a net when it is declared itself. In the below example, `valid` is declared as wire during the assignment. If signal name is used to the left of the continuous assignment, an implicit net declaration will be inferred. In the below code `dout` is not declared as net, but it is inferred during assignment.

module Implicit_Conti_Assignment (addr1,addr2,wr,din,valid1,valid2,dout); input [31:0] addr1,addr2; input [31:0] din; output [31:0] dout; input valid1,valid2,wr;

//Net (scalar) Implict continuous assignment wire valid = (valid1 | valid2);

//Implicit net declaration -dout assign dout[31:0] = (valid & wr) ? {din[31:2],2'b11} : 32'd0;

Procedural Assignment

We have already seen that continuous assignment updates net, but procedural assignment update values of reg, real, integer or time variable. The constant part select, indexed part select and bit select are possible for vector reg.

There are two types of procedural assignments called blocking and non-blocking. Blocking assignment, as the name says, gets executed in the order statements are specified. The "=" is the symbol used for blocking assignment representation. Non-blocking assignment allows scheduling of assignments. It will not block the execution. The symbol "<=" is used for non-blocking assignment representation and mainly used for concurrent data transfers.

Following example shows the differences in the simulation result by using blocking and non-blocking assignments.

/* module Nonblocking_Assignment (addr1,addr2,wr,din,valid1,valid2,data,aout); input [31:0] addr1,addr2; input [31:0] din; output [31:0] data,aout; input valid1,valid2,wr;

reg [31:0] data,aout, addr; reg valid;

always @(addr1,addr2,wr,din,valid1,valid2) begin valid <= (valid1 | valid2); addr <= (addr1[31:0] | addr2[31:0]); data <= (valid & wr) ? {din[31:2],2'b11} : 32'd0; aout <= wr ? addr: {addr1[15:0],addr2[31:16]}; end initial $monitor($time,"NON-BLOCKING: Values valid1=%b, valid2=%b, wr=%b, addr1=%d, addr2=%d, data=%d, aout=%d", valid1,valid2,wr,addr1,addr2,data,aout); endmodule */ module Blocking_Assignment (addr1,addr2,wr,din,valid1,valid2,data,aout); input [31:0] addr1,addr2; input [31:0] din; output [31:0] data,aout; input valid1,valid2,wr;

always @(addr1,addr2,wr,din,valid1,valid2) begin valid = (valid1 | valid2); addr = (addr1[31:0] | addr2[31:0]); data = (valid & wr) ? {din[31:2],2'b11} : 32'd0; aout = wr ? addr : {addr1[15:0],addr2[31:16]}; $monitor($time,"BLOCKING: Values valid1=%b, valid2=%b, wr=%b, addr1=%d, addr2=%d, data=%d, aout=%d", valid1,valid2,wr,addr1,addr2,data,aout); end endmodule

module test; reg valid1,valid2,wr; reg [31:0] addr1,addr2,din; wire [31:0] data,aout;

Blocking_Assignment Block_Assign(addr1,addr2,wr,din,valid1,valid2,data,aout);

//Nonblocking_Assignment Nonblock_Assign(addr1,addr2,wr,din,valid1,valid2,data,aout);

initial begin valid1 = 0; valid2 = 0; addr1 = 32'd12; addr2 = 32'd36; din = 32'd198; wr = 1;

#5 valid1 = 1; #10 valid1 = 0; valid2 = 1; #10 addr1 = 32'd0; addr2 = 32'd0; #5 wr = 0; #12 wr = 1;

/* ncsim> run 0NON-BLOCKING: Values valid1=0, valid2=0, wr=1, addr1= 12, addr2= 36, data= X, aout= x 5NON-BLOCKING: Values valid1=1, valid2=0, wr=1, addr1= 12, addr2= 36, data= 0, aout= 44 15NON-BLOCKING: Values valid1=0, valid2=1, wr=1, addr1= 12, addr2= 36, data= 199, aout= 44 25NON-BLOCKING: Values valid1=0, valid2=1, wr=1, addr1= 0, addr2= 0, data= 199, aout= 44 30NON-BLOCKING: Values valid1=0, valid2=1, wr=0, addr1= 0, addr2= 0, data= 0, aout= 0 42NON-BLOCKING: Values valid1=0, valid2=1, wr=1, addr1= 0, addr2= 0, data= 199, aout= 0 ncsim: *W,RNQUIE: Simulation is complete. */

/* ncsim> run 0BLOCKING: Values valid1=0, valid2=0, wr=1, addr1= 12, addr2= 36, data= 0, aout= 44 5BLOCKING: Values valid1=1, valid2=0, wr=1, addr1= 12, addr2= 36, data= 199, aout= 44 15BLOCKING: Values valid1=0, valid2=1, wr=1, addr1= 12, addr2= 36, data= 199, aout= 44 25BLOCKING: Values valid1=0, valid2=1, wr=1, addr1= 0, addr2= 0, data= 199, aout= 0 30BLOCKING: Values valid1=0, valid2=1, wr=0, addr1= 0, addr2= 0, data= 0, aout= 0 42BLOCKING: Values valid1=0, valid2=1, wr=1, addr1= 0, addr2= 0, data= 199, aout= 0 ncsim: *W,RNQUIE: Simulation is complete. ncsim> exit */

  • The Verilog-AMS Language
  • Initial and Always Processes
  • Assignment Statements

Assignment Statements 

Blocking assignment .

A blocking assignment evaluates the expression on its right hand side and then immediately assigns the value to the variable on its left hand side:

It is also possible to add delay to a blocking assignment. For example:

In this case, the expression on the right hand side is evaluated and the value is held for 10 units of time. During this time, the execution of the code is blocked in the middle of the assignment statement. After the 10 units of time, the value is stored in the variable on the left

Nonblocking Assignment 

A nonblocking assignment evaluates the expression on its right hand side without immediately assigning the value to the variable on the left. Instead the value is cached and execution is allowed to continue onto the next statement without performing the assignment. The assignment is deferred until the next blocking statement is encountered. In the example below, on the positive edge of clk the right-hand side of the first nonblocking assignment is evaluated and the value cached without changing a. Then the right-hand side of the second nonblocking assignment statement is evaluated is also cached without changing b. Execution continues until it returns to the event statement, once there the execution of the process blocks until the next positive edge of the clk. Just before the process blocks, the cached values finally assigned to the target variables. In this way, the following code swaps the values in a and b on every positive edge of clk:

Adding delay to nonblocking assignments is done as follows:

Using nonblocking assignment with delay in this manner is a way of implementing transport delay , as shown below:

../../../_images/transport-delay.png

Blocking versus Nonblocking Assignment 

Nonblocking statements allow you to schedule assignments without blocking the procedural flow. You can use the nonblocking procedural statement whenever you want to make several register assignments within the same time step without regard to order or dependence upon each other. It means that nonblocking statements resemble actual hardware more than blocking assignments.

Generally you would use nonblocking assignment whenever assigning to variables that are shared between multiple initial or always processes if the statements that access the variable could execute at the same time. Doing so resolves race conditions.

Blocking assignment is used to assign to temporary variables when breaking up large calculations into multiple assignment statements. For example:

Procedural Continuous Assignment 

Two types of continuous assignment are available in initial and always processes: assign and force .

The target of an assign statement must be a register or a concatenation of registers. The value is continuously driven onto its target and that value takes priority over values assigned in procedural assignments. Once a value is assigned with an assign statement, it can only be changed with another assign statement or with a force statement. Execution of deassign releases the continuous assignment, meaning that the value of the register can once again be changed with procedural assignments. For example, the following implements a D-type flip-flop with set and reset:

Assign statements are used to implement set and reset because they dominate over the non-blocking assignment used to update q upon positive edges of the clock c . If instead a simple procedural assignment were used instead, then a positive edge on the clock could change q even if r or s were high.

A force statement is similar to assign , except that it can be applied to both registers and nets. It overrides all other assignments until the release statement is executed. Force is often used in testbenches to eliminate initial x-values in the DUT or to place it in a particular state. For example:

VLSI Master Logo

  • Procedural Assignment

Quick links

System verilog, data type, typedef methods, loop statement.

In our previous blog, we talked about the procedural assignment in Verilog. These are almost the same in System Verilog, so let’s discuss that in this blog.

Procedural assignments come in the form of procedural blocks like “always”, “initial,” “task,” and “function.”

To regulate when assignments are assessed and/or assigned, event controls, delay controls, if…else statements, case statements, looping statements, and so on can all be utilized.

Any expression that evaluates a value can be used as the RHS of the procedural assignment. However, keep in mind that the assignment’s LHS may limit what is a permitted expression on the RHS.

The LHS can be a solitary variable, an aggregate variable, a bit-select, a part-select, a packed array slice, or an unpacked array slice.

Procedural assignments are classified into the following categories:

Blocking assignment

Non-blocking assignment.

The operator ” =” is the most basic form of assignment. But in this blog, we will introduce you to other operators such as +=, =, e.t.c.

Throughout this blog, we’ve seen blocking assignments. As a result, we shall desist from further debate. Non-blocking is a new concept, and we must distinguish between the two. So we will shortly discuss the blocking assignment.

Blocking assignment statements are executed in sequential order. The execution of the following statement is halted until the current assignment operation is completed.

So let’s understand blocking assignments with an example.

Figure 1 shows the output of the above code of blocking assignment.

what is procedural assignment in verilog

Fig 1 Blocking assignment output

The non-blocking assignment permits assignment schedule without interfering with the flow of the procedure.

The non-blocking procedural assignment statement can be used when many variable assignments can be made within the same time step without regard for order or dependency on each other.

Non-blocking syntax is:

variable_name <= [delay_or_event_control] expression.

The non-blocking assignment operator is <=. The non-blocking assignment operator is the same as the relational operator less-than-or-equal-to.

However, non-blocking is determined by the context in which it appears.

Non-blocking execution may be divided into two steps: 1. At the start of the time step, evaluate the RHS of the non-blocking statement. 2. After the time step, evaluate the LHS of the non-blocking statement.

Consider the following example. We’ll compare blocking to non-blocking:

The above code will compare blocking and non-blocking assignments and their output is shown in figure 2.

what is procedural assignment in verilog

Fig 2: Blocking and Non-blocking example output

Let me explain this code for more explanation.

There are three “initial” blocks. The first is a blocking assignment: a = b; c = a; With this assignment, “b” is allocated to “a,” and the new value of “a” is assigned to “c.” As a result, the new value of “a” (from a = b) is given to “c” (c = a). Because a = 0 and b = 1, a = b results in a = 1, and c = a results in c = 1.

As a result, the following appears in the simulation log:

0 Blocking a=1 b=1 c=1

The non-blocking assignment, on the other hand, operates as follows: Consider two flops linked in series: d <= e; f  <= d; Because they are non-blocking, the two assignments run concurrently. The first assignment does not prevent the second task from being completed. The current value of “e” is assigned to “d,” and the current value (before the assignment d = e) of “d” is assigned to “f.”

With d = 0 and e = 1, the simulation log shows the following:

0 Non-blocking d=1 e=1 f=0

Consider the preceding non-blocking as the extended version: e = temp; f = d; d = temp;

When d = 0 and e = 1, the current value of “e” (= 1) is stored in the temp variable (temp = 1). The current “d” (= 0) value is then allocated to “f” (f = d). As a result, f = 0, and the value of “e” saved in “temp” is assigned to “d.” So, d = 1.

As a result, the simulation log displays the following:

10 Using temp d=1 e=1 f=0

It should be noted that this is the same outcome as a non-blocking assignment:

So, using a simple and effective example, we can quickly grasp the concept of blocking and non-blocking assignments.

As a result, we summarise the entire blog with a few questions.

  • What exactly do you mean when you say “procedural assignment”?
  • How many different kinds of procedural assignments are there?
  • What exactly is a blocking assignment?
  • How does a non-blocking assignment differ from a blocking statement?

Please Login or Register to comment on this post

guest

Only fill in if you are not human

Recent Blogs

vlsi master logo

  • Privacy Policy
  • @VLSI_Master
  • VLSI-Master

Copyright © 2021 All rights reserved

Procedural Assignments

Cite this chapter.

what is procedural assignment in verilog

Part of the book series: The International Series in Engineering and Computer Science ((SECS,volume 667))

642 Accesses

This is a preview of subscription content, log in via an institution to check access.

Access this chapter

  • Available as PDF
  • Read on any device
  • Instant download
  • Own it forever
  • Compact, lightweight edition
  • Dispatched in 3 to 5 business days
  • Free shipping worldwide - see info
  • Durable hardcover edition

Tax calculation will be finalised at checkout

Purchases are for personal use only

Institutional subscriptions

Unable to display preview.  Download preview PDF.

Rights and permissions

Reprints and permissions

Copyright information

© 2002 Kluwer Academic Publishers

About this chapter

(2002). Procedural Assignments. In: Verilog® Quicstart. The International Series in Engineering and Computer Science, vol 667. Springer, Boston, MA. https://doi.org/10.1007/0-306-47680-0_7

Download citation

DOI : https://doi.org/10.1007/0-306-47680-0_7

Publisher Name : Springer, Boston, MA

Print ISBN : 978-0-7923-7672-9

Online ISBN : 978-0-306-47680-8

eBook Packages : Springer Book Archive

Share this chapter

Anyone you share the following link with will be able to read this content:

Sorry, a shareable link is not currently available for this article.

Provided by the Springer Nature SharedIt content-sharing initiative

  • Publish with us

Policies and ethics

  • Find a journal
  • Track your research

Behavioral Modeling Style in Verilog

The behavioral modeling style is a higher abstraction in the entire saga of Verilog programming . By higher abstraction, what is meant is that the designer only needs to know the algorithm of the circuit to code it. Hence, this modeling style is also occasionally referred to as an algorithmic modeling style. The designer does not need to know the gate-level design of the circuit.

In this post, we will take an in-depth look at behavioral modeling. It’s various features, their syntax, statements, and examples. This is a one-stop explanation of behavioral modeling in Verilog .

What is Behavioral Modeling?

We read about the other abstraction layers earlier in this Verilog course . Behavioral modeling is the topmost abstraction layer. Under this style, we describe the behavior and the nature of the digital system.

There are several ways we can code for a behavioral model in Verilog. We generally use the truth table of the system to deduce the behavior of the circuit, as done in this article: Verilog code for full adder circuit .

Behavioral modeling contains procedural statements that control the simulation and manipulate the data types of the variables involved. There is a ‘procedure’ under which these statements are executed, and this procedure contains a ‘sensitivity list’ that controls the execution of the procedure.

Too many big words?

Before diving into the various types of procedural statements, let’s start with something fundamental. Let’s take a look at how to assign a value to a variable in the Verilog behavioral style.

Continuous assignment statements

These assignments change the output net variables once there is any change in the input signal. It allows the use of Boolean logic rather than gate connections. The left-hand side of an assignment is a variable to which the right-side value is to be assigned and must be a scalar or vector net or concatenation of both. The right-hand side of an assignment, separated from the left-hand side by the equal (=) character, can be a net , a reg , or any expression that evaluates a value including function calls.

Procedural assignment statements

Procedural assignments are employed for updating the memory variables. These assignments control the flow and keep updating the new data to the variables in the left-hand side expression on the activation of the sensitivity list . It represents a logical statement in hardware design. It just represents the boolean logic or the algebraic expression of the circuit. These appear only under the always block, which has been discussed in later sections.

There are two kinds of procedural assignment statements:

  • Blocking statements

Non-blocking statements

The concept of blocking vs. non-blocking signal assignments is a unique one to hardware description languages. The main reason to use either Blocking or Non-blocking assignments is to generate either combinational or sequential logic .

Blocking statements 

Blocking assignments are executed in the order they are coded. Hence, they are sequential. Since they block the execution of the next statement, until the current statement is executed, they are called blocking assignments. The assignment is made with the “=” symbol.

Non-blocking assignments are executed in parallel. Since the execution of the next statement is not blocked due to the execution of the current statement, they are called non-blocking statements. Assignments are made with the “<=” symbol.

<=      Non-blocking Assignment  –  Sequential logic =      Blocking Assignment  – Combinational logic

Let’s start with the primary construct of a behavioral model.

Structured procedural statement

The primary mechanism for modeling the behavior of design are the following statements:

  • Initial statement
  • Always statement

These statements execute concurrently with each other. The order of these statements doesn’t matter.  The execution of an initial or always statements give the program a new control flow. These get executed at time t = 0.

Initial Statement

This executes only once. It begins its execution at the start of the simulation at time t = 0.

  • The syntax for the initial statement is:

where a procedural_statement is one of the statements we are going to discuss in this post. The timing control will specify a delay time. A detailed explanation of timing control is discussed further.

  • Here is an example of the initial statement.

The initial statement executes at time 0, which causes the system variable to be assigned the value 2 after 12-time units.

Always Statement

In contrast to the initial statement, an always statement executes repeatedly, although the execution starts at time t=0.

  • The syntax for always statement is:
  • We may use the following example when we have to provide a clock clk signal to a system in Verilog.

This always statement produces a waveform with a period of 10-time units that only change upon the positive edge (thus the keyword posedge ) of the signal. The time unit is defined in the timescale directive compiler.

Procedural continuous statement

A procedural continuous assignment is a procedural statement, that is, it can appear inside an always statement block or an initial statement block.

Now, this assignment can override all other assignment statements to a net or a register.

Point to be noted here is, this is different from a continuous assignment; a continuous assignment occurs outside the initial or always block.

There are two kinds of procedural continuous assignments.

  • Assign – deassign: these assign to registers.
  • Force – release: these primarily assign to nets, although they can also be used for registers.

Assign – deassign

The keywords  assign  and  deassign can be used for registers or a concatenation of registers only. It can not be used for memories and bit- or part-select of a register.

  • The syntax is:

assign register_name = expression; deassign register_name;

  • Consider the example:

Force – release

The keywords  force  and  release  can be used for nets, registers, bit- or part select of a net (not register), or a concatenation.

force net_or_register_name = expression; release net_or_register_name;

  • Here’s an example; you’d notice that’s not much different from the procedural statement in the previous section.

Deassign  and  release  de-activate a procedural continuous assignment. The register value remains after the de-activation until a new value is assigned.

Block statement

A block statement enables a procedure to execute a group of two or more statements to act and execute syntactically like a single statement. There are two types of block statements. These are:

Sequential Block

Parallel block.

Statements inside this block are executed sequentially. You can add delay time in each of its statements.

That will be relative to the simulation time of the execution of the previous statement. Once the execution of the current sequential block is over, the statements or blocks followed just after the current block will get executed.

Now, this sequential block is demarcated by the keywords begin … end , which marks the beginning of the block, just like any high-level programming language (like the C programming language ).

  • The syntax for a sequential block is:
  • Here is an example of a waveform generation:

In the above example,  assume that the sequential block will execute for 10-time units. The first statement, thus, executes after 12-time units. The second statement after 17-time units and so on.

A parallel block has the delimiters fork … join (the sequential block has begin … end ). The statements in the parallel block are executed concurrently.

Stated another way, all the statements inside a block, need to be executed before the control passes out of the block.

  • The syntax for a parallel block is:
  • Let’s take an example to show how the delay time works in the parallel block.

Assume that the simulation time for the above example is 10-time units. Now the first statement will be executed after 10 + 19 = 29-time units, the second statement after 20-time units, and the last statement will take 30-time units. Therefore, after 30-time units, the execution control will be transferred out of the block.

Timing control

The timing control is usually associated with procedural statements. These are helpful in providing a delay to a particular statement and expression or can make up the sensitivity list Let’s say we are dealing with a design where the operation is sensitive to an event, say, a particular edge on the clock signal. In this case, the sensitivity list will consist of the timing control.

Two types of controls exist:

Delay control

Event control.

This is useful when we want some time gap or delay between the execution of one or more statements. It is basically a “wait for delay” before executing that statement in which delay has been provided.

  • The syntax for a delay control is:
  • Here is an example:

The initial statement starts its execution at 0 time. The value of clk gets assigned to 1 every 2 seconds.

The execution of the statements can be synchronized with the change in the event. This event is controlled by the governing signals. Now there are two types of event control:

  • Edge triggered event control
  • Level sensitive event control

The form of an edge trigger event control is:

as in the example:

The statement where the value of n variable is transferred to c output gets activated once there occurs a positive edge to the clock signal.

  • posedge is detected when the signal goes from 1 to unknown or from 0 to unknown
  • negedge  is detected when the signal goes from 0 to unknown or from 1 to unknown

The level-sensitive event control is basically a type of wait statement. It waits for a condition to become true and then it’ll carry forward it’s operation.

  • Here is the syntax:

wait ( condition ) procedural_statement;

The procedural statement will execute if the condition is evaluated out to be true, otherwise, it will wait for the condition to become true. If the condition is already true then the statement will be executed immediately.

  • Example of this:

In this instance, the statement sum=0 will execute once the value of s variable is greater than 22.

Conditional statement

The conditional statements are used to decide whether a statement will be executing or not by evaluating a certain condition.

if statement

Now the basic syntax for an if-statement is:

If the condition_1 is evaluated to be a true expression, then the further procedural statements are executed.

The example below shows that the sum variable has a value of less than 56 which justifies the execution of the statements followed in the begin … end block.

if-else statement

If condition_1 is true, procedural_statement_1 is executed, otherwise procedural_statement_2 is executed.

  • Consider the following example:

nested if-else-if

  • The syntax for nested if-else-if is:

If condition_1, and condition_2, are evaluated as a true expression, then, procedural_statement_1 and procedural_statement_2 will execute respectively and explicitly.  Otherwise, the third procedural statement procedural_statement_3 is executed. This syntax combines each category. You may either use a single if-else block or nest up according to your needs of the circuit. Here is the code for the full adder circuit in behavioral modeling using the if-else statement .

Case statement

The case statement is a multi-way deciding statement which first matches a number of possibilities and then transfers a single matched input to the output. This is most useful in decoding various operations inside a processor.

  • The syntax is a follows:

Visit this post to see how the case statement can be efficiently used in implementing a demultiplexer .

Don’t care in a Case statement

In the case statement described in the above section, the values x and z are interpreted literally. There are two other forms of case statements: casex and casez. The syntax is the same as that for a case statement. The only difference is in the keyword.

  • In casez statement, the value z appears in the case expression, and if any case_item is considered as a don’t care, that bit is discarded.
  • In casex statement, both the values for the x and z are considered as don’t cares.

There are four looping statements in Verilog:

  • repeat loop
  • forever loop

The syntax for a while loop is:

This loop will keep on iterating and executing till the condition is evaluated to be false (0 value). If the condition is an undefined or impedance value, then it is taken as a false statement, hence the loop and the statements under, will not be executed.

  • Here’s an example:

This loop statement is of the form:

A for loop statement repeats the execution of the procedural statements for a certain number of times till the condition is true. The initial_assignmen t statement specifies the initial value of the loop or the index variable. The condition  specifies the condition for which the loop will keep executing, and the step_assignment mostly directs the variable to be incremented or decremented.

  • For example:

Repeat loop

This loop, as the name suggests, repeats the execution of the procedural_statement a specified number of times.

  • The syntax for a repeat loop is:

In the example below, the loop_count is denoted by count, and the procedural_statement sum=sum+10 will be executed till the count.

Forever loop

This loop continuously executes the procedural_statement . Thus to get out of such kind of loop, a disable statement may be used with the procedural statement.

  • Here is an example of this form of the loop.

This was an in-depth glossing over of the main elements of the behavioral modeling style in Verilog. As always, if there are any doubts, let us know in the comments section. Make sure to apply these concepts in your programming practice routines. Check out the various examples in the sidebar for behavioral modeling for reference.

About the author

technobyte intern chanchal

Chanchal is a zestful undergrad pursuing her B.Tech in Electronics and Communication from the Maharaja Surajmal Institute of Technology, New Delhi. She has an extensive list of projects in Verilog and SystemVerilog. In addition to her prowess in Verilog coding, she has a flair in playing the keyboard too.

Related courses to Behavioral Modeling Style in Verilog

CMOS - IC Design Course

A free course as part of our VLSI track that teaches everything CMOS. Right from the physics of CMOS to designing of logic circuits using the CMOS inverter.

VHDL Course

A free and complete VHDL course for students. Learn everything from scratch including syntax, different modeling styles with examples of basic circuits.

Digital Electronics Course

A free course on digital electronics and digital logic design for engineers. Everything is taught from the basics in an easy to understand manner.

Please take a look at your example for the “nested if-else-if ” statement. If would seem that only the first condition need be met in order to carry out the first procedural statement. Condition 2 will never be evaluated if condition 1 is true since condition 2 is in the else statement for the first condition.

That’s correct! It is an if-else statement so if the first condition is met, the second condition would be pointless.

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed .

what is procedural assignment in verilog

VLSI Verify

Procedural Assignments

In the dataflow modeling, a continuous assignment statement is discussed where LHS expression is always updated for changes in RHS expression. Refer to c ontinuous assignment for more details. In the case of procedural assignment, the LHS variable remains unchanged until the same value is updated by the next procedural statement.

  • RHS expression can be a value or an expression that evaluates to a value.
  • LHS expression can be reg, integer, real, time-variable, or memory element.
  • The procedural assignments can be placed inside procedural blocks like initial and always blocks. They can also be placed inside tasks and functions. 
  • The procedural assignments can also be placed directly inside a module while declaring a variable. (Ex. reg [3:0] i_data = 4’h7)

There are two types of procedural assignments and both of them are widely used in the designs written in the Verilog language.

  • Blocking assignments
  • Non-blocking assignments

Blocking Assignments

The blocking assignment statements are executed sequentially by evaluating the RHS operand and finishes the assignment to LHS operand without any interruption from another Verilog statement. Hence, it blocks other assignments until the current assignment completes and is named as “blocking assignment”. 

An equal ‘=’ is used as a symbol for the blocking assignment operator.

A blocking assignment does not block the execution of a statement in another procedural block. For example, two initial blocks start execution at the same simulation time. A blocking assignment in the first initial block does not block execution in another initial block.

Race around condition: A problem with blocking assignment

If a variable is used in LHS of blocking assignment in one procedural block and the same variable is used in RHS of another blocking assignment in another procedural block. The race-around condition can occur as an order of execution is unknown if both statements are scheduled at the same simulation time.

In this example, 

Since procedural blocks (both initial and always) can be executed in any order.

A. If the first initial block executed before the second initial block then 

  • The value of y will be updated as 4‘h5 in the first initial block
  • The value of data will be updated as 4‘h5 in the second initial block

B. If the second initial block executed before the first initial block then 

  • The value of data will be updated as 4‘h3 in the second initial block
  • The value of y will be updated as 4‘h3 in the first initial block

Verilog Tutorials

  • Verilog Procedural Blocks

07 Sep 2021

Verilog is a concurrent programming language, which means that different blocks of the Verilog program run in parallel. The main reason for the concurrent nature is the fact that in hardware each block of the module will operate individually in parallel once it is powered on. The greater number of hardware block means more operation will happen in parallel and thus more processing power. Also, the hardware once turned no will go on operating until it is powered off. Thus, to model the hardware in Verilog, the Verilog program also runs indefinitely until the simulation is terminated. To achieve all these behaviours, Verilog provides with procedural blocks. Let’s look into the different procedural blocks.

Initial Block

This procedural block is executed only once when the Verilog simulation begins, i.e., at time step 0. As said earlier, hardware will go on operating unless the power is switched off, thus this procedural block cannot be realised into actual hardware, i.e., it is not synthesizable. This block is mainly used in test bench or to do some house keeping activities which would not directly influence the design.

initial keyword is used to declare an initial procedural block. If the block consists of more than one statement, the statements are enclosed within begin end statement. If more than one initial block is declared in a module, all the blocks will run concurrently, i.e., will run parallelly and all will start at the same time at 0-time step.

In the below example, 3 initial blocks are declared. From the output we can see that all the blocks are running parallelly. In time step 0, all the blocks start executing, thus at 0-time step, the value of a = 5 as defined in block_1 . Then after 5-time steps, the value of a is changed by block_2 and it becomes 9. Again, at t = 9, the value of a is changed by block_1 . Also, when simulation started the monitor statement in block_3 also executed. $monitor prints the statement, whenever the value of the variable or net changes. Thus, writing it once prints the value of a 3 times. $monitor will be discussed in more details in later articles.

In below code, note that each block is assigned some name using : . This is called name blocks, and all the blocks can be assigned name if needed. This can be beneficial in some cases as it lets us disable the blocks.

Always Block

This procedural block will execute at each time step or at some events like clock edge, change in some variable, net, etc. As this block goes on executing until the simulation is stopped, this can be realized in real hardware, i.e., they are synthesizable. This block generally represents a sequential circuit as sequential circuits also operate on some event like clock edge, etc.

always keyword is used to define an always procedural block. This is also followed by a begin and end statement if more than 1 statement are present in always block. To trigger the execution of always block on some event we use @() and inside parenthesis we write the name of variable or net upon which execution will depend. This can be a single identifier or a list of identifiers, also known as sensitivity list .

In the following example, we can see that the always block goes on executing until the simulation is stopped using $finish function. Initial block is used in the code to initialize the variables with some initial value. Always block cannot be used to initialize initial values as always block will always execute the initialization and thus every time the initial value will be loaded. Play with the code in the EDA Playground and try running the code without the initial block.

In real hardware, initial block cannot exist and thus in that scenario, reset signal is used to initialize values to variable. Initial block is used here for demonstration only.

block_1 in the below code is an always block without a sensitivity list and thus will execute at every time step and will toggle the value of clk every 5-time steps. block_2 is an always block which will trigger only at the positive edge of the clk , i.e., when clk changes its value from 0 to 1. Whenever the block is executed it is increasing the value of a by 1 as we can see in the output.

Race around condition

As we have seen that different procedural blocks run parallelly, it may happen that the same variable is getting assigned with different value in 2 different blocks. In this condition, it is hard to exactly know which value will be assigned to the variable leading to an indeterminate state. This condition is known as race around condition .

To understand race around condition with respect to actual hardware through the example given below. This is a 2 port SRAM, which means 2 devices can access the same SRAM simultaneously. Now it can happen that both the devices are writing data on the location, or it may happen that one of the device it writing data on some location and the other device is reading from the same location. In 1st case, the data which arrives later in the SRAM will be stored in that memory location. The arrival of the data cannot be guaranteed as the path delay depend on many factors. Thus, it leads to a state where the output is not determinate. This is known as Write-Write race around condition.

In 2nd case, data which is sent by the SRAM to the device, which is reading the data, will also depend upon the arrival of the data from the device which is writing it. If the write data arrives before the data is sent, then a new value will be sent to the reading device, otherwise old data will be sent. This is also leads to a state where the output from the SRAM to the reading device is not determinate. This is known as Write-Read race around condition.

Thus, we can see that the race around condition which happens in Verilog, is the representation of actual hardware. If you have not read our article on the Verilog program flow, do check it out. It will help understand the race around condition and how to tackle it. Carrying forward the concept learned, let’s see some examples of race around condition in Verilog code. In the below example, the highlighted line will cause race around condition.

We will discuss ways to prevent the race around condition, in the next article, where will discuss various assignment operators in details.

Named Blocks and how to disable it

We have seen that the block can be named using : after the begin statement. This is known as named block or a labelled block. Naming a block is beneficial as it gives us the flexibility to disable a block. To disable a block we use disable keyword followed by the block name. Syntax is disable block_name;

In the below example, block_1 is disabled from the second initial block. It must be noted that in block_1 a delay is given to prevent race condition. Without delay it may happen that the display statement from block_1 executes before the second intial block disables it.

In Verilog, there is no break or continue statement, but that can be emulated in Verilog, by disabling the block.

Break statement is a quite common keyword in C, which helps to come out of a loop when some condition is met. Let’s see how we can emulate break in Verilog. In below code, a counter is implemented which stops counting when its value becomes 4. An infinite loop is used inside a count block and when the condition is met, the code disables the count block inside which it is present. Thus, the program comes out of the loop and executes the remaining statements.

We can have multiple blocks inside the initial or always block as defined in below example. Begin and end can be compared to the {} we use in many programming language. It binds multiple statement in a single block. Thus, with initial or always block we use begin and end if there are multiple statements. But it doesn’t mean that we cannot declare multiple blocks inside it.

Continue statement is another common keyword in C. This is used to skip certain iterations of the loop when some condition is met. In simple words, whenever a condition is met it will not execute the remaining statements in the loop and go to next loop. Lets see how we can emulate continue in Verilog. The code given below, prints the value of i if it is not divisible by 3. Whenever the condition is met it disables the count block. Thus, statements present after the disable statement will not execute and the program will move to the next iteration. In this way continue is emulated in Verilog.

The difference in implementation of break and continue is that for break, block within which the loop is declared is disabled and for continue the block of loop statement is disabled.

  • Introduction to Verilog
  • Verilog Event Semantics
  • Basics of Verilog
  • Verilog Syntax
  • Data Types in Verilog
  • Verilog Vectors
  • Verilog Arrays
  • Verilog Modules
  • Verilog Ports
  • Verilog Operators
  • Verilog Assignments
  • Different types of loops in Verilog
  • Conditional Statements in Verilog
  • Verilog functions and tasks
  • Compiler Directives in Verilog
  • Verilog System Functions
  • Delays in Verilog

Javatpoint Logo

  • Interview Q

Verilog Tutorial

JavaTpoint

The RHS can contain any expression that evaluates to a final value while the LHS indicates a variable or net to which RHS's value is being assigned.

Procedural Assignment

Procedural assignments occur within procedures such as initial, always, task , and functions are used to place values onto variables. The variable will hold the value until the next assignment to the same variable.

The value will be placed onto the variable when the simulation executes this statement during simulation time. This can be modified and controlled the way we want by using control flow statements such as if-else-if, looping , and case statement mechanisms.

Variable Declaration Assignment

An initial value can be placed onto a variable at the time of its declaration. The assignment does not have the duration and holds the value until the next assignment to the same variable happens.

NOTE: The variable declaration assignments to an array are not allowed.

If the variable is initialized during declaration and at 0 times in an initial block as shown below, the order of evaluation is not guaranteed, and hence can have either 8'h05 or 8'hee.

Continuous Assignment

This is used to assign values onto scalar and vector nets. And it happens whenever there is a change in the RHS.

It provides a way to model combinational logic without specifying an interconnection of gates and makes it easier to drive the net with logical expressions.

Whenever b or c changes its value, the whole expression in RHS will be evaluated and updated with the new value.

Net Declaration Assignment

This allows us to place a continuous assignment on the same statement that declares the net.

NOTE: Only one declaration assignment is possible because a net can be declared only once.

Procedural continuous assignment.

These are procedural statements that allow expressions to be continuously assigned to variables or nets. And these are the two types.

1. Assign deassign: It will override all procedural assignments to a variable and deactivate it using the same signal with deassign .

The value of the variable will remain the same until the variable gets a new value through a procedural or procedural continuous assignment.

The LHS of an assign statement cannot be a part-select, bit-select, or an array reference, but it can be a variable or a combination of the variables.

2. Force release: These are similar to the assign deassign statements but can also be applied to nets and variables.

The LHS can be a bit-select of a net, part-select of a net, variable, or a net but cannot be the reference to an array and bit or part select of a variable.

The force statement will override all other assignments made to the variable until it is released using the release keyword.

Youtube

  • Send your Feedback to [email protected]

Help Others, Please Share

facebook

Learn Latest Tutorials

Splunk tutorial

Transact-SQL

Tumblr tutorial

Reinforcement Learning

R Programming tutorial

R Programming

RxJS tutorial

React Native

Python Design Patterns

Python Design Patterns

Python Pillow tutorial

Python Pillow

Python Turtle tutorial

Python Turtle

Keras tutorial

Preparation

Aptitude

Verbal Ability

Interview Questions

Interview Questions

Company Interview Questions

Company Questions

Trending Technologies

Artificial Intelligence

Artificial Intelligence

AWS Tutorial

Cloud Computing

Hadoop tutorial

Data Science

Angular 7 Tutorial

Machine Learning

DevOps Tutorial

B.Tech / MCA

DBMS tutorial

Data Structures

DAA tutorial

Operating System

Computer Network tutorial

Computer Network

Compiler Design tutorial

Compiler Design

Computer Organization and Architecture

Computer Organization

Discrete Mathematics Tutorial

Discrete Mathematics

Ethical Hacking

Ethical Hacking

Computer Graphics Tutorial

Computer Graphics

Software Engineering

Software Engineering

html tutorial

Web Technology

Cyber Security tutorial

Cyber Security

Automata Tutorial

C Programming

C++ tutorial

Control System

Data Mining Tutorial

Data Mining

Data Warehouse Tutorial

Data Warehouse

RSS Feed

A procedural continuous assignment assigns a value to a register.

Description:

A procedural continuous assignments overrides any other procedural assignment. After the procedural continuous assignment is executed, it remains in force on the assigned register or net until it is deassigned, or until another procedural continuous assignment is made to the same register or net.

The keywords assign and deassign can be used for registers, or a concatenation of registers only. It can not be used for memories and bit- or part-select of a register.

Deassign and release de-activate a procedural continuous assignment. The register value remains after the de-activation until a new value is assigned.

A procedural continuous assignment is not the same as a continuous assignment. Procedural continuous assignments are declared inside procedural blocks.

Continuous assignment

Verilog Blocking & Non-Blocking

Blocking assignment statements are assigned using = and are executed one after the other in a procedural block. However, this will not prevent execution of statments that run in a parallel block.

Note that there are two initial blocks which are executed in parallel when simulation starts. Statements are executed sequentially in each block and both blocks finish at time 0ns. To be more specific, variable a gets assigned first, followed by the display statement which is then followed by all other statements. This is visible in the output where variable b and c are 8'hxx in the first display statement. This is because variable b and c assignments have not been executed yet when the first $display is called.

In the next example, we'll add a few delays into the same set of statements to see how it behaves.

IMAGES

  1. PPT

    what is procedural assignment in verilog

  2. PPT

    what is procedural assignment in verilog

  3. PPT

    what is procedural assignment in verilog

  4. alex9ufo 聰明人求知心切: Non-blocking Procedural Assignment in Verilog

    what is procedural assignment in verilog

  5. PPT

    what is procedural assignment in verilog

  6. PPT

    what is procedural assignment in verilog

VIDEO

  1. DIGITAL DESIGN WITH VERILOG ASSIGNMENT 1 2024 KEY

  2. System Design Through Verilog NPTEL week 3 Assignment 3

  3. English assignment making procedural text 🙌🙌🤳

  4. English practice assignment regarding procedural text on how to make oreo roll cake

  5. System Verilog 1-20

  6. System Design Through Verilog

COMMENTS

  1. Verilog Assignments

    Procedural Continuous Assignment. These are procedural statements that allow expressions to be continuously assigned to nets or variables and are of two types. assign... deassign; force... release; assign deassign. This will override all procedural assignments to a variable and is deactivated by using the same signal with deassign. The value of ...

  2. Verilog: Continuous & Procedural Assignments

    There are two types of procedural assignments called blocking and non-blocking. Blocking assignment, as the name says, gets executed in the order statements are specified. The "=" is the symbol used for blocking assignment representation. Non-blocking assignment allows scheduling of assignments. It will not block the execution.

  3. Procedural Assignments

    Procedural Assignments are a central aspect of SystemVerilog that are used to define the behavior of variables within procedural blocks such as initial, always, task, and function.These types of assignments differ significantly from Continuous Assignments as they are executed sequentially, following the flow of control in the procedural block, and not instantly upon changes to dependent variables.

  4. ASSIGNMENTS IN VERILOG

    Procedural assignments are used for updating register data types and memory data types. The expression in a blocking procedural assignment is evaluated and assigned when the statement is encountered.

  5. Using a continous assignment in a Verilog procedure?

    It is called procedural continuous assignment. It is the use of an assign or force (and their corresponding counterparts deassign and release) within procedural block. A new continuous assignment process is created when the line is reached in the procedural block. assign can be applied to register types such as reg, integer, and real. force can ...

  6. Procedural Assignment

    Description: Procedural assignments are used for updating register data types and memory data types. The expression in a blocking procedural assignment is evaluated and assigned when the statement is encountered. In a begin-end sequential statement group, execution of the next statement is blocked until the assignment is complete. In a non ...

  7. Assignment Statements

    Procedural Continuous Assignment Two types of continuous assignment are available in initial and always processes: assign and force. The target of an assign statement must be a register or a concatenation of registers. The value is continuously driven onto its target and that value takes priority over values assigned in procedural assignments.

  8. Procedural continuous assignments

    The continuous assignment is used to drive net data type variables using the 'assign' statements whereas procedural assignments are used to drive reg data type variables using initial and always block statements. Verilog also provides a third type of assignment i.e. procedural continuous assignment that drives net or reg data type variables ...

  9. Procedural Assignment

    The non-blocking procedural assignment statement can be used when many variable assignments can be made within the same time step without regard for order or dependency on each other. Non-blocking syntax is: variable_name <= [delay_or_event_control] expression. The non-blocking assignment operator is <=.

  10. PDF Verilog Synthesis

    Procedural Assignments • Verilog has two types of assignments within always blocks: • Blocking procedural assignment "=" - RHS is executed and assignment is completed before the next statement is executed; e.g., Assume A holds the value 1 … A=2; B=A; A is left with 2, B with 2. • Non-blocking procedural assignment "<="

  11. PDF Verilog Execution Semantics

    Verilog Execution Semantics I To describe both clocked (sequential) and combinatorial logic, and to avoid problems with non-determinism, Verilog uses two di erent assignment operators within procedural blocks. I Blocking assignments, "=" evaluate the RHS and update the LHS immediately before any further instructions are executed.

  12. PDF 7 PROCEDURAL ASSIGNMENTS

    assignment is one of three types of assignments you will learn in Verilog. For now, just remember that the left-hand side of a procedural assignment is a reg. The left- ... Procedural assignments are a powerful way to create combinatorial or sequential logic. Chapter 9 will describe how to create combinatorial and sequential logic.

  13. Behavioral Modeling Style in Verilog

    Procedural assignment statements. Procedural assignments are employed for updating the memory variables. These assignments control the flow and keep updating the new data to the variables in the left-hand side expression on the activation of the sensitivity list. It represents a logical statement in hardware design.

  14. Verilog assign statement

    Verilog assign statement. Signals of type wire or a similar wire like data type requires the continuous assignment of a value. For example, consider an electrical wire used to connect pieces on a breadboard. As long as the +5V battery is applied to one end of the wire, the component connected to the other end of the wire will get the required ...

  15. Procedural blocks in verilog

    We have two types of procedural blocks in verilog: initial and always block. The statements inside these blocks are executed sequentially. Does that affect the timing of these signals? For example, in the code below: initial begin. a = 1'b0; b = 1'b1; end. Will the assignment of b will take place a small time after the assignment of a?

  16. Non Blocking Procedural assignments

    Verilog procedural assignment guidelines. For a beginner in Verilog, blocking and non-blocking assignments may create confusion. If are used blindly, it may create race conditions or incorrect synthesizable design. Hence, it is important to understand how to use them. To achieve synthesized RTL correctly, Verilog coding guidelines for blocking ...

  17. Blocking Assignments

    The procedural assignments can also be placed directly inside a module while declaring a variable. (Ex. reg [3:0] i_data = 4'h7) There are two types of procedural assignments and both of them are widely used in the designs written in the Verilog language. Blocking assignments; Non-blocking assignments

  18. PDF I. Blocking vs. Nonblocking Assignments

    Evaluate b&(~c) but defer assignment of z 1. Evaluate a | b, assign result tox x 2. Evaluate a^b^c, assign result to y 3. Evaluate b&(~c), assign result to zz I. Blocking vs. Nonblocking Assignments • Verilog supports two types of assignments within always blocks, with subtly different behaviors. • Blocking assignment: evaluation and ...

  19. Verilog Procedural Blocks

    Verilog Procedural Blocks. Verilog is a concurrent programming language, which means that different blocks of the Verilog program run in parallel. The main reason for the concurrent nature is the fact that in hardware each block of the module will operate individually in parallel once it is powered on. The greater number of hardware block means ...

  20. Verilog Assignments

    And these are the two types. 1. Assign deassign: It will override all procedural assignments to a variable and deactivate it using the same signal with deassign. The value of the variable will remain the same until the variable gets a new value through a procedural or procedural continuous assignment.

  21. Procedural Continuous Assignment

    A procedural continuous assignment assigns a value to a register. Syntax: assign register_name = expression; deassign register_name; force net_or_register_name = expression; release net_or_register_name; Description: A procedural continuous assignments overrides any other procedural assignment. After the procedural continuous assignment is executed, it remains in force on the assigned register ...

  22. Verilog Blocking & Non-Blocking

    Blocking Blocking assignment statements are assigned using = and are executed one after the other in a procedural block. However, this will not prevent execution of statments that run in a parallel block. ... always Verilog initial block Verilog in a nutshell Verilog generate Behavioral modeling Verilog Block Statements Verilog Assignment Types ...

  23. Procedural Assignment Definition

    Procedural Assignment Definition. An assignment in an Always Construct in a Verilog Design File ( .v) that places a value on a Verilog HDL register or an integer. A Procedural Assignment can either be blocking or non blocking. See "Section 9.2: Procedural assignments" in the IEEE Std 1364-2001 IEEE Standard Hardware Description Language manual ...