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 moudule 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 = m_fifo_fast(clock, reset, fbus) return rtl_assign1, rtl_assign2, gfifo
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) # not sure why the chain was needed gfifo = m_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 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)) # wr1 #wr2 = Signal(bool(0)) # rd1 wr3 = Signal(bool(0)) rd1 = Signal(bool(0)) rd2 = Signal(bool(0)) rd = Signal(bool(0)) # rd3 ed1 = Signal(bool(1)) args = Namespace(width=36, size=128, name='fifo_2clock_cascade') fbus2 = FIFOBus(args=args) args.size = 16 fbus1 = FIFOBus(args=args) fbus3 = FIFOBus(args=args) # need to update the fbus refernces to reference the Signals in # the moudule port list (function arguments). fbus1.wr = wr fbus1.wdata = datain fbus1.rd = rd1 fbus2.wr = rd1 fbus2.wdata = fbus1.rdata fbus2.rd = rd2 fbus3.wr = wr3 fbus3.wdata = fbus2.rdata fbus3.rd = rd fbus3.rdata = dataout @always_comb def rtl_assign1(): wr.next = src_rdy_i and dst_rdy_o rd.next = dst_rdy_i and src_rdy_o rd1.next = not fbus1.empty and not fbus2.full rd2.next = not ed1 and not fbus3.full wr3.next = fbus2.rvld @always_comb def rtl_assign2(): dst_rdy_o.next = not fbus1.full src_rdy_o.next = not fbus3.empty # @todo: fix the m_fifo_async bug!!! # hackery, need to fix the simultaneous write and read issue # with the async FIFO! @always_seq(rclk.posedge, reset=reset) def rtl_ed1(): if ed1: ed1.next = fbus2.empty else: ed1.next = True # the original was a chain: # m_fifo_fast (16) # m_fifo_async (64)tx, (512)rx # m_fifo_fast (16) # the two small FIFOs were used to simplify the interface to # the async FIFO, the async FIFOs have some odd behaviors, the # up front fast fifo wasn't really needed. # the small fast FIFOs have a simpler (reactive) interface # it works more like a register with enable(s). gfifo1 = m_fifo_fast(wclk, reset, fbus1) gfifo2 = m_fifo_async(reset, wclk, rclk, fbus2) gfifo3 = m_fifo_fast(rclk, reset, fbus3) return rtl_assign1, rtl_assign2, rtl_ed1, gfifo1, gfifo2, gfifo3
def test_fifo_ramp(): clock = Clock(0, frequency=50e6) reset = Reset(0, active=1, async=False) glbl = Global(clock, reset) regbus = Wishbone(glbl) fifobus = FIFOBus() def _test_fifo_ramp(): tb_dut = m_fifo_ramp(clock, reset, regbus, fifobus, base_address=0x0000) tb_rbor = regbus.m_per_outputs() tb_clk = clock.gen() asserr = Signal(bool(0)) @instance def tb_stim(): try: yield delay(100) yield reset.pulse(111) # simply enable, enable the module and then # verify an incrementing pattern over the # fifobus yield regbus.write(0x00, 1) yield regbus.read(0x00) assert 1 == regbus.readval, "cfg reg write failed" # monitor the bus until ?? ramps Nramps, rr = 128, 0 while rr < Nramps: cnt = 0 for ii, sh in enumerate(( 24, 16, 8, 0, )): yield regbus.read(0x08 + ii) cnt = cnt | (regbus.readval << sh) rr = cnt except AssertionError, err: asserr.next = True for _ in xrange(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 tb_mon(): if fifobus.wr: assert _cval == fifobus.wdata _cval.next = _cval + 1 return tb_clk, tb_dut, tb_stim, tb_mon, tb_rbor
def test_afifo(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, rclk = [Signal(bool(0)), Signal(bool(0))] fbus = FIFOBus(width=args.width, size=args.size) start = Signal(bool(0)) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # clocks @always(delay(10)) def tbwclk(): wclk.next = not wclk @always(delay(12)) def tbrclk(): rclk.next = not rclk #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # FIFO writer and reader _wr = Signal(bool(0)) @instance def tb_always_wr(): was_full = False wrd = modbv(0)[args.width:] while True: if start: break yield wclk.posedge while True: yield wclk.posedge if not fbus.full and was_full: was_full = False for _ in range(17): yield wclk.posedge elif not fbus.full: fbus.wdata.next = wrd _wr.next = True yield delay(1) if not fbus.full: wrd[:] += 1 else: _wr.next = False was_full = True @always_comb def tb_always_wr_gate(): fbus.wr.next = _wr and not fbus.full @instance def tb_always_rd(): rdd = modbv(0)[args.width:] while True: if start: break yield wclk.posedge while True: try: yield rclk.posedge if not fbus.empty: fbus.rd.next = True else: fbus.rd.next = False if fbus.rvld: tmp = fbus.rdata assert tmp == rdd, " %d != %d " % (tmp, rdd) rdd[:] += 1 except AssertionError, err: for _ in range(10): yield rclk.posedge raise err
def test_ffifo(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 _test(): # @todo: use args.fast, args.use_srl_prim tbdut = m_fifo_fast(clock, reset, fbus, use_srl_prim=False) @always(delay(10)) def tbclk(): clock.next = not clock @instance def tbstim(): fbus.wdata.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): #print('nbyte %x wdata %x' % (num_bytes, ii)) yield clock.posedge fbus.wdata.next = ii fbus.wr.next = True yield clock.posedge fbus.wr.next = False fbus.wdata.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" for ii in range(num_bytes): fbus.rd.next = True yield clock.posedge #print("rdata %x ii %x " % (fbus.rdata, ii)) assert fbus.rvld assert fbus.rdata == ii, "rdata %x ii %x " % (fbus.rdata, ii) fbus.rd.next = False yield clock.posedge assert fbus.empty # Test overflows # Test underflows # Test write / read same time raise StopSimulation return tbdut, tbclk, tbstim tb_clean_vcd('test_fifo_fast_%d' % (args.size)) g = traceSignals(_test) Simulation(g).run()
def test_spi(): base_address = ba = 0x400 clock = Clock(0, frequency=50e6) reset = Reset(0, active=1, async=False) glbl = Global(clock, reset) regbus = Wishbone(glbl) fiforx,fifotx = FIFOBus(size=16), FIFOBus(size=16) spiee = SPIEEPROM() spibus = SPIBus() asserr = Signal(bool(0)) def _test_spi(): tbdut = m_spi(glbl, regbus, fiforx, fifotx, spibus, base_address=base_address) tbeep = spiee.gen(clock, reset, spibus) tbclk = clock.gen(hticks=5) # grab all the register file outputs tbmap = regbus.m_per_outputs() # get a reference to the SPI register file rf = regbus.regfiles['SPI_000'] # dumpy the registers for the SPI peripheral for name,reg in rf.registers.iteritems(): print("{0} {1:04X} {2:04X}".format(name, reg.addr, int(reg))) @instance def tbstim(): yield reset.pulse(33) try: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # loop through the registers and check the default # values, these are the offset values. for addr,sig in rf.roregs: yield regbus.read(addr+ba) assert regbus.readval == int(sig) for addr,sig in rf.rwregs: # need to skip the FIFO read / write if addr in (0x68, 0x6C,): pass else: yield regbus.read(addr+ba) assert regbus.readval == int(sig) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # enable the system print(" enable the SPI core") yield regbus.write(rf.spst.addr, 0x02) # register data drives fifo yield regbus.write(rf.spcr.addr, 0x9A) # default plus enable (98 + 02) print(" write to the transmit register") yield regbus.write(rf.sptx.addr, 0x02) yield regbus.write(rf.sptx.addr, 0x00) yield regbus.write(rf.sptx.addr, 0x00) yield regbus.write(rf.sptx.addr, 0x00) yield regbus.write(rf.sptx.addr, 0x55) yield regbus.read(rf.sptc.addr) print(regbus.readval) yield regbus.read(rf.sprc.addr) print(regbus.readval) yield delay(1000) for ii in range(1000): yield regbus.read(rf.sprc.addr) if regbus.readval == 5: break yield delay(1000) for ii in range(5): yield regbus.read(rf.sprx.addr) print("spi readback {0}".format(regbus.readval)) except Exception, err: print("@W: exception {0}".format(err)) yield delay(100) raise err yield delay(100) raise StopSimulation return tbstim, tbdut, tbeep, tbclk, tbmap