Verilog seems "hard" because people often use it in a similar fashion to a programming language, and in most cases that does not make any sense. The proper way to use it is to design the hardware, then code it up using verilog (which is trivial compared to the actual design).
In fact in terms of time spent on design, the actual coding part does not take much time at all.
In fact, this very article uses a motivating example that does not make any sense.
Having done some Verilog professionally, this is my initial reaction too. It is quality advice for anyone needing to use Verilog.
Yet if I put on my software cap and think of how things should be, the whole point of a language is to create an abstraction. This allows a designer to think and express their intent at a higher level. If an abstraction is not complete then the designer can never stop thinking in the lower level terms, which nullifies the benefit.
The problem is that programming abstractions are fundamentally different from those in hardware description languages. Whereas programming abstracts away arbitrary manipulation of memory with variables, pointers, and functions, Verilog abstracts away transistor topology and the NP-hard routing problem inherent in FPGA/ASIC design. The former is an abstraction for telling a precisely defined system what to do while the latter describes the system of equations for a (possibly nondeterministic) linear constraint solver.
Hardware description languages can never be as abstract as programming languages for the same reason that we can't create a single unifying abstraction for imperative multi and single threaded code: synchronization. Since each algorithm or data structure can have unique memory access/sync patterns, especially once optimized, there is no way to abstract away parallelization so we're forced to work with a large number of low level primitives like queues, locks, etc. In silicon, not only is everything running in parallel but each abstract unit of functionality has many more "degrees of freedom" like synchronization points, clock speeds, and physical location. It's simply impossible to cleanly abstract over all of the little tweaks you have to do in the implementation phase to get your blocks of transistors to synchronize properly.
>Hardware description languages can never be as abstract as programming languages
I'm not sure what it would even mean for HDLs to be "as abstract" as programming languages. They're different paradigms, and they have different abstractions, so you can't really compare them directly.
What I do know is that you can do a lot better than Verilog, because I've experienced it. I worked in Bluespec for a few years and as a language it's so much better than Verilog it's not even funny.
Indeed, using it made me stop thinking of Haskell as a programming language, and start thinking of it as a declarative language for constructing imperative programs in the IO monad.
> Indeed, using it made me stop thinking of Haskell as a programming language, and start thinking of it as a declarative language for constructing imperative programs in the IO monad.
Yea, the parallels between hardware design and haskell are striking. (Not just haskell, but it is perhaps the easiest to see.) In undergrad, I wrote my basic cpu project (16-bit risc) in haskell, then got it to write the verilog for me. This had the benefit of having an incredibly fast iteration cycle (including testing) paired with the ability to output an actual hardware description at any point. Very powerful. It really hammers home the difference between computation and I/O, a common theme in both CPU design and functional programs.
Also—and this is just my opinion—I much prefer declaring the computation with logical combinators rather than manually specifying how the bits are routed. This is much easier in haskell (or any functional language) than it is in verilog.
If you work smartly , there's no inherent conflict between abstraction and efficiency. For example , here's a DARPA project - which uses Chisel to implement an efficient version of the risc-V microprocessors, in an abstract, very productive manner:
Yeah, I think the problem here is that Verilog was originally created as a language for simulating hardware, not synthesising it. So its semantic model (which is essentially a bunch of imperative processes running in parallel) is not very appropriate for designing hardware.
I did some verilog in college. For many years I worked with a guy who only knew verilog and hardware design until he started coding late in his career. It was very interesting to work with his code. He used bitfields everywhere like in verilog. His functions tended to do a very small specific thing. He liked state machines and enums with long names. His style reminded me of verilog. I have not seen this coding style before or since.
I wonder if such a "low-level" coding style, based on bitfields and state machines, generally leads to better performance than more abstract patterns. While the former is close to how a human would design hardware for that task, the latter can be better optimised by the compiler.
In general, the consideration for bit fields is that your program will run slower but consume less memory. It's usually my opinion that we want to run as fast as possible while not running out of memory, so I'd say in general bit fields are less performant. If you can afford the memory, using a whole word for booleans will yield the fastest results, but will obviously consume way more memory.
I'm a fan of state machines, but I don't think they're necessarily more performant. There's nothing about them that keeps you from doing anything crazy that will bog your program down, but I find them easy to reason about. I think they're a stylistic thing, and the only real advantage I can think of is in maybe helping the design of the program. Having to define your states and how you will move between them is usually a good idea.
I'm neutral about state machines. Obviously in things like microcontrollers and HDL, state machines are really necessary. Outside of those two examples, state machines can either make code much more stable or just add unnecessary overhead with all the wasted cycles. They definitely have their place but there are better options available sometimes like threading a process. I had a project recently where we needed to build a custom message broker. A teammate wrote the entire thing in python as one big state machine. Everytime we needed to add another queue, it involved adding so much extra code to handle it. Another teammate suggested just having everything threaded so we reduce our code down to a template queue and can dynamically create them as needed. The state machine might have been more efficient memory-wise if we were doing it all in C on a PIC or more conservative in PLU usage if it was an FPGA but we were using python on a raspberry pi. We ended up with a broker that could handle more bandwidth in terms of how many queues we could publish to and consume from.
Obviously we didn't really shrug off state machines. We just created many smaller ones (two states: wait for message, push message) rather than a huge one. I think the massive state machines we learn about in our freshman classes are unnecessary in many cases. Memory is so cheap that its not always worth it to be so conservative/old school.
We could have just used something like rabbitmq but we didn't want the extra overhead of a service like that when we had so much more resource heavy stuff running on the pi.
Bluespec actually has a little sublanguage for writing state machines as control flow programs.
Essentially since Bluespec's model is a set of conditional transactions on your state, you can write an imperative sequence of transactions with a few basic flow control primitives (if-else blocks, while loops etc.), and it creates the state logic automatically.
Unfortunately it didn't seem to have received much attention, and I ran into quite a few problems when I tried to use it for anything serious (including one straight up behavioural bug).
Yeah, it sounds like you guys clearly made the right move in changing that. I am also neutral about state machines. Some times I run into one and I love it, other times, it just seems terrible. One of the projects at work has a state machine that's like ~2k lines of code. It's a monster, and it's a nightmare to modify. It's also got sub state machines nested in it, so the opportunities for fun are pretty much endless.
Personally I'm a fan of the smaller state machines you describe. You still got to deal with synchronizing them, but it just seems easier to grasp for me.
With regards to state machines , there's the idea of "hierarchical state machines" which basically add hierarchy and abstraction to state machines - and they are used in some safety-critical systems and supposed to greatly help with bug prevention.
Variants on that are also called Abstract State Machines (ASM's), Interacting State Machines, and Composable State Machines. Those terms have most hits on Google.
Are bit fields slower (at least in C)? It's a matter of load-constant mask-compare, as opposed to load-compare; I imagine it's a matter of one additional instruction per load statement, and this instruction also happens to be very fast.
It depends on if your state machine scheme is concise and makes human sense. Too many flags and state machines can become difficult to debug or work with.
I can't upvote this enough. It is imperative to make at least a block diagram before you start typing. Making some timing diagrams for critical sections will save even more headache.
It's not the same thing at all. Since modern processors abstract over the physical location/layout of memory, code at any location can access data or call code at any other location. This allows you to just jump in and write your logic without worrying about how the silicon physically moves your bits around.
You simply can't do that when designing silicon. All of your transistors have to be physically connected on a 2d plane so you can't abstract over the physical location or layout of your "objects" (logical groups of transistors and how they interconnect in this case). This means that the vast majority of possible Verilog designs are impossible to physically implement because there is only a finite amount of space to route traces from one transistor to another. Writing Verilog before drawing a block diagram is like writing an embedded IoT framework in Ruby before checking whether your target microcontrollers have enough ROM/RAM to run the Ruby interpreter.
For example, if you had a stack allocated object containing a queue and you changed it to always heap allocate the queue, it would still do the same thing as before but with a different memory layout. If you did the equivalent in silicon (like move the location of a group of transistors), at best it would break your functionality and at worst it would make the design unsynthesizable. Swapping an interface to point to an implementation with a different size (I.e. switching an IQueue* to an MPSC Queue from a SPSC Queue) is a trivial change with software but when you swap a 100 transistor interface with a 1000 transistor one you have to move the blocks around it, often requiring significant changes to avoid breaking functionality.
Sure locality is important, but I think you're overestimating the necessity of planning for it. When I was doing hardware design a few years ago, I wasn't worrying about the physical layout of anything. We kept the interconnect limited to a modular hierarchy, and we didn't seem to have many problems.
Of course, we were in a research group, so performance was less important to us. And we were working with FPGAs, so we didn't need to get it right in one go (and I think the fabric is better able to cope with looser style).
That said, I think there are cases where you can afford to sacrifice a bit of design efficiency to increase development speed. And if you're working with FPGAs, you may even be able to optimise later.
EDIT: Also the impression I got is that while industry does spend a lot of effort on it, complex designs are nowhere near as optimal as they could be. The first clue should be that an Intel chip has clearly defined blocks on it, rather than being a mess of interleaved logic. They divide the design like that to make it tractable for the designers.
> If you did the equivalent in silicon (like move the location of a group of transistors), at best it would break your functionality and at worst it would make the design unsynthesizable.
I don't think this makes much sense unless you're presupposing a prescriptive physical layout. Sure, if you were to move a bunch of synthesized circuitry somewhere else and then try to reconnect it, it's not going to work. But that's not something you'd actually do in an abstract model.
What you might do is move a bunch of HDL logic from somewhere in the module hierarchy to somewhere else, in which case the synthesizer will move everything else around to compensate.
>> Of course, we were in a research group, so performance was less important to us. And we were working with FPGAs, so we didn't need to get it right in one go.
What were you researching/designing? The higher your clock speeds/bandwidth requirements are and the more complex your designs, the more locality matters. The last design I worked on, for example, was a 32x32 crosspoint switch with total bandwidth in the low hundreds of gigabits and we eventually had to tweak cell locations manually on the mask to get the design working to spec. In modern chip design, bandwidth on that scale is pretty common so i don't think we're talking about the extremes of hardware design.
>> I don't think this makes much sense unless you're presupposing a prescriptive physical layout. Sure, if you were to move a bunch of synthesized circuitry somewhere else and then try to reconnect it, it's not going to work. But that's not something you'd actually do in an abstract model.
Again, depends on a variety of factors. Some of the designs I've worked on have had internal clock signals that couldn't travel across a fraction of the chip before attenuating too much to switch a transistor. Sure a low speed design can be synthesized without caring about physical layout but once you're in the RF/high speed digital realm, the relative location of dependent high speed blocks matters much more and the HDL abstractions start to leak or breakdown entirely.
Sure, we were doing processor architecture research, and our focus was whether new features improved software performance (while maintaining timing, and not using too much extra area), and how they could work alongside complicated processor designs. Our challenges were mostly about ensuring correct behaviour rather than meeting tight performance requirements.
Obviously these are very different fields, to the extent that I wonder if Verilog is even appropriate for what you're talking about, except for legacy reasons. If you're working in a domain where layout is so important, it feels like you should be using a tool that represents it directly, rather than inferring it.
Sure, my point is that Verilog (and RTL in general) doesn't seem any more appropriate for expressing the kind of designs you're talking about than a more abstract HDL would be. The only reason I'd even think about using it is if there weren't any alternative tools which could express layout (which is unfortunately probably the case, and exactly why you are using it).
About the chips not being "optimal", say an Intel processor has 50M gates, to be placed in a 50M squares (all possible layouts). Then there would be factorial(50M) possibilities. If you could simulate each one every clock cycle, you would need 10^1000000000 seconds. The age of the universe is about 10^17 seconds. It is just not practical to omptimize the layout like that. And having all gates in blocks gets us very acceptable local optima anyways (gates inside a block tend to be more interconnected with each other most of the cases)
Drawing a timing diagram is the same as thinking about how a CPU will execute instructions that you write or your compiler spits out.
Optimization is important in hardware due to cost, speed, and power implications of hardware design. These tradeoffs are there for software design as well, but to a much less extent.
I had a pretty cool class project once where we built the same formula solver in Verilog using three different optimizations: latency, power (watts), and area (in terms of PLU usage). I spent a long time just diagramming the timing of the various fp arithmetic blocks before I even touched the keyboard. Each design had its own quirks I had to factor in. Each block has a slightly different propagation latency so getting everything to pipeline synchronously with shift registers was certainly a chore.
I found a niche in a ASIC startup environment back in 2005 (5 years post CS degree and work experience to that date mostly being C/C++) as being "the guy that didn't want to work on the CPU" and where verilog engineers were thin on the ground (also I had an awesome boss who encouraged me to jump into the fray).
A littler bartering and I ended up owning display controllers, camera input peripherals, interrupt controllers and other such fun for 65nm and 40nm ASICs - mostly verilog (and, sigh.. TCL for test benches).
I found a singular insight got me all the way from zero to tapeout for all sorts of peripherals and infrastructure without any real support from other RTL peers in the team - design everything around a single clock (inc crossing all async signals into this singular domain as fast as possible) and then explicit pipelining of the peripherals functionality using a judgement of the process/clock speed to guesstimate how much complexity/gate density each pipeline stage could support before starting a new stage.
As I recall, my peripherals were marginally bigger than they needed to be but were extremely easy to push through the back end as the constraints were simple to define and synthesize.
I miss those days - the pressure to tape out a singular piece of art was a great way to focus the brain and the chip bring-up was exhilarating.
That's like trying to say a certain "high level language" is weird because you need to first write your program in ASM them translate it to this language
It makes no sense
I don't want to design from the bottom up and then if I'm "lucky" the compiler will give me what I wanted.
Well, what you want and the physical realities of synthesis are different :-)
In the early days of compilers, of course, you were mostly writing C as a macro language for your system's assembly language. If you wanted your program to perform well, you'd have to write C that was, more or less, a translation of assembly that you'd constructed in your head first. If you wrote bizarre C, you'd either get incorrect results, or if you were lucky, you'd get correct but inefficient results.
But that's also Dan's point: Verilog isn't a "high level language". You don't write programs with it, you describe hardware with it. (In fact, that is why it is called a 'hardware description language'!) So if you try to write a program, instead of describing hardware, you'll get something that isn't really either.
> Well, what you want and the physical realities of synthesis are different :-)
Then why doesn't the language let me describe what I want, and if reality disagrees, throws some compiling errors back?
Our current HDLs are lower level than block diagrams. And anything higher level they may claim to provide is iffy and won't work on practice. That's not a problem with the languages, but it is a problem for hardware development.
> If you wanted your program to perform well, you'd have to write C that was, more or less, a translation of assembly that you'd constructed in your head first.
Maybe in really old compilers
> You don't write programs with it, you describe hardware with it
Which is fair enough, but it seems the "hardware description" pretends to be of a higher-level than it really is.
If you need the user to describe gates and flip-flops and how they connect then make them describe this.
> You're talking about RTL, which is exactly what these languages output.
If VHDL/Verilog would output RTL, you could easily analyze it just as you analyze assembly output of your favorite compiler. Unluckily the output is some proprietary bitstream for the FPGA.
Just as a software compilation flow is devided into preprocessing, compilation, assembly, and linking, a HDL flow is divided into synthesis, mapping, place and route, timing analysis and bitstream generation. RTL is the output of the synthesis stage and is readily available to the designer, typically both as code and as a graphical schematic.
That's more like saying I expect to write highly performant software without knowing about CPU caches or the O(n) of my algorithms.
These are tools meant to scale out designs that you already have a good understanding of. Hardware is implicitly bottom up because you're dealing with physics at the bottom. Very few pieces of hardware are lenient to a single cycle of latency much less 10's of milliseconds.
A lot of times, you can get access to IP blocks. You can view a reference design of what the module does but the actual code is a binary blob owned by the chip manufacturer. You can treat these as functions and build larger designs from them. It's great because you don't have to write really low-level stuff like RTL except for hooking up the different modules. You can then do some more complex combinational logic using always blocks that kind of look like C. It's not super high level like C++ or python but you can get some higher levels of abstraction. Some IDEs have a visual way to write the code using schematics. You connect the logic modules together using wires. It makes HDL a bit easier to understand what's happening but you need to compartmentalize your code as much as possible, essentially making everything a function.
>Verilog seems "hard" because people often use it in a similar fashion to a programming language
You mean typing random stuff into the editor without understanding what any of it does and hoping for the best? Because all of the online examples I've seen of "HDL done like programming" involved exactly that. In my experience, HDL design is very similar to functional programming (minus recursion) and the principles that work in one translate well to the other.
I was thinking more in terms of realizing signals are actual electrical nodes, not location in memory, separating the design in combinations and sequential parts and choosing the right size of buffer going from one clock domain to another and stuff like that. When I see examples of verilog online, it seems like most people have no concept of these core things
I'll throw in my opinion for this. The author states how its routine for people to be older in the Hardware Industry. I work as a Verification engineer for a CPU project.
From what I see, every company in this sector works off of years of experience. Even if you are god's gift to the world of CPU design, the career options available to your are linked to the years you have worked.
I recently attended a presentation by ARM, where they boasted of this quote "At ARM, we don't really expect our graduates to be able to do anything until they're about 2 years into their careers, at which point they're expected to be decent at something"
And they boasted of it! To a theater full of CS students. And this was a 35 year old line manager making the comment.
If you want a career where you can rise based on merit, and not the numbers of years on your CV, don't pick hardware. I've seen it as an insider, the occasional "kid" comment being thrown around(ARM), designers refusing to work with junior verif staff(imagination tech), people who have written a project from scratch over 2 years not given tech lead roles as the project grew, etc.
Such an enviroment quite often bleeds younger engineers. It saps desire and motivation. Because there are so few startups, good practices don't matter. Here's some conversations I've had:
"We don't need to write tests for our software ISG, its a waste of time"
"What is wrong with me writing an extension to the software as a special case? It only executes that code if the username is me"
"We don't do training for new people".
I routinely see younger engineers with 3-4 years of experience try and spin out of CPU/Hardware and into Software.
> And they boasted of it! To a theater full of CS students.
I think this is highly contextual, and how you interpreted that statement depends on how you were primed to interpret it. You can assume they meant that it's an age based hierarchy, or you can assume that it's an extremely complex job that a CS degree doesn't adequately prepare you for, so it takes a couple years of apprenticeship before you are qualified to do something yourself.
There are plenty of industries like this, where it's not just about being smart and using your intellect to put the relatively small amount of parts together into something that works, but instead has a large chunk of learned wisdom that is not quick to impart, the importance of which is sometimes discounted until it's dealt with, and the consequences of messing up are fairly high.
Some examples: electricians, plumbers, architects. Fields that we've decided often require certification and that certification requires an apprenticeship period, because we don't want electrical fires or dead electricians, or water damage to our homes, or leaking sewage, or collapsing buildings.
In a lot of ways, I think the problem with the software engineering industry is that we don't have a system like this in place. Name me a programmer that thinks he was just as good at 22 at not making architectural or security mistakes as he was after 10 years more of programming and I'll name a programmer I never want to work with. Chances are they'll be the same person.
Yeah, when I want kernel or firmware code written, I want it done by someone experienced, or someone trained by someone experienced. I've had the very fortunate experience of being the latter person (up until only a little while ago), so looking back, I can damn well see the difference.
On the flip side, the ageism issue is not present in the hardware industry as it is in the software industry. Also, for digital design, no "cutting edge" technology is coming out anymore, so experience becomes much more useful than merit
I'm not a HW person but my interpretation of this line: "we don't really expect our graduates to be able to do anything until they're about 2 years into their careers, at which point they're expected to be decent at something" is "there is a lot of specialized knowledge that can only be gained through on-the-job experience".
In the first 2 years of work, I bounced about quite a lot within my first company, and did the following:
Formal proofs and checks for a full unit.
RTL design with another bloke on a block.
Owner of an testing tool (developer).
Owner of a testbench for top level design.
Owner of process for bringing up new pieces of RTL(4 blocks, one after the other) into the top level design.
All of this was caused because the startup I started in was stupidly undermanned, and there wasn't anyone else about. When I left that company, they had gone and hired about 12 people to do all of those tasks, and I saw myself handing over tasks to more senior people.
I had experienced atleast 3-4 different areas of the process, and became really familiar with ARMV8 (what got me my next job).
Yet this guy over here is thinking that its gonna take 2 years for someone to be even able to do 1 of those tasks?
Could argue a really long time about individual cases, but I think the Hardware industry has a very big problem with arrogance. Most companies and senior people carry an air of "no one else can do what I do" kind of bs, that I experienced in SV quite a bit. They look down on junior devs thinking that they are incapable of doing anything.
I asked in my office just now, the reasons for leaving their first jobs:
1. Wasn't allowed to do RTL design work inside the CPU
2. Wasn't given any responsibilities other than manually
writing coverage(automating this was not permitted)
3. Ownership of the block that he had written from scratch was given to a more senior person once it came to integrating it to the top level
4. Money
I find it extremely common for people(usually at the 2-3 year mark) to leave for greener pastures where they are taken in as experienced engineers, rather than useless babes. It might be a rite of passage, or it might just be the mistakes of an industry entrenched in the past
Well, the chip industry is an industry with low risk tolerance - making a buggy chip is very expensive, You'll probably see a similar behaviour in many high-risk engineering fields.
Software works differently , so no wonder it's more appealing.
I had a similar experience working in a hardware research group for a few years. We were working in Bluespec, and our process was very software like, in that we'd hack things together and fix bugs when they arose. We were doing okay in terms of getting working hardware quickly, and our process was fairly bad (e.g. we used SVN, often badly). I think a better funded team using modern practices (backed by some more traditional QA) could do really well.
And my impression from our interactions with the industry is that hardware and software are so culturally separated that there are hardly any people who end up experiencing enough of both to truly tackle the problems. Hardware people tend to think abstraction is a synonym for inefficiency, and software people often aren't familiar enough with the complications of hardware to abstract it efficiently.
Is the experience-based career mostly because the methods behind verification haven't changed much? VHDL and Verilog haven't changed much compared to the software world where new languages with novel features come out every week. The technological advances come in the form of larger FPGA fabric in chips and better fab processes but the HDL running on there is not much different than the HDL running on there 15 years ago. So what I'm thinking is that the job of a verification engineer hasn't changed much so the old guys can still keep up with the recent grads. Therefore, when a team needs a new verification eng, they look at someone who's been at it for 10+ years and the kid who just got out of school and say the old guy might cost more but he should know what he's doing after all these years whereas the kid is cheaper to hire but he's been doing this maybe a couple semesters and an internship.
I'm with GFX's interpretation. I read another article by hardware engineer talking about how many people in his company were 40-60. They kept paying experienced people not to retire because the wisdom they accumulated over the years simply didn't exist in the younger crowd. All these companies could start packaging that up and training all the young crowd. That's already a cost issue but he said bigger one was inexperienced people screwing up one design decision might cost a fortune. They just hired older ones for key positions instead to knock out the risk.
That's what I've learned reading a lot of articles on age and HW. They've been consistent. The young people are often in verification as it's mostly manual work feeding tools or doing math that doesn't require tons of experience. That's at least the impression I'm getting of people's descriptions of verification vs designing hardware.
I think it is true that the less experienced engineers start in verification however the verification role is actually quite difficult. It is much more than feeding tools and math. You only do that during the execution phase. That can be assigned to newbies.
However the creation of the verification testbench and tests is as extensive as the design. The verification team has to work in parallel with the design team so they have enough time to get things done. If they make a mistake in verification it can still also cost a fortune.
If the testbench and tests are not well designed then you are screwed in a roundabout way because the ability to quickly find the bugs isn't there. The testbench has to work on both the rtl and the back annotated netlist.
Approximately 75% of the person-months and compute resources for most projects is verification work. I have been verification lead on multiple projects and design lead on multiple projects. In either role I always looked to assign verification resources as top priority because the project is screwed without it.
On the original topic: The problem is that most commenters are not in the verification field. They don't know the amount or type of work done in verification or the commercial tools involved. This is done in SystemVerilog to do UVM - Universal Verification Methodology. It is not just Verilog. People here are concerned with ease of design. The bottleneck in the industry is in ease of verification.
I can relate to this, I did a MS in Hardware and I was good in design ( I developed couple of algorithms that didn't exist and it has application in FIFO for example) but all the jobs for the new grad is in verification! I switched to Software and I am happier with my choices. although I really miss the Hardware where an additional line of code can mean screw your performance !
I guess it depends on how you interpret the message. In my experience (working at Amazon) it does take a couple of years for a college hire to be efficient on their own. It turns out that even in software there are things to learn that a university does not prepare you for. I'd say it's also a decent mix of technical AND soft-skills that you will learn on the job to work efficiently on your own
These objections don't totally match my limited experience (not done this in a long time). When I did a lot of HDL work, I found that the main challenge was to stop thinking of hardware design like programming.
This is why dynamic typing (even if it is static type inference) is a bad idea in the hardware world. Embedded software programmers want C style types because they are often flipping bits or packing data into a specified data structure so that some hardware that expects particular bytes in particular places knows where to get it. In HDL, you are fitting your logic into very limited space, and need to constantly keep in mind what hardware the code you are writing is going to synthesize to.
Later, I realized that HDLs are often not really used like we'd think. Having written the logic in C or maybe Verilog, a lot of shops figure out what the actual desired hardware is and write verilog to specify that. So in verilog, rather than getting the compiler to infer a flipflop you can specify one and use verlilog to wire it up. Professional shops often basically use verilog to describe a circuit design in text, like a C programmer dropping into assembly.
The thing is that, like in the 1980s, you are so much fighting to get the fastest, smallest implementation possible, that like an 80s programmer, many default to assembly - to specifying the logic elements rather than leaving it to a compiler.
That means verilog as written many places is not really used like verilog at all - more like using verilog to express a netlist. Verilog is used to wrap vendor specific code so you specify a flipflop rather than a Xilinx flipflop, to make it easier to go to another vendor or to ASIC, but the clever features of verilog are only used for your test harnesses.
Part of the reason for this is that FPGAs are full of specific purpose hardware like dual port memories, and the compiler won't always infer them for you. That means you need to explicitly tell it to use them - and once you are explicitly specifying some parts of your system, you tend to do it more and more.
> Part of the reason for this is that FPGAs are full of specific purpose hardware like dual port memories, and the compiler won't always infer them for you.
You can only use a HLL if you can rely on the fact that the compiler will nearly always put out much better code than you would be able to invent in a reasonable amount of time. This is the reason why even in the late 90th for performance-intensive code (games, multimedia) the critical parts were often still written in assembly instead of C/C++.
The problem is for FPGAs the bitstream format is very closed - so you can hardly dive into the low-level abyss and "look at the generated assembly code/bistream" to rewrite the generated assembly code/bitstream code until you are satisfied with the result; you have to use the HLL (VHDL/Verilog), where you cannot trust the quality of the generated code.
Instead of looking at the "assembly" or bistream, FPGA and ASIC designers use a graphical tool to look at the inferred hardware blocks. There are also tools to visualize how these blocks are placed on the die/FPGA.
As a SW dev who frequently gets to interact with HW folks (embedded dev FTW), I frequently find their conservatism w.r.t. software tools puzzling.
Dan Luu's explanation makes me think they're driven by trauma inflicted by their existing tools. ;)
(but really, I figure they have enough trouble dealing with actual HW concerns that they don't have the bandwidth to deal with SW stuff not immediately relevant to their HW concerns.)
The problems you name are true, but another issue is that errors in HW tend to be much more expensive than errors in SW. If, say, my timing analysis tool is wrong and I spin a chip based on its results, I'm out ~$100,000 and a few months of development time. That's also why we're willing to pay $thousands for licenses to proprietary SW; you want to be really confident in your tools.
Right, except the promise of better tools is a) fewer costly errors and b) faster development time. If cost and time are what you're optimizing for, they'd be a clear better choice.
You need to prove that you can get a certain performance with a matlab algorithm, then you spend a week writing it into verilog.
Oh, and as someone whose bread and butter is ICs, I go out of my way to avoid creating FSMs. They're slow, difficult to debug, and hard to pass on to your successor.
Interesting, in my digital design and microcontroller classes, they have been beating FSMs into our heads since day one. I knew there were a few projects where I knew it wasn't totally necessary to do but used a FSM to get the checkbox on the rubric but there were many designs where I had no clue how I could do it without one and without making the code highly complex.
Isn't it more appropriate to say that Verilog is weird because of hardware? Once you go down to the lower levels you enter another realm that requires a completely different way of thinking. HW dev is not comparable to software in any way just because Verilog is a language.
I remember reading Verilog HDL Synthesis: A Practical Primer by J. Bhasker in University and found it incredibly useful for learning the synthesizable subset of Verilog and all the unwritten rules of how you need to write the code to make it synthesize a certain way.
I used that knowledge to write tetris in Verilog that output to VGA which after testing at the wave level in editor worked the first time I actually loaded it onto real hardware.[0]
I believe I understand the ideas behind Verilog. I see the problem rather in the fact that there are few tutorials available that lead you from beginner to decent "Verilog programmer". The problem begins already in the fact which FPGA board to buy, how to setup and use the environment, what software is freely available, how much does the code depend on the specific board, how to debug the code etc.
For programming there is good material for this available, but not for VHDL/Verilog.
>Is it impossible to do hardware development in C and automatically convert C to Verilog?
Yes, it is. C can be converted to Verilog only if you structure the C code as if it were Verilog.
You have to understand that, fundamentally, the CPU is a lie. It is an illusionary abstraction layer fashioned out of bare transistors that pretends to be a von Neumann architecture machine, with a nice set of registers, a instruction pointer, and so forth that chugs dutifully through assembly language instructions, one after another. (Note that nothing about the von Neumann architecture requires binary; for example, the Babbage Analytical Engine computed in decimal.)
At the transistor / gate level, _everything_ is parallel until you impose some order on it and build in clocks and flipflops and so forth to impose some sort of structure and chronological ordering on things. Few, if any, high-level languages are equipped to describe that in any sensible way.
Verilog, VHDL, and so forth are not "weird". These HDLs, while not without their warts, describes the underlying reality of computing. It is assembly language and the high-level languages that are "weird".
Perhaps I'm reading too far into what you wrote, but I'm not sure I agree that the CPU is fundamentally different from other layers of abstraction in computer systems.
All abstractions “lie” in the sense that they present a perspective of the world that is slightly different to the reality — function calls “lie” about the operations that are really being performed, the ISA “lies” about the electronics of the CPU, and transistors “lie” about the underlying behaviour of the universe.
With a CPU, everything is done procedurally. With an FPGA, all the code kind of runs at once. You build your modules and wire them together. The state of the HDL layout is static. There is no stack or heap. If a module is turned on, its doing whatever its supposed to do all the time no matter if you are feeding a real signal into it or not. Imagine threading every possible function you might need in a typical C program and "wiring" everything up with global variables that cannot be initialized at startup. Printf is always printing something and will print out some random garbage at startup unless you tell it to print something else. Simulating larger HDL designs takes a lot of memory because you have to model everything throughout the entire simulation. Simulating a CPU in something like C is much less intensive since you can call an instruction whenever you are ready for it.
I completely appreciate that “writing hardware” is a totally different problem to writing software, and that hardware comes with its own set of quirks and challenges. I'm just saying that I don't think the CPU is fundamentally different than other abstractions in the stack.
C obviously isn't a good fit for a hardware language — it's designed for software! That doesn't mean that there doesn't exist similarly abstract ways of writing hardware though (that express the inherent parallelism, etc.). It is likely that these “higher level languages for hardware” would result in less efficient hardware solutions, but that's always a trade-off that is made through abstractions. Writing a program in properly scheduled assembly code is going to be a lot more efficient than writing the same program in C.
The difference with hardware in terms of language abstractions is not that it behaves differently to software. We could easily define a programming language that expresses parallelism in a way that would map nicely to hardware. The problem, from my perspective at least (please correct me if you think I'm wrong) is that hardware needs to be extremely efficient — particularly because it cannot be easily changed. As a result, hardware languages don't tend to be particularly abstract. But this doesn't mean that hardware languages couldn't be more abstract!
Probably the highest level of abstraction for Verilog is using something like Altera's IP cores. They are binary blobs intended for a specific FPGA model that can be hooked up like any other module but they are configurable for things like bandwidth, latency, and various inputs. You can use things like floating point arithmetic modules or cores used to create things like phase locked loops, a way to convert an input frequency to a different frequency typically using a multiplier and divider. You don't need to know how these modules work underneath, its proprietary anyway but there are usually reference designs you can look at. For example, with a few clicks you can create something like a VGA driver that could interface with a synthesized CPU to create a terminal for it. You can do some neat things with IP cores but there are probably some issues with using them in a commercial form.
You know how you can't just compile normal C to a GPU and expect a speed up because the underlying computational models are so different? It's like that, just a few orders of magnitude worse.
To look at it another way, what does one gain? Hardware is highly parallelizable and HDLs give you that capability by default. Verilog is a really easy language to learn. The hard part is learning how to do hardware design.
You can do a lot with Verilog as long as you don't intend for it to run on an actual FPGA. You can initialize registers to values, print to a console, and add in hardware delays for timing. Simulation is what Verilog was meant to do in the first place. Once you want to actually synthesize the code and run it on some hardware, you have to get more creative in how you layout your code. Like having a reset input for the module so it can trigger certain events whenever you want (i.e. register initialization). So when you write your testbench, you must activate the reset input (or have something similar to a reset button on your actual hardware) before trying to use the module otherwise all the registers will just have random junk values. In my class projects we would always have a dedicated reset button on the board that would need to be pressed before you could test the design. In a production design, the reset would be tied to some sort of automatic reset (like a one shot timer or a microcontroller) when the device powers up.
I remember taking a course in college on digital logic. I wanted a light to blink on and off, so I toggled it every clock. Of course that's just a dim light, because lights toggle on and off very fast normally when they're on.
But how do you then explain the button on my FPGA that was not used in my Verilog anywhere that could switch the light off?
I think the answer ended up being that it was switching fast enough that small amounts of leakage current was enough to register as a TRUE value. And that 'undefined behavior' is worse than in C.
There's a (decade old+) paper on using genetic algorithms to design an FPGA for discriminating tones. The final design after hundreds of generations? The input wasn't connected to the output! It relied on physical details and even iirc stopped working as the FPGA temperature rose.
I've seen a similar paper quoted in one of the books on my shelf talking about a really long chain of logic gates that evolved in an FPGA for some physically situated agent (aka, robot). The chain couldn't be doing anything from a discrete logic point of view, so they got rid of it to "improve the final design". But once they did, the robot couldn't perform it's task anymore. Turned out the chain was being used as an antenna and was pumping RF information into the chip in order to help accomplish it's task.
Verilog has many drawbacks, including no support for structured signals. On the other hand, the other big language, VHDL, is really difficult to use for "modular" projects. Is anyone here familiar with CHDL, a C++ hardware design language?
Could you elaborate on why you hate it? I like it, to be honest. Despite its inefficiencies, it feels way more robust. I don't know much about Verilog, but it feels more like a hacky scripting language than a proper engineering tool.
HDLs and FPGAs, such luxury. In my undergraduate days, we had to design a 32-bit processor by laying out individual transistors by hand (n-wells, p-wells, polysilicon gates, and metallization layers) in a 25 micron CMOS process with two metallization layers in very little chip area and then prove that it worked in simulation. It was like Tetris from hell; I'm still proud of the compact barrel shifter design I came up with. We also had the option, which I will forever regret not taking, to have the chip physically fabbed as well, as long as we agreed to do the work to validate it afterward.
If Chisel is lower level than SystemC or SystemVerilog, and those two have much more acceptance, why go with Chisel ? Aren't modern systems complex enough to justify abstraction ?
I don't think they do have much adoption. SystemVerilog is still Verilog, and most of the new functions are aimed at simulation and testbench use. SystemC is rather painful as you have to write an artificially constrained subset and style of C.
> "Vendors pushing high-level synthesis have a decades long track record of overpromising and under-delivering."
Abstraction is important, but in hardware detail matters. In software you can afford to have a less efficient language if it results in faster development. This is absolutely not true of hardware.
High-level synthesis has usually held out misleading promises of portability; that you might be able to get some complex application working written by (cheaper, easier to hire) software developers, then just drop it straight onto a chip. That's simply not true because the constraints are different.
Chisel looks extremely promising, as it addresses a lot of what I'd say were Verilog pain points:
Algebraic construction and wiring
Abstract data types and interfaces
Bulk connections
Hierarchical + object oriented + functional construction
SystemVerilog does seem to be used more and more. It is just verilog from the designer's perspective, but you have less chance to make mistakes, easier to write and the synthesis tool has more control over how to optimize the design.
The author doesn't have this correct. Chisel is a domain specific language for hardware written in Scala that emits Verilog in Chisel2 or an intermediate representation of RTL (FRRITL) in Chisel3 which is then compiled in an LLVM-like fashion (passes that transform the FIRRTL) to Verilog.
SystemVerilog has all sorts of nice object-oriented features, but you can't use any of them for synthesizable code as you're dependent on the tool vendors supporting useful, yet complex things (e.g., classes, inheritance). Chisel avoids this whole problem by giving you access to extremely useful programming features (e.g., classes, functional programming) while still maintaining compatibility with whatever your ASIC/FPGA toolflow is.
Chisel has a lower level model, but since it's Scala, it's a much higher level language than SystemC or SystemVerilog.
Sure you have to specify things at the gate level, but you have the power to build abstractions on top of that (and indeed most of the ones other HDLs would provide are already there).
Seems like a lousy industry to be in. Lower wages, lower expectations, shooting themself in the foot.
Seems that unlike software devs, hardware devs don't have a say, they're merely drones to their managers. In software, lead dev will say that they need this linter, and his superior will have to either provide or argue. But it seems that ib hardware, management will just say "no", end of storg. You're not getting anywhere with this attitude.
This can also be so in software dev - in defunct bigcos.