Example #1
0
    def _declr(self):
        addClkRstn(self)
        # addr of start of array
        self.base = VectSignal(self.ADDR_WIDTH)

        # input index of item to get
        self.index = Handshaked()
        self.index.DATA_WIDTH.set(log2ceil(self.ITEMS))

        # output item from array
        self.item = Handshaked()._m()
        self.item.DATA_WIDTH.set(self.ITEM_WIDTH)

        self.ITEMS_IN_DATA_WORD = int(self.DATA_WIDTH) // int(self.ITEM_WIDTH)

        with self._paramsShared():
            # interface for communication with datapump
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_LEN.set(1)

        if self.ITEMS_IN_DATA_WORD > 1:
            assert isPow2(self.ITEMS_IN_DATA_WORD)
            f = self.itemSubIndexFifo = HandshakedFifo(Handshaked)
            f.DATA_WIDTH.set(log2ceil(self.ITEMS_IN_DATA_WORD))
            f.DEPTH.set(self.MAX_TRANS_OVERLAP)
Example #2
0
 def _declr(self):
     addClkRstn(self)
     BCD_DIGITS = self.BCD_DIGITS
     bcd = self.din = Handshaked()  # BCD data to convert
     bcd.DATA_WIDTH = 4 * BCD_DIGITS
     bin_ = self.dout = Handshaked()._m()
     bin_.DATA_WIDTH = log2ceil(10 ** BCD_DIGITS - 1)  # Converted output. Retained until next conversion
Example #3
0
 def _declr(self):
     addClkRstn(self)
     assert self.INPUT_WIDTH > 0, self.INPUT_WIDTH
     self.DECIMAL_DIGITS = self.decadic_deciamls_for_bin(self.INPUT_WIDTH)
     self.din = Handshaked()
     self.din.DATA_WIDTH = self.INPUT_WIDTH
     self.dout = Handshaked()._m()
     self.dout.DATA_WIDTH = self.DECIMAL_DIGITS * 4
Example #4
0
    def _declr(self):
        # fundamentals
        self.channel = VectSignal(self.CHANNEL_WIDTH)
        self.error = VectSignal(self.ERROR_WIDTH)
        Handshaked._declr(self)

        # packet transfer signals
        self.endOfPacket = Signal()
        self.startOfPacket = Signal()
Example #5
0
File: st.py Project: Nic30/hwtLib
    def _declr(self):
        # fundamentals
        self.channel = VectSignal(self.CHANNEL_WIDTH)
        self.error = VectSignal(self.ERROR_WIDTH)
        Handshaked._declr(self)

        # packet transfer signals
        self.endOfPacket = Signal()
        self.startOfPacket = Signal()
    def _declr(self):
        Handshaked._declr(self)
        self.addr = VectSignal(self.ADDR_WIDTH)
        # a flag which tells if the data was valid when the time of snapshot of the original register
        self.valid = Signal()

        self.orig_request_addr = VectSignal(self.ADDR_WIDTH)
        self.orig_request_id = VectSignal(self.ID_WIDTH)
        # a flag which tells if the request address equals the addres in orginal register during the time of the snapshot
        self.orig_request_addr_eq = Signal()
        # a flag which tells if this record is generated from input request or if this is a pipeline flush
        self.orig_request_valid = Signal()
Example #7
0
File: cam.py Project: mfkiwl/hwtLib
    def matchHandler(self, mem, key: Handshaked, match_res: Handshaked):

        key_data = key.data
        if self.USE_VLD_BIT:
            key_data = Concat(key.data, BIT.from_py(1))

        out_one_hot = []
        for i in range(self.ITEMS):
            b = mem[i]._eq(key_data)
            out_one_hot.append(b)

        match_res.data(Concat(*reversed(out_one_hot)))
        StreamNode([key], [match_res]).sync()
Example #8
0
File: cam.py Project: mfkiwl/hwtLib
    def _declr_match_io(self):
        if self.MATCH_PORT_CNT is None:
            # single port version
            Cam._declr_match_io(self)
        else:
            # muliport version
            self.match = HObjList(
                [Handshaked() for _ in range(self.MATCH_PORT_CNT)])
            for m in self.match:
                m.DATA_WIDTH = self.KEY_WIDTH

            self.out = HObjList(
                [Handshaked()._m() for _ in range(self.MATCH_PORT_CNT)])
            for o in self.out:
                o.DATA_WIDTH = self.ITEMS
Example #9
0
    def _declr(self):
        with self._paramsShared():
            # user requests
            self.req = AddrSizeHs()

        with self._paramsShared(exclude=({"ID_WIDTH"}, set())):
            self.w = AxiStream()

        if self.ID_WIDTH:
            ack = Handshaked(masterDir=DIRECTION.IN)
            ack.DATA_WIDTH = self.ID_WIDTH
        else:
            ack = HandshakeSync(masterDir=DIRECTION.IN)

        self.ack = ack
Example #10
0
    def _declr(self):
        addClkRstn(self)

        with self._paramsShared():
            # read interface for datapump
            # interface which sending requests to download addr of next block
            self.rDatapump = AxiRDatapumpIntf()._m()
            # because we are downloading only addres of next block
            self.rDatapump.MAX_LEN = 1

            # write interface for datapump
            self.wDatapump = AxiWDatapumpIntf()._m()
            self.wDatapump.MAX_LEN = self.BUFFER_CAPACITY // 2
            assert self.BUFFER_CAPACITY <= self.ITEMS_IN_BLOCK

            # interface for items which should be written into list
            self.dataIn = Handshaked()

        # interface to control internal register
        a = self.baseAddr = RegCntrl()
        a.DATA_WIDTH = self.ADDR_WIDTH

        self.rdPtr = RegCntrl()
        self.wrPtr = RegCntrl()
        for ptr in [self.rdPtr, self.wrPtr]:
            ptr.DATA_WIDTH = self.PTR_WIDTH

        f = self.dataFifo = HandshakedFifo(Handshaked)
        f.EXPORT_SIZE = True
        f.DATA_WIDTH = self.DATA_WIDTH
        f.DEPTH = self.BUFFER_CAPACITY

        self.ALIGN_BITS = log2ceil(self.DATA_WIDTH // 8)
Example #11
0
    def _declr(self):
        addClkRstn(self)

        with self._paramsShared():
            # interface which sending requests to download data
            # and interface which is collecting all data and only data with specified id are processed
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_BYTES = self.BUFFER_CAPACITY // 2 * self.DATA_WIDTH // 8

            self.dataOut = Handshaked()._m()

        # (how much of items remains in block)
        self.inBlockRemain = VectSignal(log2ceil(self.ITEMS_IN_BLOCK + 1))._m()

        # interface to control internal register
        a = self.baseAddr = RegCntrl()
        a.DATA_WIDTH = self.ADDR_WIDTH
        self.rdPtr = RegCntrl()
        self.wrPtr = RegCntrl()
        for ptr in [self.rdPtr, self.wrPtr]:
            ptr.DATA_WIDTH = self.PTR_WIDTH

        f = self.dataFifo = HandshakedFifo(Handshaked)
        f.EXPORT_SIZE = True
        f.DATA_WIDTH = self.DATA_WIDTH
        f.DEPTH = self.BUFFER_CAPACITY
Example #12
0
 def _declr(self):
     addClkRstn(self)
     self.clk.FREQ = self.FREQ
     with self._paramsShared(prefix="LCD_"):
         self.dataOut = Hd44780Intf()._m()
     self.dataIn = Handshaked()
     self.dataIn.DATA_WIDTH = 8
Example #13
0
 def _mkFieldIntf(self, parent: Union[StructIntf, UnionSource],
                  structField: HStructField):
     t = structField.dtype
     path = parent._field_path / structField.name
     if isinstance(t, HUnion):
         i = UnionSource(t, path, parent._instantiateFieldFn)
         i._fieldsToInterfaces = parent._fieldsToInterfaces
         return i
     elif isinstance(t, HStruct):
         i = StructIntf(t, path, parent._instantiateFieldFn)
         i._fieldsToInterfaces = parent._fieldsToInterfaces
         return i
     elif isinstance(t, HStream):
         if self.SHARED_READY:
             raise NotImplementedError(t)
         else:
             i = AxiStream()
             i._updateParamsFrom(self)
             return i
     else:
         if self.SHARED_READY:
             i = VldSynced()
         else:
             i = Handshaked()
         i.DATA_WIDTH = structField.dtype.bit_length()
         return i
Example #14
0
    def _declr(self):
        addClkRstn(self)
        # addr of start of array
        self.base = VectSignal(self.ADDR_WIDTH)

        # input index of item to get
        self.index = Handshaked()
        self.index.DATA_WIDTH.set(log2ceil(self.ITEMS))

        # output item from array
        self.item = Handshaked()._m()
        self.item.DATA_WIDTH.set(self.ITEM_WIDTH)

        self.ITEMS_IN_DATA_WORD = int(self.DATA_WIDTH) // int(self.ITEM_WIDTH)

        with self._paramsShared():
            # interface for communication with datapump
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_LEN.set(1)

        if self.ITEMS_IN_DATA_WORD > 1:
            assert isPow2(self.ITEMS_IN_DATA_WORD)
            f = self.itemSubIndexFifo = HandshakedFifo(Handshaked)
            f.DATA_WIDTH.set(log2ceil(self.ITEMS_IN_DATA_WORD))
            f.DEPTH.set(self.MAX_TRANS_OVERLAP)
Example #15
0
    def _declr(self):
        self._compute_constants()
        addClkRstn(self)
        # used to initialize the LRU data (in the case of cache reset)
        # while set port is active all other ports are blocked
        s = self.set = AddrDataHs()
        s.ADDR_WIDTH = self.INDEX_W
        s.DATA_WIDTH = self.LRU_WIDTH

        # used to increment the LRU data in the case of hit
        self.incr = HObjList(IndexWayHs() for _ in range(self.INCR_PORT_CNT))
        for i in self.incr:
            i.INDEX_WIDTH = self.INDEX_W
            i.WAY_CNT = self.WAY_CNT

        # get a victim for a selected cacheline index
        # The cacheline returned as a victim is also marked as used just now
        vr = self.victim_req = AddrHs()
        vr.ADDR_WIDTH = self.INDEX_W
        vr.ID_WIDTH = 0
        vd = self.victim_data = Handshaked()._m()
        vd.DATA_WIDTH = log2ceil(self.WAY_CNT - 1)

        m = self.lru_mem = RamXorSingleClock()
        m.ADDR_WIDTH = self.INDEX_W
        m.DATA_WIDTH = self.LRU_WIDTH
        m.PORT_CNT = (
            # victim_req preload, victim_req write back or set,
            READ, WRITE,
            #  incr preload, incr write back...
            *flatten((READ, WRITE) for _ in range(self.INCR_PORT_CNT))
        )
Example #16
0
    def _declr(self):
        self.PAGE_OFFSET_WIDTH = log2ceil(self.PAGE_SIZE).val
        self.LVL1_PAGE_TABLE_INDX_WIDTH = log2ceil(
            self.LVL1_PAGE_TABLE_ITEMS).val
        self.LVL2_PAGE_TABLE_INDX_WIDTH = int(self.ADDR_WIDTH -
                                              self.LVL1_PAGE_TABLE_INDX_WIDTH -
                                              self.PAGE_OFFSET_WIDTH)
        self.LVL2_PAGE_TABLE_ITEMS = 2**int(self.LVL2_PAGE_TABLE_INDX_WIDTH)
        assert self.LVL1_PAGE_TABLE_INDX_WIDTH > 0, self.LVL1_PAGE_TABLE_INDX_WIDTH
        assert self.LVL2_PAGE_TABLE_INDX_WIDTH > 0, self.LVL2_PAGE_TABLE_INDX_WIDTH
        assert self.LVL2_PAGE_TABLE_ITEMS > 1, self.LVL2_PAGE_TABLE_ITEMS

        # public interfaces
        addClkRstn(self)
        with self._paramsShared():
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_LEN.set(1)

        i = self.virtIn = Handshaked()
        i._replaceParam(i.DATA_WIDTH, self.VIRT_ADDR_WIDTH)

        i = self.physOut = Handshaked()._m()
        i._replaceParam(i.DATA_WIDTH, self.ADDR_WIDTH)
        self.segfault = Signal()._m()

        self.lvl1Table = BramPort_withoutClk()

        # internal components
        self.lvl1Storage = RamSingleClock()
        self.lvl1Storage.PORT_CNT.set(1)
        self.lvl1Converter = RamAsHs()
        for u in [self.lvl1Table, self.lvl1Converter, self.lvl1Storage]:
            u.DATA_WIDTH.set(self.ADDR_WIDTH)
            u.ADDR_WIDTH.set(self.LVL1_PAGE_TABLE_INDX_WIDTH)

        with self._paramsShared():
            self.lvl2get = ArrayItemGetter()
        self.lvl2get.ITEM_WIDTH.set(self.ADDR_WIDTH)
        self.lvl2get.ITEMS.set(self.LVL2_PAGE_TABLE_ITEMS)

        self.lvl2indxFifo = HandshakedFifo(Handshaked)
        self.lvl2indxFifo.DEPTH.set(self.MAX_OVERLAP // 2)
        self.lvl2indxFifo.DATA_WIDTH.set(self.LVL2_PAGE_TABLE_INDX_WIDTH)

        self.pageOffsetFifo = HandshakedFifo(Handshaked)
        self.pageOffsetFifo.DEPTH.set(self.MAX_OVERLAP)
        self.pageOffsetFifo.DATA_WIDTH.set(self.PAGE_OFFSET_WIDTH)
Example #17
0
    def _declr(self):
        addClkRstn(self)

        with self._paramsShared():
            self.axi_m = Axi3()._m()

        a = self.packetAddr = Handshaked()
        a.DATA_WIDTH = self.ADDR_WIDTH
Example #18
0
    def _declr(self):
        addClkRstn(self)
        with self._paramsShared():
            self.din = Handshaked()
            self.dout = VldSynced()._m()

            self.tx = UartTx()
            self.rx = UartRx()
Example #19
0
 def _declr(self):
     if self.RESULT_WIDTH is None:
         self.RESULT_WIDTH = 2 * self.DATA_WIDTH
     addClkRstn(self)
     self.dataIn = TwoOperandsHs()
     self.dataIn.DATA_WIDTH = self.DATA_WIDTH
     self.dataOut = Handshaked()._m()
     self.dataOut.DATA_WIDTH = self.RESULT_WIDTH
Example #20
0
    def _declr(self):
        with self._paramsShared():
            # user requests
            self.req = AddrSizeHs()

        with self._paramsShared(exclude={self.ID_WIDTH}):
            self.w = AxiStream()

        ack = self.ack = Handshaked(masterDir=DIRECTION.IN)
        ack._replaceParam(ack.DATA_WIDTH, self.ID_WIDTH)
Example #21
0
    def mkFieldIntf(self, structIntf, frameTmplItem):
        t = frameTmplItem.dtype
        if isinstance(t, HUnion):
            return self.intfCls(t, structIntf._instantiateFieldFn)
        elif isinstance(t, HStruct):
            return StructIntf(t, structIntf._instantiateFieldFn)
        else:
            p = Handshaked()

        p.DATA_WIDTH.set(frameTmplItem.dtype.bit_length())
        return p
Example #22
0
    def _declr(self):
        with self._paramsShared():
            addClkRstn(self)
            self.axi = Axi4()._m()
            self.dataIn = Handshaked()
        cntrl = self.cntrlBus = Axi4Lite()
        regs = self.regsConventor = AxiLiteEndpoint(self.REGISTER_MAP)

        cntrl._replaceParam(cntrl.ADDR_WIDTH, self.CNTRL_AW)
        cntrl._replaceParam(cntrl.DATA_WIDTH, self.DATA_WIDTH)

        regs.ADDR_WIDTH.set(self.CNTRL_AW)
        regs.DATA_WIDTH.set(self.DATA_WIDTH)
Example #23
0
 def _mkFieldIntf(self, parent: Union[StructIntf, UnionSource],
                  structField: HStructField):
     t = structField.dtype
     if isinstance(t, HUnion):
         return UnionSource(t, parent._instantiateFieldFn)
     elif isinstance(t, HStruct):
         return StructIntf(t, parent._instantiateFieldFn)
     else:
         if self.SHARED_READY:
             i = VldSynced()
         else:
             i = Handshaked()
         i.DATA_WIDTH.set(structField.dtype.bit_length())
         return i
Example #24
0
    def _declr(self):
        addClkRstn(self)

        outputs = int(self.OUTPUTS)
        assert outputs > 1, outputs

        self.selectOneHot = Handshaked()
        self.selectOneHot.DATA_WIDTH = outputs

        with self._paramsShared():
            self.dataIn = self.intfCls()
            self.dataOut = HObjList(
                self.intfCls()._m() for _ in range(int(self.OUTPUTS))
            )
Example #25
0
    def _declr(self):
        with self._paramsShared():
            addClkRstn(self)
            self.axi = Axi4()._m()
            self.axi.HAS_R = False
            self.dataIn = Handshaked()
        cntrl = self.cntrlBus = Axi4Lite()
        regs = self.regsConventor = AxiLiteEndpoint(self.REGISTER_MAP)

        cntrl.ADDR_WIDTH = self.CNTRL_AW
        cntrl.DATA_WIDTH = self.DATA_WIDTH

        regs.ADDR_WIDTH = self.CNTRL_AW
        regs.DATA_WIDTH = self.DATA_WIDTH
Example #26
0
    def _declr(self) -> None:
        assert self.KEY_WIDTH > 0
        super(FifoOutOfOrderReadFiltered, self)._declr()

        if self.HAS_READ_LOOKUP:
            # check if item is stored in CAM
            pl = self.read_lookup = Handshaked()
            pl.DATA_WIDTH = self.KEY_WIDTH

            # return one-hot encoded index of the previously searched key
            plr = self.read_lookup_res = Handshaked()._m()
            plr.DATA_WIDTH = self.ITEMS

        # check if item is stored in CAM
        pl = self.write_pre_lookup = Handshaked()
        pl.DATA_WIDTH = self.KEY_WIDTH

        # return one-hot encoded index of the previously searched key
        plr = self.write_pre_lookup_res = Handshaked()._m()
        plr.DATA_WIDTH = self.ITEMS

        self.item_valid = VectSignal(self.ITEMS)._m()
        self.item_write_lock = VectSignal(self.ITEMS)._m()

        # write to CAM, set valid flag to allocate the item
        # :note: this interface is master as it providesthe information about the read execution
        i = self.write_execute = IndexKeyInHs()._m()
        i.INDEX_WIDTH = self.read_execute.INDEX_WIDTH
        i.KEY_WIDTH = self.KEY_WIDTH

        c = self.tag_cam = CamWithReadPort()
        c.ITEMS = self.ITEMS
        c.KEY_WIDTH = self.KEY_WIDTH
        c.USE_VLD_BIT = False  # we maintaining vld flag separately
        if self.HAS_READ_LOOKUP:
            c.MATCH_PORT_CNT = 2
Example #27
0
    def _declr(self):
        addClkRstn(self)
        ITEM_INDEX_WIDTH = log2ceil(self.ITEMS - 1)

        # mark item as complete and ready to be read out
        self.write_confirm = HandshakeSync()

        # begin the read of the item
        # :note: this interface is master as it providesthe information about the read execution
        wl = self.read_execute = IndexKeyHs()._m()
        wl.KEY_WIDTH = self.KEY_WIDTH
        wl.INDEX_WIDTH = ITEM_INDEX_WIDTH

        # confirm that the item was read and the item in fifo is ready to be used again
        pc = self.read_confirm = Handshaked()
        pc.DATA_WIDTH = ITEM_INDEX_WIDTH
Example #28
0
    def _declr(self):
        addClkRstn(self)

        with self._paramsShared():
            self.axi_m = Axi3()._m()

        a = self.packetAddr = Handshaked()
        a._replaceParam(a.DATA_WIDTH, self.ADDR_WIDTH)

        with self._paramsShared():
            self.rxPacketLoader = StructReader(frameHeader)
            self.rxDataPump = Axi_rDatapump(Axi3_addr)

            self.txPacketUpdater = StructWriter(frameHeader)
            self.txDataPump = Axi_wDatapump(Axi3_addr, Axi3_w)
        for o in (self.txPacketUpdater, self.txDataPump):
            o.USE_STRB.set(True)
Example #29
0
    def mkFieldIntf(self, structIntf: Union[StructIntf, UnionSink,
                                            UnionSource], field):
        t = field.dtype
        path = structIntf._field_path / field.name
        if isinstance(t, HUnion):
            p = self.intfCls(t, path, structIntf._instantiateFieldFn)
            p._fieldsToInterfaces = structIntf._fieldsToInterfaces
            return p
        elif isinstance(t, HStruct):
            p = StructIntf(t, path, structIntf._instantiateFieldFn)
            p._fieldsToInterfaces = structIntf._fieldsToInterfaces
            return p
        else:
            p = Handshaked()

        p.DATA_WIDTH = field.dtype.bit_length()
        return p
Example #30
0
 def _mkFieldIntf(parent: StructIntf, structField: HStructField):
     """
     Instantiate interface for all members of input type
     """
     t = structField.dtype
     if isinstance(t, HUnion):
         return UnionSink(t, parent._instantiateFieldFn)
     elif isinstance(t, HStruct):
         return StructIntf(t, parent._instantiateFieldFn)
     elif isinstance(t, HStream):
         p = AxiStream()
         p.DATA_WIDTH.set(structField.dtype.elmType.bit_length())
         p.USE_STRB.set(True)
         return p
     else:
         p = Handshaked()
         p.DATA_WIDTH.set(structField.dtype.bit_length())
         return p
Example #31
0
 def _mkFieldIntf(self, parent: StructIntf, structField: HStructField):
     """
     Instantiate interface for all members of input type
     """
     t = structField.dtype
     path = parent._field_path / structField.name
     if isinstance(t, HUnion):
         p = UnionSink(t, path, parent._instantiateFieldFn)
         p._fieldsToInterfaces = parent._fieldsToInterfaces
     elif isinstance(t, HStruct):
         p = StructIntf(t, path, parent._instantiateFieldFn)
         p._fieldsToInterfaces = parent._fieldsToInterfaces
     elif isinstance(t, HStream):
         p = AxiStream()
         p._updateParamsFrom(self)
     else:
         p = Handshaked()
         p.DATA_WIDTH = structField.dtype.bit_length()
     return p
Example #32
0
    def _declr(self):
        addClkRstn(self)
        self.parseTemplate()
        self.dataIn = StructIntf(self._structT,
                                 self._createInterfaceForField)

        s = self.set = Handshaked()  # data signal is addr of structure to write
        s._replaceParam(s.DATA_WIDTH, self.ADDR_WIDTH)
        # write ack from slave
        self.writeAck = HandshakeSync()._m()

        with self._paramsShared():
            # interface for communication with datapump
            self.wDatapump = AxiWDatapumpIntf()._m()
            self.wDatapump.MAX_LEN.set(self.maxWordIndex() + 1)

        self.frameAssember = AxiS_frameForge(self._structT,
                                             tmpl=self._tmpl,
                                             frames=self._frames)
Example #33
0
File: st.py Project: Nic30/hwtLib
 def _config(self):
     Handshaked._config(self)
     self.CHANNEL_WIDTH = Param(1)
     self.ERROR_WIDTH = Param(1)
Example #34
0
class ArrayItemGetter(Unit):
    """
    Get specific item from array by index
    
    .. hwt-schematic::
    """
    def _config(self):
        self.ITEMS = Param(32)
        self.ITEM_WIDTH = Param(32)
        self.ID = Param(0)
        self.ID_WIDTH = Param(4)
        self.DATA_WIDTH = Param(64)
        self.ADDR_WIDTH = Param(32)
        self.MAX_TRANS_OVERLAP = Param(16)

    def _declr(self):
        addClkRstn(self)
        # addr of start of array
        self.base = VectSignal(self.ADDR_WIDTH)

        # input index of item to get
        self.index = Handshaked()
        self.index.DATA_WIDTH.set(log2ceil(self.ITEMS))

        # output item from array
        self.item = Handshaked()._m()
        self.item.DATA_WIDTH.set(self.ITEM_WIDTH)

        self.ITEMS_IN_DATA_WORD = int(self.DATA_WIDTH) // int(self.ITEM_WIDTH)

        with self._paramsShared():
            # interface for communication with datapump
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_LEN.set(1)

        if self.ITEMS_IN_DATA_WORD > 1:
            assert isPow2(self.ITEMS_IN_DATA_WORD)
            f = self.itemSubIndexFifo = HandshakedFifo(Handshaked)
            f.DATA_WIDTH.set(log2ceil(self.ITEMS_IN_DATA_WORD))
            f.DEPTH.set(self.MAX_TRANS_OVERLAP)

    def _impl(self):
        propagateClkRstn(self)
        ITEM_WIDTH = int(self.ITEM_WIDTH)
        DATA_WIDTH = int(self.DATA_WIDTH)
        ITEMS_IN_DATA_WORD = self.ITEMS_IN_DATA_WORD
        ITEM_SIZE_IN_WORDS = 1

        if ITEM_WIDTH % 8 != 0 or ITEM_SIZE_IN_WORDS * DATA_WIDTH != ITEMS_IN_DATA_WORD * ITEM_WIDTH:
            raise NotImplementedError(ITEM_WIDTH)

        req = self.rDatapump.req
        req.id(self.ID)
        req.len(ITEM_SIZE_IN_WORDS - 1)
        req.rem(0)

        if ITEMS_IN_DATA_WORD == 1:
            addr = Concat(self.index.data, vec(0, log2ceil(ITEM_WIDTH // 8)))
            req.addr(self.base + fitTo(addr, req.addr))
            StreamNode(masters=[self.index], slaves=[req]).sync()

            self.item.data(self.rDatapump.r.data)
            StreamNode(masters=[self.rDatapump.r], slaves=[self.item]).sync()

        else:
            r = self.rDatapump.r.data
            f = self.itemSubIndexFifo
            subIndexBits = f.dataIn.data._dtype.bit_length()
            itemAlignBits = log2ceil(ITEM_WIDTH // 8)
            addr = Concat(self.index.data[:subIndexBits],
                          vec(0, itemAlignBits + subIndexBits))

            req.addr(self.base + fitTo(addr, req.addr))
            f.dataIn.data(self.index.data[subIndexBits:])
            StreamNode(masters=[self.index],
                       slaves=[req, f.dataIn]).sync()

            Switch(f.dataOut.data).addCases([
                (ITEMS_IN_DATA_WORD - i - 1, self.item.data(r[(ITEM_WIDTH * (i + 1)): (ITEM_WIDTH * i)]))
                for i in range(ITEMS_IN_DATA_WORD)
                ])
            StreamNode(masters=[self.rDatapump.r, f.dataOut],
                       slaves=[self.item]).sync()