A reader pointed me at another HDL generation solution, MyHDL. According to the MyHDL manual,
The goal of the MyHDL project is to empower hardware designers with the elegance and simplicity of the Python language.
Sounds good to me! In the interest of science, I decided to check it out. After reading the manual and tinkering with it for a while, I'm ready to talk about my experience with MyHDL.
MyHDL Features
- Documentation: I was able to install and use MyHDL by following the excellent on-line documentation. Full marks for this!
- Language: MyHDL is a Python package. Python is a decent and usable programming language. It seems about equivalent to Perl, but I get the impression that readable code might flow a little more naturally in Python.
- Built-in verification: this is a big deal. You can code your design in MyHDL and run unit tests against it, all within pure Python. Execution is very fast, and the unit tests have all the power of a modern, "free", high-level language. (Europa has nothing like this.)
- Verilog generation: the toVerilog method converts your design to Verilog. (Right, well, without this feature, MyHDL would be useless.)
- Co-simulation flow (via PLI). I haven't used this yet, but it looks like a well-thought-out story for testing the generated Verilog against the same set of unit tests which were created during the pure-Python design phase. If this works well, it sounds like an extremely useful feature.
- Hierarchy. It should be possible to create a complete, deeply hierarchical design composed of well-defined functional blocks, as I've been demonstrating in Europa.
- Synthesizable subset: it's possible to create a design in MyHDL, and a body of unit tests, only to be informed (by toVerilog) that unsupported language features were used in the design. I don't know that the supported subset will grow as MyHDL is developed - the architecture may prevent this.
- Flat Verilog: toVerilog delivers a single Verilog file with no hierarchy. This is fine for small designs, but I foresee that this flat output structure will be inadequate for large, complex designs. Of course, you could verify an entire system in one step, then generate each system sub-module's Verilog file as a separate step, but then the top-level instance that stitches all the sub-modules together will not have been verified.
Simple example: switchable inverter
I'll start off with the simplest imaginable example: a purely combinational module with one input and one output. The output is either the same as the input, or its logical inverse, according to a generation parameter. Don't close your browser window - even this simple example demonstrates interesting facets of MyHDL.
Here's the implementation:
from myhdl import always_comb def inv_or_buf(mode, a, x): @always_comb def buffer(): x.next = a @always_comb def inverter(): x.next = not a if (mode == 0): logic = buffer else: logic = inverter return logic
A few things to note:
- inv_or_buf is a function which returns a locally-defined function (in this case, either buffer or inverter, depending on the generation parameter mode)
- Regular python operators are used to model the logic (either python's not operator, or a simple assignment)
- Suppose mode were used within a single local function to determine whether to buffer or invert the input? Then I'd have a 2-input combinational function, which may seem familiar - in fact, it's a 2-input XOR gate. So, input parameters are either treated as HDL module ports or as generation-time parameters - which it is depends on how the parameters are used.
- Two local functions are created, but only one is returned. This is a MyHDL idiom for creating parameterized logic. (Many thanks to reader Stefaan for his hints on this - It's alien enough to my usual way of thinking that I don't think I would have hit upon it.)
- always_comb is a decorator on the locally-defined functions, which are generator functions. For more info on these topics, you'll want to refer to the MyHDL and python documentation.
Here's something that stands out for me about MyHDL: the low-level routines which define behavior are very simple, with not much more expressive power than the HDL they will eventually be transformed to. If you want to define behavior which depends on a parameter, then for all but the simplest of behaviors, you must declare logic for all possible parameter values, and then conditionally return only the logic which corresponds to the particular parameterization. There is a special case which allows for building ROM-like logic (anything where an output doesn't depend on inputs in an easily-computable way); fortunately, you can make any combinational logic function in ROM-like logic. I rely on this in my implementation of the Avalon-ST error adapter, which I'll get to later.
Generating some Verilog
Here's some code to invoke inv_or_buf, and produce Verilog:
from myhdl import toVerilog, Signal, intbv from inv_or_buf import inv_or_buf def make_some_verilog(mode, name): a = Signal(intbv(0)[1:]) x = Signal(intbv(0)[1:]) toVerilog.name = name toVerilog(inv_or_buf, mode, a, x) make_some_verilog(0, "buffer") make_some_verilog(1, "inverter")
The resulting Verilog output shows up in two files:
buffer.v:
module buffer ( a, x ); input [0:0] a; output [0:0] x; wire [0:0] x; assign x = a; endmodule
inverter.v:
module inverter ( a, x ); input [0:0] a; output [0:0] x; wire [0:0] x; assign x = (!a); endmodule
The output is not the most readable code you've ever seen, but it does appear to be correct.
Leaving some for later
That's it for now. I haven't touched on MyHDL unit testing, which is one of its major strengths - I'll leave that for a future article.
Comments (1)
As you may know, I'm a big fan of Python. But this was the first I've heard of MyHDL.
I'm impressed it uses decorators and generators, which have been added to Python fairly recently.
I'll look forward to your article on MyHDL unit testing. There are a lot of different tools out there to support unit testing in Python--I wonder if MyHDL recommends or requires any of them.
Posted by Daryl Spitzer | February 7, 2008 8:45 AM
Posted on February 7, 2008 08:45