Ejemplo n.º 1
0
Archivo: cam.py Proyecto: 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()
 def receive_write_confirm(self, b: Axi4_b, read_confirm: Handshaked):
     read_confirm.data(b.id)
     StreamNode([b], [read_confirm]).sync()
Ejemplo n.º 3
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()
Ejemplo n.º 4
0
class MdioMaster(Unit):
    """
    Master for MDIO interface.

    :ivar ~.FREQ: frequency of input clock
    :ivar ~.MDIO_FREQ: frequency of output MDIO clock

    * based on:
        * https://opencores.org/websvn/filedetails?repname=ethmac10g&path=%2Fethmac10g%2Ftrunk%2Frtl%2Fverilog%2Fmgmt%2Fmdio.v
        * https://github.com/NetFPGA/netfpga/blob/master/lib/verilog/core/io/mdio/src/nf2_mdio.v

    .. hwt-autodoc::
    """
    def _config(self):
        self.FREQ = Param(int(100e6))
        self.MDIO_FREQ = Param(int(2.5e6))

    def _declr(self):
        addClkRstn(self)
        self.md = Mdio()._m()
        self.rdata = Handshaked()._m()
        self.rdata.DATA_WIDTH = Mdio.D_W
        self.req = MdioReq()

    def _packet_sequence_timer(self, mdio_clk_rising, mdio_clk_falling, rst_n):
        """
        Create timers for all important events in protocol main FSM
        """
        PRE_W = Mdio.PRE_W
        ADDR_BLOCK_W = Mdio.ADDR_BLOCK_W
        TA_W = Mdio.TA_W
        preamble_last = self._sig("preamble_last")
        addr_block_last = self._sig("addr_block_last")
        turnarround_last_en = self._sig("turnarround_last_en")
        data_last = self._sig("data_last")

        CNTR_MAX = PRE_W + ADDR_BLOCK_W + TA_W + Mdio.D_W - 1
        timer = self._reg("packet_sequence_timer",
                          dtype=Bits(log2ceil(CNTR_MAX)),
                          def_val=0,
                          rst=self.rst_n & rst_n)
        If(mdio_clk_falling, timer(timer + 1))
        preamble_last(mdio_clk_falling & timer._eq(PRE_W - 1))
        addr_block_last(mdio_clk_falling & timer._eq(PRE_W + ADDR_BLOCK_W - 1))
        turnarround_last_en(timer._eq(PRE_W + ADDR_BLOCK_W + TA_W - 1))
        data_last(mdio_clk_rising & timer._eq(CNTR_MAX))

        return preamble_last, addr_block_last, turnarround_last_en, data_last

    def _impl(self):
        # timers and other registers
        CLK_HALF_PERIOD_DIV = ceil(self.clk.FREQ / (self.MDIO_FREQ * 2))
        mdio_clk = self._reg("mdio_clk", def_val=0)
        r_data_vld = self._reg("r_data_vld", def_val=0)
        req = self.req
        clk_half_period_en = ClkBuilder(self, self.clk).timer(
            ("clk_half_period_en", CLK_HALF_PERIOD_DIV))
        If(
            clk_half_period_en,
            mdio_clk(~mdio_clk),
        )
        mdio_clk_rising = clk_half_period_en & ~mdio_clk
        mdio_clk_falling = clk_half_period_en & mdio_clk
        idle = self._sig("idle")
        preamble_last, addr_block_last, turnarround_last_en, data_last =\
            self._packet_sequence_timer(
                mdio_clk_rising, mdio_clk_falling, ~idle)
        is_rx = self._reg("is_rx", def_val=0)

        # protocol FSM
        st_t = HEnum("st_t", ["idle", "pre", "addr_block", "ta", "data"])
        st = FsmBuilder(self, st_t)\
            .Trans(st_t.idle, (req.vld & ~r_data_vld, st_t.pre))\
            .Trans(st_t.pre, (preamble_last, st_t.addr_block))\
            .Trans(st_t.addr_block, (addr_block_last, st_t.ta))\
            .Trans(st_t.ta, (turnarround_last_en & (
                                (is_rx & mdio_clk_falling)
                                | (~is_rx & mdio_clk_rising)), st_t.data))\
            .Trans(st_t.data, (data_last, st_t.idle)).stateReg

        idle(st._eq(st_t.idle))
        req.rd(idle & ~r_data_vld)
        If(idle, is_rx(req.opcode._eq(Mdio.OP.READ)))

        # TX logic
        md = self.md
        TX_W = md.ST_W + md.OP_W + md.PA_W + md.RA_W + md.TA_W + md.D_W
        tx_reg = self._reg("tx_reg", Bits(TX_W))
        If(
            idle & req.vld,
            tx_reg(
                Concat(
                    Mdio.ST, req.opcode, req.addr.phy, req.addr.reg, Mdio.TA,
                    req.wdata))).Elif(
                        mdio_clk_falling
                        & In(st,
                             [st_t.addr_block, st_t.data, st_t.ta, st_t.data]),
                        tx_reg(tx_reg << 1))
        md.c(mdio_clk)

        # because MDIO uses open-drain, this means that if t=0 the value of the signal is 1
        md.io.o(0)
        tx_bit = tx_reg[tx_reg._dtype.bit_length() - 1]
        md.io.t(~idle & ~tx_bit & (st._eq(st_t.addr_block)
                                   | (In(st, [st_t.data, st_t.ta]) & ~is_rx)))

        # RX logic
        rx_reg = self._reg("rx_reg", Bits(md.D_W))
        If(
            st._eq(st_t.data) & is_rx & mdio_clk_rising,
            shift_in_msb_first(rx_reg, self.md.io.i))

        If(idle & self.rdata.rd, r_data_vld(0)).Elif(addr_block_last,
                                                     r_data_vld(is_rx))
        self.rdata.vld(idle & r_data_vld)
        self.rdata.data(rx_reg)
Ejemplo n.º 5
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()