def fifo_cdc(glbl, emesh_i, emesh_o): """ map the packet interfaces to the FIOF interface """ fifo_intf = FIFOBus(size=16, width=len(emesh_i.bits)) @always_comb def rtl_assign(): wr.next = emesh_i.access and not fifo_intf.full rd.next = not fifo_intf.empty and not emesh_i.wait emesh_o.wait.next = fifo_intf.full @always(emesh_o.clock.posedge) def rtl_access(): if not emesh_i.wait: emesh_o.access.next = fifo_intf.rd # assign signals ot the FIFO interface fifo_intf.wdata = emesh_i.bits fifo_intf.rdata = emesh_o.bits g_fifo = cores.fifo.fifo_async(glbl.reset, emesh_i.clock, emesh_o.clock, fifo_intf) return rtl_assign, rtl_access, g_fifo
def icestick(clock, led, pmod, uart_tx, uart_rx): """ Lattice Icestick example """ glbl = Global(clock, None) gticks = glbl_timer_ticks(glbl, include_seconds=True) # get interfaces to the UART fifos fbustx = FIFOBus(width=8, size=8) fbusrx = FIFOBus(width=8, size=8) # get the UART comm from PC guart = uartlite(glbl, fbustx, fbusrx, uart_tx, uart_rx) @always_comb def beh_loopback(): fbusrx.rd.next = not fbusrx.empty fbustx.wr.next = not fbusrx.empty fbustx.wdata.next = fbusrx.rdata lcnt = Signal(modbv(0, min=0, max=4)) @always(clock.posedge) def beh_led_count(): if glbl.tick_sec: lcnt.next = lcnt + 1 led.next = (1 << lcnt) # system to test/interface # other stuff return instances()
def m_fifo_short(clock, reset, clear, datain, src_rdy_i, dst_rdy_o, dataout, src_rdy_o, dst_rdy_i): wr = Signal(bool(0)) rd = Signal(bool(0)) args = Namespace(width=36, size=16, name='fifo_2clock_cascade') fbus = FIFOBus(args=args) # need to update the fbus refernces to reference the Signals in # the module port list (function arguments). fbus.wr = wr fbus.wdata = datain fbus.rd = rd fbus.rdata = dataout @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 gfifo = fifo_fast(clock, reset, fbus) return rtl_assign1, rtl_assign2, gfifo
def fifo_cdc(glbl, emesh_i, emesh_o): """ map the packet interfaces to the FIFO interface """ wr, rd = Signals(bool(0), 2) fifo_intf = FIFOBus(width=len(emesh_i.bits)) @always_comb def beh_assign(): wr.next = emesh_i.access and not fifo_intf.full rd.next = not fifo_intf.empty and not emesh_i.wait emesh_o.wait.next = fifo_intf.full @always(emesh_o.clock.posedge) def beh_access(): if not emesh_i.wait: emesh_o.access.next = fifo_intf.read # assign signals ot the FIFO interface fifo_intf.write_data = emesh_i.bits fifo_intf.read_data = emesh_o.bits fifo_inst = cores.fifo.fifo_async(clock_write=emesh_i.clock, clock_read=emesh_o.clock, fifobus=fifo_intf, reset=glbl.reset, size=16) return beh_assign, beh_access, fifo_inst
def fifo_cdc(glbl, emesh_i, emesh_o): """ map the packet interfaces to the FIFO interface """ wr, rd = Signals(bool(0), 2) fifo_intf = FIFOBus(width=len(emesh_i.bits)) @always_comb def beh_assign(): wr.next = emesh_i.access and not fifo_intf.full rd.next = not fifo_intf.empty and not emesh_i.wait emesh_o.wait.next = fifo_intf.full @always(emesh_o.clock.posedge) def beh_access(): if not emesh_i.wait: emesh_o.access.next = fifo_intf.read # assign signals ot the FIFO interface fifo_intf.write_data = emesh_i.bits fifo_intf.read_data = emesh_o.bits fifo_inst = cores.fifo.fifo_async( clock_write=emesh_i.clock, clock_read=emesh_o.clock, fifobus=fifo_intf, reset=glbl.reset, size=16 ) return beh_assign, beh_access, fifo_inst
def fifo_short(clock, reset, clear, datain, src_rdy_i, dst_rdy_o, dataout, src_rdy_o, dst_rdy_i): glbl = Global(clock, reset) wr = Signal(bool(0)) rd = Signal(bool(0)) args = Namespace(width=36, size=16, name='fifo_2clock_cascade') fbus = FIFOBus(width=args.width) # need to update the fbus refernces 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 @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 fifo_inst = fifo_fast(glbl, fbus, size=args.size) return myhdl.instances()
def fifo_cdc(glbl, emesh_i, emesh_o): """ map the packet interfaces to the FIOF interface """ fifo_intf = FIFOBus(size=16, width=len(emesh_i.bits)) @always_comb def rtl_assign(): wr.next = emesh_i.access and not fifo_intf.full rd.next = not fifo_intf.empty and not emesh_i.wait emesh_o.wait.next = fifo_intf.full @always(emesh_o.clock.posedge) def rtl_access(): if not emesh_i.wait: emesh_o.access.next = fifo_intf.read # assign signals ot the FIFO interface fifo_intf.write_data = emesh_i.bits fifo_intf.read_data = emesh_o.bits g_fifo = cores.fifo.fifo_async(glbl.reset, emesh_i.clock, emesh_o.clock, fifo_intf) return rtl_assign, rtl_access, g_fifo
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
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) uart_fifo = 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, uart_fifo, serial_in=uart_rx, serial_out=uart_tx) #map uart_fifo to separate readpath and writepath assign_rw = uart_fifo.assign_read_write_paths(fbusrx,fbustx) # 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, assign_rw, beh_led_control, beh_led_read, beh_assign)
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)
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)
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)
def testbench_uart(args=None): # @todo: get numbytes from args numbytes = 7 clock = Clock(0, frequency=50e6) reset = Reset(0, active=0, async=True) glbl = Global(clock, reset) mdlsi, mdlso = Signal(bool(1)), Signal(bool(1)) uartmdl = UARTModel() fifotx = FIFOBus() fiforx = FIFOBus() def _bench_uart(): tbmdl = uartmdl.process(glbl, mdlsi, mdlso) tbdut = uartlite(glbl, fifotx, fiforx, mdlso, mdlsi) tbclk = clock.gen() @always_comb def tblpbk(): fifotx.wdata.next = fiforx.rdata fifotx.wr.next = not fiforx.empty fiforx.rd.next = not fiforx.empty @instance def tbstim(): yield reset.pulse(33) yield delay(1000) yield clock.posedge for ii in range(numbytes): wb = randint(0, 255) print("send {:02X}".format(wb)) uartmdl.write(wb) timeout = ((clock.frequency / uartmdl.baudrate) * 40) rb = uartmdl.read() while rb is None and timeout > 0: yield clock.posedge rb = uartmdl.read() timeout -= 1 if rb is None: raise TimeoutError print("received {:02X}".format(rb)) assert rb == wb, "{:02X} != {:02X}".format(rb, wb) yield delay(100) raise StopSimulation return tbdut, tbmdl, tbclk, tblpbk, tbstim run_testbench(_bench_uart, args=args)
def icestick(clock, led, pmod, uart_tx, uart_rx): """ Lattice Icestick example """ glbl = Global(clock, None) tick_inst = glbl_timer_ticks(glbl, include_seconds=True) # get interfaces to the UART fifos fbusrtx = FIFOBus(width=8) # get the UART comm from PC uart_inst = uartlite(glbl, fbusrtx, uart_tx, uart_rx) @always_comb def beh_loopback(): fbusrtx.write_data.next = fbusrtx.read_data fbusrtx.write.next = (not fbusrtx.full) & fbusrtx.read lcnt = Signal(modbv(0, min=0, max=4)) @always(clock.posedge) def beh_led_count(): if glbl.tick_sec: lcnt.next = lcnt + 1 led.next = (1 << lcnt) # system to test/interface # other stuff return myhdl.instances()
def spi_slave_led(clock, sck, mosi, miso, cs, leds ,out): glbl = Global(clock) spibus = SPIBus(sck=sck, mosi=mosi, miso=miso, ss=cs) fifobus = FIFOBus() div = divisor (clock, clk_div, 10) fifobus.write_clock=clock fifobus.read_clock=clock rtl = recv_to_led(clock, fifobus, leds,out) tbdut = spi_slave_fifo(glbl, spibus, fifobus) @always_comb def map(): spibus.csn.next = cs return myhdl.instances()
def test_adc128s022(): clock = Clock(0, frequency=50e6) reset = Reset(0, active=0, async=False) glbl = Global(clock, reset) fifobus = FIFOBus(width=16) spibus = SPIBus() channel = Signal(intbv(0, min=0, max=8)) step = 3.3 / 7 analog_channels = [Signal(3.3 - step * ii) for ii in range(0, 8)] print(analog_channels) assert len(analog_channels) == 8 def check_empty(clock, fifo): for ii in range(4000): if not fifo.empty: break yield clock.posedge @myhdl.block def bench_adc128s022(): tbdut = adc128s022(glbl, fifobus, spibus, channel) tbmdl = adc128s022_model(spibus, analog_channels, vref_pos=3.3, vref_neg=0.) tbclk = clock.gen() @instance def tbstim(): sample = intbv(0)[16:] yield reset.pulse(33) yield clock.posedge # check the conversion value for each channel, should get # smaller and smaller for ch in range(0, 8): channel.next = (ch + 1) % 8 # next channel yield check_empty(clock, fifobus) # should have a new sample if not fifobus.empty: fifobus.read.next = True sample[:] = fifobus.read_data yield clock.posedge fifobus.read.next = False yield clock.posedge print("sample {:1X}:{:4d}, fifobus {} \n".format( int(sample[16:12]), int(sample[12:0]), str(fifobus))) assert fifobus.empty else: print("No sample!") yield delay(100) raise StopSimulation return tbdut, tbmdl, tbclk, tbstim run_testbench(bench_adc128s022)
def test_spi_slave(args=None): args = tb_default_args(args) clock = Clock(0, frequency=50e6) reset = Reset(0, active=1, async=False) glbl = Global(clock, reset) spibus, fifobus = SPIBus(), FIFOBus() # monitor the FIFOBus signals data = Signal(intbv(0)[8:]) rd, wr, full, empty = Signals(bool(0), 4) @myhdl.block def bench_spi_slave(): tbdut = spi_slave_fifo(glbl, spibus, fifobus) tbclk = clock.gen() @instance def tbstim(): yield reset.pulse(40) yield delay(1000) yield clock.posedge # @todo: make generic # @todo: random_sequence = [randint(0, fifobus.write_data.max) for _ in range(ntx)] yield spibus.writeread(0x55) yield spibus.writeread(0xAA) yield spibus.writeread(0xCE) assert spibus.get_read_data() == 0x55 yield spibus.writeread(0x01) assert spibus.get_read_data() == 0xAA yield spibus.writeread(0x01) assert spibus.get_read_data() == 0xCE raise StopSimulation @always_comb def tb_fifo_loopback(): if not fifobus.full: fifobus.write.next = not fifobus.empty fifobus.read.next = not fifobus.empty fifobus.write_data.next = fifobus.read_data # monitors @always_comb def tbmon(): data.next = fifobus.read_data rd.next = fifobus.read wr.next = fifobus.write full.next = fifobus.full empty.next = fifobus.empty return tbdut, tbclk, tbstim, tb_fifo_loopback, tbmon run_testbench(bench_spi_slave, args=args)
def spi_slave_pulsegen(clock, sck, mosi, miso, cs, leds, out): clk_div = Signal(False) clk_pulse = Signal(False) glbl = Global(clock) spibus = SPIBus(sck=sck, mosi=mosi, miso=miso, ss=cs) fifobus = FIFOBus() fifobus.write_clock = clock fifobus.read_clock = clock div = divisor(clock, clk_div, 1) divp = divisor(clock, clk_pulse, 1) rtl = recv_to_plsgen(clk_div, clk_pulse, fifobus, leds, out) #rtl = recv_to_led(clk_div, fifobus, leds) tbdut = spi_slave_fifo_async(glbl, spibus, fifobus) @always_comb def map(): spibus.csn.next = cs return myhdl.instances()
def fifo_short(clock, reset, clear, datain, src_rdy_i, dst_rdy_o, dataout, src_rdy_o, dst_rdy_i): wr = Signal(bool(0)) rd = Signal(bool(0)) args = Namespace(width=36, size=16, name='fifo_2clock_cascade') fbus = FIFOBus(size=args.size, width=args.width) # need to update the fbus refernces 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 @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 gfifo = fifo_fast(reset, clock, fbus) return rtl_assign1, rtl_assign2, gfifo
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()
def bench_doublebuffer_conversion(): """test bench for conversion""" clock = Signal(bool(0)) reset = ResetSignal(0, active=1, async=True) buffer_sel = Signal(bool(0)) width_data = 20 width_depth = 64 # instantiation of fifo-bus, clock and rledoublefifo dfifo_bus = FIFOBus(width=width_data) inst = doublefifo(clock, reset, dfifo_bus, buffer_sel, depth=width_depth) inst_clock = clock_driver(clock) inst_reset = reset_on_start(reset, clock) @instance def tbstim(): """some tests for conversion purpose""" # select first buffer buffer_sel.next = False yield clock.posedge # write first data into double buffer dfifo_bus.write.next = True # convert signed number to unsigned dfifo_bus.write_data.next = 3 yield clock.posedge dfifo_bus.write.next = False yield clock.posedge assert dfifo_bus.empty yield clock.posedge print("Conversion done!!") raise StopSimulation return tbstim, inst, inst_clock, inst_reset
def spi_controller_top(clock, reset, sck, mosi, miso, ss): """SPI top-level for conversion testing""" glbl = Global(clock, reset) spibus = SPIBus(sck, mosi, miso, ss) fifobus = FIFOBus() cso = spi_controller.cso() cso.isstatic = True cfg_inst = cso.instances() spi_controller.debug = False spi_inst = spi_controller(glbl, spibus, fifobus, cso=cso) @always_comb def fifo_loopback(): fifobus.write_data.next = fifobus.read_data fifobus.write.next = fifobus.read_valid fifobus.read.next = not fifobus.empty return myhdl.instances()
def test_(args=None): if args is None: args = Namespace(width=8, size=16, name='test') reset = ResetSignal(0, active=1, async=True) wclk = Clock(0, frequency=22e6) rclk = Clock(0, frequency=50e6) fbus = FIFOBus(width=args.width) start = Signal(bool(0)) @myhdl.block 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() run_testbench(bench_)
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)
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. Ports: 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 fbustx = FIFOBus(width=8, size=4) fbusrx = FIFOBus(width=8, size=4) uart_fifo = 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, uart_fifo, uart_rx, uart_tx) #map uart_fifo to separate readpath and writepath assign_rw = uart_fifo.assign_read_write_paths(fbusrx,fbustx) # 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:] pmod.next = 0 # @todo: PMOD OLED memmap control return (tick_inst, uart_inst, assign_rw, cmd_inst, beh_led_control, beh_led_read, beh_assign)
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)
def test_fifo_sync(args=None): """ verify the synchronous FIFO """ if args is None: args = Namespace(width=8, size=16, name='test') else: # @todo: verify args has the attributes needed for the FIFOBus pass reset = ResetSignal(0, active=1, async=True) clock = Signal(bool(0)) fbus = FIFOBus(width=args.width, size=args.size) def bench_fifo_sync(): # @todo: use args.fast, args.use_srl_prim tbdut = fifo_sync(clock, reset, fbus) @always(delay(10)) def tbclk(): clock.next = not clock @instance def tbstim(): fbus.write_data.next = 0xFE reset.next = reset.active yield delay(33) reset.next = not reset.active for ii in range(5): yield clock.posedge # test the normal cases for num_bytes in range(1, args.size + 1): # write some bytes for ii in range(num_bytes): yield clock.posedge fbus.write_data.next = ii fbus.write.next = True yield clock.posedge fbus.write.next = False fbus.write_data.next = 0xFE # if 16 bytes written make sure FIFO is full yield clock.posedge if num_bytes == args.size: assert fbus.full, "FIFO should be full!" assert not fbus.empty, "FIFO should not be empty" fbus.read.next = True yield clock.posedge for ii in range(num_bytes): yield clock.posedge fbus.read.next = True assert fbus.read_valid assert fbus.read_data == ii, "rdata %x ii %x " % ( fbus.read_data, ii) fbus.read.next = False yield clock.posedge assert fbus.empty # Test overflows # Test underflows # Test write / read same time raise StopSimulation return tbdut, tbclk, tbstim run_testbench(bench_fifo_sync)
def bench(): reset = ResetSignal(0, active=1, async=True) clock = Signal(bool(0)) fbus = FIFOBus(width=args.width, size=args.size) tbdut = fifo_sync(clock, reset, fbus) @instance def tbclk(): clock.next = False while True: yield delay(5) clock.next = not clock @instance def tbstim(): print("start simulation") fbus.read.next = False fbus.write.next = False fbus.clear.next = False reset.next = True yield delay(20) reset.next = False yield clock.posedge print("r, w, e, f") print("%d, %d, %d, %d, should be empty" % ( fbus.read, fbus.write, fbus.empty, fbus.full, )) assert fbus.empty fbus.write.next = True fbus.write_data.next = 0xAA yield clock.posedge fbus.write.next = False yield clock.posedge print("%d, %d, %d, %d, should not be empty" % ( fbus.read, fbus.write, fbus.empty, fbus.full, )) assert not fbus.empty print("FIFO count %d (%d%d%d%d)" % (fbus.count, fbus.read, fbus.write, fbus.empty, fbus.full)) print("more writes") fbus.write.next = True fbus.write_data.next = 1 for ii in range(15): yield clock.posedge print( "FIFO count %d (%d%d%d%d)" % (fbus.count, fbus.read, fbus.write, fbus.empty, fbus.full)) fbus.write_data.next = ii + 2 fbus.write.next = False yield clock.posedge print("FIFO count %d (%d%d%d%d)" % (fbus.count, fbus.read, fbus.write, fbus.empty, fbus.full)) yield clock.posedge print("%d, %d, %d, %d, should be full" % ( fbus.read, fbus.write, fbus.empty, fbus.full, )) # assert fbus.full fbus.read.next = True assert fbus.read_data == 0xAA yield fbus.read_valid.posedge fbus.read.next = False yield delay(1) print("%d, %d, %d, %d" % ( fbus.read, fbus.write, fbus.empty, fbus.full, )) yield clock.posedge yield clock.posedge fbus.read.next = True for ii in range(15): print("FIFO count %d data %d (%d%d%d%d)" % (fbus.count, fbus.read_data, fbus.read, fbus.write, fbus.empty, fbus.full)) yield clock.posedge fbus.read.next = False yield clock.posedge print("%d, %d, %d, %d" % ( fbus.read, fbus.write, fbus.empty, fbus.full, )) print("end simulation") raise StopSimulation return tbdut, tbclk, tbstim
def test_spi_controller_cso(args=None): args = tb_default_args(args) clock = Clock(0, frequency=50e6) reset = Reset(0, active=1, isasync=False) glbl = Global(clock, reset) spibus = SPIBus() # a FIFOBus to push-pull data from the SPI controller fifobus = FIFOBus(width=8) # control-status object for the SPI controller cso = spi_controller.cso() spiee = SPIEEPROM() asserr = Signal(bool(0)) @myhdl.block def bench_spi_cso(): spi_controller.debug = True # enable debug monitors tbdut = spi_controller(glbl, spibus, fifobus, cso=cso) tbeep = spiee.process(clock, reset, spibus) tbclk = clock.gen(hticks=5) @instance def tbstim(): yield reset.pulse(33) yield delay(100) yield clock.posedge try: # enable the SPI core cso.enable.next = True cso.bypass_fifo.next = True cso.loopback.next = True # write to the transmit FIFO values = (0x02, 0x00, 0x00, 0x00, 0x55) for data in values: cso.tx_byte.next = data cso.tx_write.next = True yield clock.posedge cso.tx_write.next = False while cso.tx_fifo_count > 0: yield delay(100) while cso.rx_fifo_count < 5: yield delay(100) ii, nticks = 0, 0 while ii < len(values): if cso.rx_empty: cso.rx_read.next = False else: cso.rx_read.next = True if cso.rx_byte_valid: assert values[ii] == cso.rx_byte, \ "{:<4d}: data mismatch, {:02X} != {:02X}".format( ii, int(values[ii]), int(cso.rx_byte)) ii += 1 nticks = 0 yield clock.posedge, cso.rx_empty.posedge cso.rx_read.next = False if nticks > 30: raise TimeoutError nticks += 1 cso.rx_read.next = False yield clock.posedge except AssertionError as err: asserr.next = True print("@E: assertion {}".format(err)) yield delay(100) traceback.print_exc() raise err raise StopSimulation # monitor signals for debugging tx_write, rx_read = Signals(bool(0), 2) @always_comb def tbmon(): rx_read.next = cso.rx_read tx_write.next = cso.tx_write return tbdut, tbeep, tbclk, tbstim, tbmon run_testbench(bench_spi_cso, args=args)
def de0nano_converters( clock, reset, led, # ADC signals adc_cs_n, adc_saddr, adc_sdat, adc_sclk, # Accelerometer and I2C signals i2c_sclk, i2c_sdat, g_sensor_cs_n, g_sensor_int, # LT24 LCD display signals lcd_on, lcd_resetn, lcd_csn, lcd_rs, lcd_wrn, lcd_rdn, lcd_data): """ The port names are the same as those in the board definition (names in the user manual) for automatic mapping by the rhea.build automation. """ # signals and interfaces glbl = Global(clock, reset) adcbus = SPIBus() adcbus.mosi, adcbus.miso, adcbus.csn, adcbus.sck = (adc_saddr, adc_sdat, adc_cs_n, adc_sclk) fifobus = FIFOBus(width=16, size=16) channel = Signal(intbv(0, min=0, max=8)) # ---------------------------------------------------------------- # global ticks gtick = glbl_timer_ticks(glbl, include_seconds=True, user_timer=16) # ---------------------------------------------------------------- # instantiate the ADC controller (retieves samples) gconv = adc128s022(glbl, fifobus, adcbus, channel) # read the samples out of the FIFO interface fiford = Signal(bool(0)) @always(clock.posedge) def rtl_read(): fiford = not fifobus.empty @always_comb def rtl_read_gate(): fifobus.rd.next = fiford and not fifobus.empty # for now assign the samples to the LEDs for viewing heartbeat = Signal(bool(0)) @always_seq(clock.posedge, reset=reset) def rtl_leds(): if glbl.tick_sec: heartbeat.next = not heartbeat led.next = concat(fifobus.rdata[12:5], heartbeat) # ---------------------------------------------------------------- # LCD dislay lcd = LT24Interface() resolution, color_depth = lcd.resolution, lcd.color_depth lcd.assign(lcd_on, lcd_resetn, lcd_csn, lcd_rs, lcd_wrn, lcd_rdn, lcd_data) # color bars and the interface between video source-n-sink vmem = VideoMemory(resolution=resolution, color_depth=color_depth) gbar = color_bars(glbl, vmem, resolution=resolution, color_depth=color_depth) # LCD video driver glcd = lt24lcd(glbl, vmem, lcd) gens = gtick, gconv, rtl_read, rtl_leds, gbar, glcd return gens
def test_spi_memory_mapped(args=None): args = tb_default_args(args) base_address = ba = 0x400 clock = Clock(0, frequency=50e6) reset = Reset(0, active=1, isasync=False) glbl = Global(clock, reset) regbus = Wishbone(glbl) fifobus = FIFOBus(size=16) spiee = SPIEEPROM() spibus = SPIBus() asserr = Signal(bool(0)) @myhdl.block def bench_spi(): tbdut = spi_controller(glbl, spibus, fifobus=fifobus, mmbus=regbus) tbeep = spiee.gen(clock, reset, spibus) tbclk = clock.gen(hticks=5) # grab all the register file outputs tbmap = regbus.interconnect() # get a reference to the SPI register file rf = regbus.regfiles['SPI_000'] # dumpy the registers for the SPI peripheral print("SPI register file") for name, reg in rf.registers.items(): print(" {0} {1:04X} {2:04X}".format(name, reg.addr, int(reg))) print("") @instance def tbstim(): yield reset.pulse(33) yield delay(100) yield clock.posedge try: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # loop through the registers and check the default # values, these are the offset values. for addr, sig in rf.roregs: yield regbus.readtrans(addr + ba) assert regbus.get_read_data() == int(sig), \ "Invalid read-only value" for addr, sig in rf.rwregs: # need to skip the FIFO read / write if addr in ( rf.sptx.addr, rf.sprx.addr, ): pass else: yield regbus.readtrans(addr + ba) assert regbus.get_read_data() == int(sig), \ "Invalid default value" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # enable the system print("enable the SPI core") yield regbus.writetrans(rf.spst.addr, 0x02) # register data drives fifo yield regbus.writetrans(rf.spcr.addr, 0x9A) # default plus enable (98 + 02) print("write to the transmit register") for data in (0x02, 0x00, 0x00, 0x00, 0x55): print("\nwriting to sptx {:02x}".format(data)) yield regbus.writetrans(rf.sptx.addr, data) print("") yield regbus.readtrans(rf.sptc.addr) print("TX FIFO count {}".format(regbus.get_read_data())) yield regbus.readtrans(rf.sprc.addr) print("RX FIFO count {}".format(regbus.get_read_data())) yield delay(1000) print("wait for return bytes") for ii in range(1000): yield regbus.readtrans(rf.sprc.addr) if regbus.get_read_data() == 5: break yield delay(10) # verify bytes received and not timeout print("RX FIFO count {}".format(regbus.get_read_data())) assert regbus.get_read_data() == 5 print("read the returned bytes") for ii in range(5): yield regbus.readtrans(rf.sprx.addr) print("spi readback {0}".format(regbus.get_read_data())) except Exception as err: print("@W: exception {0}".format(err)) yield delay(100) traceback.print_exc() raise err yield delay(100) raise StopSimulation return tbstim, tbdut, tbeep, tbclk, tbmap run_testbench(bench_spi, args=args)
from rhea.models.spi import SPIEEPROM from rhea.system import Global, Clock, Reset, Signals from rhea.system import Wishbone from rhea.system import FIFOBus from rhea.utils.test import run_testbench, tb_convert, tb_args, tb_default_args # global signals used by many clock = Clock(0, frequency=100e6) reset = Reset(0, active=1, isasync=True) glbl = Global(clock, reset) portmap = dict(glbl=glbl, spibus=SPIBus(), fifobus=FIFOBus(), cso=spi_controller.cso()) @myhdl.block def spi_controller_top(clock, reset, sck, mosi, miso, ss): """SPI top-level for conversion testing""" glbl = Global(clock, reset) spibus = SPIBus(sck, mosi, miso, ss) fifobus = FIFOBus() cso = spi_controller.cso() cso.isstatic = True cfg_inst = cso.instances() spi_controller.debug = False
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)
def test_async_fifo(args=None): """ verify the asynchronous FIFO """ if args is None: args = Namespace(width=8, size=16, name='test') reset = ResetSignal(0, active=1, async=True) wclk = Clock(0, frequency=22e6) rclk = Clock(0, frequency=50e6) fbus = FIFOBus(width=args.width) start = Signal(bool(0)) @myhdl.block 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()
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()
def uartlite(glbl, fifobus, serial_in, serial_out, baudrate=115200): """ The top-level for a minimal fixed baud UART The function instantiates the various components required for the UART. Uses an external FIFOBus interface to communicate with other modules(provide the r/w stobe, data etc.). Arguments(Ports): glbl: rhea.Global interface, clock and reset from glbl fbustx: The transmit FIFO bus, interface to the TX FIFO (see fifo_fast.py) tbusrx: The receive FIFObus, interface to the RX FIFO serial_in: The UART external serial line in serial_out: The UART external serial line out Parameters: baudrate: the desired baudrate for the UART Returns: myhdl generators : syncs of external r/w line to the internal r/t : The actual TX and RX FIFOs : baud strobe instantiation : uart tx and rx generators : map internal FIFOBus to external user FIFOBus This module is myhdl convertible """ clock, reset = glbl.clock, glbl.reset baudce, baudce16 = [Signal(bool(0)) for _ in range(2)] tx, rx = Signal(bool(1)), Signal(bool(1)) # the FIFO interfaces for each FIFO path fbustx = FIFOBus(fifobus.size, fifobus.width) fbusrx = FIFOBus(fifobus.size, fifobus.width) # create synchronizers for the input signals, the output # are not needed, guarantee IO registers syncrx_inst = syncro(clock, serial_in, rx) synctx_inst = syncro(clock, tx, serial_out) # FIFOs for tx and rx fifo_tx_inst = fifo_fast(reset, clock, fbustx) fifo_rx_inst = fifo_fast(reset, clock, fbusrx) # generate a strobe for the desired baud rate baud_inst = uartbaud(glbl, baudce, baudce16, baudrate=baudrate) # instantiate the UART paths tx_inst = uarttx(glbl, fbustx, tx, baudce) rx_inst = uartrx(glbl, fbusrx, rx, baudce16) # separate the general fifobus into two for transmitting and receiving @always_comb def assign_read(): """Map external UART FIFOBus interface to internal Map the external UART FIFOBus interface attribute signals to internal RX FIFO interface. """ # fifobus.read_data is the channel that the UART # reads data on and fifobus.write_data is the one # it writes to. # read into the fifobus from the RX fifo queue # whenever available by checking the queue fbusrx.read.next = fifobus.read fifobus.empty.next = fbusrx.empty fifobus.read_data.next = fbusrx.read_data fifobus.read_valid.next = fbusrx.read_valid @always_comb def assign_write(): """Map external UART FIFOBus interface to internal Map external UART FIFOBus interface attribute signals to internal TX FIFO interface. """ # queue to TX fifo whenever given ext. strobe # which will auto. be transferred by uarttx() fbustx.write.next = fifobus.write & (not fbustx.full) fbustx.write_data.next = fifobus.write_data fifobus.full.next = fbustx.full return myhdl.instances()
nvacant = Signal(modbv(nitems, min=0, max=nitems)) ntenant = Signal(modbv(0, min=0, max=nitems)) if fifo_fast.debug: @always_seq(clock.posedge, reset=reset) def rtl_occupancy(): if fbus.clear: nvacant.next = nitems ntenant.next = 0 elif fbus.read and not fbus.write: nvacant.next = nvacant + 1 ntenant.next = ntenant - 1 elif fbus.write and not fbus.read: nvacant.next = nvacant - 1 ntenant.next = ntenant + 1 @always_comb def rtl_count(): fbus.count.next = ntenant return myhdl.instances() # fifo_fast block attributes, these will affect all instances fifo_fast.portmap = dict(reset=ResetSignal(0, active=1, async=False), clock=Signal(bool(0)), fbus=FIFOBus()) fifo_fast.debug = True fifo_fast.occupancy_assertions = True
def doublefifo(clock, reset, dfifo_bus, buffer_sel, depth=16): """ I/O ports: dfifo_bus : A FIFOBus connection interace buffer_sel : select a buffer Constants : depth : depth of the fifo used width_data : width of the data to be stored in FIFO """ # width of the input data width_data = len(dfifo_bus.write_data) # input to both the FIFO's fifo_data_in = Signal(intbv(0)[width_data:]) # FIFOBus instantiation from rhea glbl = Global(clock, reset) fbus1 = FIFOBus(width=width_data) fbus2 = FIFOBus(width=width_data) assert isinstance(glbl, Global) assert isinstance(fbus1, FIFOBus) assert isinstance(fbus2, FIFOBus) # instantiate two sync FIFO's fifo_sync1 = fifo_sync(glbl, fbus1, depth) fifo_sync2 = fifo_sync(glbl, fbus2, depth) @always_comb def assign(): """write data into FIFO's""" fbus1.write_data.next = fifo_data_in fbus2.write_data.next = fifo_data_in @always_seq(clock.posedge, reset=reset) def mux2_logic(): """select buffer to pump data""" if not buffer_sel: fbus1.write.next = dfifo_bus.write else: fbus2.write.next = dfifo_bus.write fifo_data_in.next = dfifo_bus.write_data @always_comb def logic(): """read or write into buffer""" fbus1.read.next = dfifo_bus.read if ( buffer_sel) else False fbus2.read.next = dfifo_bus.read if ( not buffer_sel) else False dfifo_bus.read_data.next = fbus1.read_data if ( buffer_sel) else fbus2.read_data dfifo_bus.empty.next = fbus1.empty if ( buffer_sel) else fbus2.empty return ( fifo_sync1, fifo_sync2, assign, mux2_logic, logic)
def tb_fifo_ramp(args): clock = Clock(0, frequency=50e6) reset = Reset(0, active=1, async=False) glbl = Global(clock, reset) regbus = Wishbone(glbl) fifobus = FIFOBus() def _bench_fifo_ramp(): tbdut = fifo_ramp(clock, reset, regbus, fifobus, base_address=0x0000) tbrbor = regbus.interconnect() tbclk = clock.gen() asserr = Signal(bool(0)) @instance def tbstim(): print("start fifo ramp test") try: yield delay(100) yield reset.pulse(111) # verify an incrementing pattern over the fifobus yield regbus.writetrans(0x07, 2) # div of two yield regbus.readtrans(0x07) assert 2 == regbus.get_read_data() yield regbus.writetrans(0x00, 1) # enable yield regbus.readtrans(0x00) assert 1 == regbus.get_read_data(), "cfg reg write failed" # monitor the bus until ?? ramps Nramps, rr, timeout = 128, 0, 0 while rr < Nramps and timeout < (20 * Nramps): cnt = 0 for ii, sh in enumerate(( 24, 16, 8, 0, )): yield delay(1000) yield regbus.readtrans(0x08 + ii) cntpart = regbus.get_read_data() cnt = cnt | (cntpart << sh) print( "{:<8d}: ramp count[{:<4d}, {:d}]: {:08X}, {:02X} - timeout {:d}" .format(now(), rr, ii, cnt, cntpart, timeout)) timeout += 1 # @todo: add ramp check if cnt != rr or (timeout % 1000) == 0: print(" ramp {} {}".format( int(cnt), int(rr), )) rr = int(cnt) print("{}, {}, {}".format(Nramps, rr, timeout)) except AssertionError as err: asserr.next = True for _ in range(10): yield clock.posedge raise err raise StopSimulation # monitor the values from the fifo bus, it should # be a simple "ramp" increasing values _mask = 0xFF _cval = Signal(modbv(0, min=0, max=256)) @always(clock.posedge) def tbmon(): if fifobus.write: assert _cval == fifobus.write_data _cval.next = _cval + 1 return tbclk, tbdut, tbstim, tbmon, tbrbor run_testbench(_bench_fifo_ramp, args=args)