コード例 #1
0
ファイル: fifo.py プロジェクト: nkavaldj/myhdl_lib
def fifo(rst, clk, full, we, din, empty, re, dout, afull=None, aempty=None, afull_th=None, aempty_th=None, ovf=None, udf=None, count=None, count_max=None, depth=None, width=None):
    """ Synchronous FIFO

        Input  interface: full,  we, din
        Output interface: empty, re, dout
            It s possible to set din and dout to None. Then the fifo width will be 0 and the fifo will contain no storage.

        Extra interface:
        afull     (o) - almost full flag, asserted when the number of empty cells <= afull_th
        aempty    (o) - almost empty flag, asserted when the number of full cells <= aempty_th

        afull_th  (i) - almost full threshold, in terms of fifo cells; signal or constant; Optional, default depth/2
        aempty_th (i) - almost empty threshold, in terms of fifo cells; signal or constant; Optional, default depth/2

        count     (o) - number of occupied fifo cells

        count_max (o) - max number of occupied fifo cells reached since the last reset
        ovf       (o) - overflow flag, set at the first write in a full fifo, cleared at reset
        udf       (o) - underflow flag, set at the first read from an empty fifo, cleared at reset

        Parameters:
        depth         - fifo depth, must be >= 1; if not set or set to `None` default value 2 is used
        width         - data width in bits, must be >= 0; if not set or set to `None` the `din` width is used

    """

    if (width == None):
        width = 0
        if din is not None:
            width = len(din)
    if (depth == None):
        depth = 2

    full_flg        = Signal(bool(1))
    empty_flg       = Signal(bool(1))
    we_safe         = Signal(bool(0))
    re_safe         = Signal(bool(0))

    rd_ptr          = Signal(intbv(0, min=0, max=depth))
    rd_ptr_new      = Signal(intbv(0, min=0, max=depth))
    wr_ptr          = Signal(intbv(0, min=0, max=depth))
    wr_ptr_new      = Signal(intbv(0, min=0, max=depth))

    @always_comb
    def safe_read_write():
        full.next       = full_flg
        empty.next      = empty_flg
        we_safe.next    = we and not full_flg
        re_safe.next    = re and not empty_flg


    #===========================================================================
    # Write, Read, Full, Empty
    #===========================================================================
    @always_comb
    def ptrs_new():
        rd_ptr_new.next     = ((rd_ptr + 1) % depth)
        wr_ptr_new.next     = ((wr_ptr + 1) % depth)

    @always(clk.posedge)
    def state_main():
        if (rst):
            wr_ptr.next     = 0
            rd_ptr.next     = 0
            full_flg.next   = 0
            empty_flg.next  = 1
        else:
            # Write pointer
            if (we_safe): wr_ptr.next = wr_ptr_new
            # Read pointer
            if (re_safe): rd_ptr.next = rd_ptr_new
            # Empty flag
            if (we_safe):
                empty_flg.next  = 0
            elif (re_safe and (rd_ptr_new == wr_ptr)):
                empty_flg.next  = 1
            # Full flag
            if (re_safe):
                full_flg.next   = 0
            elif (we_safe and (wr_ptr_new == rd_ptr)):
                full_flg.next   = 1


    #===========================================================================
    # Count, CountMax
    #===========================================================================
    ''' Count '''
    if (count != None) or (count_max != None) or (afull != None) or (aempty != None):
        count_r = Signal(intbv(0, min=0, max=depth+1))
        count_new  = Signal(intbv(0, min=-1, max=depth+2))

        if (count != None):
            assert count.max > depth
            @always_comb
            def count_out():
                count.next = count_r

        @always_comb
        def count_comb():
            if   (we_safe and not re_safe):
                    count_new.next = count_r + 1
            elif (not we_safe and re_safe):
                    count_new.next = count_r - 1
            else:
                    count_new.next = count_r

        @always(clk.posedge)
        def count_proc():
            if (rst):
                count_r.next = 0
            else:
                count_r.next = count_new

    ''' Count max '''
    if (count_max != None):
        assert count_max.max > depth
        count_max_r = Signal(intbv(0, min=0,max=count_max.max))
        @always(clk.posedge)
        def count_max_proc():
            if (rst):
                count_max_r.next = 0
            else:
                if (count_max_r < count_new):
                    count_max_r.next = count_new

        @always_comb
        def count_max_out():
            count_max.next = count_max_r

    #===========================================================================
    # AlmostFull, AlmostEmpty
    #===========================================================================
    ''' AlmostFull flag '''
    if (afull != None):
        if (afull_th == None):
            afull_th = depth//2
        @always(clk.posedge)
        def afull_proc():
            if (rst):
                afull.next = 0
            else:
                afull.next = (count_new >= depth-afull_th)

    ''' AlmostEmpty flag '''
    if (aempty != None):
        if (aempty_th == None):
            aempty_th = depth//2
        @always(clk.posedge)
        def aempty_proc():
            if (rst):
                aempty.next = 1
            else:
                aempty.next = (count_new <=  aempty_th)


    #===========================================================================
    # Overflow, Underflow
    #===========================================================================
    ''' Overflow flag '''
    if (ovf != None):
        @always(clk.posedge)
        def ovf_proc():
            if (rst):
                ovf.next = 0
            else:
                if (we and full_flg ):
                    ovf.next = 1

    ''' Underflow flag '''
    if (udf != None):
        @always(clk.posedge)
        def udf_proc():
            if (rst):
                udf.next = 0
            else:
                if (re and empty_flg):
                    udf.next = 1

    if width>0:
        #===========================================================================
        # Memory instance
        #===========================================================================
        mem_we      = Signal(bool(0))
        mem_addrw   = Signal(intbv(0, min=0, max=depth))
        mem_addrr   = Signal(intbv(0, min=0, max=depth))
        mem_di      = Signal(intbv(0)[width:0])
        mem_do      = Signal(intbv(0)[width:0])

        # RAM: Simple-Dual-Port, Asynchronous read
        mem = ram_sdp_ar(   clk     = clk,
                            we      = mem_we,
                            addrw   = mem_addrw,
                            addrr   = mem_addrr,
                            di      = mem_di,
                            do      = mem_do )

        @always_comb
        def mem_connect():
            mem_we.next         = we_safe
            mem_addrw.next      = wr_ptr
            mem_addrr.next      = rd_ptr
            mem_di.next         = din
            dout.next           = mem_do

    return instances()
コード例 #2
0
ファイル: fifo_async.py プロジェクト: nkavaldj/myhdl_lib
def fifo_async(wrst, rrst, wclk, rclk, wfull, we, wdata, rempty, re, rdata, depth=None, width=None):
    """ Asynchronous FIFO

        Implements the design described in:
            Clifford E. Cummings, "Simulation and Synthesis Techniques for Asynchronous FIFO Design," SNUG 2002 (Synopsys
            Users Group Conference, San Jose, CA, 2002) User Papers, March 2002, Section TB2, 2nd paper. Also available at
            www.sunburst-design.com/papers

        Write side interface:
            wrst   - reset 
            wclk   - clock
            wfull  - full flag, immediate set on 'write', delayed clear on 'read' due to clock domain synchronization
            we     - write enable
            wdata  - write data
        Read side interface
            rrst   - reset
            cclk   - clock
            rempty - empty flag, immediate set on 'read', delayed clear on 'write' due to clock domain synchronization
            re     - read enable
            rdata  - read data
        Parameters
            depth - fifo depth. If not set, default 4 is used. Must be >=4. Must be power of 2
            width - data width. If not set, data with equals len(wdata). Can be [0,1,2,3...)
                    It is possible to instantiate a fifo with data width 0 (no data) if width=0 or width=None and wdata=None
    """

    if width == None:
        width = 0
        if wdata is not None:
            width = len(wdata)

    if depth == None:
        depth = 4
    assert depth >= 4, "Fifo_async parameter 'depth' must be >= 4 , detected depth={}".format(depth)
    assert (depth & (depth - 1)) == 0, "Fifo_async parameter 'depth' must be 2**n, detected depth={}".format(depth)

    full_flg = Signal(bool(1))
    empty_flg = Signal(bool(1))
    full_val = Signal(bool(1))
    empty_val = Signal(bool(1))
    we_safe = Signal(bool(0))
    re_safe = Signal(bool(0))
    rd_ptr = Signal(intbv(0, min=0, max=depth))
    wr_ptr = Signal(intbv(0, min=0, max=depth))

    WIDTH = len(rd_ptr)

    rd_ptr_bin = Signal(intbv(0)[WIDTH + 1 :])
    rd_ptr_bin_new = Signal(intbv(0)[WIDTH + 1 :])
    rd_ptr_gray = Signal(intbv(0)[WIDTH + 1 :])
    rd_ptr_gray_new = Signal(intbv(0)[WIDTH + 1 :])
    rd_ptr_gray_sync1 = Signal(intbv(0)[WIDTH + 1 :])
    rd_ptr_gray_sync2 = Signal(intbv(0)[WIDTH + 1 :])
    wr_ptr_bin = Signal(intbv(0)[WIDTH + 1 :])
    wr_ptr_bin_new = Signal(intbv(0)[WIDTH + 1 :])
    wr_ptr_gray = Signal(intbv(0)[WIDTH + 1 :])
    wr_ptr_gray_new = Signal(intbv(0)[WIDTH + 1 :])
    wr_ptr_gray_sync1 = Signal(intbv(0)[WIDTH + 1 :])
    wr_ptr_gray_sync2 = Signal(intbv(0)[WIDTH + 1 :])

    @always_comb
    def safe_read_write():
        wfull.next = full_flg
        rempty.next = empty_flg
        we_safe.next = we and not full_flg
        re_safe.next = re and not empty_flg

    @always(wclk.posedge)
    def sync_r2w():
        """ Read-domain to write-domain synchronizer """
        if wrst:
            rd_ptr_gray_sync1.next = 0
            rd_ptr_gray_sync2.next = 0
        else:
            rd_ptr_gray_sync1.next = rd_ptr_gray
            rd_ptr_gray_sync2.next = rd_ptr_gray_sync1

    @always(rclk.posedge)
    def sync_w2r():
        """ Write-domain to read-domain synchronizer """
        if rrst:
            wr_ptr_gray_sync1.next = 0
            wr_ptr_gray_sync2.next = 0
        else:
            wr_ptr_gray_sync1.next = wr_ptr_gray
            wr_ptr_gray_sync2.next = wr_ptr_gray_sync1

    @always_comb
    def bin_comb():
        wr_ptr_bin_new.next = wr_ptr_bin
        rd_ptr_bin_new.next = rd_ptr_bin
        if we_safe:
            wr_ptr_bin_new.next = (wr_ptr_bin + 1) % wr_ptr_bin.max
        if re_safe:
            rd_ptr_bin_new.next = (rd_ptr_bin + 1) % rd_ptr_bin.max

    @always_comb
    def gray_comb():
        wr_ptr_gray_new.next = (wr_ptr_bin_new >> 1) ^ wr_ptr_bin_new
        rd_ptr_gray_new.next = (rd_ptr_bin_new >> 1) ^ rd_ptr_bin_new

    @always_comb
    def full_empty_comb():
        empty_val.next = rd_ptr_gray_new == wr_ptr_gray_sync2
        full_val.next = (
            (wr_ptr_gray_new[WIDTH] != rd_ptr_gray_sync2[WIDTH])
            and (wr_ptr_gray_new[WIDTH - 1] != rd_ptr_gray_sync2[WIDTH - 1])
            and (wr_ptr_gray_new[WIDTH - 1 :] == rd_ptr_gray_sync2[WIDTH - 1 :])
        )

    @always(wclk.posedge)
    def wptr_proc():
        if wrst:
            wr_ptr_bin.next = 0
            wr_ptr_gray.next = 0
            full_flg.next = 0
        else:
            wr_ptr_bin.next = wr_ptr_bin_new
            wr_ptr_gray.next = wr_ptr_gray_new
            full_flg.next = full_val

    @always(rclk.posedge)
    def rptr_proc():
        if rrst:
            rd_ptr_bin.next = 0
            rd_ptr_gray.next = 0
            empty_flg.next = 1
        else:
            rd_ptr_bin.next = rd_ptr_bin_new
            rd_ptr_gray.next = rd_ptr_gray_new
            empty_flg.next = empty_val

    if width > 0:
        # ===========================================================================
        # Memory instance
        # ===========================================================================
        mem_we = Signal(bool(0))
        mem_addrw = Signal(intbv(0, min=0, max=depth))
        mem_addrr = Signal(intbv(0, min=0, max=depth))
        mem_di = Signal(intbv(0)[width:0])
        mem_do = Signal(intbv(0)[width:0])

        # RAM: Simple-Dual-Port, Asynchronous read
        mem = ram_sdp_ar(clk=wclk, we=mem_we, addrw=mem_addrw, addrr=mem_addrr, di=mem_di, do=mem_do)

        @always_comb
        def mem_connect():
            mem_we.next = we_safe
            mem_addrw.next = wr_ptr_bin[WIDTH:]
            mem_addrr.next = rd_ptr_bin[WIDTH:]
            mem_di.next = wdata
            rdata.next = mem_do

    return instances()
コード例 #3
0
ファイル: big_fifo.py プロジェクト: bryanhpchiang/HoloBlade
def fifo(rst, clk, full, we, din, empty, re, dout, afull=None, aempty=None, afull_th=None, aempty_th=None, ovf=None, udf=None, count=None, count_max=None, depth=None, width=None):
    """ Synchronous FIFO
        Input  interface: full,  we, din
        Output interface: empty, re, dout
            It s possible to set din and dout to None. Then the fifo width will be 0 and the fifo will contain no storage.
        Extra interface:
        afull     (o) - almost full flag, asserted when the number of empty cells <= afull_th
        aempty    (o) - almost empty flag, asserted when the number of full cells <= aempty_th
        afull_th  (i) - almost full threshold, in terms of fifo cells; signal or constant; Optional, default depth/2
        aempty_th (i) - almost empty threshold, in terms of fifo cells; signal or constant; Optional, default depth/2
        count     (o) - number of occupied fifo cells
        count_max (o) - max number of occupied fifo cells reached since the last reset
        ovf       (o) - overflow flag, set at the first write in a full fifo, cleared at reset
        udf       (o) - underflow flag, set at the first read from an empty fifo, cleared at reset
        Parameters:
        depth         - fifo depth, must be >= 1; if not set or set to `None` default value 2 is used
        width         - data width in bits, must be >= 0; if not set or set to `None` the `din` width is used
    """

    if (width == None):
        width = 0
        if din is not None:
            width = len(din)
    if (depth == None):
        depth = 2

    full_flg        = Signal(bool(1))
    empty_flg       = Signal(bool(1))
    we_safe         = Signal(bool(0))
    re_safe         = Signal(bool(0))

    rd_ptr          = Signal(intbv(0, min=0, max=depth))
    rd_ptr_new      = Signal(intbv(0, min=0, max=depth))
    wr_ptr          = Signal(intbv(0, min=0, max=depth))
    wr_ptr_new      = Signal(intbv(0, min=0, max=depth))

    @always_comb
    def safe_read_write():
        full.next       = full_flg
        empty.next      = empty_flg
        we_safe.next    = we and not full_flg
        re_safe.next    = re and not empty_flg


    #===========================================================================
    # Write, Read, Full, Empty
    #===========================================================================
    @always_comb
    def ptrs_new():
        rd_ptr_new.next     = ((rd_ptr + 1) % depth)
        wr_ptr_new.next     = ((wr_ptr + 1) % depth)

    @always(clk.posedge)
    def state_main():
        if (rst):
            wr_ptr.next     = 0
            rd_ptr.next     = 0
            full_flg.next   = 0
            empty_flg.next  = 1
        else:
            # Write pointer
            if (we_safe): wr_ptr.next = wr_ptr_new
            # Read pointer
            if (re_safe): rd_ptr.next = rd_ptr_new
            # Empty flag
            if (we_safe):
                empty_flg.next  = 0
            elif (re_safe and (rd_ptr_new == wr_ptr)):
                empty_flg.next  = 1
            # Full flag
            if (re_safe):
                full_flg.next   = 0
            elif (we_safe and (wr_ptr_new == rd_ptr)):
                full_flg.next   = 1


    #===========================================================================
    # Count, CountMax
    #===========================================================================
    ''' Count '''
    if (count != None) or (count_max != None) or (afull != None) or (aempty != None):
        count_r = Signal(intbv(0, min=0, max=depth+1))
        count_new  = Signal(intbv(0, min=-1, max=depth+2))

        if (count != None):
            assert count.max > depth
            @always_comb
            def count_out():
                count.next = count_r

        @always_comb
        def count_comb():
            if   (we_safe and not re_safe):
                    count_new.next = count_r + 1
            elif (not we_safe and re_safe):
                    count_new.next = count_r - 1
            else:
                    count_new.next = count_r

        @always(clk.posedge)
        def count_proc():
            if (rst):
                count_r.next = 0
            else:
                count_r.next = count_new

    ''' Count max '''
    if (count_max != None):
        assert count_max.max > depth
        count_max_r = Signal(intbv(0, min=0,max=count_max.max))
        @always(clk.posedge)
        def count_max_proc():
            if (rst):
                count_max_r.next = 0
            else:
                if (count_max_r < count_new):
                    count_max_r.next = count_new

        @always_comb
        def count_max_out():
            count_max.next = count_max_r

    #===========================================================================
    # AlmostFull, AlmostEmpty
    #===========================================================================
    ''' AlmostFull flag '''
    if (afull != None):
        if (afull_th == None):
            afull_th = depth//2
        @always(clk.posedge)
        def afull_proc():
            if (rst):
                afull.next = 0
            else:
                afull.next = (count_new >= depth-afull_th)

    ''' AlmostEmpty flag '''
    if (aempty != None):
        if (aempty_th == None):
            aempty_th = depth//2
        @always(clk.posedge)
        def aempty_proc():
            if (rst):
                aempty.next = 1
            else:
                aempty.next = (count_new <=  aempty_th)


    #===========================================================================
    # Overflow, Underflow
    #===========================================================================
    ''' Overflow flag '''
    if (ovf != None):
        @always(clk.posedge)
        def ovf_proc():
            if (rst):
                ovf.next = 0
            else:
                if (we and full_flg ):
                    ovf.next = 1

    ''' Underflow flag '''
    if (udf != None):
        @always(clk.posedge)
        def udf_proc():
            if (rst):
                udf.next = 0
            else:
                if (re and empty_flg):
                    udf.next = 1

    if width>0:
        #===========================================================================
        # Memory instance
        #===========================================================================
        mem_we      = Signal(bool(0))
        mem_addrw   = Signal(intbv(0, min=0, max=depth))
        mem_addrr   = Signal(intbv(0, min=0, max=depth))
        mem_di      = Signal(intbv(0)[width:0])
        mem_do      = Signal(intbv(0)[width:0])

        # RAM: Simple-Dual-Port, Asynchronous read
        mem = ram_sdp_ar(   clk     = clk,
                            we      = mem_we,
                            addrw   = mem_addrw,
                            addrr   = mem_addrr,
                            di      = mem_di,
                            do      = mem_do )

        @always_comb
        def mem_connect():
            mem_we.next         = we_safe
            mem_addrw.next      = wr_ptr
            mem_addrr.next      = rd_ptr
            mem_di.next         = din
            dout.next           = mem_do

    return instances()
コード例 #4
0
def fifo_speculative(rst, clk, full, we, din, empty, re, dout, wr_commit=None, wr_discard=None, rd_commit=None, rd_discard=None, afull=None, aempty=None, count=None, afull_th=None, aempty_th=None, ovf=None, udf=None, count_max=None,  depth=None, width=None):
    """ Speculative FIFO

        Input  interface: full,  we, din,  wr_commit, wr_discard
        Output interface: empty, re, dout, rd_commit, rd_discard

        we         (i) - writes data speculatively (the data can be later removed from the fifo)
        wr_commit  (i) - accept the speculatively written data (can be read)
        wr_discard (i) - remove the speculatively written data at once
        full       (o) - asserted when there are no empty cells to write data speculatively

        If we is asserted together with the wr_commit or wr_discard, the data being written is affected by the commit/discard command.
        If wr_commit and wr_discard are asserted simultaneously, the wr_discard wins.

        re         (i) - reads data speculatively (the data can be later restored)
        rd_commit  (i) - removes the speculatively read data at once
        rd_discard (i) - restores the speculatively read data (will be read again)
        empty      (o) - asserted when there are no committed date to be read

        If re is asserted together with the rd_commit or rd_discards, the data being read is affected by the commit/discard command.
        If rd_commit and rd_discard are asserted simultaneously, the rd_discard wins.

        Note: This fifo can be Full and Empty at the same time - all fifo cells are occupied by data that are either speculatively written or speculatively read

        Extra interface:
        afull      (o) - almost full flag, asserted when the number of empty cells <= afull_th
        aempty     (o) - almost empty flag, asserted when the number of full cells <= aempty_th

        afull_th   (i) - almost full threshold, in terms of fifo cells; Optional, default depth/2
        aempty_th  (i) - almost empty threshold, in terms of fifo cells; Optional, default depth/2

        count      (o) - number of occupied fifo cells, committed and not committed (speculatively written/read)
        count_max  (o) - max number of occupied fifo cells reached since the last reset
        ovf        (o) - overflow flag, set at the first write in a full fifo, cleared at reset
        udf        (o) - underflow flag, set at the first read from an empty fifo, cleared at reset
    """

    if (width == None):
        width = len(din)
    if (depth == None):
        depth = 2

    assert ((wr_commit != None) and (wr_discard != None)) or ((wr_commit == None) and (wr_discard == None)), "SFIFO ERROR: Interface signals wr_commit and wr_discard must be either both used or both left unused"
    assert ((rd_commit != None) and (rd_discard != None)) or ((rd_commit == None) and (rd_discard == None)), "SFIFO ERROR: Interface signals rd_commit and rd_discard must be either both used or both left unused"

    wr_commit       = wr_commit  if (wr_commit  != None) else Signal(bool(1))
    wr_discard      = wr_discard if (wr_discard != None) else Signal(bool(0))
    rd_commit       = rd_commit  if (rd_commit  != None) else Signal(bool(1))
    rd_discard      = rd_discard if (rd_discard != None) else Signal(bool(0))

    full_flg        = Signal(bool(1))
    empty_flg       = Signal(bool(1))
    we_safe         = Signal(bool(0))
    re_safe         = Signal(bool(0))
    swr_non0        = Signal(bool(0))
    srd_non0        = Signal(bool(0))
    wr_commit_non0  = Signal(bool(0))
    rd_commit_non0  = Signal(bool(0))
    wr_discard_non0 = Signal(bool(0))
    rd_discard_non0 = Signal(bool(0))

    # Almost full/empty and their thresholds
    afull_flg       = Signal(bool(0))
    aempty_flg      = Signal(bool(0))
    if (afull_th == None):
        afull_th = depth//2
    if (aempty_th == None):
        aempty_th = depth//2

    afull           = afull  if (afull  != None) else Signal(bool(0))
    aempty          = aempty if (aempty != None) else Signal(bool(0))
    count           = count  if (count  != None) else Signal(intbv(0, min=0, max=depth + 1))

    ovf             = ovf       if (ovf       != None) else Signal(bool(0))
    udf             = udf       if (udf       != None) else Signal(bool(0))
    count_max       = count_max if (count_max != None) else Signal(intbv(0, min=0, max=depth+1))

    rd_ptr          = Signal(intbv(0, min=0, max=depth))
    wr_ptr          = Signal(intbv(0, min=0, max=depth))
    srd_ptr         = Signal(intbv(0, min=0, max=depth))
    srd_ptr_new     = Signal(intbv(0, min=0, max=depth))
    swr_ptr         = Signal(intbv(0, min=0, max=depth))
    swr_ptr_new     = Signal(intbv(0, min=0, max=depth))

    # Data written in the fifo (committed and not committed)
    data_count      = Signal(intbv(0, min=0,   max=depth + 1))
    data_count_max  = Signal(intbv(0, min=0,   max=depth + 1))

    @always_comb
    def out_assign():
        full.next           = full_flg
        empty.next          = empty_flg
        afull.next          = afull_flg
        aempty.next         = aempty_flg
        count.next          = data_count
        count_max.next      = data_count_max

    @always_comb
    def safe_read_write():
        we_safe.next        = we and not full_flg
        re_safe.next        = re and not empty_flg

    @always_comb
    def non_zero_commits():
        wr_commit_non0.next     = wr_commit and (swr_non0 or we_safe) and not wr_discard
        rd_commit_non0.next     = rd_commit and (srd_non0 or re_safe) and not rd_discard
        #
        wr_discard_non0.next    = wr_discard and (swr_non0 or we_safe)
        rd_discard_non0.next    = rd_discard and (srd_non0 or re_safe)

    """ ---------------------------- """
    """ - Write, Read, Full, Empty - """
    """ ---------------------------- """

    @always_comb
    def sptrs_new():
        """ Next value for the speculative pointers """

        if (wr_discard):
            swr_ptr_new.next     = wr_ptr
        elif (we_safe):
            swr_ptr_new.next     = ((swr_ptr + 1) % depth)
        else:
            swr_ptr_new.next     = swr_ptr

        if (rd_discard):
            srd_ptr_new.next     = rd_ptr
        elif (re_safe):
            srd_ptr_new.next     = ((srd_ptr + 1) % depth)
        else:
            srd_ptr_new.next     = srd_ptr

    @always(clk.posedge)
    def state_main():
        if (rst):
            wr_ptr.next     = 0
            rd_ptr.next     = 0
            swr_ptr.next    = 0
            srd_ptr.next    = 0
            swr_non0.next   = 0
            srd_non0.next   = 0
            full_flg.next   = 0
            empty_flg.next  = 1
        else:

            # Speculative Write pointer
            swr_ptr.next = swr_ptr_new

            # Speculative Read pointer
            srd_ptr.next = srd_ptr_new

            # Write pointer
            if (wr_commit): wr_ptr.next = swr_ptr_new

            # Read pointer
            if (rd_commit): rd_ptr.next = srd_ptr_new

            # Empty flag
            if (wr_commit_non0 or rd_discard_non0):
                empty_flg.next  = 0
            elif (re_safe and (srd_ptr_new == wr_ptr)):
                empty_flg.next  = 1

            # Full flag
            if (rd_commit_non0 or wr_discard_non0):
                full_flg.next   = 0
            elif (we_safe and (swr_ptr_new == rd_ptr)):
                full_flg.next   = 1

            # swr_non0 flag
            if (wr_commit or wr_discard):
                swr_non0.next   = 0
            elif (we_safe):
                swr_non0.next   = 1

            # srd_non0 flag
            if (rd_commit or rd_discard):
                srd_non0.next   = 0
            elif (re_safe):
                srd_non0.next   = 1


    """
    rd                        srd            wr                        swr            rd
    ^                         ^              v                         v              ^
    |#########################|%%%%%%%%%%%%%%|*************************|..............|
    |<------ srd_count ------>|<------------>|<------ swr_count ------>|<------------>|
    |<--------------- wr_count ------------->|<--------------- rd_count ------------->|
    |<----------------------------------- depth ------------------------------------->|
    """

    """ ------------------------------------ """
    """ - Almost_Full, Almost_Empty, Count - """
    """ ------------------------------------ """
    # count of the speculatively written data
    swr_count       = Signal(intbv(0, min=0,   max=depth + 1))
    # count of the speculatively read data
    srd_count       = Signal(intbv(0, min=0,   max=depth + 1))
    # count of the write committed data
    wr_count        = Signal(intbv(0, min=0,   max=depth + 1))
    # count of the not write committed positions
    rd_count        = Signal(intbv(0, min=0,   max=depth + 1))

    @always(clk.posedge)
    def state_extra():
        if (rst):
            swr_count.next      = 0
            srd_count.next      = 0
            wr_count.next       = 0
            rd_count.next       = depth
            data_count.next     = 0
            afull_flg.next      = 0
            aempty_flg.next     = 1
            data_count_max.next = 0
        else:
            swr_count_new   = 0
            if (not wr_commit and not wr_discard):
                swr_count_new   = int((swr_count + 1) if (we_safe) else swr_count)

            swr_count.next  = swr_count_new

            srd_count_new   = 0
            if (not rd_commit and not rd_discard):
                srd_count_new   = int((srd_count + 1 if (re_safe) else srd_count))

            srd_count.next  = srd_count_new

            wr_add_new = 0
            if (wr_commit and not wr_discard):
                wr_add_new  = int((swr_count + 1) if (we_safe) else swr_count)

            rd_add_new = 0
            if (rd_commit and not rd_discard):
                rd_add_new  = int((srd_count + 1) if (re_safe) else srd_count)

            wr_count_new    = wr_count + wr_add_new - rd_add_new
            rd_count_new    = rd_count - wr_add_new + rd_add_new

            wr_count.next   = wr_count_new
            rd_count.next   = rd_count_new

            aempty_flg.next = ((wr_count_new - srd_count_new) <= aempty_th)
            afull_flg.next  = ((rd_count_new - swr_count_new) <= afull_th )

            # Count data in the fifo
            data_count_new  = wr_count_new + swr_count_new
            data_count.next = data_count_new

            if (data_count_max < data_count_new): data_count_max.next = data_count_new

    ''' Overflow flag '''
    if (ovf != None):
        @always(clk.posedge)
        def ovf_proc():
            if (rst):
                ovf.next = 0
            else:
                if (we and full_flg ):
                    ovf.next = 1

    ''' Underflow flag '''
    if (udf != None):
        @always(clk.posedge)
        def udf_proc():
            if (rst):
                udf.next = 0
            else:
                if (re and empty_flg):
                    udf.next = 1

    """ ------------------- """
    """ - Memory instance - """
    """ ------------------- """
    mem_we      = Signal(bool(0))
    mem_addrw   = Signal(intbv(0, min=0, max=depth))
    mem_addrr   = Signal(intbv(0, min=0, max=depth))
    mem_di      = Signal(intbv(0)[width:0])
    mem_do      = Signal(intbv(0)[width:0])

    # RAM: Simple-Dual-Port, Asynchronous Read
    mem = ram_sdp_ar(   clk     = clk,
                        we      = mem_we,
                        addrw   = mem_addrw,
                        addrr   = mem_addrr,
                        di      = mem_di,
                        do      = mem_do )

    @always_comb
    def mem_connect():
        mem_we.next         = we_safe
        mem_addrw.next      = swr_ptr
        mem_addrr.next      = srd_ptr
        mem_di.next         = din
        dout.next           = mem_do

    return instances()