It’s Saturday night and I have been cleaning up my github repos. And I found this old defunct project I wrote few years ago. So, I thought to write this post about it.
This is a quick prototype for Python Hardware Description Language(Ironically, Named PHDL). Basically, I wanted to figure out semantics to specify verilog design programmatically. I started with defining components I need to generate a module. The snippet below shows Port
and Parameter
. I am using python templates to generate fragments of texts after full tree is build.
I used the most confusing variable names. Don’t mind me. That’s just me committing python war crimes.
class Port(Signal):
def __init__(self,direction, *args):
Signal.__init__(self, *args)
self.direction = direction
def render(self):
pdims = "".join([f"[{p.MSB}:{p.LSB}]" for p in self.pdims])
updims = "".join([f"[{p.MSB}:{p.LSB}]" for p in self.updims])
txt = f"{self.direction} {self.type_} {pdims} {self.name} {updims}"
return txt
class Parameter():
def __init__(self, name="", type_ = "", value=None, **kargs):
self.name = name
self.type_ = type_
self.value = value
def render(self):
txt = f"parameter {self.name} {self.type_}" + (f"= {self.value}" if self.value else "")
return txt
400 lines later, I had the infra done to specify simple modules and instance as follows
import verilog as verilog
m = verilog.Module(name="top")
m.ports.append(verilog.Port("input","p1", "logic",[verilog.Dimension(0,3)]))
m.ports.append(verilog.Port("input","p2", "logic",[verilog.Dimension(0,3)]))
m.params.append(verilog.Parameter("pr1",value=3))
m.items.append(verilog.Instance(name="u_controller",
module="controller",
params_override=[("ff",3)],
ports_conn=[("ff",3)]
))
print(m.render())
And the output generated as follows. I know. Not great but not terrible.
module #(parameter pr1 = 3) top (input logic [0:3] p1 ,input logic [0:3] p2 );
controller #( .ff(3) ) u_controller(.ff(3));
endmodule