Hardware Description Language (HDL) abstraction - VHDL - Systemverilog
Model picture source: pixabay

Hardware Description Language (HDL) abstraction - VHDL - Systemverilog

Again, I have to refer to the series about the reasons why we do things a certain way in ASIC design: (B)ASIC: what is synchronous design?.

When I say Verilog in this article, it is Verilog or SystemVerilog that I intend to say.

What abstraction is not

Schematic entry

Closely related to the concept of synchronous design, the general rule is that we don't do schematic entry. Karnaugh maps are part of digital design courses. But a Hardware description is intended for abstraction. A clocked process triggers once for every active edge and evaluates the process. Combinational paths through the design trigger other combinational logic. Which is complicated to schedule in simulation. And it breaks the partitioning of a design. If your unit outputs are always the output of a flip-flop (clocked process) things are simplified. Then a LEGO approach to put units together to form a subsystem or even a system, makes sense. We contain the complexity to the unit level. It is so basic but rarely understood. Abstraction is not combinational gating everywhere without actually knowing the combinational loops you might create combining units. Why make your own life so difficult?

Abstraction requires simplifications to make complex systems possible. -- El Berto


A netlist is the technology specific implementation

Even when an ASIC design uses VHDL as abstraction, the technology dependent design (a netlist or gatelevel netlist, generated by the synthesis tool) is always in Verilog. Verilog has the unique ability to be simple and light-weight for the purpose of simulation this gatelevel netlist. With or without timing. because the basic type in VHDL std_logic has 9 possible values (binary representation needs 4 bits) and a wire in Verilog has 4 possible values (binary representation needs just 2 bits). For hundred thousands of objects, VHDL would need double the number of bits (RAM or disk) to account for all the wires in a netlist. Even though you could write out a netlist in VHDL, it would make things slower because a lot more information needs to be processed and stored for exactly the same netlist.

Verilog is the best choice for gatelevel simulation of the technology specific netlist because of its simple "bit" types. -- El Berto

The simple types make Verilog the only choice for fast gatelevel simulation. But this simplicity and especially the fact that Verilog is non-deterministic is a disadvantage for RTL design. I have personally seen a simulation with the same seed and code but with UVM verbosity set to UVM_HIGH PASS. The reason I ran with UVM_HIGH verbosity is that the testcase with the same seed would FAIL with verbosity UVM_LOW. Just changing the verbosity level of exactly the same simulation gives a different result. The reason is most likely the fact that the scheduler schedules things differently based on the verbosity level. A different simulator brand might not show the same problem. I haven't validated that statement. But non-determinism is always a potential issue.

Systemverilog has its merit for verification. A whole framework is available, UVM, the Universal Verification Methodology. Complex protocols like USB and PCIe have validated VIPs (Verification IP) which shorten the verification of those protocols. At the same time, it has encouraged bad practices that consume a lot of time and money: every scenario is compiled code, unit level verification need to be lean and efficient, random makes lazy, ...

Verilog has its pro's and con's, just like VHDL. And a netlist is no longer an abstraction.

What is abstraction then?

Math is abstracted hardware

A + B is an adder abstraction. In math, we don't think of widths to store results. But in digital design, the width of both A and B decides the width of the result. If you add an 8-bit number to an 8-bit number, your result is a 9-bit number. Even though in Verilog you can just assign it to an 8-bit wide result. It will compile for simulation, you can verify the unit completely. And the synthesis team will come back to you a few weeks later with a warning that the carry bit of the adder is removed. Is this intentional, they ask you. Well, in VHDL, that would not compile and elaborate for simulation. You need to explicitly code your adder in such a way that you specify what you want to do with the carry bit. If you don't use it, fine. If you need it, fine as well. The point is to specify it when you write your RTL. Yes, most engineers hate to fix all the petty complaints that VHDL imposes at compile and elaboration for simulation. But the alternative is that you have designed a unit fast. Push it through verification. A few weeks later, when you are doing something else, the lint checks or the synthesis people will ask you about the warnings they see in their runs. They don't know shit about your unit so they cannot assess your code. And you don't remember exactly what that adder was all about. Hence, you refresh your memory, fix the RTL and rerun the verification. Even if all turns out 100% OK, you have lost time.

Both VHDL and Verilog abstract mathematics. Now, the most natural way for mathematics is to use numbers. And there are two kinds, unsigned and signed numbers. Special cases are integer and natural. A chip boundary, the IO (Input/Output) is about pins with logic levels. The boundary of the chip is always "bits" or "vectors", std_logic and std_logic_vector in VHDL. Inside the design, we abstract types to vectors (no numbers) in cases of bus protocols, flags, ... or numbers (signed, unsigned, integer, ...) in case of address, counters, ... Adding two unsigned numbers is different than adding two signed numbers (sign extension). It matters and thus it is important to use the correct type to get the correct technology implementation. The synthesis tool derives hardware based on the description you feed it. If you feed it dubious information, you get something "Garbage In Garbage Out" style. ASIC design used to be about extreme risk reduction to get first time right silicon. Well, use the HDL syntax that allows you to reduce risk and delay for the benefit of the project.

We have talked about small adders, but some additions require wide numbers. It could be that in synchronous design, the addition cannot finish in one clock cycle. Remember, the synthesis tools are as dumb as they were 20 years ago. They do not auto-pipeline an adder. You have to do that yourself. Tools and their lack of evolution is one of the best kept secrets we should never talk about openly. It is a career killer. Now, adders are one thing, subtraction is another math operation that might require pipelining. And when we talk multiplication, the tools can provide a multiplier. But multiplication is fare more compute intense than an adder, it requires pipelining almost all the time. And dividers is worse than multipliers. Of course, a divide by two and a multiply by two is just a bit shift operation. That is not what I am talking about. I am talking specific pipelining that is using the clock as a parameter in combination with the delay of technology specific gates. We can abstract but we get fast into the area of very specific hardware that is closely linked to the technology (ASIC, FPGA) and the clock frequency available (or the maximum possible in that technology). This is exactly why HLS and Chisel and the likes always need to do the same as we, simple hardware peasants, do in HDL. Get very technology specific instead of pure abstraction.

HDL design is not the same as schematic entry. At the same time, abstraction via HDL syntax requires understanding of the underlying hardware the synthesis tools generate. Both statements are NOT mutually exclusive. -- El Berto

The way to use abstraction on the unit level is to write the RTL design, to verify the unit exhaustively and to run basic synthesis and STA timing checks on the unit. Thanks to synchronous design, the outputs of the unit are registered so the timing is easy to check (preliminary, 10% margin on maximum frequency for example). It doesn't go to the synthesis, DFT and STA people before the RTL is verified and clean for synthesis, DFT and STA.

Partitioning is abstraction

Back in the nineties, the system architect developed the specification of the chip before the project started. Unbelievable in 2020, but companies did that actually. Now, the ISO and whatever certification and the project management playbook require it as well. But it never happens, chaos theory is so much more fun than a sound strategy. After all, it is just a few hundred million for a complex chip in 7nm silicon, right? That should put things in perspective for you, the level of amateurism you wouldn't believe as an outsider.

The architect models the chip in a behavioral way, with software or sometimes SystemC. Not cycle accurate. Because the purpose is to apply stimulus and capture the output of the chip model for analysis. To see if the chip is feasible, have an idea of performance and to write the specification for the design. The system level is the software modeling world. And partitioning the design is an important step. Here is why. To distribute units and subsystems to different teams, different locations even different companies (subcontractors), partitioning is key. Make sure the interface definition is known to both sides interfacing each other. Use synchronous design to make sure timing is contained to the subsystem. Moreover, verification should not force signals in RTL from the testbench. Partitioning means that you keep the parts independent, you never compromise partitioning, ever. Most handy features like incremental recompile for simulation and synthesis are total and utter bullshit because they do not deal well with changes in files and the fact that in principle, every line of code could change something in a totally different unit, especially in Systemverilog. Even if it is for assertions, loggers or whatever, it violates the partitioning principle. To keep things manageable, simple and separate (for flexible outsourcing, multiple teams, multiple geo design groups working together) you need the simplification of independency of units and subsystems.

Functions/procedures

A natural counter (natural is 0 to maximum value) can be a:

  • Wrap around counter: it wraps around when it reaches it max value, goes back to zero and continues counting.
  • Saturating counter: if you are counting events, you don't want a wrap around counter for obvious reasons.
  • Read reset counter: this is more software access related, if the counter value must be cleared when read, it can be hardware RR (read and reset the counter to zero). Care should be taken that an event that happens in the same clock cycle as the read is not lost.
  • ...

I see a lot of units called counter.vhd or counter.v in designs. An adder is not a unit in HDL, it is part of a bigger unit. Whenever we use adders in a design, we have a function that returns the result. The functions "wrapcount" and "satcount" are examples that make it easy to reuse a known good wrap-around counter and a known good saturating counter implementation. In VHDL we store those general purpose functions in a package that all projects use. In verilog it would be an include file. The main thing is to understand that hardware adders should use the software like function approach and NOT instantiate a counter module (which is more hardware view). Projects with thousands of counter8.vhd, counter16.sv and adder_12x12 are clouding the partitioning. The goal of partitioning is to define units that have enough functionality that belongs together. In case of a counter/adder, use functions as the abstraction, not units.

Variables

VHDL signals are heavy on memory and processing since they store older values in memory fo the concept of attributes in VHDL. Attributes (follow that link to see examples) are preceded by a "tick": like 'event, 'length, ... . Variables in VHDL are a software concept, where values are overwritten immediately and no history is present. Software engineers do sometimes have an issue with understanding signal values but understand variables. A variable is a good thing for keeping things lean. Faster simulation, less memory use, ... Hardware engineers with a verilog background find it difficult to grasp the idea of a variable. A variable can be a net or a register. If the variable is read before it is assigned, it is a register because it implies memory of the value in the previous clock cycle. If a variable is assigned before it is read, it is a net, a wire that holds a temporary value in the logic path to a register (flip-flop). Engineers that understand the HDL they are using are not afraid of variables, they use it to their advantage. Something that links to the synchronous design practice: RTL is verified for simulation and synthesis (STA) on the unit level. In your synthesis report, you check for latches (no latches, DFT rule) and you check for the names of the registers. The latter shows you if you have inadvertently turned a variable into registers. You can always optimize the code to remove unwanted or unnecessary registers.

To be continued

Obviously there is more to abstraction than just this.

I enjoy the discussion, but I have noticed that this first step, the abstraction of hardware is a very important and necessary first step to understand digital circuits design using HDL.

Thank you, Unai Martinez Corral for your input.

The purpose of HDL is:

  • Abstract hardware: we infer hardware and avoid instantiating specific implementations. When we need to instantiate specific implementations in HDL (pipelined multiplier), we use a wrapper and put the implementation specific multiplier grouped with other implementation specific items. When we need to instantiate technology specific items, example memories in ASIC projects or DSP blocks in FPGA, we use wrappers and put them grouped together for this specific technology. Note that implementation is still agnostic in underlying technology even though it is tuned to performance for that technology.
  • Schematic entry is not easy to verify, but a description of hardware can be automated (self-checking). Since projects started out as a few hundred to a few thousand gates, the natural way to verify HDL was with HDL. ASIC designers doing design and verification. The size of the projects is now a factor thousand bigger. But the fact is that verification does not need to be in any HDL. On the boundary with the UUT, unit under test, there is a need to have HDL supported types to allow a high-impedant, pull-up, pull-down or undefined state of the IO. Again, for verification, there is no strict need to use HDL. And certainly on the system level (toplevel verification, feasibility study, performance, golden models, ...) it is more appropriate to use a non-HDL language. It does not require an expensive HDL license for that part (important when silicon validation runs the same testcase scenarios without the design in HDL).

Obviously a HDL has issues with power concepts because power is located in the technology specific domain. The whole abstraction concept doesn't deal well with power connections (that aren't there). That has always been an issue in mixed-signal and analog IP instantiation in digital VLSI design as well. An ASIC has IO pads that have power connections as well, so it is not a new thing, it was always there from the beginning.

Today, power domains need digital controllers but have level shifters and isolation cells. Memories can have dual rail supplies to retain memory, minimizing power consumption by reducing the voltage (second rail). The complexity of silicon is a compromise. Schematic entry will yield a denser and faster performing chip than the same design in a HDL. But it isn't feasible to verify that design, and in HDL it can be done (Pareto principle for time spent: 20% design, 80% verification). For power and analog, HDL isn't great, specifically, analog has its own HDL, AMS, analog and mixed-signal derived from HDL. If bright minds brain storm about improvement, we should know the prerequisites and the history. And, for sure, when commercial interest is a factor, we exclude the role the tools play in why things are where they are now. Engineers solve problems, businesses create problems.

Terminology and terms

On Quora and on Linkedin, I have noticed (from the civil discussions, not the rage mob) that there are many people involved in the "silicon" discussion. Everyone talks about ASIC and FPGA from a background. Software (application), firmware (embedded), CAD (EDA, tools), AI (which is kind of software background), DSP (sat comm people), ...

Programming vs Field Programmable Gate Array: the pure hardware nazi's consider programming an FPGA the right terminology. But the questions I answered, got and see passing by on Quora, show the confusion that software people see when they see the word "programming". Doing software all your life, programming is a hard shortcut in the brain that means compiler. Which isn't so wrong, HDL engineers compile for synthesis and simulation. But it is not towards an instruction set of a certain processor. In synthesis we target boolean logic. In simulation, it is more software that is executed on a processor. I tend to use the term "configure" and "reconfigure" an FPGA. Essentially hoping that this avoids the shortcut in software brains that might give them the wrong impression. Of course, resistance is futile. But I am resisting even though it is like the mosquito taking a leak in the ocean. At least my intentions are good.

The tower of Babel is an ancient Bible narrative of people not speaking the same language. To improve in a multi-disciplinary world today, we have to understand each others terminology.

This quote isn't specific to an individual at all, but something to explain my terminology issues trying to understand what others are trying to say to me:

"Overall, VHDL is a general purpose language specially good for modeling parallel systems and not friendly with dynamic typing, polymorphism, etc. "

Digital circuits are indeed parallel by nature, even though we can do serial as well. programming as in writing software and targeting an ISA (Instruction Set Architecture), is mainly serial in nature. Over time, multiple cores and even multiple threads per core were introduced but software struggles with parallel processing for a long, long time. Since hardware is the foundation for software, it is perfectly reasonable to expect that hardware does play a role in this "software has parallel issues". Software and hardware people talk next to each other because the nature of their profession (parallel-serial, digital gates-instructions, ...) is so different. On top of that, they use their own specific terminology that creates misunderstandings and confusion. I have worked for a few big international semiconductor companies, even ASIC professionals do have differences in terminology. An NCO (numerical controlled oscillator) versus a clock synthesizer for example. So, before a discussion starts, we need to understand each others terminology.

Another factor is that software is a big sector and hardware isn't. Specifically, FPGA and ASIC design are niches that are quite small. There is no chip methodology (UVM is for verification, and the term "universal" is great framing, but it isn't universal) that links design to verification to synthesis, STA, DFT to floorplan and place&route. Are you able to distinguish a good ASIC engineer from a bad one? Or are you just happy you found one? Again, just to picture the issues surrounding the discussion).

When I try to understand the quote above:

  • HDL is software syntax but it describes hardware. A case statement is a non-priority multiplexer. An if then else is a nested priority multiplexer. Digital circuits are parallel but when we talk about "models", we are talking about (a) behavioral HDL code to make a clear distinction between synthesizable (RTL) and non-synthesizable HDL code (BEH, behavioral, testbench code). Our terminology hard codes models and modeling to non-RTL code.
  • Dynamic typing in hardware is the software automatic casting done in verilog to a certain extent. VHDL has explicit type casting since an unsigned number has no sign bits and a signed number has. The reason is math in hardware and not because we like to make things difficult for ourselves.
  • Polymorphism: object oriented programming with classes and hierarchy. An interesting discussion coming from the software realm, which we see also in systemverilog. Worth to have a discussion but what are we talking about in RTL.

Every software language for abstracting hardware is a HDL synthesizable subset with types and conversions that do exactly the same thing as the HDL. You can't get rid of clocks and resets and synchronous design because the whole tool flow is built on that concept. DFT tools use the registers chained together to shift in a pattern, capture it and compare to the expected to detect manufacturing defects.

I'm the odd one out and always have been one. Because I want to understand and learn every day. I welcome smart and respectful discussions and can adapt my views if they are faulty. My contribution is to show what my background allows me to explain. And to see how those things link together to improve.

"Combining GHDL + VUnit (which includes OSVVM) + VHPIDIRECT (VHDL 2008) is a very powerful environment"

It certainly looks that way. Most people today contact me and ask for help because they like what I write. it is impossible for anyone with a certain level of visibility and expertise to help people on an individual basis. Therefor I welcome other experienced people that take the time to interact to exchange ideas and share them. That way, everyone interested in this kind of stuff can read, learn and even disagree. Helping on a community level rather than the impossible one on one (for free).

Of course the image of a beautiful woman will attract more attention to this article than the usual 20 or so. It was intentional, just look at the pictures of agency recruiters if you think this is misogynist.

Again, a big thank you to Unai (unable to tag you) for the discussion, I feel I have still a lot to learn about his view on the system/HDL/software field.

I will add this to my summary article I try to keep up to date: I will teach you how to design an FPGA

Applause for ourselves!!! 😂

Feel free to pet my ego with a small click on the like button!

Make me feel even more overrated with a share!

#semiconductors #asic #fpga #technology #VHDL #verilog #vlsi

#HARDWAREACCELERATORS

Unai Martinez Corral

Investigador y Profesor en Universidad del País Vasco/Euskal Herriko Unibertsitatea

4y

Bert, first off, thanks a lot for your kind words and for keeping sharing ideas with the community. I must say, I found nothing wrong with your article. There are specific opinions which I might not completely agree with, but overall I think it is a very interesting and adequate compendium of ideas. Let me focus on the following purposely disruptive assertion: "VHDL is a general purpose language". As an exercise, please, do try to forget your +20y of experience with RTL design and pre 2008 VHDL. Just imagine you are a CS or EE student which knows how to code in C and ASM (maybe for uC) and is probably familiar with Matlab/Simulink/Octave. Now, you are told: There is this (software) language called VHDL (learn it as name, not the acronym), whose main feature is that all the statements in the code are parallel/concurrent by definition. Then, you can create processes for sequentializing specific parts/pieces of your code. This is opposed to C, Python, Rust... where statements are sequential by definition, and specific features/libraries exist in order to introduce concurrency/parallelism in the code. There is GHDL, which is a FLOSS and multi-platform compiler for VHDL. It can use three diferent compiler backends: well-known GCC or LLVM, or a built-in in-memory machine code generator (mcode). Because all statements are concurrent by default, execution of VHDL programs requires a runtime library to handle the internal (implicit) scheduling. GHDL's runtime library is named GRT and it is built into the binaries which are compiled from your VHDL sources. As in other languages, libraries and frameworks exist to make programming in VHDL easier. For example, VUnit provides a communication library, which is equivalent to queues in Python, channels in golang, etc. Hence, if you ever need to program/design any model which is inherently concurrent/parallel, I strongly suggest to evaluate VHDL. For example, Simulink models (of any kind) are good candidates to be coded in VHDL. Moreover, GHDL provides a Foreign Function Interface (FFI), currently named VHPIDIRECT. It allows to execute "any" existing function in a shared library (or written in C, Ada, Python...) directly from VHDL, as any other "internal" function/procedure. At the same time, the simulation can be wrapped in a foreign language. NOTE: Adding this to the next revision of the standard is being discussed in the VASG. --- Note that I avoided any reference to hardware, RTL, synthesis, etc. That is the point I want to make. The language and coding styles are tightly coupled but different things. Synthesizable VHDL is just a subset with a tradition of being forced to very specific coding styles (because tools would need to find patterns). I argue that the difficulty for software developers to approach VHDL resides on the specific coding styles that are used for RTL description and the implied constraints. But anyone familiar with C or Ada will find modern VHDL a very pleasant software language to work with (as long as strong typing is an important feature for the use case). Why is this important? Because writing testbenches and doing verification, is software. SV is neither a better or a worse (software) language for verification. The value of UVM resides on the investment that multiple companies did during the last 15y to build tooling and libraries. However, currently it comes at the cost of paying for not cheap licenses and training. On the other hand, VUnit + OSSVM suffice for multiple projects, especially those targeting FPGAs. These are free and open source, and are known to work with GHDL. --- Regarding performance, simulation time with GHDL is comparable to any vendor simulator. Especially for short unit tests, because GHDL's startup time is negligible, as there is no license server checking. Yet, GHDL is currently single threaded, thus CPU bound; and optimization phases of the backends (LLVM) could be improved. On the other hand, GHDL runs on plaftorms such as arm/arm64 and ppc. Hence, it is possible to partition simulations or distribute unit tests into multiple low-cost SBCs, which AFAIAA is not possible with any vendor tool. So, I believe that GHDL is the GCC for RTL design and verification. I honestly think that VHDL is a safer language to work with, because it is more strict by design, and it fails fast. But, regardless, GHDL (VUnit, OSVVM) is what makes it really worth to consider as a serious alternative to SV (UVM). During the last year, GHDL gained synthesis support. It can either generate a VHDL 1993 netlist, or be plugged into Yosys to generate an optimized verilog netlist. That allows for verilog gate-level simulation, or synthesizing the VHDL 1993 netlist with any vendor tool. It also allows formal verification using PSL (part of VHDL 2008) and Symbiyosys; again something which is surprisingly comparable (not to say better) than vendor tools. But this is a whole different story. --- Please, note that none of this conflicts with what you already know about VHDL as a hardware description language. That still holds. I am just proposing a dialectic exercise to envision how to make VHDL easier to approach for software developers; as opposed to plainly accepting that VHDL needs SV. Of course, I expect VHDL to be useful in hardware oriented projects only/mostly, but not all VHDL users/developers need to know about synthesis, because not all the tasks in the design and development of hardware are about synthesis.

Lars Asplund

Main author and maintainer of VUnit. ASIC/FPGA/DSP Developer consulting for Q-Free ASA

4y

"Most handy features like incremental recompile for simulation and synthesis are total and utter bullshit because they do not deal well with changes in files and the fact that in principle, every line of code could change something in a totally different unit, especially in Systemverilog." VUnit does dependency scanning to properly provide incremental compile to all supported simulators. For larger projects it would be impossible to practise a quick code/test loop if you had to recompile everything for every iteration. Only files that have changed and the files depending on those are recompiled

Anil Achoora

Embedded| Cyber Security| Quantum Computing Enthusiast

4y

That was very much enriching

Lars Asplund

Main author and maintainer of VUnit. ASIC/FPGA/DSP Developer consulting for Q-Free ASA

4y

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics