예제 #1
0
def _di_to_bus_rx(dut, num_transfers=500, max_delay=100):

    wb_master = WishboneMaster(dut, dut.clk)

    for i in range(num_transfers):
        delay = random.randint(0, max_delay)

        for _ in range(delay):
            yield RisingEdge(dut.clk)

        # Wait until the UART signals that it is ready for a read
        while True:
            lsr_can_read = yield _lsr_can_read(dut, wb_master)
            if lsr_can_read:
                break
            yield RisingEdge(dut.clk)

        # Only look at the LSB of the 32-bit wide result.
        ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x8)])
        res = ret.pop(0).datrd & 0xFF

        data = _di_to_bus_fifo.pop(0);

        if data != res:
           raise TestFailure("Expected result to be 0x%x, got 0x%x" %
                             (data, res))

        yield RisingEdge(dut.clk)
예제 #2
0
def test_uart_irq_tbe(dut):
    """
    Check if the Transmit Buffer Empty interrupt is sent
    """

    yield _init_dut(dut)
    yield _activate_module(dut)

    wb_master = WishboneMaster(dut, dut.clk)

    # ensure that IRQ is lowered before we start sending
    if dut.irq.value != 0:
        raise TestFailure("irq is not lowered at start.")

    # Enable TBE interrupt by setting bit 2 in IER
    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x2, sel=0x4)])
    yield RisingEdge(dut.clk)

    # ensure that IRQ is still lowered before we start sending
    if dut.irq.value != 1:
        raise TestFailure("irq is not high (indicating an empty transmit buffer)")

    yield RisingEdge(dut.clk)

    # simulate the CPU sending a single char to the UART device
    yield _bus_to_di_tx(dut, num_transfers=1, random_data=False)

    # check that IRQ is now lowered
    if dut.irq.value != 0:
        raise TestFailure("irq it not lowered after receiving data.")

    # Let the UART module empty its send buffer
    yield _bus_to_di_rx(dut, num_transfers=1)

    # check that IRQ is now high again, indicating an empty transmit buffer
    if dut.irq.value != 1:
        raise TestFailure("irq not high again after emptying the transmit buffer.")

    # Disable the TBE interrupt again
    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x0, sel=0x4)])
    yield RisingEdge(dut.clk)

    # Ensure that the interrupt signal is now lowered
    if dut.irq.value != 0:
        raise TestFailure("irq not lowered after disabling the interrupt.")
예제 #3
0
def _lsr_can_read(dut, wb_master):
    """
    Check if the UART LSR register signals data available in its input buffer
    """
    ret = yield wb_master.send_cycle([WBOp(adr=0x4, dat=None, sel=0x4)])
    lsr = ret.pop(0).datrd & 0xFF

    # Reading is possible if DR (bit 0) is set
    raise ReturnValue(lsr & (1 << 0))
예제 #4
0
def _lsr_can_write(dut, wb_master):
    """
    Check if the UART LSR register signals space in its output buffers
    """
    ret = yield wb_master.send_cycle([WBOp(adr=0x4, dat=None, sel=0x4)])
    lsr = ret.pop(0).datrd & 0xFF

    # Writing is possible if THRE (bit 5) and TEMPT (bit 6) are set
    raise ReturnValue(lsr & (1 << 5) and lsr & (1 << 6))
예제 #5
0
def test_uart_read_empty(dut):
    """
    Ensure that the bus doesn't block even though no data is available to read
    """

    yield _init_dut(dut)
    yield _activate_module(dut)

    # WB master with 10 cycles timeout
    wb_master = WishboneMaster(dut, dut.clk, timeout=10)

    # Read from Receiver Buffer Register (RBR)
    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x0)])
    res = ret.pop(0).datrd & 0xFF
예제 #6
0
def test_uart_irq_rbf(dut):
    """
    Check if the Receive Buffer Full interrupt is sent
    """

    yield _init_dut(dut)
    yield _activate_module(dut)

    _di_to_bus_fifo.clear()

    wb_master = WishboneMaster(dut, dut.clk)

    # ensure that IRQ is lowered before we start sending
    if dut.irq.value != 0:
        raise TestFailure("irq is not lowered at start.")

    # Enable RBF interrupt by setting bit 1 in IER
    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x1, sel=0x4)])
    yield RisingEdge(dut.clk)

    # ensure that IRQ is still lowered before we start sending
    if dut.irq.value != 0:
        raise TestFailure("irq is not low, even though receive buffer is empty")

    yield RisingEdge(dut.clk)

    # send a single packet to the UART module
    yield _di_to_bus_tx(dut, num_transfers=1, random_data=False)

    for _ in range(4):
        yield RisingEdge(dut.clk)

    # check that IRQ is now high
    if dut.irq.value != 1:
        raise TestFailure("irq it not high after receiving a character")

    # simulate CPU consuming the incoming character
    yield _di_to_bus_rx(dut, num_transfers=1)

    # check that IRQ is now lowered again
    if dut.irq.value != 0:
        raise TestFailure("irq it not lowered after the incoming character has been consumed")
예제 #7
0
def _bus_to_di_tx(dut, num_transfers=500, max_delay=100, random_data=False):

    wb_master = WishboneMaster(dut, dut.clk)

    for i in range(num_transfers):
        delay = random.randint(0, max_delay)

        for _ in range(delay):
            yield RisingEdge(dut.clk)

        # Wait until the UART signals that it is ready for writes
        while True:
            lsr_can_write = yield _lsr_can_write(dut, wb_master)
            if lsr_can_write:
                break
            yield RisingEdge(dut.clk)

        data = random.randint(0, 255) if random_data else 0x42
        _bus_to_di_fifo.append(data)

        yield wb_master.send_cycle([WBOp(adr=0x0, dat=data, sel=0x8)])
예제 #8
0
def test_uart_16550_registers(dut):
    """
    Test accessibility and functionality of the implemented UART registers, as
    well as their correct reset values.
    """

    yield _init_dut(dut)
    yield _activate_module(dut)

    wb_master = WishboneMaster(dut, dut.clk)

    # IER, verify reset values and persistence
    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x4)])
    res = ret.pop(0).datrd & 0xFF

    if 0 != res:
        raise TestFailure("IER test failed! Wrong reset values: 0x%x" % res)

    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x3, sel=0x4)])

    for _ in range(10):
        yield RisingEdge(dut.clk)

    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x4)])
    res = ret.pop(0).datrd & 0xFF

    if res != 0x3:
        raise TestFailure("IER test failed! Written value not stored, Wrote: 0x%x, Read: 0x%x"
                          % (0x3, res))

    # IIR (Read Only) & FCR (Write Only), make sure the FIFOs can be enabled
    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x1, sel=0x2)])

    # Only check if the FIFOs have been enabled correctly
    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x2)])
    res = ret.pop(0).datrd & 0xC0

    if res != 0xC0:
        raise TestFailure("FCR test failed! FIFOs not enabled. 0x%x" % res)

    # LCR, make sure DLAB can be set
    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x1)])
    res = ret.pop(0).datrd

    if res != 0x0:
        raise TestFailure("LCR test failed! Wrong reset values: 0x%x" % res)

    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x80, sel=0x1)])

    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x1)])
    res = ret.pop(0).datrd & 0xFF

    if res != 0x80:
        raise TestFailure("LCR test failed! Written value not stored, Wrote: 0x%x, Read: 0x%x"
                          % (0x80, res))

    # LSR (Read Only), verify correct reset value
    ret = yield wb_master.send_cycle([WBOp(adr=0x4, dat=None, sel=0x4)])
    res = ret.pop(0).datrd & 0xFF

    if res != 0x60:
        raise TestFailure("LSR test failed! Wrong reset values: 0x%x" % res)

    # DLM & DLL, verify accessibility
    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x80, sel=0x1)])

    # Set Baudrate to 115200 (LSB first)
    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x1, sel=0x8)])
    yield wb_master.send_cycle([WBOp(adr=0x0, dat=0x0, sel=0x4)])

    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x8)])
    res = ret.pop(0).datrd & 0xFF

    if res != 0x1:
        raise TestFailure("DLL test failed! Wrote: 0x%x, Read: 0x%x"
                          % (0x1, res))

    ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x4)])
    res = ret.pop(0).datrd & 0xFF

    if res != 0x0:
        raise TestFailure("DLM test failed! Wrote: 0x%x, Read: 0x%x"
                          % (0x0, res))
예제 #9
0
def test_both_directions(dut):
    """
    Randomly alternate between read/write cycles on the WISHBONE bus
    """

    NUM_TRANSFERS = 1000
    MAX_DELAY     = 50
    RANDOM_DATA   = True

    yield _init_dut(dut)
    yield _activate_module(dut)

    _bus_to_di_fifo.clear()
    _di_to_bus_fifo.clear()

    wb_master = WishboneMaster(dut, dut.clk)

    rx_packets = NUM_TRANSFERS
    tx_packets = NUM_TRANSFERS

    write_thread = cocotb.fork(_di_to_bus_tx(dut, num_transfers=NUM_TRANSFERS,
                                             max_delay=MAX_DELAY,
                                             random_data=RANDOM_DATA))
    read_thread = cocotb.fork(_bus_to_di_rx(dut, num_transfers=NUM_TRANSFERS,
                                            max_delay=MAX_DELAY))

    # randomly pick a direction and send/receive any remaining packets
    while tx_packets or rx_packets:
        if random.randint(0,1):
            if not tx_packets:
                continue

            for _ in range(random.randint(0, MAX_DELAY)):
                yield RisingEdge(dut.clk)

            # Check if the UART signals space in its send buffer
            lsr_can_write = yield _lsr_can_write(dut, wb_master)
            if not lsr_can_write:
                continue

            data = random.randint(0, 255) if RANDOM_DATA else 0x42
            _bus_to_di_fifo.append(data)

            yield wb_master.send_cycle([WBOp(adr=0x0, dat=data, sel=0x8)])

            yield RisingEdge(dut.clk)

            tx_packets -= 1
        else:
            if not rx_packets:
                continue

            for _ in range(random.randint(0, MAX_DELAY)):
                yield RisingEdge(dut.clk)

            # Check if the UART signals available data in its read buffer
            lsr_can_read = yield _lsr_can_read(dut, wb_master)
            if not lsr_can_read:
                continue

            ret = yield wb_master.send_cycle([WBOp(adr=0x0, dat=None, sel=0x8)])
            res = ret.pop(0).datrd & 0xFF

            data = _di_to_bus_fifo.pop(0)

            if data != res:
                raise TestFailure("Expected result to be 0x%x, got 0x%x"
                                  % (data, res))

            yield RisingEdge(dut.clk)

            rx_packets -= 1

    # we implicitly wait for the write_thread in the loop above
    yield read_thread.join()