Пример #1
0
def m_fifo_2clock_cascade(
    wclk,       # in:  write side clock
    datain,     # in:  write data
    src_rdy_i,  # in:  
    dst_rdy_o,  # out: 
    space,      # out: how many can be written
    
    rclk,       # in:  read side clock
    dataout,    # out: read data
    src_rdy_o,  # out: 
    dst_rdy_i,  # in:  
    occupied,   # out: number in the fifo

    reset,      # in:  system reset
):


    wr = Signal(bool(0))
    rd = Signal(bool(0))
    dataout_d = Signal(intbv(0, min=dataout.min, max=dataout.max))

    args = Namespace(width=36, size=128, name='fifo_2clock_cascade')
    fbus = FIFOBus(args=args)
    # need to update the fbus refernces to reference the Signals in
    # the moudule port list (function arguments).
    fbus.wr = wr
    fbus.wdata = datain
    fbus.rd = rd
    fbus.rdata = dataout_d

    @always_comb
    def rtl_assign1():
        wr.next = src_rdy_i & dst_rdy_o
        rd.next = dst_rdy_i & src_rdy_o

    @always_comb
    def rtl_assign2():
        dst_rdy_o.next = not fbus.full
        src_rdy_o.next = not fbus.empty

    # the original was a chain:
    #    m_fifo_fast  (16)
    #    m_fifo_async (??)
    #    m_fifo_fast  (16)
    gfifo = fifo_async(reset, wclk, rclk, fbus)
    # @todo: calculate space and occupied based on fbus.count
        
    # @todo: the output is delayed two clock from the "read" strobe
    #   the m_fifo_async only has a delta of one (read valid strobe
    #   aligns with valid data).  Need to delay the data one more
    #   clock cycle???
    
    @always(rclk.posedge)
    def rtl_delay():
        dataout.next = dataout_d

    return rtl_assign1, rtl_assign2, gfifo, rtl_delay
Пример #2
0
def fifo_2clock_cascade(
    wclk,       # in:  write side clock
    datain,     # in:  write data
    src_rdy_i,  # in:  
    dst_rdy_o,  # out: 
    space,      # out: how many can be written
    
    rclk,       # in:  read side clock
    dataout,    # out: read data
    src_rdy_o,  # out: 
    dst_rdy_i,  # in:  
    occupied,   # out: number in the fifo

    reset,      # in:  system reset
):
    """ """
    wr = Signal(bool(0))
    rd = Signal(bool(0))
    dataout_d = Signal(intbv(0, min=dataout.min, max=dataout.max))

    args = Namespace(width=36, size=128, name='fifo_2clock_cascade')
    fbus = FIFOBus(width=args.width)
    # need to update the fbus references to reference the Signals in
    # the module port list (function arguments).
    fbus.write = wr
    fbus.write_data = datain
    fbus.read = rd
    fbus.read_data = dataout_d

    @always_comb
    def beh_assign1():
        wr.next = src_rdy_i & dst_rdy_o
        rd.next = dst_rdy_i & src_rdy_o

    @always_comb
    def beh_assign2():
        dst_rdy_o.next = not fbus.full
        src_rdy_o.next = not fbus.empty

    # the original was a chain:
    #    fifo_fast  (16)
    #    fifo_async (??)
    #    fifo_fast  (16)
    fifo_inst = fifo_async(wclk, rclk, fbus, reset=reset, size=args.size)

    # @todo: calculate space and occupied based on fbus.count
        
    # @todo: the output is delayed two clock from the "read" strobe
    #   the m_fifo_async only has a delta of one (read valid strobe
    #   aligns with valid data).  Need to delay the data one more
    #   clock cycle???
    
    @always(rclk.posedge)
    def beh_delay():
        dataout.next = dataout_d

    return myhdl.instances()
Пример #3
0
    def _test1():

        tbdut = fifo_async(reset, wclk, rclk, fbus)

        @instance
        def tbstim():
            print("start test 1")
            fbus.wdata.next = 0xFE
            reset.next = reset.active
            yield delay(3 * 33)
            reset.next = not reset.active

            # reset is delayed by at least two
            for ii in range(5):
                yield wclk.posedge

            # test normal cases
            for num_bytes in range(1, args.size + 1):

                # Write some byte
                for ii in range(num_bytes):
                    yield wclk.posedge
                    fbus.wdata.next = ii
                    fbus.wr.next = True

                yield wclk.posedge
                fbus.wr.next = False

                # If 16 bytes written make sure FIFO is full
                yield wclk.posedge
                if num_bytes == args.size:
                    assert fbus.full, "FIFO should be full!"

                while fbus.empty:
                    yield rclk.posedge

                fbus.rd.next = True
                yield rclk.posedge
                for ii in range(num_bytes):
                    yield rclk.posedge
                    fbus.rd.next = True
                    assert fbus.rvld
                    assert fbus.rdata == ii, "rdata %x ii %x " % (fbus.rdata,
                                                                  ii)

                yield rclk.posedge
                fbus.rd.next = False
                yield rclk.posedge
                assert fbus.empty

            # Test overflows
            # Test underflows
            # Test write / read same time

            raise StopSimulation

        return tbdut, tbwclk, tbrclk, tbstim
Пример #4
0
    def bench_async_fifo():

        tbclkw = wclk.gen()
        tbclkr = rclk.gen()
        tbdut = fifo_async(wclk, rclk, fbus, reset)
        tbpr = procuder_consumer(wclk, rclk, fbus, start)

        @instance
        def tbstim():
            print("start test 1")
            fbus.write_data.next = 0xFE
            reset.next = reset.active
            yield delay(3 * 33)
            reset.next = not reset.active

            # reset is delayed by at least two
            for ii in range(5):
                yield wclk.posedge

            # test normal cases
            for num_bytes in range(1, args.size + 1):

                # Write some byte
                for ii in range(num_bytes):
                    yield wclk.posedge
                    fbus.write_data.next = ii
                    fbus.write.next = True

                yield wclk.posedge
                fbus.write.next = False

                # If 16 bytes written make sure FIFO is full
                yield wclk.posedge
                if num_bytes == args.size:
                    assert fbus.full, "FIFO should be full!"

                while fbus.empty:
                    yield rclk.posedge

                fbus.read.next = True
                yield rclk.posedge
                for ii in range(num_bytes):
                    yield rclk.posedge
                    fbus.read.next = True
                    assert fbus.read_valid
                    assert fbus.read_data == ii, "rdata %x ii %x " % (
                        fbus.read_data, ii)

                yield rclk.posedge
                fbus.read.next = False
                yield rclk.posedge
                assert fbus.empty

            raise StopSimulation

        return myhdl.instances()
Пример #5
0
    def _test1():
        
        tbdut = fifo_async(reset, wclk, rclk, fbus)
                
        @instance
        def tbstim():
            print("start test 1")
            fbus.wdata.next = 0xFE
            reset.next = reset.active
            yield delay(3*33)
            reset.next = not reset.active

            # reset is delayed by at least two
            for ii in range(5):
                yield wclk.posedge
        
            # test normal cases
            for num_bytes in range(1, args.size+1):
        
                # Write some byte
                for ii in range(num_bytes):
                    yield wclk.posedge
                    fbus.wdata.next = ii
                    fbus.wr.next  = True
                    
                yield wclk.posedge
                fbus.wr.next = False
        
                # If 16 bytes written make sure FIFO is full
                yield wclk.posedge
                if num_bytes == args.size:
                    assert fbus.full, "FIFO should be full!"
        
                while fbus.empty:
                    yield rclk.posedge
                    
                fbus.rd.next = True
                yield rclk.posedge
                for ii in range(num_bytes):
                    yield rclk.posedge
                    fbus.rd.next = True
                    assert fbus.rvld
                    assert fbus.rdata == ii, "rdata %x ii %x " % (fbus.rdata, ii)
        
                yield rclk.posedge
                fbus.rd.next = False
                yield rclk.posedge
                assert fbus.empty
                    
            # Test overflows        
            # Test underflows        
            # Test write / read same time
            
            raise StopSimulation
        
        return tbdut, tbwclk, tbrclk, tbstim
Пример #6
0
    def bench_async_fifo():

        tbclkw = wclk.gen()
        tbclkr = rclk.gen()
        tbdut = fifo_async(wclk, rclk, fbus, reset)
        tbpr = procuder_consumer(wclk, rclk, fbus, start)
                
        @instance
        def tbstim():
            print("start test 1")
            fbus.write_data.next = 0xFE
            reset.next = reset.active
            yield delay(3*33)
            reset.next = not reset.active

            # reset is delayed by at least two
            for ii in range(5):
                yield wclk.posedge
        
            # test normal cases
            for num_bytes in range(1, args.size+1):
        
                # Write some byte
                for ii in range(num_bytes):
                    yield wclk.posedge
                    fbus.write_data.next = ii
                    fbus.write.next  = True
                    
                yield wclk.posedge
                fbus.write.next = False
        
                # If 16 bytes written make sure FIFO is full
                yield wclk.posedge
                if num_bytes == args.size:
                    assert fbus.full, "FIFO should be full!"
        
                while fbus.empty:
                    yield rclk.posedge
                    
                fbus.read.next = True
                yield rclk.posedge
                for ii in range(num_bytes):
                    yield rclk.posedge
                    fbus.read.next = True
                    assert fbus.read_valid
                    assert fbus.read_data == ii, "rdata %x ii %x " % (fbus.read_data, ii)
        
                yield rclk.posedge
                fbus.read.next = False
                yield rclk.posedge
                assert fbus.empty

            raise StopSimulation
        
        return myhdl.instances()
Пример #7
0
    def _test2():

        tbdut = fifo_async(reset, wclk, rclk, fbus)

        @instance
        def tbstim():
            print("start test 2")
            fbus.wdata.next = 0xFE
            reset.next = reset.active
            yield delay(3 * 33)
            reset.next = not reset.active

            yield delay(44)
            start.next = True

            for ii in range(2048):
                yield delay(100)

            raise StopSimulation

        return (tbdut, tbwclk, tbrclk, tb_always_wr, tb_always_wr_gate,
                tb_always_rd, tbstim)
Пример #8
0
    def _test2():
        
        tbdut = fifo_async(reset, wclk, rclk, fbus)
         
        @instance
        def tbstim():
            print("start test 2")
            fbus.wdata.next = 0xFE
            reset.next = reset.active
            yield delay(3*33)
            reset.next = not reset.active

            yield delay(44)
            start.next = True

            for ii in range(2048):
                yield delay(100)

            raise StopSimulation

        return (tbdut, tbwclk, tbrclk, tb_always_wr, tb_always_wr_gate, 
                tb_always_rd, tbstim)
Пример #9
0
    def bench_():
        tbclkw = wclk.gen()
        tbclkr = rclk.gen()
        tbdut = fifo_async(wclk, rclk, fbus, reset)
        tbpr = procuder_consumer(wclk, rclk, fbus, start)

        @instance
        def tbstim():
            print("start test 2")
            fbus.write_data.next = 0xFE
            reset.next = reset.active
            yield delay(3 * 33)
            reset.next = not reset.active

            yield delay(44)
            start.next = True

            for ii in range(2048):
                yield delay(100)

            raise StopSimulation

        return myhdl.instances()
Пример #10
0
    def bench_():
        tbclkw = wclk.gen()
        tbclkr = rclk.gen()
        tbdut = fifo_async(wclk, rclk, fbus, reset)
        tbpr = procuder_consumer(wclk, rclk, fbus, start)

        @instance
        def tbstim():
            print("start test 2")
            fbus.write_data.next = 0xFE
            reset.next = reset.active
            yield delay(3*33)
            reset.next = not reset.active

            yield delay(44)
            start.next = True

            for ii in range(2048):
                yield delay(100)

            raise StopSimulation

        return myhdl.instances()
Пример #11
0
def emesh_fifo(reset, emesh_i, emesh_o):
    """ EMesh transmit FIFO
    """

    # @todo: add rx channels ...

    nbits = len(emesh_i.txwr.bits)
    fbus_wr, fbus_rd, fbus_rr = [FIFOBus(width=nbits) for _ in range(3)]

    @myhdl.block
    def emesh_to_fifo(epkt, fbus):
        """ assign the EMesh inputs to the FIFO bus """
        @always_comb
        def beh_assign():
            fbus.write_data.next = epkt.bits
            print(epkt)
            if epkt.access:
                fbus.write.next = True
            else:
                fbus.write.next = False
        return beh_assign,

    def fifo_to_emesh(fbus, epkt, clock):
        """ assign FIFO bus to emesh output """
        fpkt = EMeshPacket()

        # map the bit-vector to the EMeshPacket interface
        map_inst = epkt_from_bits(fpkt, fbus.read_data)

        # the FIFOs work with a read acknowledge vs. a read
        # request - meaning the data is available before the
        # read and transitions to the next data after the read
        # strobe

        # @todo: there is (might be) an error here if the FIFO
        #   works in read-ack, if wait is set the same packet
        #   will be stuck on the bus, need to make sure the EMesh
        #   ignores the packet when wait is set
        @always_comb
        def beh_read():
            if not fbus.empty and not epkt.wait:
                fbus.read.next = True
            else:
                fbus.read.next = False

        @always(clock.posedge)
        def beh_assign():
            # @todo: check and see if this will convert fine
            # @todo: epkt.assign(fpkt)
            if fbus.read_valid:
                print("YES READ VALID {} {} {}".format(fbus.read_data, fpkt, epkt))
                epkt.access.next = fpkt.access
                epkt.write.next = fpkt.write
                epkt.datamode.next = fpkt.datamode
                epkt.ctrlmode.next = fpkt.ctrlmode
                epkt.dstaddr.next = fpkt.dstaddr
                epkt.data.next = fpkt.data
                epkt.srcaddr.next = fpkt.srcaddr
            else:
                epkt.access.next = False

        return map_inst, beh_read, beh_assign

    # create a FIFO foreach channel: write, read, read-response
    fifo_insts = []
    for epkt, fifobus in zip((emesh_i.txwr, emesh_i.txrd, emesh_i.txrr,),
                             (fbus_wr, fbus_rd, fbus_rr,)):
        fifo_insts += emesh_to_fifo(epkt, fifobus)
        fifo_insts += fifo_async(
            clock_write=emesh_i.clock, clock_read=emesh_o.clock,
            fifobus=fifobus, reset=reset, size=16
        )

    # assign the output of the FIFO
    for epkt, fifobus in zip((emesh_o.txwr, emesh_o.txrd, emesh_o.txrr,),
                             (fbus_wr, fbus_rd, fbus_rr,)):
        fifo_insts += fifo_to_emesh(fifobus, epkt, emesh_o.clock)

    return fifo_insts
Пример #12
0
def bench_conversion_fifo_async():
    args = Namespace(width=8, size=32, fifosize=64, name='test')

    clock_write, clock_read = Signals(bool(0), 2)
    reset = ResetSignal(0, active=1, async=False)

    fbus = FIFOBus(width=args.width)
    fifosize = args.fifosize
    tbdut = fifo_async(clock_write, clock_read, fbus, reset, size=fifosize)

    @instance
    def tbclkr():
        clock_read.next = False
        while True:
            yield delay(5)
            clock_read.next = not clock_read

    @instance
    def tbclkw():
        clock_write.next = False
        while True:
            yield delay(5)
            clock_write.next = not clock_write

    @instance
    def tbstim():
        print("start simulation")
        fbus.write.next = False
        fbus.write_data.next = 0
        fbus.read.next = False
        fbus.clear.next = False

        print("reset")
        reset.next = reset.active
        yield delay(10)
        reset.next = not reset.active
        yield delay(10)

        print("some clock cycles")
        for ii in range(10):
            yield clock_write.posedge

        print("some writes")
        for ii in range(fifosize):
            fbus.write.next = True
            fbus.write_data.next = ii
            yield clock_write.posedge
        fbus.write.next = False
        yield clock_write.posedge

        for ii in range(fifosize):
            fbus.read.next = True
            yield clock_read.posedge
            print("%d %d %d %d" % (
                fbus.write,
                fbus.write_data,
                fbus.read,
                fbus.read_data,
            ))
        fbus.read.next = False

        print("end simulation")
        raise StopSimulation

    return myhdl.instances()
Пример #13
0
def emesh_fifo(reset, emesh_i, emesh_o):
    """ EMesh transmit FIFO
    """

    # @todo: add rx channels ...

    nbits = len(emesh_i.txwr.bits)
    fbus_wr, fbus_rd, fbus_rr = [FIFOBus(width=nbits) for _ in range(3)]

    @myhdl.block
    def emesh_to_fifo(epkt, fbus):
        """ assign the EMesh inputs to the FIFO bus """
        @always_comb
        def beh_assign():
            fbus.write_data.next = epkt.bits
            print(epkt)
            if epkt.access:
                fbus.write.next = True
            else:
                fbus.write.next = False

        return beh_assign,

    def fifo_to_emesh(fbus, epkt, clock):
        """ assign FIFO bus to emesh output """
        fpkt = EMeshPacket()

        # map the bit-vector to the EMeshPacket interface
        map_inst = epkt_from_bits(fpkt, fbus.read_data)

        # the FIFOs work with a read acknowledge vs. a read
        # request - meaning the data is available before the
        # read and transitions to the next data after the read
        # strobe

        # @todo: there is (might be) an error here if the FIFO
        #   works in read-ack, if wait is set the same packet
        #   will be stuck on the bus, need to make sure the EMesh
        #   ignores the packet when wait is set
        @always_comb
        def beh_read():
            if not fbus.empty and not epkt.wait:
                fbus.read.next = True
            else:
                fbus.read.next = False

        @always(clock.posedge)
        def beh_assign():
            # @todo: check and see if this will convert fine
            # @todo: epkt.assign(fpkt)
            if fbus.read_valid:
                print("YES READ VALID {} {} {}".format(fbus.read_data, fpkt,
                                                       epkt))
                epkt.access.next = fpkt.access
                epkt.write.next = fpkt.write
                epkt.datamode.next = fpkt.datamode
                epkt.ctrlmode.next = fpkt.ctrlmode
                epkt.dstaddr.next = fpkt.dstaddr
                epkt.data.next = fpkt.data
                epkt.srcaddr.next = fpkt.srcaddr
            else:
                epkt.access.next = False

        return map_inst, beh_read, beh_assign

    # create a FIFO foreach channel: write, read, read-response
    fifo_insts = []
    for epkt, fifobus in zip((
            emesh_i.txwr,
            emesh_i.txrd,
            emesh_i.txrr,
    ), (
            fbus_wr,
            fbus_rd,
            fbus_rr,
    )):
        fifo_insts += emesh_to_fifo(epkt, fifobus)
        fifo_insts += fifo_async(clock_write=emesh_i.clock,
                                 clock_read=emesh_o.clock,
                                 fifobus=fifobus,
                                 reset=reset,
                                 size=16)

    # assign the output of the FIFO
    for epkt, fifobus in zip((
            emesh_o.txwr,
            emesh_o.txrd,
            emesh_o.txrr,
    ), (
            fbus_wr,
            fbus_rd,
            fbus_rr,
    )):
        fifo_insts += fifo_to_emesh(fifobus, epkt, emesh_o.clock)

    return fifo_insts
Пример #14
0
def bench_conversion_fifo_async():
    args = Namespace(width=8, size=32, fifosize=64, name='test')

    clock_write, clock_read = Signals(bool(0), 2)
    reset = ResetSignal(0, active=1, async=False)

    fbus = FIFOBus(width=args.width)
    fifosize = args.fifosize
    tbdut = fifo_async(clock_write, clock_read, fbus, reset, size=fifosize)

    @instance
    def tbclkr():
        clock_read.next = False
        while True:
            yield delay(5)
            clock_read.next = not clock_read

    @instance
    def tbclkw():
        clock_write.next = False
        while True:
            yield delay(5)
            clock_write.next = not clock_write

    @instance
    def tbstim():
        print("start simulation")
        fbus.write.next = False
        fbus.write_data.next = 0
        fbus.read.next = False
        fbus.clear.next = False

        print("reset")
        reset.next = reset.active
        yield delay(10)
        reset.next = not reset.active
        yield delay(10)

        print("some clock cycles")
        for ii in range(10):
            yield clock_write.posedge

        print("some writes")
        for ii in range(fifosize):
            fbus.write.next = True
            fbus.write_data.next = ii
            yield clock_write.posedge
        fbus.write.next = False
        yield clock_write.posedge

        for ii in range(fifosize):
            fbus.read.next = True
            yield clock_read.posedge
            print("%d %d %d %d" % (
                fbus.write, fbus.write_data, fbus.read, fbus.read_data,))
        fbus.read.next = False

        print("end simulation")
        raise StopSimulation

    return myhdl.instances()
Пример #15
0
def spi_slave_fifo_async(glbl, spibus, fifobus):
    """
    This is an SPI slave peripheral, when the master starts clocking
    any data in the TX FIFO (fifobus.write) will be sent (the next
    byte) and the received byte will be copied to RX FIFO
    (fifobus.read).  The `cso` interface can be used to configure
    how the SPI slave peripheral behaves.

    (Arguments == Ports)
    Arguments:
        glbl (Global): global clock and reset
        spibus  (SPIBus): the external SPI interface
        fifobus (FIFOBus): the fifo interface
        cso (ControlStatus): the control status signals
    """
    fifosize = 8

    # Use an async FIFO to transfer from the SPI SCK clock domain and
    # the internal clock domain.  This allows for high-speed SCK.
    clock, reset = glbl.clock, glbl.reset
    assert isinstance(spibus, SPIBus)
    assert isinstance(fifobus, FIFOBus)

    sck, csn = spibus.sck, spibus.csn
    # the FIFOs for the receive and transmit (external perspective)
    readpath = FIFOBus(width=fifobus.width)
    writepath = FIFOBus(width=fifobus.width)

    # the FIFO instances
    #tx_fifo_inst = fifo_async(glbl, writepath, size=fifosize)
    #rx_fifo_inst = fifo_async(glbl, readpath, size=fifosize)
    #mp_fifo_inst = fifobus.assign_read_write_paths(readpath, writepath)

    tx_fifo_inst = fifo_async(fifobus.write_clock,
                              clock,
                              writepath,
                              reset,
                              size=fifosize)
    rx_fifo_inst = fifo_async(clock,
                              fifobus.read_clock,
                              readpath,
                              reset,
                              size=fifosize)
    mp_fifo_inst = fifobus.assign_read_write_paths(readpath, writepath)

    spi_start = Signal(bool(0))
    ireg, icap, icaps = Signals(intbv(0)[8:], 3)
    oreg, ocap = Signals(intbv(0)[8:], 2)
    bitcnt, b2, b3 = Signals(intbv(0, min=0, max=10), 3)

    @always(csn.negedge)  #, sck.posedge
    def csn_falls():
        #        if sck:
        spi_start.next = True
#        elif not csn:
#            spi_start.next = True

# SCK clock domain, this allows high SCK rates

    @always(sck.posedge, csn.posedge)
    def sck_capture_send():
        if csn:
            b2.next = 0
            bitcnt.next = 0
        else:
            if bitcnt == 0 or spi_start:
                spibus.miso.next = ocap[7]
                oreg.next = (ocap << 1) & 0xFF
            else:
                spibus.miso.next = oreg[7]
                oreg.next = (oreg << 1) & 0xFF

            ireg.next = concat(ireg[7:0], spibus.mosi)
            bitcnt.next = bitcnt + 1
            if bitcnt == (8 - 1):
                bitcnt.next = 0
                b2.next = 8
                icap.next = concat(ireg[7:0], spibus.mosi)
            else:
                b2.next = 0

    # synchronize the SCK domain to the clock domain
    s1 = syncro(clock, icap, icaps)
    s2 = syncro(clock, b2, b3)

    gotit = Signal(bool(0))

    @always(clock.posedge)
    def beh_io_capture():
        # default no writes
        readpath.write.next = False
        writepath.read.next = False

        if b3 == 0:
            gotit.next = False
        elif b3 == 8 and not gotit:
            readpath.write.next = True
            readpath.write_data.next = icaps
            gotit.next = True
            ocap.next = writepath.read_data
            if not writepath.empty:
                writepath.read.next = True

    return myhdl.instances()