Ejemplo n.º 1
0
def arbiter_priority(req_vec, gnt_vec=None, gnt_idx=None, gnt_vld=None):
    """ Static priority arbiter: grants the request with highest priority, which is the lower index
            req_vec - (i) vector of request signals, req_vec[0] is with the highest priority
            gnt_vec - (o) optional, vector of grants, one grant per request, only one grant can be active at at time
            gnt_idx - (o) optional, grant index, index of the granted request
            gnt_vld - (o) optional, grant valid, indicate that there is a granted request
    """
    REQ_NUM = len(req_vec)
    gnt_vec_s = Signal(intbv(0)[REQ_NUM:])
    gnt_idx_s = Signal(intbv(0, min=0, max=REQ_NUM))
    gnt_vld_s = Signal(bool(0))

    @always_comb
    def prioroty_encoder():
        gnt_vec_s.next = 0
        gnt_idx_s.next = 0
        gnt_vld_s.next = 0
        for i in range(REQ_NUM):
            if ( req_vec[i]==1 ):
                gnt_vec_s.next[i] = 1
                gnt_idx_s.next = i
                gnt_vld_s.next = 1
                break

    if gnt_vec!=None: _vec = assign(gnt_vec, gnt_vec_s)
    if gnt_idx!=None: _idx = assign(gnt_idx, gnt_idx_s)
    if gnt_vld!=None: _vld = assign(gnt_vld, gnt_vld_s)

    return instances()
Ejemplo n.º 2
0
def arbiter_roundrobin(rst, clk, req_vec, gnt_vec=None, gnt_idx=None, gnt_vld=None, gnt_rdy=None):
    """ Round Robin arbiter: finds the active request with highest priority and presents its index on the gnt_idx output.
            req_vec - (i) vector of request signals, priority changes dynamically
            gnt_vec - (o) optional, vector of grants, one grant per request, only one grant can be active at at time
            gnt_idx - (o) optional, grant index, index of the granted request
            gnt_vld - (o) optional, grant valid, indicate that there is a granted request
            gnt_rdy - (i) grant ready, indicates that the current grant is consumed and priority should be updated.
                          The priority is updated only if there is a valid grant when gnt_rdy is activated.
                          When priority is updated, the currently granted req_vec[gnt_idx] gets the lowest priority and
                          req_vec[gnt_idx+1] gets the highest priority.
                          gnt_rdy should be activated in the same clock cycle when output the grant is used
    """
    REQ_NUM = len(req_vec)
    ptr = Signal(intbv(0, min=0, max=REQ_NUM))

    gnt_vec_s = Signal(intbv(0)[REQ_NUM:])
    gnt_idx_s = Signal(intbv(0, min=0, max=REQ_NUM))
    gnt_vld_s = Signal(bool(0))

    @always(clk.posedge)
    def ptr_proc():
        if (rst):
            ptr.next = REQ_NUM-1
        elif (gnt_rdy and gnt_vld_s):
            ptr.next = gnt_idx_s

    @always_comb
    def roundrobin_encoder():
        gnt_vec_s.next = 0
        gnt_idx_s.next = 0
        gnt_vld_s.next = 0
        for i in range(REQ_NUM):
            if (i>ptr):
                if ( req_vec[i]==1 ):
                    gnt_vec_s.next[i] = 1
                    gnt_idx_s.next = i
                    gnt_vld_s.next = 1
                    return
        for i in range(REQ_NUM):
            if ( req_vec[i]==1 ):
                gnt_vec_s.next[i] = 1
                gnt_idx_s.next = i
                gnt_vld_s.next = 1
                return

    if gnt_vec!=None: _vec = assign(gnt_vec, gnt_vec_s)
    if gnt_idx!=None: _idx = assign(gnt_idx, gnt_idx_s)
    if gnt_vld!=None: _vld = assign(gnt_vld, gnt_vld_s)

    return instances()
Ejemplo n.º 3
0
def hs_arbmux(rst, clk, ls_hsi, hso, sel, ARBITER_TYPE="priority"):
    """ [Many-to-one] Arbitrates a list of input handshake interfaces.
        Selects one of the active input interfaces and connects it to the output.
        Active input is an input interface with asserted "valid" signal
            ls_hsi - (i) list of input handshake tuples (ready, valid)
            hso    - (o) output handshake tuple (ready, valid)
            sel    - (o) indicates the currently selected input handshake interface
            ARBITER_TYPE - selects the arbiter type to be used, "priority" or "roundrobin"
    """
    N = len(ls_hsi)
    ls_hsi_rdy, ls_hsi_vld = zip(*ls_hsi)
    ls_hsi_vld = list(ls_hsi_vld)

    # Needed to avoid: "myhdl.ConversionError: Signal in multiple list is not supported:"
    ls_vld = [Signal(bool(0)) for _ in range(N)]
    _a = [assign(ls_vld[i], ls_hsi_vld[i]) for i in range(N)]

    sel_s = Signal(intbv(0, min=0, max=N))
    @always_comb
    def _sel():
        sel.next = sel_s

    priority_update = None

    if (ARBITER_TYPE == "roundrobin"):
        hso_rdy, hso_vld = hso
        priority_update = Signal(bool(0))

        @always_comb
        def _prio():
            priority_update.next = hso_rdy and hso_vld

    _arb = arbiter(rst=rst, clk=clk, req_vec=ls_vld, gnt_idx=sel_s, gnt_rdy=priority_update, ARBITER_TYPE=ARBITER_TYPE)

    _mux = hs_mux(sel=sel_s, ls_hsi=ls_hsi, hso=hso)

    return instances()
Ejemplo n.º 4
0
def checksum(rst, clk, rx_vld, rx_sop, rx_eop, rx_dat, rx_mty, chksum, sum16=None, sumN=None, init_sum=None, MAX_BYTES=1500):
    """ Calculates checksum on a stream of packetised data
            rx_vld   - (i) valid data
            rx_sop   - (i) start of packet
            rx_eop   - (i) end of packet
            rx_dat   - (i) data
            rx_mty   - (i) empty bits when rx_eop
            init_sum - (i) initial value for the sum (e.g. sum of the some fields from a packet header)
            sumN     - (o) optional, plane sum
            sum16    - (o) optional, 16 bit sum (every time the sum overflows, the overflow is added to the sum)
            chksum   - (o) optional, checksum (~sum16)
            MAX_BYTES - a limit: maximum number of bytes that may arrive in a single packet
        Assumes Big-endian data.
        The results are ready in the first clock cycle after rx_eop
    """

    DATA_WIDTH = len(rx_dat) 

    assert DATA_WIDTH%16==0, "checksum: expects len(rx_dat)=16*x, but len(tx_dat)={}".format(DATA_WIDTH)

    NUM_BYTES = DATA_WIDTH // 8
    NUM_WORDS = DATA_WIDTH // 16

    SUM_WIDTH    = 16 + int(ceil(log(MAX_BYTES/2,2))) + 1
    SUM16_WIDTH  = 16 + int(ceil(log(NUM_WORDS,2))) + 1


    if (init_sum != None):
        assert len(init_sum)<=16, "checksum: expects len(init_sum)<={}, but len(init_sum)={}".format(16, len(init_sum))
        SUM_WIDTH    += 1
        SUM16_WIDTH  += 1
    else:
        init_sum = 0

    FF_MASK = intbv(0)[DATA_WIDTH:].max-1
    mdata = Signal(intbv(0)[DATA_WIDTH:])

    @always_comb
    def _mask_empty():
        mdata.next = rx_dat
        if rx_eop:
            mdata.next = rx_dat & (FF_MASK<<(rx_mty*8))

    # Slice masked data in 16 bit words
    mdata16 = [Signal(intbv(0)[16:]) for _ in range(NUM_WORDS)]
    _ass = [assign(mdata16[w], mdata((w+1)*16, w*16)) for w in range(NUM_WORDS)]

    if sumN!=None:
        assert len(sumN)>=SUM_WIDTH, "checksum: expects len(sumN)>={}, but len(sumN)={}".format(SUM_WIDTH, len(sumN))

        sumN_reg = Signal(intbv(0)[SUM_WIDTH:])

        @always_seq(clk.posedge, reset=rst)
        def _accuN():
            ''' Accumulate '''
            if (rx_vld):
                s = 0

                if (rx_sop):
                    s = int(init_sum)
                else:
                    s = int(sumN_reg)

                for w in range(NUM_WORDS):
                    s += mdata16[w]

                sumN_reg.next = s

        @always_comb
        def _passN():
            sumN.next = sumN_reg


    if chksum!=None or sum16!=None:

        sum16_reg = Signal(intbv(0)[SUM16_WIDTH:])

        @always_seq(clk.posedge, reset=rst)
        def _accu16():
            ''' Accumulate 16 bit words'''
            if (rx_vld):
                s = 0

                if (rx_sop):
                    s = int(init_sum)
                else:
                    s = int(sum16_reg)

                for w in range(NUM_WORDS):
                    s += mdata16[w]

                ss = intbv(s)[SUM16_WIDTH:]

                sum16_reg.next = ss[:2*8] + ss[2*8:]

        if sum16!=None:
            assert len(sum16)>=16, "checksum: expects len(sum16)>={}, but len(sum16)={}".format(16, len(sum16))
            @always_comb
            def _pass16():
                sum16.next = sum16_reg[16:]

        if chksum!=None:
            assert len(chksum)>=16, "checksum: expects len(chksum)>={}, but len(chksum)={}".format(16, len(chksum))
            @always_comb
            def _invert():
                chksum.next = ~sum16_reg[16:] & 0xFFFF

    return instances()