I'm very interested in programming languages and HDLs, and I was curious as to which features of HDLs you find the most helpful/expressive, or the most frustrating. I only have experience with Verilog, but I'm also curious about your insights into languages like VHDL, Migen, SpinalHDL, etc. as well. I'm not asking this to start a flame war about which is the "best" language, but just to get a deeper insight into which syntactical features and idioms are particularly useful, and which make expressing a design awkward or difficult. I'm thinking of developing an HDL embedded in Racket (a lisp/scheme language), which is why I'm asking.
First question would be: have you looked at existing alternative HDLs, such as - as you mentioned - SpinalHDL, nMigen, Chisel, ...?
What do you think you could do better or at least differently, apart from using Racket? Also what's your rationale for using Racket here?
I understand that your topic is to help you answer at least the two first questions, but IMHO, if you're not skilled enough in existing HDLs to be able to answer this yourself, designing a new HDL might be a tricky endeavour. Now getting feedback from others is always good, but I think that would have helped if you had started by exposing what you intended on implementing and why.
I may add thoughts as the thread unfolds. Oh and you were well inspired to warn against starting a language war, but - unless no one posts here - I think it has a good chance of happening anyway.
to get a deeper insight into which syntactical features and idioms are particularly useful, and which make expressing a design awkward or difficult.
In that case, the following paper should be of interest to you:
An Implementation of Lola-2 or Translating from Lola to Verilog by N.Wirth, 30.11.2014
https://people.inf.ethz.ch/wirth/Lola/LolaCompiler.pdf
First question would be: have you looked at existing alternative HDLs, such as - as you mentioned - SpinalHDL, nMigen, Chisel, ...?
I've looked at nMigen to some degree, however the documentation is rather limited at this phase so the learning curve feels pretty steep.
What do you think you could do better or at least differently, apart from using Racket? Also what's your rationale for using Racket here?
One advantage of nMigen is that it is embedded into Python, so that in addition to describing hardware with the nMigen libraries, you can make use of the rest of Python to allow for more automation and generation of your HDL. A really trivial example would be calculating filter coefficients and then inserting them into the design. Unfortunately the syntax nMigen uses for describing hardware is pretty awkward because it has to conform to Python's syntax. Racket allows you to extend its syntax pretty easily, and so I think it would be possible to create a really clean embedded HDL. The advantages would be having an elegant syntax for the HDL, while still having access to Racket as full featured programming language for automation and generation.
I understand that your topic is to help you answer at least the two first questions, but IMHO, if you're not skilled enough in existing HDLs to be able to answer this yourself, designing a new HDL might be a tricky endeavour. Now getting feedback from others is always good, but I think that would have helped if you had started by exposing what you intended on implementing and why.
I agree with you. For Verilog, some of the things that annoy me about its syntax is that you can't write to the same register in different always blocks, even if the logic is designed so that there will never be an issue with multiple drivers to a single register. For example:
// let cond_a and cond_b be mutually exclusive events
// we may write write:
always @(posedge clk) begin
if(cond_a) begin
foo <= 2'b1;
end
else(cond_b) begin
foo <= 2'b3;
end
end
// but if cond_a and cond_b are generated by fairly unrelated portions of the design
// it might be nice to have separate always blocks in different parts of the code to
// write to foo. For example:
always @(posedge clk) begin
if(cond_a) begin
foo <= 2'b1;
end
// some more stuff here
end
// lots more stuff here
always @(posedge clk) begin
if(cond_b) begin
foo <= 2'b3;
end
// some more stuff here
end
// while in some cases this might be a lot more clear and readable,
// it is illegal in Verilog
Another feature I think might be really nice in Verilog, is a way to group a set of signals together and refer to them as a single bus. There are certainly ways to do this quickly, but it might be nice to have something like the record type that VHDL has.
I certainly don't know enough about other HDLs to actually attempt to write one yet, but I was hoping that some people would point out things they liked in various languages, so I could go investigate them and learn about useful features/idioms.
Another feature I think might be really nice in Verilog, is a way to group a set of signals together and refer to them as a single bus. There are certainly ways to do this quickly, but it might be nice to have something like the record type that VHDL has.
Take a look at SystemVerilog. It's got all of those, and more!
One advantage of nMigen is that it is embedded into Python, so that in addition to describing hardware with the nMigen libraries, you can make use of the rest of Python to allow for more automation and generation of your HDL. A really trivial example would be calculating filter coefficients and then inserting them into the design. Unfortunately the syntax nMigen uses for describing hardware is pretty awkward because it has to conform to Python's syntax. Racket allows you to extend its syntax pretty easily, and so I think it would be possible to create a really clean embedded HDL. The advantages would be having an elegant syntax for the HDL, while still having access to Racket as full featured programming language for automation and generation.
I get why you are thinking this way, but I think if you are looking to use a high level language to generate your HDL you would be best served by sticking to a language with extensive library support, documentation, examples, and a wide base of knowledgeable developers. Python is obviously pretty good here as one of the most popular languages in the world, and while it isn't on the same level as LISP in terms of defining custom syntax for domain specific languages it is way better than most of the other top 10 programming languages. I'm not saying you have to use python, but I would really try to use a more popular language even if the syntax isn't quite as elegant as you would like.
I'm only interested in synthesis and that is best done with factory tools. Unless it is supported by Vivado, I probably don't care what an alternative HDL can do.
I suppose there could be a macro like language over the top of VHDL/Verilog/SystemVerilog but I don't see why.
I'm only interested in synthesis and that is best done with factory tools. Unless it is supported by Vivado, I probably don't care what an alternative HDL can do.
I suppose there could be a macro like language over the top of VHDL/Verilog/SystemVerilog but I don't see why.
All alternative HDLs I know of (there may be a few obscure exception in research labs), including those cited above, generate Verilog or VHDL (most use Verilog) as an intermediary, so they are usable with any exisiting synthesis tool (otherwise their applicability would be more than extremely limited.)
I'm pretty sure that's what the OP has in mind too.
I'm only interested in synthesis and that is best done with factory tools. Unless it is supported by Vivado, I probably don't care what an alternative HDL can do.
That is exactly what all of these tools do. They are basically a set of libraries / macros for a conventional programming language such that execution of the program on a CPU produces Verilog or other HDL for synthesis. They are basically like a *much* more expressive version of verilog 'generate' blocks that also let you take advantage of all of the other functionality of the conventional programming language.
There's nothing wrong with macros.
But what you can do with some alternative HDLs would be very clunky to do with macros, or generics, or whatever. That's the whole point. It's a bit the same idea as implementing any other new programming language.
Now, as was discussed in others threads, actually using an "odd" (read: not widely known or accepted) HDL is a tough choice that I would personally not make. But admittedly, some, like SiFive, have done it with Chisel with success. Pick your poison.
The problem with macros (and with any DSL for that matter) is that it's extremely easy to overuse them and turn your code into un-comprehendible mess. It's like that infamous joke about Perl scripts, which are often easier to re-write from scratch rather than to figure out how existing ones work, hence the name - "write-only code". I'm sure most folks who programmed in C/C++ for any significant amount of time have come across a macros hell - and C preprocessor is a relatively simple macros "language" by modern standards - there are much more sophisticated ones out there nowadays, which can make situation even worse if left unchecked.
The problem with macros (and with any DSL for that matter) is that it's extremely easy to overuse them and turn your code into un-comprehendible mess. It's like that infamous joke about Perl scripts, which are often easier to re-write from scratch rather than to figure out how existing ones work, hence the name - "write-only code". I'm sure most folks who programmed in C/C++ for any significant amount of time have come across a macros hell - and C preprocessor is a relatively simple macros "language" by modern standards - there are much more sophisticated ones out there nowadays, which can make situation even worse if left unchecked.
I agree. VHDL for example is pretty capable in itself. Yet I've seen people writing Python scripts to generate VHDL code which could have been written much simpler in VHDL directly compared to the Python code
"Macros" are good for avoiding using "hard-coded" values in code, making those easier to read and to maintain, and otherwise avoiding repeating the same code sequences.
Of course, if the language you're using already allows this without resorting to "macros", then use the built-in language features. But that's not always the case. VHDL in that regard is pretty good, and with the generic packages introduced in VHDL-2008, there's very little need to write code generators for VHDL, even if you want an extremely configurable design.
Now of course one reason to write an alternative HDL would be to be able to express things in a different way. Something that Chisel allows, for instance.