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)
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_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 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 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 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 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.cores.spi import SPIBus 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()
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 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