Exemple #1
0
def testbench_memmap(args=None):
    """  """
    args = tb_default_args(args)

    clock = Clock(0, frequency=50e6)
    reset = Reset(0, active=1, isasync=False)
    glbl = Global(clock, reset)
    csbus = Barebone(glbl, data_width=8, address_width=16)

    @myhdl.block
    def bench_memmap():
        tbdut = peripheral(csbus)
        tbclk = clock.gen()

        print(csbus.regfiles)

        @instance
        def tbstim():
            yield reset.pulse(111)

            raise StopSimulation

        return tbdut, tbclk, tbstim

    run_testbench(bench_memmap)
Exemple #2
0
def test_spi_models(args=None):
    args = tb_default_args(args)
    clock = Clock(0, frequency=125e6)
    glbl = Global(clock)
    ibus = Barebone(glbl)
    spibus = SPIBus()

    def bench():

        tbdut = spi_controller_model(clock, ibus, spibus)
        tbspi = SPISlave().process(spibus)
        tbclk = clock.gen()

        @instance
        def tbstim():
            yield clock.posedge

            yield ibus.writetrans(0x00, 0xBE)
            yield delay(100)
            yield ibus.readtrans(0x00)

            raise StopSimulation

        return tbdut, tbspi, tbclk, tbstim

    run_testbench(bench, args=args)
Exemple #3
0
def led_blinker_top(clock, reset, leds, buttons):

    glbl = Global(clock, reset)
    csrbus = Barebone()
    dbtns = Signal(buttons.val)

    led_inst = led_blinker(glbl, csrbus, leds)
    dbn_inst = button_debounce(glbl, buttons, dbtns)
    btn_inst = button_controller(glbl, csrbus, dbtns)

    # above all the components have been added, now build the
    # register file (figures out addresses, etc) and then get
    # the memory-mapped bus interconnect
    csrbus.regfile_build()
    bus_inst = csrbus.interconnect()

    return myhdl.instances()
def test_memmap_command_bridge(args=None):
    nloops = 37
    args = tb_default_args(args)
    clock = Clock(0, frequency=50e6)
    reset = Reset(0, active=1, async=False)
    glbl = Global(clock, reset)
    fbtx, fbrx = FIFOBus(), FIFOBus()
    memmap = Barebone(glbl, data_width=32, address_width=28)

    fbtx.clock = clock
    fbrx.clock = clock

    def _bench_command_bridge():
        tbclk = clock.gen()
        tbdut = memmap_command_bridge(glbl, fbtx, fbrx, memmap)
        tbfii = fifo_fast(clock, reset, fbtx)
        tbfio = fifo_fast(clock, reset, fbrx)
        # @todo: add other bus types
        tbmem = memmap_peripheral_bb(clock, reset, memmap)

        # save the data read ...
        read_value = []

        @instance
        def tbstim():
            yield reset.pulse(32)

            try:
                # test a single address
                pkt = CommandPacket(True, 0x0000)
                yield pkt.put(fbtx)
                yield pkt.get(fbrx, read_value, [0])
                pkt = CommandPacket(False, 0x0000, [0x5555AAAA])
                yield pkt.put(fbtx)
                yield pkt.get(fbrx, read_value, [0x5555AAAA])

                # test a bunch of random addresses
                for ii in range(nloops):
                    randaddr = randint(0, (2**20) - 1)
                    randdata = randint(0, (2**32) - 1)
                    pkt = CommandPacket(False, randaddr, [randdata])
                    yield pkt.put(fbtx)
                    yield pkt.get(fbrx, read_value, [randdata])

            except Exception as err:
                print("Error: {}".format(str(err)))
                traceback.print_exc()

            yield delay(2000)
            raise StopSimulation

        return tbclk, tbdut, tbfii, tbfio, tbmem, tbstim

    run_testbench(_bench_command_bridge, args=args)
Exemple #5
0
def catboard_blinky_host(clock, led, uart_tx, uart_rx):
    """
    The LEDs are controlled from the RPi over the UART
    to the FPGA.
    """

    glbl = Global(clock, None)
    ledreg = Signal(intbv(0)[8:])

    # create the timer tick instance
    tick_inst = glbl_timer_ticks(glbl, include_seconds=True)

    # create the interfaces to the UART
    fbustx = FIFOBus(width=8, size=4)
    fbusrx = FIFOBus(width=8, size=4)

    # create the memmap (CSR) interface
    memmap = Barebone(glbl, data_width=32, address_width=32)

    # create the UART instance.
    uart_inst = uartlite(glbl,
                         fbustx,
                         fbusrx,
                         serial_in=uart_rx,
                         serial_out=uart_tx)

    # create the packet command instance
    cmd_inst = command_bridge(glbl, fbusrx, fbustx, memmap)

    @always_seq(clock.posedge, reset=None)
    def beh_led_control():
        memmap.done.next = not (memmap.write or memmap.read)
        if memmap.write and memmap.mem_addr == 0x20:
            ledreg.next = memmap.write_data

    @always_comb
    def beh_led_read():
        if memmap.read and memmap.mem_addr == 0x20:
            memmap.read_data.next = ledreg
        else:
            memmap.read_data.next = 0

    # blink one of the LEDs
    tone = Signal(intbv(0)[8:])

    @always_seq(clock.posedge, reset=None)
    def beh_assign():
        if glbl.tick_sec:
            tone.next = (~tone) & 0x1
        led.next = ledreg | tone[5:]

    return (tick_inst, uart_inst, cmd_inst, beh_led_control, beh_led_read,
            beh_assign)
Exemple #6
0
def m_btn_led_mm(clock, reset, leds, btns, bus_type='W'):
    """ A toy example to demostrate bus agnosticism
    This example instantiates a memory-map controller and a
    memory-map peripheral.  This example shows how the 
    controllers and peripherals can be passed the memmap
    interface.  The passing of the interface allows the 
    modules (components) to be bus agnostic.

    This example solves a simple task in a complicated manner
    to show the point.  When a button press is detected a 
    bus cycle is generated to write the "flash" pattern to 
    the LED peripheral.

    Note: for easy FPGA bit-stream generation the port names
    match the board names defined in the *gizflo* board definitions.
    """
    glbl = Global(clock=clock, reset=reset)

    if bus_type == 'B':
        regbus = Barebone(glbl, data_width=8, address_width=16)
    elif bus_type == 'W':
        regbus = Wishbone(glbl, data_width=8, address_width=16)
    elif bus_type == 'A':
        regbus = AvalonMM(glbl, data_width=8, address_width=16)
    #elif bus_type == 'X':
    #    regbus = AXI4Lite(glbl, data_wdith=8, address_width=16)
    else:
        raise Exception("Invalid bus type {}".format(bus_type))

    gbtn = button_controller(glbl, regbus, btns)  # memmap controller
    gled = led_peripheral(glbl, regbus, leds)     # memmap peripheral
    gmap = regbus.interconnect()                  # bus combiner

    print(vars(regbus.regfiles['LED_000']))

    return gbtn, gled, gmap
Exemple #7
0
def m_btn_led_mm(clock, reset, leds, btns, bus_type='W'):
    """ A toy example to demostrate bus agnosticism
    This example instantiates a memory-map controller and a
    memory-map peripheral.  This example shows how the 
    controllers and peripherals can be passed the memmap
    interface.  The passing of the interface allows the 
    modules (components) to be bus agnostic.

    This example solves a simple task in a complicated manner
    to show the point.  When a button press is detected a 
    bus cycle is generated to write the "flash" pattern to 
    the LED peripheral.

    Note: for easy FPGA bit-stream generation the port names
    match the board names defined in the *gizflo* board definitions.
    """
    glbl = Global(clock=clock, reset=reset)

    if bus_type == 'B':
        regbus = Barebone(glbl, data_width=8, address_width=16)
    elif bus_type == 'W':
        regbus = Wishbone(glbl, data_width=8, address_width=16)
    elif bus_type == 'A':
        regbus = AvalonMM(glbl, data_width=8, address_width=16)
    #elif bus_type == 'X':
    #    regbus = AXI4Lite(glbl, data_wdith=8, address_width=16)
    else:
        raise Exception("Invalid bus type {}".format(bus_type))

    gbtn = button_controller(glbl, regbus, btns)  # memmap controller
    gled = led_peripheral(glbl, regbus, leds)  # memmap peripheral
    gmap = regbus.interconnect()  # bus combiner

    print(vars(regbus.regfiles['LED_000']))

    return gbtn, gled, gmap
Exemple #8
0
def atlys_blinky_host(clock, reset, led, sw, pmod, uart_tx, uart_rx):
    """
    This example is similar to the other examples in this directory but
    the LEDs are controlled externally via command packets sent from a
    host via the UART on the icestick.

    """
    glbl = Global(clock, reset)
    ledreg = Signal(intbv(0)[8:])

    # create the timer tick instance
    tick_inst = glbl_timer_ticks(glbl, include_seconds=True)

    # create the interfaces to the UART
    fbustx = FIFOBus(width=8, size=32)
    fbusrx = FIFOBus(width=8, size=32)

    # create the memmap (CSR) interface
    memmap = Barebone(glbl, data_width=32, address_width=32)

    # create the UART instance.
    cmd_tx = Signal(bool(0))
    uart_inst = uartlite(glbl, fbustx, fbusrx, uart_rx, cmd_tx)

    # create the packet command instance
    cmd_inst = memmap_command_bridge(glbl, fbusrx, fbustx, memmap)

    @always_seq(clock.posedge, reset=reset)
    def beh_led_control():
        memmap.done.next = not (memmap.write or memmap.read)
        if memmap.write:  # and memmap.mem_addr == 0x20:
            ledreg.next = memmap.write_data

    @always_comb
    def beh_led_read():
        if memmap.read and memmap.mem_addr == 0x20:
            memmap.read_data.next = ledreg
        else:
            memmap.read_data.next = 0

    # blink one of the LEDs
    status = [Signal(bool(0)) for _ in range(8)]
    statusbv = ConcatSignal(*reversed(status))

    @always_seq(clock.posedge, reset=reset)
    def beh_assign():
        # status / debug signals
        if glbl.tick_sec:
            status[0].next = not status[0]
        status[1].next = memmap.mem_addr == 0x20
        status[2].next = uart_rx
        status[3].next = uart_tx
        led.next = ledreg | statusbv | sw

        pmod.next = 0

        if sw[0]:
            uart_tx.next = uart_rx
        else:
            uart_tx.next = cmd_tx

    # @todo: PMOD OLED memmap control

    return (tick_inst, uart_inst, cmd_inst, beh_led_control, beh_led_read,
            beh_assign)
Exemple #9
0
def testbench_to_generic(args=None):
    """ Test memory-mapped bus and the mapping to a generic bus

    :param args:
    :return:
    """
    depth = 16  # number of memory address
    width = 32  # memory-mapped bus data width
    maxval = 2**width

    run = False if args is None else True
    args = tb_default_args(args)

    if not hasattr(args, 'num_loops'):
        args.num_loops = 10

    clock = Clock(0, frequency=100e6)
    reset = Reset(0, active=1, async=False)
    glbl = Global(clock, reset)

    if hasattr(args, 'bustype'):
        address_width = 18
        membus = busmap[args.bustype](glbl,
                                      data_width=width,
                                      address_width=address_width)
    else:
        address_width = int(ceil(log(depth, 2))) + 4
        membus = Barebone(glbl, data_width=width, address_width=address_width)

    @myhdl.block
    def bench_to_generic():
        tbdut = peripheral_memory(membus, depth=depth)
        tbitx = membus.interconnect()
        tbclk = clock.gen()
        testvals = {}

        @instance
        def tbstim():
            yield reset.pulse(42)
            yield clock.posedge

            # only testing one peripheral, set the peripheral/slave
            # address to the first ...
            if isinstance(membus, Barebone):
                membus.per_addr.next = 1
                peraddr = 0
            else:
                peraddr = 0x10000

            yield clock.posedge

            for ii in range(args.num_loops):
                randaddr = randint(0, depth - 1) | peraddr
                randdata = randint(0, maxval - 1)
                testvals[randaddr] = randdata
                yield membus.writetrans(randaddr, randdata)
            yield clock.posedge

            for addr, data in testvals.items():
                yield membus.readtrans(addr)
                read_data = membus.get_read_data()
                assert read_data == data, "{:08X} != {:08X}".format(
                    read_data, data)
            yield clock.posedge

            yield delay(100)
            raise StopSimulation

        return tbdut, tbitx, tbclk, tbstim

    if run:
        run_testbench(bench_to_generic, args=args)
Exemple #10
0
def uart_blinky(clock, led, uart_tx, uart_rx):
    """
    Uses UART module to control LEDs while blinking the first LED.
    LEDs used are pins 0-7 on wing A.
    Expected behavior after upload is that LED[0] blinks on/off.
    When sending 
    0xDE 0x02 0x00 0x00 0x00 0x20 0x04 0xCA 0x00 0x00 0x00 0xFF
    via serial connection, all LEDs should turn on.
    For details about the message format see
    /rhea/cores/memmap/command_bridge.py
    """
    reset = ResetSignal(0, active=0, async=True)

    glbl = Global(clock, reset)
    ledreg = Signal(intbv(0)[8:])

    # create the timer tick instance
    tick_inst = glbl_timer_ticks(glbl, include_seconds=True)

    # create the interfaces to the UART
    fifobus = FIFOBus(width=8)

    # create the memmap (CSR) interface
    memmap = Barebone(glbl, data_width=32, address_width=32)

    # create the UART instance.
    uart_inst = uartlite(glbl,
                         fifobus,
                         serial_in=uart_rx,
                         serial_out=uart_tx,
                         fifosize=4)

    # create the packet command instance
    cmd_inst = command_bridge(glbl, fifobus, memmap)

    @always_seq(clock.posedge, reset=reset)
    def beh_led_control():
        memmap.done.next = not (memmap.write or memmap.read)
        if memmap.write and memmap.mem_addr == 0x20:
            ledreg.next = memmap.write_data

    @always_comb
    def beh_led_read():
        if memmap.read and memmap.mem_addr == 0x20:
            memmap.read_data.next = ledreg
        else:
            memmap.read_data.next = 0

    # blink one of the LEDs
    tone = Signal(intbv(0)[8:])
    reset_dly_cnt = Signal(intbv(0)[5:])

    @always_seq(clock.posedge, reset=None)
    def beh_assign():
        if glbl.tick_sec:
            tone.next = (~tone) & 0x1
        led.next = ledreg | tone[5:]

    @always(clock.posedge)
    def reset_tst():
        '''
        For the first 4 clocks the reset is forced to lo
        for clock 6 to 31 the reset is set hi
        then the reset is lo
        '''
        if (reset_dly_cnt < 31):
            reset_dly_cnt.next = reset_dly_cnt + 1
            if (reset_dly_cnt <= 4):
                reset.next = 1
            if (reset_dly_cnt >= 5):
                reset.next = 0
        else:
            reset.next = 1

    return (tick_inst, cmd_inst, uart_inst, beh_led_control, beh_led_read,
            beh_assign, reset_tst)
Exemple #11
0
def memmap_command_bridge(glbl, fifobusi, fifobuso, mmbus):
    """ Convert a command packet to a memory-mapped bus transaction
    
    This module will decode the incomming packet and start a bus 
    transaction, the memmap_controller_basic is used to generate
    the bus transactions, it convertes the Barebone interface to 
    the MemoryMapped interface being used. 
    
    The variable length command packet is:
        00: 0xDE
        01: command byte (response msb indicates error)
        02: address high byte 
        03: address byte 
        04: address byte 
        05: address low byte 
        06: length of data (max length 256 bytes)
        07: 0xCA   # sequence number, fixed for now
        08: data high byte 
        09: data byte
        10: data byte
        11: data low byte
        Fixed 12 byte packet currently supported, future
        to support block write/reads up to 256-8-4
        12 - 253: write / read (big-endian)
        @todo: last 2 bytes crc
    The total packet length is 16 + data_length

    Ports:
      glbl: global signals and control
      fifobusi: input fifobus, host packets to device (interface)
      fifobuso: output fifobus, device responses to host (interface)
      mmbus: memory-mapped bus (interface)

    this module is convertible
    """
    assert isinstance(fifobusi, FIFOBus)
    assert isinstance(fifobuso, FIFOBus)
    assert isinstance(mmbus, MemoryMapped)
    fbrx, fbtx = fifobusi, fifobuso
    clock, reset = glbl.clock, glbl.reset
    bb = Barebone(glbl,
                  data_width=mmbus.data_width,
                  address_width=mmbus.address_width)

    states = enum(
        'idle',
        'wait_for_packet',  # receive a command packet
        'check_packet',  # basic command check
        'write',  # bus write
        'write_end',  # end of the write cycle
        'read',  # read bus cycles for response
        'read_end',  # end of the read cycle
        'response',  # send response packet
        'response_full',  # check of RX FIFO full
        'error',  # error occurred
        'end'  # end state
    )

    state = Signal(states.idle)
    ready = Signal(bool(0))
    error = Signal(bool(0))
    bytecnt = intbv(0, min=0, max=256)

    # known knows
    pidx = (
        0,
        7,
    )
    pval = (
        0xDE,
        0xCA,
    )
    assert len(pidx) == len(pval)
    nknown = len(pidx)

    bytemon = Signal(intbv(0)[8:])

    # only supporting 12byte packets (single read/write) for now
    packet_length = 12
    data_offset = 8
    packet = [Signal(intbv(0)[8:]) for _ in range(packet_length)]
    command = packet[1]
    address = ConcatSignal(*packet[2:6])
    data = ConcatSignal(*packet[8:12])
    datalen = packet[6]

    # convert generic memory-mapped bus to the memory-mapped interface
    # passed to the controller
    mmc_inst = memmap_controller_basic(bb, mmbus)

    @always_comb
    def beh_fifo_read():
        if ready and not fbrx.empty:
            fbrx.rd.next = True
        else:
            fbrx.rd.next = False

    @always_seq(clock.posedge, reset=reset)
    def beh_state_machine():

        if state == states.idle:
            state.next = states.wait_for_packet
            ready.next = True
            bytecnt[:] = 0

        elif state == states.wait_for_packet:
            if fbrx.rvld:
                # check the known bytes, if the values is unexpected
                # goto the error state and flush all received bytes.
                for ii in range(nknown):
                    idx = pidx[ii]
                    val = pval[ii]
                    if bytecnt == idx:
                        if fbrx.rdata != val:
                            error.next = True
                            state.next = states.error

                packet[bytecnt].next = fbrx.rdata
                bytecnt[:] = bytecnt + 1

            # @todo: replace 20 with len(CommandPacket().header)
            if bytecnt == packet_length:
                ready.next = False
                state.next = states.check_packet

        elif state == states.check_packet:
            # @todo: some packet checking
            # @todo: need to support different address widths, use
            # @todo: `bb` attributes to determine which bits to assign
            bb.per_addr.next = address[32:28]
            bb.mem_addr.next = address[28:0]
            assert bb.done
            bytecnt[:] = 0

            if command == 1:
                state.next = states.read
            elif command == 2:
                bb.write_data.next = data
                state.next = states.write
            else:
                error.next = True
                state.next = states.error

        elif state == states.write:
            # @todo: add timeout
            if bb.done:
                bb.write.next = True
                state.next = states.write_end

        elif state == states.write_end:
            bb.write.next = False
            if bb.done:
                state.next = states.read

        elif state == states.read:
            # @todo: add timeout
            if bb.done:
                bb.read.next = True
                state.next = states.read_end

        elif state == states.read_end:
            bb.read.next = False
            if bb.done:
                # @todo: support different data_width bus
                packet[data_offset + 0].next = bb.read_data[32:24]
                packet[data_offset + 1].next = bb.read_data[24:16]
                packet[data_offset + 2].next = bb.read_data[16:8]
                packet[data_offset + 3].next = bb.read_data[8:0]
                state.next = states.response

        elif state == states.response:
            fbtx.wr.next = False
            if bytecnt < packet_length:
                if not fbtx.full:
                    fbtx.wr.next = True
                    fbtx.wdata.next = packet[bytecnt]
                    bytecnt[:] = bytecnt + 1
                state.next = states.response_full
            else:
                state.next = states.end

        elif state == states.response_full:
            fbtx.wr.next = False
            state.next = states.response

        elif state == states.error:
            if not fbrx.rvld:
                state.next = states.end
                ready.next = False

        elif state == states.end:
            error.next = False
            ready.next = False
            state.next = states.idle

        else:
            assert False, "Invalid state %s" % (state, )

        bytemon.next = bytecnt

    return beh_fifo_read, mmc_inst, beh_state_machine
def test_memmap_command_bridge(args=None):
    nloops = 37
    args = tb_default_args(args)
    clock = Clock(0, frequency=50e6)
    reset = Reset(0, active=1, async=False)
    glbl = Global(clock, reset)
    fifobus = FIFOBus()
    memmap = Barebone(glbl, data_width=32, address_width=28)

    fifobus.clock = clock

    def bench_command_bridge():
        tbclk = clock.gen()
        tbdut = command_bridge(glbl, fifobus, memmap)

        readpath, writepath = FIFOBus(), FIFOBus()
        readpath.clock = writepath.clock = clock
        tbmap = fifobus.assign_read_write_paths(readpath, writepath)
        tbftx = fifo_fast(reset, clock, writepath)  # user write path
        tbfrx = fifo_fast(reset, clock, readpath)  # user read path

        # @todo: add other bus types
        tbmem = memmap_peripheral_bb(clock, reset, memmap)

        # save the data read ...
        read_value = []

        @instance
        def tbstim():
            yield reset.pulse(32)
            fifobus.read.next = False
            fifobus.write.next = False
            assert not fifobus.full
            assert fifobus.empty
            assert fifobus.read_data == 0
            fifobus.write_data.next = 0

            try:
                # test a single address
                pkt = CommandPacket(True, 0x0000)
                yield pkt.put(readpath)
                yield pkt.get(writepath, read_value, [0])

                pkt = CommandPacket(False, 0x0000, [0x5555AAAA])
                yield pkt.put(readpath)
                yield pkt.get(writepath, read_value, [0x5555AAAA])

                # test a bunch of random addresses
                for ii in range(nloops):
                    randaddr = randint(0, (2**20) - 1)
                    randdata = randint(0, (2**32) - 1)
                    pkt = CommandPacket(False, randaddr, [randdata])
                    yield pkt.put(readpath)
                    yield pkt.get(writepath, read_value, [randdata])

            except Exception as err:
                print("Error: {}".format(str(err)))
                traceback.print_exc()

            yield delay(2000)
            raise StopSimulation

        wp_read, wp_valid = Signals(bool(0), 2)
        wp_read_data = Signal(intbv(0)[8:])
        wp_empty, wp_full = Signals(bool(0), 2)

        @always_comb
        def tbmon():
            wp_read.next = writepath.read
            wp_read_data.next = writepath.read_data
            wp_valid.next = writepath.read_valid
            wp_full.next = writepath.full
            wp_empty.next = writepath.empty

        return tbclk, tbdut, tbmap, tbftx, tbfrx, tbmem, tbstim, tbmon

    run_testbench(bench_command_bridge, args=args)
Exemple #13
0
def icestick_blinky_host(clock, led, pmod, uart_tx, uart_rx, uart_dtr,
                         uart_rts):
    """
    This example is similar to the other examples in this directory but
    the LEDs are controlled externally via command packets sent from a
    host via the UART on the icestick.

    (arguments == ports)
    Arguments:
      clock:
      led:
      pmod:
      uart_tx:
      uart_rx:
    """

    glbl = Global(clock, None)
    ledreg = Signal(intbv(0)[8:])

    # create the timer tick instance
    tick_inst = glbl_timer_ticks(glbl, include_seconds=True)

    # create the interfaces to the UART
    fifobus = FIFOBus(width=8)

    # create the memmap (CSR) interface
    memmap = Barebone(glbl, data_width=32, address_width=32)

    # create the UART instance.
    uart_inst = uartlite(glbl, fifobus, uart_rx, uart_tx)

    # create the packet command instance
    cmd_inst = command_bridge(glbl, fifobus, memmap)

    @always_seq(clock.posedge, reset=None)
    def beh_led_control():
        memmap.done.next = not (memmap.write or memmap.read)
        if memmap.write and memmap.mem_addr == 0x20:
            ledreg.next = memmap.write_data

    @always_comb
    def beh_led_read():
        if memmap.read and memmap.mem_addr == 0x20:
            memmap.read_data.next = ledreg
        else:
            memmap.read_data.next = 0

    # blink one of the LEDs
    tone = Signal(intbv(0)[8:])

    @always_seq(clock.posedge, reset=None)
    def beh_assign():
        if glbl.tick_sec:
            tone.next = (~tone) & 0x1
        led.next = ledreg | tone[5:]

        pmod.next = 0

    # @todo: PMOD OLED memmap control

    return myhdl.instances()