VHDL Code Generation
VHDL is a Hardware Description Language that is used for describing a digital system either for designs, tests, or synthesis onto some programmable hardware (ie a FPGA). It is a language that I hate the feel of, but love what is below the surface. Thanks to its history in Ada, it has a very nice type system. Much of what I dislike is also tied to Ada influences, the syntax. It is syntaxtically verbose, with the code style following along. For anyone who has programmed vhdl has most certainly written signalname: std_logic_vector(x downto 0);
many times over and over. Many of the vhdl forms have their own peculiarities. All of these different forms, sometimes for similar uses creates an attitude of "there is more than one way to code it". Lastly, the code does not seem to have a standard method of indentation. For some this point may seem minor, but for the readability of code indentation is very helpful in seeing the structure.
Ideally I think a HDL should have a different set of priorities.
-
Simple regular language
-
Focus on synthesizable forms
-
Abbreviate common forms (state machines, combinational logic, ranges)
-
Sane indentation and code style
-
Ensure edge cases can be described
<!--:truncate:-->
For these reasons I built up a simple language ModV. It is an intermediate language that compiles down to VHDL.It does a decent job at the first few points and it leaves the possibility of offloading unknown edge cases to VHDL.
Language Description
Headers
One entity is described per file starting with the header that states the name and the ports. For vector ports, the size of the port or a range can be specified. At this time, all ranges are assumed to be high to low.
module entity_name --port declarations head: gen generic logv[8] input in log clk in log output out logv[7..0] end
Signals
Signal declarations look similar to VHDL declarations with minor syntactical changes. As groups of signals are common, they can be placed into blocks.
--inline signals signal sig integer --block signals signal: test logv[8] foobar boolean(false) asig, bsig, csig log end
Defining Basic Types
As state machines are one of the important elements of digital hardware, they have their own syntax for definitions.
enum state_t(state_a,state_b,testing) signal state state_t
Basic Combinational Logic
For basic combinational logic, the when and with-input-select statements have been translated into alternatives. The idiom of setting something to '1’s or '0’s using the (others ⇒ val)
form is fairly common so that is abbreviated with *.
--ternary operator output = input=='1' ? gen : *'0' --Lookup tables test = lookup(state): state_a: 0xab state_b: 0x4f others: 0xff end
Synchronous Systems
Synchronous systems need to have actions on a clock edge. The basic statement of a synchronous block requires the clock as an input to determine when to perform the assignments. Inside of this block an extra set of statements become available. This is a result of the thin veil over the way VHDL distinguishes between combinational and sequential logic.
sync(clk): --abbreviated one statement blocks if(sig==123) foobar = true case(test) 0xab: asig = 1 bsig = 0 0xf0: asig = 1 bsig = 1 others: asig = 0 bsig = 0 end async x = y end
A Full Example
In order to get a better feel for this, a simple Hex Display Decoder was created. In my opinion this is a fairly clean result.
module HexDisplay head: D in logv[4] en in boolean Q out logv[7] end arch: signal hex logv[7] Q = en ? hex : *'1' hex = lookup(D): 0x0:"1000000" 0x1:"1111001" 0x2:"0100100" 0x3:"0110000" 0x4:"0011001" 0x5:"0010010" 0x6:"0000010" 0x7:"1111000" 0x8:"0000000" 0x9:"0011000" 0xa:"0001000" 0xb:"0000011" 0xc:"1000110" 0xd:"0100001" 0xe:"0000110" 0xf:"0001110" end end
Implementation
With this idea in mind a simple implementation was created using yacc and lex. This implementation is by no means robust or very well written, but it does translate the listed forms into their vhdl equivalents. This is hosted in git and can be downloaded from: git://fundamental-code.com/modv
Synthesizer Integration
Currently one demo of a synthesizer integration is available with Altera Quartus. Assuming that their tools are in the path, the project ("here":http://fundamental-code.com/log/modv/modv-stopwatch.tar.gz) should build a working project for the DE1 Board. As most people (that I have seen) tend not to call the binary tools for synthesis directly, I have the project populated with the generated files.
Future
I am not sure if I am going to work on extending this project in the future too much. It mostly depends if I get any response and if I am doing significant work in vhdl for synthesis. If future work is done, then the priorities are:
-
Error Handling
-
Parser cleanup
-
Sanity checks on semantics
EDIT: a sane translation of VHDL records should also be added to the implementation.