3
votes

I've been programming in more functional-style languages and have gotten to appreciate things like tuples, and higher-order functions such as maps, and folds/aggregates. Do either VHDL or Verilog have any of these kinds of constructs?

It seems like an HDL would be the perfect application of these kinds of pure combinators—while these combinators are merely simulated by an imperative process in Haskell, F#, LINQ, etc., hardware actually is pure functionality between clock ticks.

An initial glance, both languages look oddly imperative. To me it seems so weird that imperative CPU applications are starting to be written in functional languages, while functional HDL code is written in an imperative-looking style.

Anyway, the question is, is there any way to do even simple things like

divByThreeCount = count (\x -> x `mod` 3 == 0) myArray

or

myArray2 = map (\x -> x `mod` 3) myArray

or even better yet let me define my own higher-level constructs recursively, in either of these languages? If not, which language is the closest?

Does either language seem to be planning on making progress in that direction? Or is this really not as useful as I, being a rookie in HDLs, would think?

2
What would HDLs look like as hardware? As you know, it's not possible to send circuits through wires. Are you only interested in higher-order functions that operate at compile time?Tanner Swett
@TannerL.Swett correct. Obviously things that require dynamic memory allocation won't work. It might be possible to do some kind of continuation passing that compiles into a state machine that gets executed over multiple clock cycles, but that's far beyond what I'm asking. Just asking for some higher-order functions and combinators that can operate at compile time on fixed-size arrays.lobsterism
Well, there may exist hardware descriptions languages that are embedded in Haskell. Each module could be represented as a value of type Module, and then you could easily define a module parameterized by whatever type you like.Tanner Swett

2 Answers

4
votes

I think you're right that there is a clash between the imperative style of HDLs and the more functional aspects of combinatorial circuits. Describing parallel circuits with languages which are linear in nature is odd, but I think a full blown functional HDL would be a disaster.

The thing with functional languages (I find) is that it's very easy to write code which takes huge resources, either in time, memory, or processing power. That's their power; they can express complexity quite succinctly, but they do so at the expense of resource management. Put that in an HDL and I think you'll have a lot of large, power hungry designs when synthesised.

Take your map example:

myArray2 = map (\x -> x `mod` 3) myArray

How would you like that to synthesize? To me you've described a modulo operator per element of the array. Ignoring the fact that modulo isn't cheap, was that what you intended, and how would you change it if it wasn't? If I start breaking that function up in some way so that I can say "instantiate a single operator and use it multiple times" I lost a lot of the power of functional languages.

...and then we've got retained state. Retained state is everywhere in hardware. You need it. You certainly wouldn't use a purely functional language.

That said, don't throw away your functional design patterns. Combinatorial processes (VHDL) and "always blocks" (Verilog) can be viewed as functions that apply themselves to the data presented at their input. Pipelines can be viewed as chains of functions. Often the way you structure a design looks functional, and can share a lot with the "Actor" design pattern that's popular in Erlang.

So is there stuff to learn from functional programming? Certainly. Do I wish VHDL and Verilog took more from functional languages? Sometimes. The trouble is functional languages get too high level too quickly. If I can't distinguish between "use one instance of f() many times" and "use many instances of f()" then it doesn't do what a Hardware Description Language must do... describe hardware.

1
votes

Have a look at http://clash-lang.org for an example of a higher-order language that is transpiled into VHDL/Verilog. It allows functions to be passed as arguments, currying etc., even a limited set of recursive data structures (Vec). As you would expect the pure moore function instantiates a stateful Moore machine given step/output functions and a start state. It has this signature:

moore :: (s -> i -> s) -> (s -> o) -> s -> Signal i -> Signal o

Signals model the time-evolved values in sequential logic.