简体   繁体   中英

Dynamic Instantiation: How to dynamically wire interfaces in myHDL

I'm trying to make a python library for dynamically making a UART interface between a PC and FPGA using pySerial using myHDL 1.0dev

It takes names for datatypes and their properties, and instantiates a RAM block, as well as allow access to read/write commands on the PC. However, I'm running into problems dynamically wiring the RAMs.

For a minimal working example, I have these two classes.

class RamBus(object):
    def __init__(self):
        self.clk     = Signal(bool(0))

class UartBus(object):
    def __init__(self):
        self.interfaces = dict()
    def add(self, name, bus):
        self.interfaces[name] = bus
        setattr(self,name,bus)

UartBus is for holding many RamBuses. Now I'll try to dynamically connect them with the arbiter block.

@block
def arbiter(clk,uartbus):
    modules = []
    for key in uartbus.interfaces:
        print key

        @block
        def electrician(rambus=uartbus.interfaces[key]):
            @always_comb
            def wiring():
                rambus.clk.next = clk
            return wiring
        f = electrician
        modules.append(electrician())
    return modules

If I convert it with this code, I get an incorrect conversion

uartbus = UartBus()

uartbus.add('power',RamBus())
uartbus.add('freq',RamBus())

#attempt conversion
clk = Signal(bool(0))
arbiter(clk,uartbus).convert()

Here's the incorrect verilog.

`timescale 1ns/10ps

module arbiter (
    clk
);


input clk;

wire electrician_0_rambus_clk;
wire electrician_0_rambus_clk;

assign electrician_0_rambus_clk = clk;
assign electrician_0_rambus_clk = clk;

endmodule

And both wires have the same name! Using dictionaries in side the @always_comb doesn't work because dictionaries aren't supported by any version of myHDL so far for conversion. How do I correctly implement dynamic wiring?

So I found out the answer, while I was writing this, and since I think its a useful trick to know I decided to post the question anyways.

@block
def arbiter(clk,uartbus):
    modules = []
    for key in uartbus.interfaces:

        #note that there is no @block here!
        def electrician(rambus=uartbus.interfaces[key]):
            @always_comb
            def wiring():
                rambus.clk.next = clk
            return wiring

        #here we can redefine the name that electrician 
        #has so that myHDL converts it with that name.
        electrician.func_name = key
        #then we apply the block decorator
        electrician = block(electrician)

        modules.append(electrician())
        print key

    return modules

And here is the correct verilog.

// File: arbiter.v
// Generated by MyHDL 1.0dev
// Date: Tue Jun 28 14:03:01 2016

`timescale 1ns/10ps

module arbiter (
    clk
);


input clk;

wire freq_0_rambus_clk;
wire power_0_rambus_clk;

assign freq_0_rambus_clk = clk;
assign power_0_rambus_clk = clk;

endmodule

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM