135 lines
3.2 KiB
Python
135 lines
3.2 KiB
Python
|
from migen.fhdl.std import *
|
||
|
from migen.bus import wishbone
|
||
|
from migen.bus.transactions import *
|
||
|
from migen.sim.generic import run_simulation
|
||
|
|
||
|
from misoclib.ethmac import EthMAC
|
||
|
from misoclib.ethmac.phys import loopback
|
||
|
|
||
|
class WishboneMaster():
|
||
|
def __init__(self, obj):
|
||
|
self.obj = obj
|
||
|
self.dat = 0
|
||
|
|
||
|
def write(self, adr, dat):
|
||
|
self.obj.cyc = 1
|
||
|
self.obj.stb = 1
|
||
|
self.obj.adr = adr
|
||
|
self.obj.we = 1
|
||
|
self.obj.sel = 0xF
|
||
|
self.obj.dat_w = dat
|
||
|
while self.obj.ack == 0:
|
||
|
yield
|
||
|
self.obj.cyc = 0
|
||
|
self.obj.stb = 0
|
||
|
yield
|
||
|
|
||
|
def read(self, adr):
|
||
|
self.obj.cyc = 1
|
||
|
self.obj.stb = 1
|
||
|
self.obj.adr = adr
|
||
|
self.obj.we = 0
|
||
|
self.obj.sel = 0xF
|
||
|
self.obj.dat_w = 0
|
||
|
while self.obj.ack == 0:
|
||
|
yield
|
||
|
self.dat = self.obj.dat_r
|
||
|
self.obj.cyc = 0
|
||
|
self.obj.stb = 0
|
||
|
yield
|
||
|
|
||
|
class SRAMReaderDriver():
|
||
|
def __init__(self, obj):
|
||
|
self.obj = obj
|
||
|
|
||
|
def start(self, slot, length):
|
||
|
self.obj._slot.storage = slot
|
||
|
self.obj._length.storage = length
|
||
|
self.obj._start.re = 1
|
||
|
yield
|
||
|
self.obj._start.re = 0
|
||
|
yield
|
||
|
|
||
|
def wait_done(self):
|
||
|
while self.obj.ev.done.pending == 0:
|
||
|
yield
|
||
|
def clear_done(self):
|
||
|
self.obj.ev.done.clear = 1
|
||
|
yield
|
||
|
self.obj.ev.done.clear = 0
|
||
|
yield
|
||
|
|
||
|
class TB(Module):
|
||
|
def __init__(self):
|
||
|
self.submodules.ethphy = loopback.LoopbackPHY()
|
||
|
self.submodules.ethmac = EthMAC(phy=self.ethphy, with_hw_preamble_crc=True)
|
||
|
|
||
|
# use sys_clk for each clock_domain
|
||
|
self.clock_domains.cd_eth_rx = ClockDomain()
|
||
|
self.clock_domains.cd_eth_tx = ClockDomain()
|
||
|
self.comb += [
|
||
|
self.cd_eth_rx.clk.eq(ClockSignal()),
|
||
|
self.cd_eth_rx.rst.eq(ResetSignal()),
|
||
|
self.cd_eth_tx.clk.eq(ClockSignal()),
|
||
|
self.cd_eth_tx.rst.eq(ResetSignal()),
|
||
|
]
|
||
|
|
||
|
def gen_simulation(self, selfp):
|
||
|
selfp.cd_eth_rx.rst = 1
|
||
|
selfp.cd_eth_tx.rst = 1
|
||
|
yield
|
||
|
selfp.cd_eth_rx.rst = 0
|
||
|
selfp.cd_eth_tx.rst = 0
|
||
|
|
||
|
wishbone_master = WishboneMaster(selfp.ethmac.bus)
|
||
|
sram_reader_driver = SRAMReaderDriver(selfp.ethmac.sram_reader)
|
||
|
|
||
|
sram_writer_slots_offset = [0x000, 0x200]
|
||
|
sram_reader_slots_offset = [0x400, 0x600]
|
||
|
|
||
|
length = 1500-2
|
||
|
|
||
|
payload = [i%0xFF for i in range(length)] + [0, 0, 0, 0]
|
||
|
|
||
|
errors = 0
|
||
|
|
||
|
for slot in range(2):
|
||
|
# fill tx memory
|
||
|
for i in range(length//4+1):
|
||
|
dat = 0
|
||
|
dat |= payload[4*i+0] << 24
|
||
|
dat |= payload[4*i+1] << 16
|
||
|
dat |= payload[4*i+2] << 8
|
||
|
dat |= payload[4*i+3] << 0
|
||
|
yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat)
|
||
|
|
||
|
# send tx data & wait
|
||
|
yield from sram_reader_driver.start(slot, length)
|
||
|
yield from sram_reader_driver.wait_done()
|
||
|
yield from sram_reader_driver.clear_done()
|
||
|
|
||
|
# get rx data (loopback on PHY Model)
|
||
|
rx_dat = []
|
||
|
for i in range(length//4+1):
|
||
|
yield from wishbone_master.read(sram_writer_slots_offset[slot]+i)
|
||
|
dat = wishbone_master.dat
|
||
|
rx_dat.append((dat >> 24) & 0xFF)
|
||
|
rx_dat.append((dat >> 16) & 0xFF)
|
||
|
rx_dat.append((dat >> 8) & 0xFF)
|
||
|
rx_dat.append((dat >> 0) & 0xFF)
|
||
|
|
||
|
# check rx data
|
||
|
for i in range(length):
|
||
|
#print("%02x / %02x" %(rx_dat[i], payload[i]))
|
||
|
if rx_dat[i] != payload[i]:
|
||
|
errors += 1
|
||
|
|
||
|
for i in range(200):
|
||
|
yield
|
||
|
#print(selfp.ethmac.sram_reader._length.storage)
|
||
|
|
||
|
print("Errors : %d" %errors)
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
run_simulation(TB(), ncycles=16000, vcd_name="my.vcd", keep_files=True)
|