How to dynamically infer ports?

I have just started with MyHDL and was able to build a demo ip core with it. https://github.com/bonfireprocessor/bonfire-pwm

The project is a simple PWM driver for RGB LEDs with a Wishbone interface.

The only thing I’m struggling with is, that I don’t find a way to dynamically change the top level ports (my target language is VHDL).

The number of LEDs to support is configurable. I want a red, green, blue output port per LED on the VHDL toplevel.

I have not figured out how to do it. I created a class rgb_bundle

class rgb_bundle:
    def __init__(self):
        self.red=Signal(bool(0))
        self.green=Signal(bool(0))
        self.blue=Signal(bool(0))

When I create a single Signal instance of it and pass it to my toplevel block it works fine.
But I want a dynamic number of rgb_bundles which are mapped to ports.

When I pass a list of rgb_bundles it is completely ignored.

My current testcode looks like:

from myhdl import *
from rgb_bundle import *
from bonfire_led_pwm import *
from wishbone_bundle import *
 numChannels=4

wb = Wishbone_bundle(False,4,2,32,False,False)


rgb={}
for i in range(4):
    rgb["rgb_"+str(i)]=rgb_bundle()

clock  = Signal(bool(0))
reset = ResetSignal(0, active=1, isasync=False)


@block
def test(wb,clock,reset,rgb_0,rgb_1, **kwagrs):

    @always_seq(clock.posedge,reset=reset)
    def dummy():
        pass

    return instances()
    test_01=test(wb,clock,reset,**rgb)

The conversion looks as I want it:

entity test is
    port (
        clock: in std_logic;
        reset: in std_logic;
        rgb_0_blue: in std_logic;
        rgb_0_green: in std_logic;
        rgb_0_red: in std_logic;
        rgb_1_blue: in std_logic;
        rgb_1_green: in std_logic;
        rgb_1_red: in std_logic;
        wb_we: in std_logic;
        wb_adr: in std_logic_vector(1 downto 0);
        wb_stb: in std_logic;
        wb_ack: in std_logic;
        wb_cyc: in std_logic;
        wb_db_read: in std_logic_vector(31 downto 0);
        wb_db_write: in std_logic_vector(31 downto 0)
    );
end entity test;

It works because I have hard coded the parameters rgb_1 and rgb_2 for testing purposes, but of course this is not the solution.

I must confess that I’m not proficient in Python.

I hope somebody here can help me.

Thomas

Edit: Fixed the block quotes

Hi Thomas,
Welcome to the MyHDL community!
You hit a weak spot. At the moment conversion of a list of Signals is not supported, and by extrapolation, neither is conversion of a list of interfaces.
@DrPi has a (local) patch for the list of Signals. He creates additional types in a VHDL package.
However a list of Interfaces, as you like to have, takes further effort.
Regards,
Josy

Yeah, this is a limitation. It’s actually non trivial IMO because you end up with all sorts of potential naming corner cases. The real problem is the lack of support for rich semantics in V* that make them poor IRs.

Interestingly, I suspect there is a work around for this using python meta-programming like approaches. Where you effectively create the correct function at run time based on the list - that is you expand out the list at elaboration time. This is potentially a bit flaky because the conversion code tends to look at the code, not the objects.

Thanks for you quick answers. It is a bit unfortunate, because dynamically configurable toplevel ports was one of the problems I hoped to solve with MyHDL. So regarding configuration it currently does not go far beyond the possibilities of VHDL generic/generate.

Nevertheless with my first experiment I found a lot of things I like:

  • Much less boilerplate and redundant coding
  • No generic needed for the sole purpose of configurable bit length
  • Interfaces, which also save a lot of redundant typing
  • The possibility to encapsulate more then one block in a single Python module, so it allows to create libraries
  • Simulation
  • Signals semantics like in VHDL

On the other side the limitations of conversion create a steep learning curve, I spent much more time with getting my code converted to VHDL than getting it correctly simulated.

I’m also struggling with finding a way to write test benches which work well in MyHDL and can be converted to VHDL/Verilog. I will write an extra post for this topic.

I’ve done quite a bit of work on convertible tests. Much of this is in veriutils.

Hi,
Creating a PR for lists in ports is on my high priority TODO list.
Will do ASAP.

My PR is waiting for approval/merge.