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.
"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.
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.
Another example is that defining barrel shifters is impossible to parameterize, because you need to hardcode the mux cases (see the Xilinx datasheet). 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.
 http://www.xilinx.com/support/sw_manuals/2_1i/download/xsisy... (pg 51)
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.
Could you please provide a summary? I know optimization is hard and thereby slow. But is that why? Thanks.
Synthesis sometimes feels like a great blind spot in the hierarchy of abstractions. It is hard, critical, and yet appears to be developed only by niche players.
the fact that logic takes so long to synthesize and simulate really has little to do with Verilog's deficiencies
IMO it has everything to do with the open-ended nature of synthesis. When you compile software, it's very procedural. You have a linear chain or network of paths. You construct it. You improve on it where you can. Hardware on the other hand- you have a cloud described in RTL, you construct it. That's not hard. But when you get to improving it? It's like the packing problem, with N elements, and to make things better every element can be substituted with a variety of different shapes!
And software engineers don't crossover to the hardware side often.
So the people suffering with the "slow" tools etc, are usually not in a very good position to do anything about it.
But really, the slow side is in the place and route. If you don't over constrain your design, this can go pretty quickly actually. It's when timing is tight, and first pass guesses aren't coming up with a satisfactory solution that things slow down.
I think there's one EE/CE professor at my university working on the SAT solvers that form the crux of the optimizers in most of these tools, but at the end of the day it's still a bunch of heuristics that, worst case, run in O(2^n) time.
If that's the case, then why are Chisel and bluespec much faster to simulate despite having less investment in tooling?
Take a look at the work of John Koza. His systems were used to automatically generate electrical circuits:
I looked at his stuff a lot when I was trying to pick my path for my MS thesis. I ended up going down a completely different route though.
... combined with features for simulating dynamic loads, say by modeling a party full of people jumping around.
From what I've seen of SystemC, I thought it was basically the same idea but with a different syntax - the entirety is available for simulation, but only a subset of the language constructs are synthesizable.
My advice if you are a programmer or computer scientist and you get tasked with writing Verilog of VHDL "code" you need to be able to explain the difference -- You've just been offered a job as a hardware designer and engineer. Having spent 5 years doing hardware engineering and a lot longer doing software consulting I can say it's an entirely different set of skills if not an entirely different career path.
"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?
Personally, I would love to call this nonsense out: Say, "OK, you get to lead a team that is prohibited from using any Haskell-based solution. My team will compete with yours and must use a Haskell-based solution. May the best team win."
Check for example Lustre/Scade: http://www.esterel-technologies.com/
or its more recent successor Lucid synchrone:
The latter has explicit recursion which can be disabled when designing embedded systems.
Haskell libraries closely follow this paradigm with their functional reactive DSLs.
Recursion is actually useful to recursively define circuits with repeated patterns, e.g., the butterfly FFT.
Could you elaborate on this? Depending on what you mean, I might have a direct counter-example.
* 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.
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.
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.
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.
...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?
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) is a very good match to functional languages, however Sequential logic is "very different" (from an analysis point of view)
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.
As far as monads go, the things that helped me was (1) think of writing in monads not as programming in an imperative language, but as writing a functional program that returns an imperative program (as a value in a rather opaque type), and (2) forget about do-notations and learn about using the arrow-like operators directly.
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:
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]
-> func bind(function,structure): return collapse(map(function,structure))
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.
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?"
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).
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?
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.
The creator did a good talk about it at PyCon Taiwan earlier this year: http://www.youtube.com/watch?v=LSgOpvr8FII
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).
"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.
"Originally, Verilog was intended to describe and allow simulation; only afterwards was support for synthesis added."