Used to be in the early days that some people depended on how the original verilog interpreter ordered events, it was a silly thing (models would only run on one simulator, cause of lots of angst).
'<=' assignment fixed a lot of these problems, using it correctly means that you can model synchronous logic without caring about event ordering (at the cost of an extra copy and an extra event which can be mostly optimised away by a compiler).
In combination 'always @(*)' and '=', and assign give you reliable combinatorial logic.
In real world logic a lot of event ordering is non deterministic - one signal can appear before/after another depending on temperature all in all it's best not to design depending it if you possibly can, do it right and you don't care about event ordering, let your combinatorial circuits waggle around as their inputs change and catch the result in flops synchronously.
IMHO Verilog's main problems are that it: a) mixes flops and wires in a confusing way, and b) if you stay away from the synthesisable subset lets you do things that do depend on event ordering that can get you into trouble (but you need that sometimes to build test benches)
I remember having this debate back in the late 1990s when I was in college for my electrical and computer engineering (ECE) degree. At the time as students, we didn't really know about nuances like delta cycles, so preferring Verilog or VHDL came down to matter of personal taste.
Knowing what I know now, I'm glad that they taught us VHDL. Also that's one of the reasons that it's worth trying to get into the best college that you can, because as long as you're learning stuff, you might as well learn the most rigorous way of doing it.
---
It's these sorts of nuances that make me skeptical of casual languages like Ruby and even PHP (my favorite despite its countless warts). I wish that we had this level of insight back during the PHP 4 to 5 transition, because so many easily avoidable mistakes were made in a design-by-committee fashion.
For example, PHP classes don't use copy-on-write like arrays, so we missed out on avoiding a whole host of footguns, as well as being able to use [] or -> interchangeably like in JavaScript. While we're at it, the "." operator to join arrays was a tragic choice (they should have used & or .. IMHO) because then we could have used "." for the object operator instead of -> (borrowed from C++), but I digress.
I often dream of writing a new language someday at the intersection of all of these lessons learned, so that we could write imperative-looking code that runs in a functional runtime. It would mostly encourage using higher-order methods strung together, but have a smart enough optimizer that it can handle loops and conditional logic by converting them to higher-order methods internally (since pure code has no side effects). Basically the intermediate code (i-code) would be a tree representation in the same form as Lisp or a spreadsheet, that could be transpiled to all of these other languages. But with special treatment of mutability (monadic behavior). The code would be pure-functional but suspend to read/write outside state in order to enforce the functional core, imperative shell pattern.
A language like that might let us write business logic that's automatically parallelized and could be synthesized in hardware unmodified. It would tend to execute many thousands of times faster than anything today on modifiable hardware like an FPGA. I'd actually prefer to run it on a transputer, but those fell out of fashion decades ago after monopoly forces took over.
VHDL had this figured out as early as 1987. I spent many years writing Verilog test benches and chasing numerous race conditions; those types of bugs simply don't exist in VHDL.
The Verilog rules—using non-blocking assignments for sequential logic and blocking assignments for combinational logic—fail as soon as the scenario becomes slightly complex. Verilog is suitable when you already have the circuit in your head and just need to write it down quickly. In contrast, VHDL forces you to think about concurrent processes in the correct way. While the former is faster to write, the latter is the correct approach.
Even though SystemVerilog added some patches, the underlying execution model still has inherent race conditions.
((Shai-Hulud Desires the Verilog))
Real hardware has hold violations. If you get your delta cycles wrong, that's exactly what you get in VHDL...
They're both modeling languages. They can model high-level RTL or gate-level and they can behave very different if you're not careful. "just simulation what the hardware does" is itself an ambiguous statement. Sometimes you want one model, sometimes the other.
> The Delta Cycle logic is actually quite similar to functional reactive programming. It separates how a value changes from when a process responds to that change.
This is what I use when I play with hardware simulation in Haskell: type S a = [a]
register :: a -> S a -> S a
register a0 as = a0:as
-- combinational logic can be represented as typical pure
-- functions and then glued into "circuits" with register's
-- and map/zip/unzip functions.
This thing also separates externally visible events recorded in the (infinite) list of values from externally unobservable pure (combinational) logic. But, one can test combinational logic separately, with property based testing, etc.And afaik HDLs are almost exclusively used for hardware synthesis, never seen any software written in those languages.
So it doesn't seem important at all. In fact, for software simulation of hardware you'd want the simulation to randomly choose anything possible in hardware, so the Verilog approach seems correct.
The fundamental problem is that we're trying to create a simulation model of real hardware that is (a) realistic enough to tell us something reasonable about how to expect the hardware to behave and (b) computationally efficient enough to tell us about a in a reasonable period of time.
You could, of course, simplify the timing model a lot. In the end you get down to “there is some time passing for the signal to get through this logic, we don’t know how much but we assume it’s less than any clock period”.. in which case we end up with delta cycles.
And in the 21 years since, I’ve never once ran into an actual simulation determinism issues.
It’s not bad to have a strict simulation model, but if some very basic coding style rules are followed (which everybody does), it’s just not a problem.
I don’t agree at all with the statement that Verilog fails when things become too complex. The world’s most complex chips are built with it. If there were ever a slight chance that chips couldn’t be designed reliably with it, that could never be the case.
Anyway, not really relevant, but this all reminds me of the famous Verilog vs VHDL contest of 1997: https://danluu.com/verilog-vs-vhdl/
I always thought it was confusing to design a circuit mentally (or on paper) out of things like muxes, encoders, flip flops, etc. and not have language-level elements to represent these things (without defining your own components obviously).
I remember looking this up, and I believe it’s because the languages were originally designed for simulation and verification, and there are things you might want to do in a simulation/verification language for testing that are outside of what the hardware can do. Mixing the two is confusing IMO, but clearly demarcating the hardware-realizable subset of the language would be better than the current state.
But with a solid design flow (which should include linting tools like Spyglass for both VHDL and Verilog), it’s not a major concern.
VHDL's delta cycles are weird, and there's edge cases there too, but the extra ceremony works more like a childproof cap than a crown jewel.
There's no major implementation which doesn't handle warning or even failing the flow on accidental latch logic inside an always_comb.
Do you consider 800+mm2 slabs of 3nm of silicon still toy size? Because there's a very high chance that those were written in Verilog, and I've never had to chase sim vs synthesis mismatches.
> Verilog gives you enough rope.
Yes. If you don't know what you're doing and don't follow the industry standard practises.
That being said, I still have a preference for the VHDL simulation model. A design that builds correctness directly into the language structure is inherently more elegant than one that relies on coding conventions to constrain behavior.
You generally do not want to simulate or describe raw gate-level netlists. Both languages are capable of that. Old school Verilog (not SystemVerilog) is still the defacto netlist exchange format for many tools.
It's just aggravatingly slow to sim and needlessly verbose. Feeding high-level RTL to Verilator to do basic cycle-accurate sim has exceptionally fast iteration speed these days.
I.e. just because teams manage to do something with a tool does not mean the tool didn't impede (or vice versa, enable) the result. It just says that it's possible. A qualitative comparison with other tools cannot be established on that basis.
I remember inserting clock signal assignments in VHDL to get a balanced delta cycle clock tree. In Verilog, that all simply gets flattened.
I can describe the VHDL delta cycle model pretty well, and I can’t for Verilog, yet the Verilog model has given me less issues in practice
As for elegance: I can’t stand the verboseness of VHDL anymore. :-)
At the end of the day, what I write will become an electrical circuit - in a FPGA or an ASIC (or both), having the complex exact modelling with wire delays, capacitance, cross talk, cell behavior too early makes it impossibly to simulate fast enough to iterate. So then we need to have a more idealized world, but keeping in mind that (1) it is an idealized world and (2) sooner or later the model will be the rubber on the road.
To me, Verilog and SystemVerilog allow me to do this efficiently. Warts and all.
Oh, and also, where in my toolchain is my VHDL model translated/transformed into Verilog? How good is that translation? How much does the dual licensing cost.
Things like mixed language simulation, formal verification between a verilog netlist and RTL in Verilog, mapping to cell libraries in Verilog. Integration of IP cores written in SystemVerilog with your model?
Are the tools for VHDL as well tested as with code in Verilog? How big is the VHDL team at the tool vendor, library vendor, IP vendor, fab vendor compared to the Verilog, SV team? Can I expect the same support as a VHDL user as for Verilog? How much money does a vendor earn from VHDL customers compared to Verilog, SV? How easy is it to find employees with VHDL experience?
VHDL may be a very nice language for simulation. But the engineering, business side is messy. And dev time, money can't be ignored. Getting things as fast and cheap as possibly still meeting a lot of functional, business requirements is what we as engineers are responsible for. Does VHDL make that easier or not?
https://github.com/amaranth-lang/amaranth
While VHDL makes a fun academic toy language, it has always been Verilog in the commercial settings. Both languages can develop hard to trace bugs when the optimizer decides to simply remove things it thinks are unused. =3
It's not? Why would it?
As much as I like Verilog, VHDL is a first class RTL language just like Verilog. I've done plenty of chips that contain both VHDL and Verilog. They both translate directly to gate level.
These days, most EDA tools use Verific parser and elaborator front-ends. The specific tool magic happens after that and that API is language agnostic.
> How easy is it to find employees with VHDL experience?
On the East Coast and in Europe: much easier than finding employees with Verilog experience. (At least that was the case 20 years ago, I have no clue how it is today.)
One thing that has changed a lot is that SystemVerilog is now the general language of choice for verification, which helps give (System)Verilog an edge for RTL design too.
The Amaranth HDL python project does look fun =3
I spent the first half of my career working at some of the largest companies at the time on huge communication ASICs that were all written in VHDL, there was no Verilog in sight.
As much as I prefer to write Verilog now, VHDL is without question a more robust and better specified language, with features that Verilog only gained a decade later through SystemVerilog.
There's a reason why almost all major EDA tool support VHDL just as well as Verilog.
Many new school HDLs are working in this space and they couldn't be farther from the "representative of what digital circuits are constructed from" idea. Often they're high-level programmatic generators, very far from describing things in terms of actual PDK primitives.
Typical issues are still as given before. Many small IP vendors, esp for communication, networking are using and understand, support only SV. I agree on SV for verification is a big driver.
scala is popular in places like Alphabet, that apparently allow go & scala projects in production.
However, I agree while scala is very powerful in some ways, it just doesn't have a fun aesthetic. If one has to go spelunking for scalable hardware accelerators, a vendors linux DMA llvm C/C++ API is probably less fragile.
For my simple projects, one zynq 7020 per node is way more than we should ever need. =3
Posted on 2010-11-03 by Jan Decaluwe
Last modified on 2026-03-27
Tagged as: JanHDL
In this post, I would like to talk about VHDL’s crown jewel: how it preserves determinism in a concurrent language. Here is a figure of how it works:

What you see is a simplified example of VHDL’s delta cycle algorithm in action. Delta cycles are an HDL concept used to order events that occur in zero physical time. The red circles refer to signal value updates. The blue squares are process evaluations.
A delta cycle starts with a number of signal value updates. A signal value update may trigger a number of processes. In the second phase of the delta cycle, these processes are evaluated. In these processes, signals assignments may occur that schedule value updates in the next delta cycle. And so on.
Let us now zoom in on a single delta cycle:

The delta cycle starts with value updates of signals s, t, and u. The signals were assigned to by independent processes in a previous delta cycle. Signal s triggers two processes P and Q, that also use the value of signals t and u.
As signal updates are conceptually concurrent events, the order of the updates is undefined. The same holds for process evaluations. Therefore, another valid possibility is as follows:

It is easy to see that the result at the end of the delta cycle will be the same as before. Processes P and Q always see the same signal values. The point of the delta cycle algorithm is that signal value updates and process evaluations are kept in separate sets. The signal set is always handled completely before the process set. The order within each set is not relevant for the result. In other words, the result is deterministic even though the execution order within each set is not.
Let’s now come back to the subject of the previous post: the case of Verilog. The two situations above are possible, in addition to many others. For example:

Or even:

What you see is that in Verilog, value update events may validly appear before or after process evaluations. In other words, in terms of event ordering, all bets are off. Well, at least causality is preserved :-). Depending on execution order, the processes will see different values. Therefore, the result is non-deterministic.
I believe that delta cycle event ordering is the most important difference between VHDL and Verilog. Let’s investigate where it comes from. In VHDL, you cannot use ordinary variables to communicate between processes. VHDL has special objects for that purpose: signals. Signals accomplish two things: the value update event is delayed to a future delta cycle, and it is held in a dedicated set that is processed atomically. In this way, determinism is achieved, as demonstrated in the first two examples.
In contrast, Verilog doesn’t have anything like signals. The procedural thing that holds value is (confusingly) called a reg. Regs are used both for computation inside processes and for communication between them. What Verilog does have is two types of procedural assignment: blocking, which is much like ordinary variable assignment, and nonblocking, which delays the value update to a future delta cycle. Using blocking assignments for communication is conceptually unsafe, as values are updated immediately. But nonblocking assignments don’t solve the problem either. They merely influence the delta cycle in which an event becomes active. Once active, they just behave like other events. The fundamental difference is that Verilog does not handle value update events and process evaluation events in separate phases.
Nonblocking assignments are still an improvement. In a purely synchronous design that uses nonblocking assignments for communication, there are only two types of delta cycles: one in which a single clock event triggers all processes, and a second with value update events only. For this special case, the result is deterministic. But that’s also why I called nonblocking assignments a half-baked solution: they solve the problem for an important case, but not in general. Beyond the synchronous design paradigm, like in test benches and high-level models, you are basically on your own.
VHDL’s delta cycle algorithm is its crown jewel. It gives you built-in determinism. Let us treasure it - Verilog doesn’t have anything like it. At the same time, you will agree with me that there is nothing too complicated about the concept. It seems like a zero-cost solution for an important problem. So why then didn’t Verilog do it in a similar way? Perhaps the Verilog language designers had a good reason that we are not aware of yet. That will be the topic of a future post.
For completeness, let me add that VHDL has a few exotic nondeterministic corners also, such as shared variables, file-based IO, and asymmetric resolution functions. However, this is not an issue in practice. During my whole VHDL career, I have never felt the need to use anything else than signals for communication. In contrast, whenever I pick up Verilog, the whole blocking/nonblocking issue invariably comes back. For example, even for synchronous design where a safe solution is available, it is very easy to find highly-regarded reference texts that use blocking assignments for communication. (Verilog designers, don’t do it like that!)
This article is part of Jan’s blog about his personal views on HDL design.
Thanks to Jonathan Bromley for helping me to gain the insights that I try to explain in this post.