
Why hardware development is hard: Verilog is weird - luu
http://danluu.github.io/blog/2013/09/07/why-hardware-development-is-hard/
======
austinz
The problem is that Verilog/VHDL isn't a "programming language" in the sense
that C, Lisp, Haskell, or Python are programming languages. So approaching
them with a programming language mindset is asking for a lot of pain and
misunderstanding.

HDLs like Verilog and VHDL describe digital circuits, not algorithms and
instructions for manipulating data. If C code is akin to instructions for
getting to a grocery store and shopping for vegetables, HDL code is describing
the blueprint of a house textually. Maybe the solution is building some ultra
high level abstraction that can somehow encompass both problem domains, but
given how difficult hardware synthesis with existing HDLs is right now I don't
know if that'll happen anytime soon. And the fact that logic takes so long to
synthesize and simulate really has little to do with Verilog's deficiencies;
if anything it's a limitation of the register-transfer level abstraction
that's currently used to design digital hardware.

~~~
jwise0
The author touches on this, when he says:

"To write Verilog that will produce correct hardware, you have to first
picture the hardware you want to produce."

I think that's the crux of the issue. Most digital designers _do_ have a
picture of the actual hardware, as a block diagram, in their heads. When I
write RTL, the process is very front-loaded: I spend hours with a pen and
paper before I even sit down at the keyboard. The algorithms in question are
only a small part of the work of building functioning hardware; where when
designing software, I would let the compiler make decisions about how long it
expects certain operations to take, and what to inline where, these are all
things that I plot "by hand" when building hardware, before I even open a text
editor.

I think, then, that the author kind of misses the point when he goes on to say
that "you have to figure out how to describe it in this weird C-like [...]
language" \-- to be honest, that's the same for all types of programming: when
I go home and write C, I have to take abstract concepts and express them in
this weird C-like language, too! Arcane syntax is irritating, but is not
something fundamentally 'hard' (unless it's _too_ arcane, anyway).

By the way -- I also often wondered "why the hell does synthesis take so
long?". I originally assumed it was because Xilinx's (and Synopsys's, and ...)
software engineers were terrible and had no idea how to write efficient
programs. This might be true, but I now believe is probably not the majority
of it; if "why's it taking so long?" is a question that interests you, I
recommend looking into the VLSI CAD tools class on Coursera.

[1]
[https://www.coursera.org/course/vlsicad](https://www.coursera.org/course/vlsicad)

~~~
cyanoacry
By far, most of my time spent in FPGA dev so far has been envisioning the
state machines and timing details involved. I use VHDL, so it's never been a
question of "how can I make VHDL output what I want?"\---for me, it's always
the struggle of "why can't I just ask VHDL to make n of these units?", where n
is some upstream provided number.

I think the author might need to step away and look at it from the other side:
how can we take a working, but overly-verbose language like VHDL and make it
more powerful? At least VHDL was envisioned from the beginning as a hardware
description language, and it definitely shows.

~~~
DigitalJack
Generate statements are your friend.

~~~
cyanoacry
VHDL generics and generate work nicely for 1d cases, but for 2d cases
(systolic arrays), it's difficult to make the scripting really work without
hard-coding a bunch of corner cases.

Another example is that defining barrel shifters is impossible to
parameterize, because you need to hardcode the mux cases (see the Xilinx
datasheet[1]). That's kind of insane, considering that bit-shifting is a very
common and basic operation. This is particularly problematic if you're trying
to describe something without having to resort to platform-specific
instantiation blocks.

It's a little frustrating that VHDL doesn't have a higher-level standard
instantiation library, because you're chained to a platform the moment you
start doing anything other than basic flip-flops.

[1]
[http://www.xilinx.com/support/sw_manuals/2_1i/download/xsisy...](http://www.xilinx.com/support/sw_manuals/2_1i/download/xsisyn.pdf)
(pg 51)

~~~
DigitalJack
Well, I suppose you could say assembly is an analog of writing hdl that is
very structural.

I haven't done it myself, but generates can be nested. You'd have to check to
see if your tools support it or not though.

With the xilinx example, I'm not sure what you mean. Is it choosing to do
multi-level muxing vs a naive muxing solution? I'd start by just writing a
simple behavioral version, and only if that didn't meet performance
constraints would I bother doing anything structural about it.

It's late and maybe I'm just not thinking it through. I'll take a stab at some
of this and maybe it'll be clearer to me.

------
tripzilch
So um, _why_ do they hate Haskell?

"it's politically difficult", "scary", "one person suggested banning any
Haskell based solution"

Just going by his description (as I don't know much about hardware design
except a single uni course ~15 years ago), it sounds as if a functional
programming language like Haskell would be a perfect fit?

"one person suggested banning any Haskell based solution" \-- that's pretty
much literally calling a taboo on Haskell.

The article doesn't really name any reasons for this, can anyone here explain,
maybe?

The only reason I can imagine would be perhaps that if you've got some
seasoned veteran hardware developers living breathing verilog that are used to
doing it "this way" for decades, they will be adverse to change, especially if
it means learning a new programming language, perhaps in particular if it
means a new paradigm or because of Haskell's pure/mathematical/function
theoretical bend? (I'm just guessing here)

However (and this is where I'm most probably certainly wrong), if you're
developing systems that cost 8 figures to prototype, and the current solutions
are super slow and/or inaccurate to test, shouldn't even seasoned veterans, at
least some of them, be able to swallow their pride?

~~~
skylan_q
Functional programming doesn't make sense for this sort of thing as you can't
define a circuit recursively. Mitrion-C is an example of a higher-level
functional language aimed at configuring FPGAs. It's pretty useless unless you
have insider knowledge on how the system works.

~~~
DanWaterworth
> you can't define a circuit recursively

Could you elaborate on this? Depending on what you mean, I might have a direct
counter-example.

~~~
stinos
please show that example anyway :P pretty sure skylan_q means you'd run out of
hardware gates if you try something infinite?

~~~
DanWaterworth
Well, you can define a combinational circuit as something that has n inputs
and m outputs and it is one of:

* a gate,

* a circuit that takes two inputs and produces two outputs by swapping the order,

* a circuit that takes one input and produces one output,

* a circuit that takes one input and produces no outputs,

* the circuit obtained by taking two circuits and composing them in serial,

* the circuit obtained by taking two circuits and composing them in parallel.

This produces a simple inductive definition for combinational circuits.
Synchronous, sequential circuits can be obtained by taking a combinational
circuit and connecting the first n outputs to the first n inputs via D flip-
flops. If you want asynchronous circuits, you can add another combinator that
takes a circuit and a connects the first n outputs to the first n inputs
without the flip-flops.

With these definitions, it's quite straight forward to manipulate circuits in
a functional manner.

------
Qantourisc
In school we learned VHDL. I found it EASY to adapt. However you have to ditch
the notion you are working with a programming language.

So either build your own CPU in VHDL specifically optimized for you problem.
Or "code" it like you would build hardware!

This means taking a different look at things:

for example storing in an array: you create a bus: address bus, of the width
you need, data-bus of data width you need to write (keep it reasonable, or you
run out of routing), and a write/read bit. Then hook your counter up to that,
increment the time and databus, and have fun.

~~~
frozenport
VHDL for FPGA's is easy but in the real world you need to deal with things
like latency, PLLs, et al. There are few academic programs that make students
aware of the trials and tribulations in modern hardware design.

------
zhyder
IMO the syntax of Verilog isn't so problematic. Adhering to a simple style
guide will avoid most gotchas. The author does make a passing reference to the
real problems though:

1\. Simulation is many orders of magnitude slower than the same code running
in production (and you see code in production only after many months and
dollars). You don't face this slowdown when writing software.

2\. Compared to software, there is much less code reuse in hardware. With
software, it doesn't cost much if your binary is 10% or even 100% bigger, so
your class can be written a more general/reusable but less efficient way. But
a 10% increase in the size of a chip makes it significantly more expensive, so
as a hardware designer you tend to create one-off 'classes' that are as
efficient as possible, but less general/reusable.

~~~
aylons
You can overcome 2 by building a software that parametrizes your hardware.

Just like a core wizard, you can build a Python scripts that output the
Verilog/VHDL code according to the desired settings. Not only accelerates the
process, but may also prevent bugs on the long run.

------
nnq
> The aversion to Haskell is so severe that when we discussed a hardware style
> here at Google, one person suggested banning any Haskell based solution

...curious, but why would folks in this field even care about what programming
language is this based on? Theoretically abusing the concept, wouldn't you
just use something Brainfuck based if you found a nice way to describe your
hardware using some BF based software and DSL? Most attributes of programming
languages that we software guys care about seem irrelevant at this level, so
Haskell or C or Lisp, why would it matter?

~~~
raverbashing
Well, because some languages are harder. Haskell is a tough nut to crack
(especially the "Monad" thing, but the type system also gives some question
marks as well)

Yeah, functional languages are closer to what hardware does, but more
importantly, they may be close _but not close enough_

As the example showed, you have several side effects. Combinational logic
([http://en.wikipedia.org/wiki/Combinational_logic](http://en.wikipedia.org/wiki/Combinational_logic))
is a very good match to functional languages, however Sequential logic is
"very different" (from an analysis point of view)

------
csense
> not because of deficiencies in [Haskell], but because it’s politically
> difficult to get people to use a Haskell based language

I know tons of languages, but I've never really been able to understand
Haskell. The whole monad thing is just...weird. I've read several
descriptions, and had it explained to me multiple times on HN, but I still
just Don't Get It. And I feel like I _should_ Get It, because I have a degree
in math including an upper-level course in logic.

To me, that suggests a problem with the language design of Haskell -- maybe
monads are a bad abstraction, maybe the syntax should be different, maybe
there's a brilliant and simple explanation that I haven't found yet. But the
bottom line is that the learning curve for people coming from other languages
needs to be a lot lower for Haskell to ever be anything but a tiny niche.

~~~
FreeFull
There isn't much to Monads at all. One problem that some Haskell beginners hit
is that they read some bunk monad explanations and only get confused, and that
monads get so hyped up that when met with the actual description, they try to
look for something more that isn't actually there.

Monads are just a set two or three operations on a data structure, which obey
certain laws. The operations are either ( map(function,structure),
collapse(structure), create(value) ) or ( bind(function,structure),
create(value) ) where you can implement map and collapse in terms of bind, and
vice versa. You don't even need to know the laws to use monads, only to create
a new monad.

map(function,structure) is a function that applies a function to every element
in the structure. Pretty straightforward. For example:

    
    
        -> map(addThree,[1,2,3])
        [4,5,6]
    

Collapse is a function which takes structures embedded in a structure of the
same type, and gets rid of one level. For lists, it's the same as
concatenating all sublists.

    
    
        -> collapse([[],[3,4],[6,1,2]])
        [3,4,6,1,2]
    

Create takes a value and puts it into the structure in the simplest way
possible.

    
    
        -> create(3)
        [3]
    

These three functions are enough to have a monad over your structure, and are
how monads are usually defined in mathematics. But lets look at the
alternative.

For the sake of explaining bind, let's introduce a new function which we will
just use as an example:

    
    
        -> func makeThree(value): return [value,value+1,value+2]
    

Let's say we have a list of values [3,1,5] and we want to apply makeThree on
it to get a new list. Let's try doing it using map.

    
    
        -> map(makeThree,[3,1,5])
        [[3,4,5],[1,2,3],[5,6,7]]
    

We got a list of lists rather than just the simple list we wanted, but we can
use collapse to get it into what we want:

    
    
        -> collapse(map(makeThree,[3,1,5]))
        [3,4,5,1,2,3,5,6,7]
    

And here is an example of using bind to do the same thing:

    
    
        -> func bind(function,structure): return collapse(map(function,structure))
        -> bind(makeThree,[3,1,5])
        [3,4,5,1,2,3,5,6,7]
    

This definition of bind is valid for all monads. I have used the list monad as
an example here, but many other structures are also monads. You don't really
see the power of what you can really do with monads until you use them in a
language that supports them well. In the actual definition of monads, collapse
is called join. The definition using bind is the one that is more popular in
programming, while the definition using join and map is more popular in
mathematics.

I'm not actually going to show what the laws governing the interactions
between these functions are in this comment, but I can explain them if you
ask.

~~~
phyalow
TDIL, thanks!

------
DigitalJack
Something seems off to me about this post.

One generally simulates the RTL long before doing anything with gates. Mostly
because RTL is faster. Only when you have things sufficiently nailed down,
have done all the timing analaysis, etc, do you start running gate sims.

Even for pretty damn large designs, compiling RTL shouldn't be a big
hinderance…minutes instead of hours.

Considering the magnitude of complexity involved with gate sims, I find it
hard to complain. I can't speak for other vendors, but Mentor's questa does a
pretty amazing job at optimizing and running at "speed."

The main issue I think is that simulations are generally single core affairs.
When you've got millions of gates in your design, having to serialize that
event simulation down to a single core is surely going to be a bottleneck.

When the simulators can run on multiple machines, partitioning the design
(this is the tricky part), and run more in parallel, we'll see some speed
advances.

But for that to work, you'd have to be very careful how you do your design. If
it's spaghetti with tentacles reaching out from every part of the design to
every other part, you probably won't have much luck splitting that up for
parallel sims.

Personally, I think verilog _is_ weird, but I come from a VHDL background.
Like verilog you have a subset that is synthesizable, but it's harder to shoot
yourself in the foot with VHDL in my opinion.

I spend a lot of my time in SystemVerilog doing verification these days. It
brings some nice concepts to the verification table, but what an awful
language. It's like they stapled 3 different languages together, and took
everything that is bad about OO and stuffed it in there without ever asking
"Does this actually make Verification easier?"

~~~
owenfi
VCS took 15 minutes for SV recompile and 60+ for clean compile (depending on
level of "clean" and level of "compile") for "large" projects on top of the
line servers.

------
aortega
Obviously hardware development looks hard and weird to software people, in the
same way C++ looks weird to an EE.

It's slow only because the synthesizer makes huge efforts in the optimization
of the design, trying to pack the logic in as little resources as possible.
Shut down optimizations and suddenly its blazing fast (like icarus verilog).

------
shubb
Chip vendors often give you a way to instantiate on chip hardware (memories,
latches, etc).

I found the path of least resistance (and highest performance) was to figure
out what circuit I wanted, then basically use Verilog to wire these primitives
together to make it. By causing verilog to use an actual memory block, rather
than a stack of flipflops, you would yield a nice performance increase also.

The trouble is that doing that isn't vendor neutral, and the whole approach
probably wouldn't be any good if you were targeting ASIC. It was just 'alright
at college'.

In 'real' pro verilog development, do people do this?

~~~
morrad
I'm late to this discussion, but as a "real pro" VHDL coder, I can at least
sate your curiosity.

At my company, we abstract the vendor specific implementations to have a
common interface that we can then use to keep the rest of our code vendor
neutral.

For example, within the "Dual Port RAM" section of our revision control
system, we have separate files that instanciate memory control blocks for
Xilinx Spartan and Altera's Cyclone FPGAs, and generalize the interfaces so
that all I see when creating a design is a vendor agnostic "dpram" component
interface. When I need to use one in our design, I just need to import the
correct file into my build corresponding to the actual FPGA that will be used.
Migrating to another vendor involves changing which file gets during
synthesis.

Cheers.

------
jahagirdar
I would ask your team to take a second look at Bluespec. I had used it for a
project some 4 years back, Even today When I have to code something I wish I
had Bluespec.

------
redcircle
Cyclicity CDL is nice: [http://cyclicity-
cdl.sourceforge.net/cdl.php](http://cyclicity-cdl.sourceforge.net/cdl.php)

~~~
Jach
I'd also like to point out MyHDL:
[http://www.myhdl.org/doku.php](http://www.myhdl.org/doku.php) It allows the
full power of Python (being just another module) while you're developing and
testing, and when you're ready to compile to hardware you can compile the RTL
subset of your program to Verilog or VHDL and take it to hardware from there.

The creator did a good talk about it at PyCon Taiwan earlier this year:
[http://www.youtube.com/watch?v=LSgOpvr8FII](http://www.youtube.com/watch?v=LSgOpvr8FII)

~~~
nwhitehead
MyHDL is great, more people should use it. I find it especially powerful for
building test frameworks. I love using the power of Python for all the
verification logic.

------
zw123456
LOL, I love this thread. Hardware is the new Software! But Hardware
description languages are just that, structured languages that describe
hardware. If you come from a background of programming, it will be hard for
you. I am someone who comes from a background of hardware that had to learn
software, but then when Verilog came along, oh man, was I in heaven. Do not
think of VHDL or Verilog as a language, think of it more in terms of HTML,
HTML is a mark up language for type setting, HDL is a mark up language for
hardware. Hardware is not sequential, everything will happen at the same time
unless you prevent that with a state machine. With sequential languages like C
or Pascal etc., everything happens sequentially unless you go out of you want
to try to make things happen seemingly at once. With HDL, you have the
opposite problem, everything will happen at once on each clock cycle, unless
you make a state maching to make things sequential. Once you see this, and the
amazing power of it, you will see why I say... Hardware is the next Software.

------
owenfi
Isn't the reset synchronous? (Small Quibble)

Agreed that hardware language is generally hard to pick up on but "produced
something random" is a bit strong (excluding bugs in simulators, which are a
bit more common than I would've expected).

------
rootlocus
I'm having a hard time reading this article, considering he starts off with
false information like:

"The problem is that Verilog was originally designed as a language to describe
simulations, so it has constructs to describe arbitrary interactions between
events. When X transitions from 0 to 1, do Y. [...] But then someone had the
bright idea of using Verilog to represent hardware."

Verilog was made from the start with the sole intention of describing
hardware. Hardware programming and software programming are fundamentally
different. Comparing them is irrelevant.

~~~
jonmrodriguez
From Wikipedia:

"Originally, Verilog was intended to describe and allow simulation; only
afterwards was support for synthesis added."

[http://en.wikipedia.org/wiki/Verilog#History](http://en.wikipedia.org/wiki/Verilog#History)

