Skip to content
Snippets Groups Projects
gearbox.py 3.23 KiB
Newer Older
Kia's avatar
Kia committed
from nmigen import *
Kia's avatar
Kia committed
from nmigen.hdl.rec import *

Kia's avatar
Kia committed
from nmigen.cli import main


Kia's avatar
Kia committed
class GearboxBusLayout(Layout):
    def __init__(self, *, in_width, out_width):
        super().__init__([
            # DATA
            ("data_in",        unsigned(in_width)),      # FROM SOURCE
            ("data_out",       unsigned(out_width)),     # TO DEST

            # CONTROL
            ("valid_in",       1),                       # FROM SOURCE
            ("ready_out",      1),                       # TO SOURCE

            ("ready_in",       1),                       # FROM DEST
            ("valid_out",      1),                       # TO DEST

        ])

class GearboxBus(Record):
    def __init__(self, *, in_width, out_width):
        super().__init__(GearboxBusLayout(in_width=in_width, out_width=out_width))

class ArbitraryGearbox(Elaboratable):
        def __init__(self, *, in_width, out_width):
            self.in_width = in_width
            self.out_width = out_width
Kia's avatar
Kia committed
            self.bus = GearboxBus(in_width=in_width, out_width=out_width)
Kia's avatar
Kia committed

        def elaborate(self, platform):
            m = Module()
Kia's avatar
Kia committed
            loop = Signal(1)
            len_storage = self.in_width + self.out_width
            #storage   = Signal(len_storage, reset=0b001_010_011_100_101_110_111)
            #storage   = Signal(len_storage, reset= 0b111_110_101_100_011_010_001)


Kia's avatar
Kia committed
            storage   = Signal(len_storage, reset= 0b1_100_011_00)
Kia's avatar
Kia committed

            write_ptr = Signal(range(len_storage))
Kia's avatar
Kia committed
            read_ptr  = Signal(range(len_storage), reset=2)

            # read index logic here
            with m.If(read_ptr + self.out_width >= len_storage):
                m.d.sync += read_ptr.eq(read_ptr + self.out_width - len_storage)
            with m.Else():
                m.d.sync += read_ptr.eq(read_ptr + self.out_width)

            # read-out case analysis here:

            with m.If(read_ptr + self.out_width <= len_storage):
                m.d.comb += self.bus.data_out.eq(storage.bit_select(read_ptr, self.out_width))
            with m.Else():
Kia's avatar
Kia committed
                with m.Switch(read_ptr):
                    for cand_rptr in range(len_storage - self.out_width + 1, len_storage):
                        with m.Case(cand_rptr):
                            m.d.comb += loop.eq(1)
                            non_wrapping_bitwidth = len_storage - cand_rptr
                            wrapping_bitwidth     = self.out_width + cand_rptr - len_storage
                            m.d.comb += self.bus.data_out.eq(Cat(
                                storage.bit_select(cand_rptr, non_wrapping_bitwidth), # the non-wrapping bits are less-significant
                                storage.bit_select(0,         wrapping_bitwidth)      # ...than the wrapping bit
                                ))
Kia's avatar
Kia committed



Kia's avatar
Kia committed

            return m




class DummyPlug(Elaboratable):

Kia's avatar
Kia committed
    #def __init__(self):
Kia's avatar
Kia committed
    def elaborate(self, platform):
        m = Module()

Kia's avatar
Kia committed
        m.submodules.table = table = ArbitraryGearbox(in_width=(9-3), out_width=3)
Kia's avatar
Kia committed
        counter = Signal(8)
        m.d.sync += counter.eq(counter+1)

        with m.If(counter == 3):
            m.d.comb += table.bus.data_in.eq(1)
Kia's avatar
Kia committed

Kia's avatar
Kia committed
if __name__ == '__main__':
    baka =DummyPlug()
Kia's avatar
Kia committed
    main(baka)
    #platform.build(DummyPlug())