Beispiel #1
0
    gs4 = m_sync_mbits(rclk, rrst, wptr, rq2_wptr)

    @always_comb
    def rtl_assigns():
        fbus.empty.next = rempty
        fbus.full.next = wfull

    _we = Signal(bool(0))
    @always_comb
    def rtl_wr():
        _we.next = fbus.wr and not fbus.full
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Memory for the FIFO
    g_fifomem = m_fifo_mem_generic(wclk, _we, fbus.wdata, waddr,
                                   rclk, fbus.rdata,  raddr,
                                   mem_size=fbus.size)


    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # --Text from the paper--
    # The read pointer is a dual nbit Gray code counter.  The nbit 
    # pointer (rptr) is passed to the write clock domain through the 
    # syncs.  The (n-1)bit pointer (raddr) is used to address the FIFO 
    # buffer.  The FIFO empty output is registered and is asserted on 
    # the next rising rclk edge when the next rptr value equals the 
    # sync wptr value. 
    rbin = Signal(modbv(0)[Asz+1:])
    #raddr.assign(rbin[Asz:0]

    @always_seq(rclk.posedge, reset=rrst)
Beispiel #2
0
def m_fifo_sync(clock, reset, fbus):
    """ Simple synchronous FIFO

    PORTS
    =====

    PARAMETERS
    ==========
    """

    # @todo: this is intended to be used for small fast fifo's but it
    #        can be used for large synchronous fifo as well
    N = fbus.size

    if fmod(log(N, 2), 1) != 0:
        Asz = int(ceil(log(N, 2)))
        N = 2**Asz
        print("@W: m_fifo_sync only supports power of 2 size")
        print("    forcing size (depth) to %d instread of " % (N, fbus.size))

    wptr = Signal(modbv(0, min=0, max=N))
    rptr = Signal(modbv(0, min=0, max=N))
    _vld = Signal(False)

    # generic memory model
    g_fifomem = m_fifo_mem_generic(clock,
                                   fbus.wr,
                                   fbus.wdata,
                                   wptr,
                                   clock,
                                   fbus.rdata,
                                   rptr,
                                   mem_size=fbus.size)

    # @todo: almost full and almost empty flags
    read = fbus.rd
    write = fbus.wr

    @always_seq(clock.posedge, reset=reset)
    def rtl_fifo():
        if fbus.clear:
            wptr.next = 0
            rptr.next = 0
            fbus.full.next = False
            fbus.empty.next = True

        elif read and not write:
            fbus.full.next = False
            if not fbus.empty:
                rptr.next = rptr + 1
            if rptr == (wptr - 1):
                fbus.empty.next = True

        elif write and not read:
            fbus.empty.next = False
            if not fbus.full:
                wptr.next = wptr + 1
            if wptr == (rptr - 1):
                fbus.full.next = True

        elif write and read:
            wptr.next = wptr + 1
            rptr.next = rptr + 1

        _vld.next = read

    @always_comb
    def rtl_assign():
        fbus.rvld.next = _vld & fbus.rd

    nvacant = Signal(intbv(N, min=-0, max=N + 1))  # # empty slots
    ntenant = Signal(intbv(0, min=-0, max=N + 1))  # # filled slots

    @always_seq(clock.posedge, reset=reset)
    def dbg_occupancy():
        if fbus.clear:
            nvacant.next = N
            ntenant.next = 0
        else:
            v = nvacant
            f = ntenant

            if fbus.rvld:
                v = v + 1
                f = f - 1
            if fbus.wr:
                v = v - 1
                f = f + 1

            nvacant.next = v
            ntenant.next = f

    fbus.count = ntenant

    return (
        g_fifomem,
        rtl_fifo,
        rtl_assign,
        dbg_occupancy,
    )
Beispiel #3
0
    def rtl_assigns():
        fbus.empty.next = rempty
        fbus.full.next = wfull

    _we = Signal(bool(0))

    @always_comb
    def rtl_wr():
        _we.next = fbus.wr and not fbus.full

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Memory for the FIFO
    g_fifomem = m_fifo_mem_generic(wclk,
                                   _we,
                                   fbus.wdata,
                                   waddr,
                                   rclk,
                                   fbus.rdata,
                                   raddr,
                                   mem_size=fbus.size)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # --Text from the paper--
    # The read pointer is a dual nbit Gray code counter.  The nbit
    # pointer (rptr) is passed to the write clock domain through the
    # syncs.  The (n-1)bit pointer (raddr) is used to address the FIFO
    # buffer.  The FIFO empty output is registered and is asserted on
    # the next rising rclk edge when the next rptr value equals the
    # sync wptr value.
    rbin = Signal(modbv(0)[Asz + 1:])
    #raddr.assign(rbin[Asz:0]
Beispiel #4
0
def m_fifo_sync(clock, reset, fbus):
    """ Simple synchronous FIFO

    PORTS
    =====

    PARAMETERS
    ==========
    """

    # @todo: this is intended to be used for small fast fifo's but it
    #        can be used for large synchronous fifo as well
    N = fbus.size

    if fmod(log(N, 2), 1) != 0:
        Asz = int(ceil(log(N, 2)))
        N = 2 ** Asz
        print("@W: m_fifo_sync only supports power of 2 size")
        print("    forcing size (depth) to %d instread of " % (N, fbus.size))

    wptr = Signal(modbv(0, min=0, max=N))
    rptr = Signal(modbv(0, min=0, max=N))
    _vld = Signal(False)

    # generic memory model
    g_fifomem = m_fifo_mem_generic(clock, fbus.wr, fbus.wdata, wptr, clock, fbus.rdata, rptr, mem_size=fbus.size)

    # @todo: almost full and almost empty flags
    read = fbus.rd
    write = fbus.wr

    @always_seq(clock.posedge, reset=reset)
    def rtl_fifo():
        if fbus.clear:
            wptr.next = 0
            rptr.next = 0
            fbus.full.next = False
            fbus.empty.next = True

        elif read and not write:
            fbus.full.next = False
            if not fbus.empty:
                rptr.next = rptr + 1
            if rptr == (wptr - 1):
                fbus.empty.next = True

        elif write and not read:
            fbus.empty.next = False
            if not fbus.full:
                wptr.next = wptr + 1
            if wptr == (rptr - 1):
                fbus.full.next = True

        elif write and read:
            wptr.next = wptr + 1
            rptr.next = rptr + 1

        _vld.next = read

    @always_comb
    def rtl_assign():
        fbus.rvld.next = _vld & fbus.rd

    nvacant = Signal(intbv(N, min=-0, max=N + 1))  # # empty slots
    ntenant = Signal(intbv(0, min=-0, max=N + 1))  # # filled slots

    @always_seq(clock.posedge, reset=reset)
    def dbg_occupancy():
        if fbus.clear:
            nvacant.next = N
            ntenant.next = 0
        else:
            v = nvacant
            f = ntenant

            if fbus.rvld:
                v = v + 1
                f = f - 1
            if fbus.wr:
                v = v - 1
                f = f + 1

            nvacant.next = v
            ntenant.next = f

    fbus.count = ntenant

    return (g_fifomem, rtl_fifo, rtl_assign, dbg_occupancy)