Verilog Delay Control

There are two types of timing controls in Verilog - delay and event expressions. The delay control is just a way of adding a delay between the time the simulator encounters the statement and when it actually executes it. The event expression allows the statement to be delayed until the occurrence of some simulation event which can be a change of value on a net or variable ( implicit event ) or an explicitly named event that is triggered in another procedure.

Simulation time can be advanced by one of the following methods.

Gates and nets that have been modeled to have internal delays also advance simulation time.

Delay Control

If the delay expression evaluates to an unknown or high-impedance value it will be interpreted as zero delay. If it evaluates to a negative value, it will be interpreted as a 2's complement unsigned integer of the same size as a time variable.

Note that the precision of timescale is in 1ps and hence $realtime is required to display the precision value for the statement with a delay expression (a+b)*10ps.

Event Control

Value changes on nets and variables can be used as a synchronization event to trigger execution other procedural statements and is an implicit event. The event can also be based on the direction of change like towards 0 which makes it a negedge and a change towards 1 makes it a posedge .

  • A negedge is when there is a transition from 1 to X, Z or 0 and from X or Z to 0
  • A posedge is when there is a transition from 0 to X, Z or 1 and from X or Z to 1

A transition from the same state to the same state is not considered as an edge. An edge event like posedge or negedge can be detected only on the LSB of a vector signal or variable. If an expression evaluates to the same result it cannot be considered as an event.

Named Events

The keyword event can be used to declare a named event which can be triggered explicitly. An event cannot hold any data, has no time duration and can be made to occur at any particular time. A named event is triggered by the -> operator by prefixing it before the named event handle. A named event can be waited upon by using the @ operator described above.

Named events can be used to synchronize two or more concurrently running processes. For example, the always block and the second initial block are synchronized by a_event . Events can be declared as arrays like in the case of b_event which is an array of size 5 and the index 3 is used for trigger and wait purpose.

Event or operator

The or operator can be used to wait on until any one of the listed events is triggered in an expression. The comma , can also be used instead of the or operator.

Implicit Event Expression List

The sensitivity list or the event expression list is often a common cause for a lot of functional errors in the RTL. This is because the user may forget to update the sensitivity list after introducing a new signal in the procedural block.

If the user decides to add new signal e and capture the inverse into z , special care must be taken to add e also into the sensitivity list.

Verilog now allows the sensitivity list to be replaced by * which is a convenient shorthand that eliminates these problems by adding all nets and variables that are read by the statemnt like shown below.

Level Sensitive Event Control

Execution of a procedural statement can also be delayed until a condition becomes true and can be accomplished with the wait keyword and is a level-sensitive control.

The wait statement shall evaluate a condition and if it is false, the procedural statements following it shall remain blocked until the condition becomes true.

DMCA.com Protection Status

  • The Verilog-AMS Language
  • Continuous Assigns

Continuous Assigns 

A module may have any number of continuous assign statements. Continuous assign statements are used to drive values on to wires. For example:

This is referred to as a continuous assign because the wire on the left-hand side of the assignment operator is continuously driven with the value of the expression on the right hand side. The target of the assign statement must be a wire. The continuous assign statement is not a procedural statement and so must be used at the module level; it cannot be placed in an initial or always process.

You can add delay to a continuous assign statement as follows:

In this case, the value of a changes 10 units of time after the expression b & c changes. Continuous assign statement implement inertial delay, meaning that continuous assign statements swallow glitches. This is illustrated below with the assumption that the unit of time is 1ns.

../../_images/inertial-delay.png

It is possible to specify up to three delay values on a continuous assignment:

When you specify more than one:

The first delay refers to the transition to the 1 value (rise delay).

The second delay refers to the transition to the 0 value (fall delay).

The third delay refers to the transition to the high-impedance value.

When a value changes to the unknown (x) value, the delay is the smallest of the delays specified.

If only two delays are specified, then the delay to high-impedance is the smallest of the two values specified.

Reference Designer

  • Tutorials Home

Verilog Basic Tutorial

  • Verilog Introduction
  • Installing Verilog and Hello World
  • Simple comparator Example
  • Code Verification
  • Simulating with verilog
  • Verilog Language and Syntax
  • Verilog Syntax Contd..
  • Verilog Syntax - Vector Data
  • Verilog $monitor
  • Verilog Gate Level Modeling
  • Verilog UDP
  • Verilog Bitwise Operator
  • Viewing Waveforms
  • Full Adder Example
  • Multiplexer Example
  • Always Block for Combinational ckt
  • if statement for Combinational ckt
  • Case statement for Combinational ckt
  • Hex to 7 Segment Display
  • casez and casex
  • full case and parallel case
  • Verilog for loop
  • Verilog localparam and parameter

Sequential Ckt Tutorial

  • Sequential Circuits
  • Serial Shift Register
  • Binary Counters
  • Ring Counter

Misc Verilog Topics

  • Setting Path Variable
  • Verilog Tutorial Videos
  • Verilog Interview questions #1
  • Verilog Interview questions #2
  • Verilog Interview questions #3
  • Verilog Books
  • Synchronous and Asynchronous Reset
  • Left and Right shift >
  • Negative Numbers
  • Blocking Vs Non Blocking
  • wand and wor
  • delay in verilog
  • $dumpfile and $dumpvars
  • Useful Resources
  • Verilog Examples

Verilog Quizs

  • Verilog Quiz # 1
  • Verilog Quiz # 2
  • Verilog Quiz # 3
  • Verilog Quiz # 4
  • Verilog Quiz # 5
  • Verilog Quiz # 6
  • Verilog Quiz # 7
  • Verilog Quiz # 8
  • Verilog Quiz # 9

Other Tutorials

  • Verilog Simulation with Xilinx ISE
  • VHDL Tutorial
50 ;
#10 (a | b); // Example of intra-assignment delay
(a | b); // evaluate the RHS and hold it temporarily #10; // Wait for 10 units of time p = temp; // Assign the temporary evaluation to LHS
notgatedelay( input p, output q ); not #3 (q,p) ; endmodule  
notgatedelay( input p, output q ); not #(2:3:4) (q,p) ; endmodule  
andgatedelay( input p,q, output r );   and #(2,4) u_and (r,p,q); endmodule
#(2,4) u_and (r,p,q);
1ns / 100ps module stimulus; // Inputs reg p,q; wire r; andgatedelay n1 ( .p(p), .q(q), .r(r) ); initial begin $dumpfile("test.vcd"); $dumpvars(0,stimulus); p = 0; q =0;   #20 p = 1; #20 q = 1; #20 p = 0; #20 p = 1; #40; end   initial begin $monitor($time, " p=%1b,q=%1b, r = %1b",p,q,r); end   endmodule

Copyright © 2009 Reference Designer

Tutorials | Products | Services | Contact Us

Procedural timing control

Delay timing control.

Regular delay control

The non-zero delay is specified at the LHS of the procedural statement.

Intra-assignment delay control

Delay is specified between the assignment operator and the RHS operand.

Zero delay control

The zero delay is specified at LHS of procedural statement

Event timing control

Regular event control

An event control is specified using @ symbol

Event OR control

Multiple events are declared using the ‘or’ keyword or comma ‘,’ symbol.

Named event control

The event declared using  symbol as event triggering symbol as waiting for event trigger.

Level sensitive timing control

The ‘wait’ keyword is used in the declaration

a. Regular event control

@(posedge clk) q = d;

The q = d is executed whenever the clk signal does transition from 0/X/Z to 1.

@(negedge clk) q = d;

The q = d is executed whenever the clk signal does transition from 1/X/Z to 0.

out = @(posedge clk) (a & b)

The a & b is evaluated immediately but assigned to out at the positive edge of the clk.

out = @(negedge clk) (a & b)

The a & b is evaluated immediately but assigned to out at the negative edge of the clk.

b. Event OR control

always @(clk or rst_n)

Level sensitive for clk and rst_n signals using or keyword. 

always @(posedge clk or negedge rst_n)

Edge sensitive for clk and rst_n signals using or keyword.

always @(clk, rst_n)

Level sensitive for clk and rst_n signals using a comma.

always @(posedge clk, negedge rst_n)

Edge sensitive for clk and rst_n signals using a comma.

c. Named event control

D. level sensitive timing control.

assignment delay in verilog

Javatpoint Logo

  • Interview Q

Verilog Tutorial

JavaTpoint

Verilog delay statements can have delays specified either on the left-hand side of the assignment operator's right-hand side.

An inter-assignment delay statement has delay value on the left-hand side of the assignment operator.

Inter assignment are those delay statements where the execution of the entire statement or assignment got delayed.

In , Inter assignment delays often correspond to the inertial delay or the 's regular delay statements.

It indicates that the statement itself is executed the delay expires, and is the most commonly used form of delay control.

Here, q becomes 1 at time 10 units because the statement gets evaluated at 10 time units and RHS which is a combination of a, b and c evaluates to 1. After completion the execution, it gives the following output.

Intra assignment delay indicates that the statement itself is executed the delay expires, and it is the most commonly used form of delay control.

They can be used with blocking and non-blocking assignments. If a statement with intra-assignment timing controls is encountered during simulation, then the expression will be evaluated, and its value will be stored.

Then, the statement's execution will be suspended until the time specified by the delay control expires. Changes in the expression value up to the time of the event will be ignored.

An intra-assignment delay is declared to the right-hand side of the assignment operator. This indicates that the statement is evaluated, and the values of all signals on RHS are captured first.

The above code gives the below output:

At 5 time units, a and c are assigned using non-blocking statements. And the behavior of non-blocking statements is evaluated but gets assigned to the variable only at the end of the time step.

So the value of a and c is evaluated to 1 but not assigned when the next non-blocking statement q is executed. So when RHS of q is evaluated, a and c still has an old value of 0, and hence $monitor does not detect a change to display the statement.

To observe the change, let us change assignment statements to a and c from non-blocking to blocking.

And the output looks like as:





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

Blocking (immediate) and Non-Blocking (deferred) Assignments in Verilog

There are Two types of Procedural Assignments in Verilog.

  • Blocking Assignments
  • Nonblocking Assignments

To learn more about Delay: Read  Delay in Assignment (#) in Verilog

Blocking assignments

  • Blocking assignments (=) are done sequentially in the order the statements are written.
  • A second assignment is not started until the preceding one is complete. i.e, it blocks all the further execution before it itself gets executed.

Blocking

Non-Blocking assignments

  • Nonblocking assignments (<=), which follow each other in the code, are started in parallel.
  • The right hand side of nonblocking assignments is evaluated starting from the completion of the last blocking assignment or if none, the start of the procedure.
  • The transfer to the left hand side is made according to the delays. An intra- assignment delay in a non-blocking statement will not delay the start of any subsequent statement blocking or non-blocking. However normal delays are cumulative and will delay the output.
  • Non-blocking schedules the value to be assigned to the variables but the assignment does not take place immediately. First the rest of the block is executed and the assignment is last operation that happens for that instant of time.

Non_Blocking

To learn more about Blocking and Non_Blocking Assignments: Read Synthesis and Functioning of Blocking and Non-Blocking Assignments

The following example shows  interactions  between blocking  and non-blocking for simulation only (not for synthesis).

Mixed

For Synthesis (Points to Remember):

  • One must not mix “<=” or “=” in the same procedure.
  • “<=” best mimics what physical flip-flops do; use it for “always @ (posedge clk..) type procedures.
  • “=” best corresponds to what c/c++ code would do; use it for combinational procedures.

Spread the Word

  • Click to share on Facebook (Opens in new window)
  • Click to share on Twitter (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Tumblr (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to email a link to a friend (Opens in new window)
  • Click to print (Opens in new window)

Related posts:

  • Synthesis and Functioning of Blocking and Non-Blocking Assignments.
  • Delay in Assignment (#) in Verilog
  • Ports in Verilog Module
  • Module Instantiation in Verilog

Post navigation

Leave a reply cancel reply.

Your email address will not be published. Required fields are marked *

Save my name, email, and website in this browser for the next time I comment.

Notify me of follow-up comments by email.

Notify me of new posts by email.

Stack Exchange Network

Stack Exchange network consists of 183 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Intra-assignment delay in verilog

What is the difference between x=#5 a; where a blocking statement is used

And x<=#5 a; where a non blocking statement is used

Souhardya Mondal's user avatar

If you've a blocking assignment statement it'll be executed in the order that's specified in a sequential block. For example,

The a is assigned to x at simulation time 5, while b is assigned to y at simulation time 10. Now consider nonblocking assignment statements with intra-assignment delays that follow in a sequential block:

In the above case both a and b are concurrently assigned to x and y at simulation time 5. In other words, non-blocking assignment statements don't block execution of other statements that follow in a sequential block. Or it can be said that the ordering of non-blocking assignment statements in a sequential block doesn't matter at all.

dirac16's user avatar

Your Answer

Sign up or log in, post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged verilog or ask your own question .

  • Featured on Meta
  • Upcoming sign-up experiments related to tags

Hot Network Questions

  • proper way to write C code that injects message into /var/log/messages
  • Does a publication similar to the American Mathematical Monthly exist in Theoretical Computer Science?
  • Can a compact group have an infinite sequence of closed subgroups?
  • Modify the width of each digit (0, 1, ..., 9) of a TTF font
  • Voronoi mesh of a circular image
  • TikZ - diagram of a 1D spin chain
  • How to create a flow that checks the overlaping dates on records?
  • Rewarding the finding of zeroes of a hash function
  • A Colorful explosion
  • Need help identifying a (possibly) 1984 Winter Olympics bicycle
  • How to turn a desert into a fertile farmland with engineering?
  • Numerical approximation of the integral by using data
  • What does "the dogs of prescriptivism" mean?
  • Is FDISK /MBR really undocumented, and why?
  • Who is a "sibling"?
  • Mōnstrō and mōnstrum - how exactly are they related?
  • How to prove the following integral inequality problem
  • Freewheeling diode in a capacitor
  • When should a function be given an argument vs getting the data itself?
  • Transpose these notes!
  • Does USCIS require spouses being sponsored for Permanent Residency to leave the United States?
  • Physical meaning of each term of the square modulus of a wave function
  • Binary black hole merging condition
  • Short story about a group of astronauts/scientist that find a sentient planet that seems friendly but is not

assignment delay in verilog

Gisselquist Technology, LLC

Assignment delay's and Verilog's wait statement

Sep 21, 2022

I’ve now spent more time than I want to admit to debugging simulation issues when using Verilog’s simulation semantics. Let me therefore share some problems I’ve come across, together with my proposed solution for them.

The Problems

Today’s problem stems from logic like the following:

In general, this comes to me in “working” simulation code that’s been handed down to me to maintain. The simulations that use this logic often take hours to run, and so debugging this sort of thing can be very time consuming. (Costly too–my hourly rate isn’t cheap.)

Let’s walk through this logic for a moment–before tearing it apart.

Fig 1. Avoid assignment delays

In this example the first condition, the one I’ve called trigger_condition above, is simply some form of data change condition. Sometimes its a reference to a clock edge, sometimes its a reference to a particular piece of data changing. This isn’t the problem.

The second condition, some_other_condition_determining_relevance , is used to weed out all the times the always block might get triggered when you don’t want it to be. For example, it might be triggered during reset or when the slave device being modeled is currently responsive to some other trigger_condition . This is natural. This is not (yet) a problem either.

So what’s the problem with the logic above? Well, let’s start with the #1 assignment delay. In this case, it’s not representing a true hardware delay. No, the #1 is there in order to schedule Verilog simulation statement execution. Part of the reason why it’s there is because the rest of the block uses blocking logic (i.e. via the = ). Hence, if this block was triggered off of a clock edge, the #1 allows us to reason about what follows the clock edge but before the next edge.

Fig 2. Recipe for trouble

Now, let me ask, what happens five years from now when clock speeds get faster? Some poor soul (like me) will be hired to maintain this logic, and that poor soul will look at the #1 and ask, why is this here? Maybe it was a 1ns delay, and they are now trying to run a clock at 500MHz instead of 100MHz. That 1ns delay will need to be understood, and replaced– everywhere it was used. It doesn’t help that the 1ns doesn’t come with any explanations, but that may be specific to the examples I’m debugging.

Here’s a second problem, illustrated in Fig. 2: what happens when you use this one nanosecond delay in multiple always blocks, similar to this one, all depending on each other? Which one will execute first?

The third problem often follows this one, and it involves a wait statement of some type. To illustrate this, let me modify the example above a bit more.

In this case, the user wants to make certain his logic is constant across the clock edge, and so he sets all his values on the negative edge of the clock. This leads to two problems: what happens when the #1 delay conflicts with the clock edge? And what happens when the output value depends upon other inputs that are set on the negative clock edge?

Fig 3. Giant case statement dispatching tasks

Fig. 3 shows another problem, this time when using a case statement. In this case, it’s an attempt to implement a command structure within a modeled device. The device can handle one of many commands, so depending on which one is received you go and process that command. The actual example this is drawn from was worse, since it depended not only on commands but rather command sequences, and the command sequences were found within case statements within case statements.

What’s wrong with this? Well, what happens when the original trigger takes place a second time, but the logic in the always block hasn’t finished executing? Perhaps this is erroneous. Perhaps it finishes just barely on the wrong side of the next clock edge. In my case, I find the bug four hours later–on a good day. It doesn’t help that simulations tend to run rather slow.

Fig 4. FSMs are often easier to debug than long-running tasks

A better approach would’ve been to use a state machine rather than embedded tasks. Why is this better? Well, if for no other reason, a case statement would contain state variables which could be seen in the trace file. That means that you could then find and debug what would (or should) happen when/if the new command trigger shows up before a prior command completes.

Fig 5. Repeat LLC logic

These problems are only compounded when this logic is copied. For example, imagine a device that can do tasks A, B, and C, but requires one of two IO protocols to accomplish task A, B, or C. Now, if that IO protocol logic is copied and embedded into each of the protocol tasks, then all three will need to be updated when the IO protocol is upgraded. (I2C becomes I3C, SPI becomes Quad SPI, etc.)

While some of these problems are specific to hardware, many are not. Magic numbers are a bad idea in both RTL and software. Design reuse and software reuse are both very real things. Even a carpenter will build a custom jig of some type when he has to make fifty copies of the same item.

The good news is that better approaches exist.

Defining terms

Before diving into some better approaches, let me take just a couple of moments to introduce the terms I will be using. In general, a test bench has three basic (types of) components, as illustrated in Fig. 6.

Fig 6. Test bench components

The Device Under Test (DUT) : The is the hardware component that’s being designed, and for which the test has been generated.

Since the DUT is intended to be synthesizable, Verilog delay statements are inappropriate here.

The Hardware Device Model, or just model : Our hardware component is being designed to interact with an external piece of hardware. This component is often off-chip, and so our “model” is a simulation component designed to interact with our IP in the same way the actual hardware would.

Although I’ve called these “models” “emulators” in the past, these aren’t truly “emulators”. An “emulator” would imply a description of the actual hardware existed, such as an RTL description, yielding an additional level of realism in simulation. Barring sufficient information from the external device’s manufacturer to actually and truly “emulate” the device, the test designer often settles for a “model” instead.

Hardware models may naturally require Verilog delays in order to model the interfaces they are designed for. For example, a signal may take some time to transition from a known value to an unknown one following a clock transition. As another example, a hardware device may become busy following a command of some kind. The good news is that Verilog can model both of these behaviors nicely.

How to handle these delays “properly” will become part of the discussion below.

The Test Script, or driver : This is the component of the design that interacts with the device under test, sequencing commands to given to it to make sure all of the capabilities of the DUT are properly tested.

This component of the Verilog test script often reads more like it is software than hardware. Indeed, we’ve already discussed the idea of replacing the test script with a piece of software compiled for a soft-core CPU existing in the test environment, and then emulating that CPU as part of the simulation model . The benefit of this approach is that it can test and verify the software that will be used to drive the hardware under test. The downside is that simulation’s are slow, and adding a CPU to the simulation environment can only slow it down further.

For the purposes of our discussion today I’ll simply note that the test script commonly interacts with the design in a synchronous manner. Any delays, therefore, need to be synchronized with the clock.

There is another problem with the driver that we won’t be discussing today. This is the simple reality that there’s no way to test all possible driver delays. Will a test driver accurately test if your DUT can handle back to back requests, requests separated by a single clock cycle, by two clock cycles, by N clock cycles? You can’t simulate all of these possible delays, but you can catch them using formal methods.

Not shown in Fig. 6, but also relevant is the Simulation Environment : While the DUT and model are both necessary components of any simulation environment, the environment might also contains such additional components as an AXI interconnect , CPU , DMA, and/or RAM , all of which are neither the test script, DUT, or model.

Ideally these extra components will have been tested and verified in other projects prior to the current one, although this isn’t always the case.

Now that we’ve taken a moment to define our terms, we can now return to the simulation modeling problem we began.

Better practices

The good news is that Verilog was originally written as a language for driving simulations.

Even better, subsets of Verilog exist which can do a good job of modeling synthesizable logic. This applies to both asynchronous and synchronous logic. The assignment delay problems that I’ve outlined above, however, arise from trying to use Verilog to model a mix of logic and software when the goal was to create a hardware device model.

Here are some tips, therefore, for using delays in Verilog:

Write synthesizable simulation logic where possible.

This is really only an issue for test bench or modeling logic. It’s not really an issue for logic that was meant to be synthesizable in the first place.

The good news about writing test bench logic in a synthesizable fashion is that you might gain the ability to synthesize your model in hardware, and then run tests on it just that much faster. You could then also get a second benefit by formally verifying your device model–it’d save you that much time later when running integrated simulations.

As an example, compare the following two approaches for verifying a test chip:

ASIC Test chip #1: Has an SPI port capable of driving internal registers. This is actually a really good idea, since you can reduce the number of wires necessary to connect to such a test chip. The problem, however, was that the SPI driver came from encrypted vendor IP. Why was this a problem? It became a problem when the test team tried to connect to the device once it had been realized in hardware. They tried to connect their CPU to this same SPI port to drive it–and then didn’t drive it according to protocol properly.

The result of testing ASIC test chip #1? I got a panic’d call from a client, complaining that the SPI interface to the test chip wasn’t working and asking if I could find the bugs in it.

ASIC Test chip #2: Also has a SPI port for reading and writing internal registers. In this chip, however, the SPI port was formally verified as a composition of both the writer and the reader–much as Fig. 7 shows below.

Fig 7. Sometimes, you'll have both RTL pieces available to you

I say “much as Fig. 7 shows” because the verification of this port wasn’t done with using the CPU as part of the test script. However, because both the SPI master and SPI slave were verified together, and even better because they were formally verified in an environment containing both components, the test team can begin it’s work with a verified RTL interface.

You can even go one step farther by using a soft-core CPU to verify the software driver at the same time. This is the full extent of what’s shown in Fig. 7. As I mentioned above, the formal verification for ASIC test chip #2 stopped at the AXI-lite control port for the SPI master. When testing this chip as part of an integrated test, a test script was used to drive a Bus Functional Model (BFM), rather than actual CPU software. However, if you just read the test script’s calls to the BFM, you would have the information necessary to build a verified software driver.

Use always @(*) for combinatorial blocks, and always @(posedge clk) (or negedge) or always @(posedge clk or negedge reset_n) for synchronous logic.

While I like using the positive edge of a clock for everything, the actual edge you need to use will likely be determined by the device and protocol you are modeling. The same is true of the reset.

I would discourage the use of always @(trigger) , where trigger is some combinatorial signal–lest you forget some required trigger component. I would also discourage the use of any always @(posedge trigger) blocks where trigger wasn’t a true clock–lest you create a race condition within your logic. I use the word discourage , however, because some modeling contexts require triggering on non-clocked logic. If there’s no way around it, then you do what you have to do to get the job done.

Synchronous (clocked) logic should use non-blocking assignments ( <= ), and combinatorial logic should use blocking assignments ( = ).

It seems like my debugging problems began when the prior designer used a delay instead of proper blocking assignments.

Just … don’t do this. When you start doing things like this, you’ll never know if (whatever) expression had finished evaluating, or be able to keep track of when the #1 delay needs to be updated.

Device models aren’t test drivers. Avoid consuming time within them–such as with a wait statement of any type. Let the time be driven elsewhere by external events.

This applies to both delays and wait conditions within always blocks, as well as any tasks that might be called from within them. Non-blocking assignment delays work well for this purpose.

Ideally, device models should use finite state machines, as in Fig. 4, to model the passing of time if necessary, rather than consuming time with wait statements or ill defined assignment delays, as in Fig. 3.

When driving synchronous logic from a test script, synchronize any test driven signals using non-blocking assignments.

I have now found the following simulation construct several times over:

Sometimes the author uses the negative edge of the clock instead of the positive edge here to try to “schedule” things away from the clock edge. Indeed, I’ve been somewhat guilty of this myself . Sadly, this causes no end of confusion when trying to analyze a resulting trace file.

A better approach would be to synchronize this logic with non-blocking assignments.

This will avoid any delta-time cycle issues that would otherwise be very difficult to find and debug. Note that this also works because this block is the only block controlling ARVALID from within the test bench. Should you wish to control ARVALID from multiple test bench clocks, you may run into other concurrency problems.

While you can still do this sort of thing with Verilator, I’ll reserve my solution for how to do it for another post.

Pick a clock edge and use it. Don’t transition on both edges–unless the hardware protocol requires it.

As I alluded to above, I’ve seen a lot of AXI modeling that attempts to set the various AXI signals on the negative edge of the clock so that any and all logic inputs will be stable later when the positive edge comes around. This approach is all well and good until someone wants to do post–layout timing analysis, or some other part of your design also wants to use the negative edge, and then pain ensues.

Sadly, this means that the project may be turned in and then rest in a “working” state for years before the problem reveals itself.

In a similar fashion, what happens when you have two always blocks, both using a #1 delay as illustrated in Fig. 2 above? Or, alternatively, what happens when you want the tools to put real post place-and-route delays into your design for a timing simulation? You may find you’ve already lost your timing slack due to a poor simulation test bench or model. Need I say that it would be embarrassing to have to own up to a timing failure in simulation, due to your own simulation constructs?

There is a time for using multiple always blocks–particularly when modeling DDR devices.

Fig 8. Example DDR simulation logic

In today’s high speed devices, I’ve often found the need for multiple always blocks, triggered off of different conditions, to capture the various triggers and describe the behavior I want. One, for example, might trigger off the positive edge, and another off the negative edge. This is all fine, well, and good for simulation (i.e. test bench ) logic. While this would never work in hardware, it can easily be used to accurately model behavior in simulation.

Use assignment delays to model physical hardware delays only .

For example, if some event will cause the ready line to go low for 50 microseconds, then you might write:

Notice how I’ve carefully chosen not to consume any time within this always block, yet I’ve still managed to create something that will capture the passage of time. In this case, I’ve used the Verilog <= together with a delay statement to schedule the transition of ready from zero back to one by #tWAIT ns.

I’ve now used this approach on high speed IO lines as well, with a lot of success. For example, if the data will be valid tDVH after the clock goes high and remain valid for tDV nanoseconds, then you might write:

I’ve even gone so far in some cases to model the ‘x values in this fashion as well. That way the output is properly ‘x while the voltage is swinging from one value to the next.

No magic numbers ! Capture hardware delays in named parameters, specparams, and registers, rather than using numeric assignment delays.

For example, were I modeling a flash memory, I might do something like the following to model an erase:

Notice the use of tERASE rather than some arbitrary erase time buried among the logic. Placing all such device dependent times in one location (at the top of the file) will then make it easier to upgrade this logic for a new and faster device at a later time.

We can also argue about when the actual erase should take place. As long as the user can’t interact with the device while it’s busy , this probably doesn’t make a difference. Alternatively, we could register the erase address and set a time for later when the erase should take place.

Even this isn’t perfect, however, since we now have a transition taking place on something other than a clock. Given that the interface clock isn’t continuous, this may still be the best option to create a reliable edge.

  • The rule of 3 applies to hardware as well as software: if you have to write the same logic more than twice, then you are doing something wrong. Refactor it. Encapsulate it. Make a module to describe it, and then reuse that module.
Fig 9. If you have to build it more than twice, refactor it

Remember our example from Fig. 5 above? Fig. 9 shows a better approach to handling three separate device tasks, each with two separate protocols that might be used to implement them.

For protocols that separate themselves nicely between the link layer control (LLC) protocol and a media access control (MAC) layer, this works nicely to rearrange the logic so that each layer only needs to be written once, rather than duplicated within structures implementing both MAC and LLC layers together.

Fig 10. The rule of Gold

Remember: fully verified, well tested, well written logic is pure re-usable gold in this business. Do the job right the first time, and you’ll reap dividends for years to come.

Today’s story

A client recently called me to ask if I could modify an IP I had written so that it would be responsive on an APB slave input with a different clock frequency from the one the rest of the device model used.

The update required inserting an APB cross clock domain bridge into the IP. This wasn’t hard, since I’d built (and formally verified) such a bridge two months prior–I just needed to connect the wires and do a bit of signal renaming for the case when the bridge wasn’t required.

That was the easy part.

But, how shall this new capability be tested? It would need an updated test script and more.

Thankfully, this was also easy.

Because I had built the top level simulation construct using parameters, which could easily be overridden by the test driver , the test suite was easy to update: I just had to set an asynchronous clock parameter, create a new parameter for the clock speed, adjust the clock speed itself, and away I went. Thankfully, I had already (over time) gotten rid of any inappropriate delays, so the update went smoothly.

Smoothly? Indeed, the whole update took less than a half an hour. (This doesn’t include the time it took to originally build and verify a generic APB cross-clock domain bridge.)

… and that’s what you would hope for from well written logic.

Well, okay, it’s not all roses–I still have to go back and update the user guide, update the repository, increment the IP version, update the change log, and then bill for the task. Those tasks will take longer than the actual update, but such is the business we are in.

Let’s face it, this article is a rant. I know it. Perhaps you’ll learn something from it. Perhaps I’ll learn something from any debate that will ensue. (Feel free to comment on Reddit …)

Yes, I charge by the hour. Yes, messes like these will keep me gainfully employed and my family well fed for years to come. However, I’d rather charge for doing the useful work of adding new capabilities to a design rather than fixing up someone else’s mess.

  • Stack Overflow Public questions & answers
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Talent Build your employer brand
  • Advertising Reach developers & technologists worldwide
  • Labs The future of collective knowledge sharing
  • About the company

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Why does this simulate continuous assignment with delay of 2 as if had delay of 3

I have this system verilog code, that does continuous assignment for some simple operations with delays and a simple testbench with clocks.

I am running this and getting this result:

scheme1

I am getting the expected delay of 1ns for bb and then expected delay of 2ns for n1 , but for some reason n2 changes it's x state to 1 only after 3ns after the value of bb have become known, instead of 2ns .

What's interesting is if I get rid of bb and have 2ns delay, then everything works as expected

scheme2

And if I try to keep the same duration for the whole module, then n2 never gets out of the x state.

scheme3

All of this behavior seems rather weird to me and I cannot understand if this is actually to be expected or is it a tool bug. But either way I suspect it have something to do with the duration of the clock and that it is close to the duration of the simulation of the module, because if I set the clocks to be slower, then everything starts to work properly.

scheme4

My guess is it has something to do with event scheduling, but I am quite unsure of that as I am not experienced in this area and because I don't want to have gaps in my understanding any help is really welcome.

  • system-verilog

dave_59's user avatar

This is known as the inertial delay model —the LHS cannot change faster than the delay on RHS.

Basically, a continuous assignment can only have one pending scheduled update to the LHS at a time. In certain cases, a new scheduled update cancels the pending update.

This is defined in section 10.3.3 Continuous assignment delays in the IEEE 1800-2017 SystemVerilog LRM

There other kinds of delay models to choose from using a variety of different constructs.

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged verilog system-verilog or ask your own question .

  • Featured on Meta
  • Upcoming sign-up experiments related to tags
  • The return of Staging Ground to Stack Overflow
  • Policy: Generative AI (e.g., ChatGPT) is banned

Hot Network Questions

  • Need help identifying a (possibly) 1984 Winter Olympics bicycle
  • What is the purpose of the M1 pin on a Z80
  • Traveling between two Schengen Countries using a Verlustanzeige?
  • Does a publication similar to the American Mathematical Monthly exist in Theoretical Computer Science?
  • Proof/Reference to a claim about AC and definable real numbers
  • How does C++ select the `delete` operator in case of replacement in subclass?
  • if people are bred like dogs, what can be achieved?
  • Numerical approximation of the integral by using data
  • My 5-year-old is stealing food and lying
  • Does dynamic stability decrease with airspeed
  • A Colorful explosion
  • Parity of a number with missing digits
  • Output the Steiner system S(5,8,24)
  • How to create a flow that checks the overlaping dates on records?
  • WORD REQUEST: A class for students who want to get better at a subject, aside from their public education
  • How can I enable read only mode in microSD card
  • Are there really half-a billion visible supernovae exploding all the time?
  • When should a function be given an argument vs getting the data itself?
  • TikZ - diagram of a 1D spin chain
  • Medical - Must use corrective lens(es)…
  • Mōnstrō and mōnstrum - how exactly are they related?
  • Comprehensive Guide to saying Mourners' Kaddish
  • Why does detector inefficiency (or dark counts) count as a "loop-hole" in Bell-inequality tests?
  • Hard-to-find historical grey literature - any tips?

assignment delay in verilog

COMMENTS

  1. Verilog Inter and Intra Assignment Delay

    An intra-assignment delay is one where there is a delay on the RHS of the assignment operator. This indicates that the statement is evaluated and values of all signals on the RHS is captured first. Then it is assigned to the resultant signal only after the delay expires. module tb;

  2. Delay in Assignment (#) in Verilog

    Syntax: #delay. It delays execution for a specific amount of time, 'delay'. There are two types of delay assignments in Verilog: Delayed assignment: #Δt variable = expression; // " expression" gets evaluated after the time delay Δt and assigned to the "variable" immediately. Intra-assignment delay: variable = #Δt expression ...

  3. Verilog Delay Control

    Verilog Delay Control. There are two types of timing controls in Verilog - delay and event expressions. The delay control is just a way of adding a delay between the time the simulator encounters the statement and when it actually executes it. The event expression allows the statement to be delayed until the occurrence of some simulation event ...

  4. Delay after and before assignment in SV

    The intra-assignment delay statement is left over from very early Verilog before non-blocking assignments were added to the language. They no longer should be used. ... begin temp = B; #delay A = temp; end You ahould instead use A <= Delay B; which delays the assignment to A without blocking the flow of procedural statements. jaswanth_b August ...

  5. Continuous Assigns

    Continuous assign statements are used to drive values on to wires. For example: assign a = b & c; This is referred to as a continuous assign because the wire on the left-hand side of the assignment operator is continuously driven with the value of the expression on the right hand side. The target of the assign statement must be a wire.

  6. Basic question on intra-assignment delay in Verilog

    Intra-assignment delays in a Verilog always block should NEVER be used (NEVER!). There is no known hardware that behaves like this intra-assignment delay using blocking assignments. If I could take this out of the Verilog language I would, but I can't because of backward compatibility. In Verilog training, I always say, "if your mother and I ...

  7. PDF Correct Methods For Adding Delays To Verilog Behavioral Models

    Adding delays to the left hand side (LHS) of any sequence of blocking assignments to model combinational logic is also flawed. The adder_t7a example shown in Figure 4 places the delay on the first blocking assignment and no delay on the second assignment. This will have the same flawed behavior as the adder_t1 example.

  8. Delay in Verilog

    A delay is specified by a # followed by the delay amount. The exact duration of the delay depends upon timescale. For example, if with `timescale 2ns/100ps, a delay with statement. #50 ; will mean a delay of 100 ns. Delays can also be specified within an assignment statement as in. p = #10 ( a | b); // Example of intra-assignment delay.

  9. #20 Inter and intra assignment delay

    In this verilog tutorial use of inter assignment delay and intra assignment delay has been covered in details with verilog code. Most of the time during VLSI...

  10. PDF Verilog Nonblocking Assignments With Delays, Myths & Mysteries

    SNUG Boston 2002 Verilog Nonblocking Assignments Rev 1.4 With Delays, Myths & Mysteries 44 11.6 The 20,000 flip-flop benchmark with #1 delays in the I/O flip-flops All of the preceding mixed RTL and gate-level simulation problems can be traced to signals becoming skewed while crossing module boundaries.

  11. Procedural timing control

    Intra-assignment delay control delays computed value assignment by a specified value. The RHS operand expression is evaluated at the current simulation time and assigned to LHS operand after a specified delay value. ... In Verilog, the keyword 'event' is used to declare 'named events' that trigger an event using -> symbol and it is ...

  12. Verilog Inter and Intra Delay

    In Verilog, Inter assignment delays often correspond to the inertial delay or the VHDL's regular delay statements. It indicates that the statement itself is executed after the delay expires, and is the most commonly used form of delay control. Example. Here, q becomes 1 at time 10 units because the statement gets evaluated at 10 time units and ...

  13. Blocking (immediate) and Non-Blocking (deferred) Assignments in Verilog

    An intra- assignment delay in a non-blocking statement will not delay the start of any subsequent statement blocking or non-blocking. However normal delays are cumulative and will delay the output. Non-blocking schedules the value to be assigned to the variables but the assignment does not take place immediately.

  14. ASSIGNMENTS IN VERILOG

    The evaluation of the assignment is delayed by the delay when the delay is specified before the register name. ... Verilog language has the capability of designing a module in several coding ...

  15. Intra-assignment delay in verilog

    The a is assigned to x at simulation time 5, while b is assigned to y at simulation time 10. Now consider nonblocking assignment statements with intra-assignment delays that follow in a sequential block: initial begin. x<=#5 a; y<=#5 b; end. In the above case both a and b are concurrently assigned to x and y at simulation time 5.

  16. Verilog inter vs intra delay

    It is not an intra-assignment delay. Time must advance by 5 for each loop of the always. The non-blocking assignment (NBA) is superfluous. Use a blocking assignment. always #5 clk = !clk; always clk = #5 !clk; // this is intra-assigment (blocking) delay. I have a fundamental verilog event region question that I want clarification on. The ...

  17. verilog

    3. In the first case the whole assignment is delayed by 5 'time units'. In the second case value of b is read but the assignment is delayed by 5 'time units'. The difference is if b changes in the 'next' 5 time units. - In the first case the new, (changed) value of b gets assigned. - In the second case the old value of b is assigned.

  18. Blocking, delayed assignment vs Non-blocking, delayed assignment on a

    I am posting this question after going through a famous presentation on "understanding verilog blocking and non-blocking assignments by stuart sutherland" which literally discusses every possible variant. Input 0-10 LOW 10-20 HIGH 20-30 LOW 30-33- HIGH 33-36-LOW 36-45 HIGH 45-end of simulation LOW For the 2 cases below my analysis is output follows input with the mentioned delay. so the ...

  19. Assignment delay's and Verilog's wait statement

    Even better, subsets of Verilog exist which can do a good job of modeling synthesizable logic. This applies to both asynchronous and synchronous logic. The assignment delay problems that I've outlined above, however, arise from trying to use Verilog to model a mix of logic and software when the goal was to create a hardware device model.

  20. How does #delay work for Verilog non-blocking statements?

    How does event scheduling in Verilog work with respect to delays and non-blocking statements? verilog; delay; Share. Follow edited Feb 12, 2021 at 10:40. ... (Non Blocking Assignment) region and hence it will have the original values of the nonblocking assigned signals in the same timeslot. Share. Follow edited Feb 12, 2021 at 10:44.

  21. verilog

    I have this system verilog code, that does continuous assignment for some simple operations with delays and a simple testbench with clocks. ... This is defined in section 10.3.3 Continuous assignment delays in the IEEE 1800-2017 SystemVerilog LRM. There other kinds of delay models to choose from using a variety of different constructs.