continue code refactoring
This commit is contained in:
parent
4cd73fc9da
commit
8a2b65f21d
|
@ -1,4 +1,10 @@
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.flow.actor import Sink, Source
|
||||||
|
from migen.bank.description import *
|
||||||
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.flow.actor import EndpointDescription
|
from migen.flow.actor import EndpointDescription
|
||||||
|
|
||||||
eth_mtu = 1532
|
eth_mtu = 1532
|
||||||
|
|
|
@ -1,54 +1,17 @@
|
||||||
from liteethernet.common import *
|
from liteeth.common import *
|
||||||
from liteethernet.mac import LiteEthernetMAC
|
from liteeth.mac.core import LiteEthMACCore
|
||||||
|
from liteeth.mac.frontend import wishbone
|
||||||
class LiteEthernetMAC(Module, AutoCSR):
|
|
||||||
def __init__(self, phy, frontend="wishbone", with_hw_preamble_crc=True, endianness="be"):
|
|
||||||
self.submodules.core = LiteEthernetMAC(phy, with_hw_preamble, endianness)
|
|
||||||
|
|
||||||
|
class LiteEthMAC(Module, AutoCSR):
|
||||||
|
def __init__(self, phy, interface="wishbone", dw, endianness="be",
|
||||||
|
with_hw_preamble_crc=True):
|
||||||
|
self.submodules.core = LiteEthMACCore(phy, endianness, with_hw_preamble)
|
||||||
if interface == "wishbone":
|
if interface == "wishbone":
|
||||||
nrxslots = 2
|
self.interface = wishbone.LiteETHMACWishboneInterface(), dw, nrxslots, ntxslots)
|
||||||
ntxslots = 2
|
elif interface == "dma":
|
||||||
|
|
||||||
self.bus = wishbone.Interface()
|
|
||||||
|
|
||||||
# SRAM Memories
|
|
||||||
sram_depth = buffer_depth//(32//8)
|
|
||||||
self.submodules.sram_writer = SRAMWriter(sram_depth, nrxslots)
|
|
||||||
self.submodules.sram_reader = SRAMReader(sram_depth, ntxslots)
|
|
||||||
self.submodules.ev = SharedIRQ(self.sram_writer.ev, self.sram_reader.ev)
|
|
||||||
|
|
||||||
# Connect to pipelines
|
|
||||||
self.comb += [
|
|
||||||
self.rx_pipeline.source.connect(self.sram_writer.sink),
|
|
||||||
self.sram_reader.source.connect(self.tx_pipeline.sink)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Interface
|
|
||||||
wb_rx_sram_ifs = [wishbone.SRAM(self.sram_writer.mems[n], read_only=True)
|
|
||||||
for n in range(nrxslots)]
|
|
||||||
# TODO: FullMemoryWE should move to Mibuild
|
|
||||||
wb_tx_sram_ifs = [FullMemoryWE(wishbone.SRAM(self.sram_reader.mems[n], read_only=False))
|
|
||||||
for n in range(ntxslots)]
|
|
||||||
wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs
|
|
||||||
|
|
||||||
wb_slaves = []
|
|
||||||
decoderoffset = log2_int(sram_depth)
|
|
||||||
decoderbits = log2_int(len(wb_sram_ifs))
|
|
||||||
for n, wb_sram_if in enumerate(wb_sram_ifs):
|
|
||||||
def slave_filter(a, v=n):
|
|
||||||
return a[decoderoffset:decoderoffset+decoderbits] == v
|
|
||||||
wb_slaves.append((slave_filter, wb_sram_if.bus))
|
|
||||||
self.submodules += wb_sram_if
|
|
||||||
wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True)
|
|
||||||
self.submodules += wb_con
|
|
||||||
|
|
||||||
elif interface == "lasmi":
|
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
elif interface == "core":
|
||||||
elif interface == "expose":
|
self.sink = self.core.sink
|
||||||
# expose pipelines endpoints
|
self.source = self.core.source
|
||||||
self.sink = tx_pipeline.sink
|
|
||||||
self.source = rx_pipeline.source
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("EthMAC only supports Wishbone, LASMI or expose interfaces")
|
raise ValueError("EthMAC only supports Wishbone, DMA or core interfaces")
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
from migen.fhdl.std import *
|
|
||||||
from migen.flow.actor import EndpointDescription
|
|
||||||
|
|
||||||
eth_mtu = 1532
|
|
||||||
eth_preamble = 0xD555555555555555
|
|
||||||
buffer_depth = 2**log2_int(eth_mtu, need_pow2=False)
|
|
||||||
|
|
||||||
def eth_description(dw):
|
|
||||||
layout = [
|
|
||||||
("d", dw),
|
|
||||||
("last_be", dw//8),
|
|
||||||
("error", dw//8)
|
|
||||||
]
|
|
||||||
return EndpointDescription(layout, packetized=True)
|
|
|
@ -1,43 +1,42 @@
|
||||||
|
from liteeth.common import *
|
||||||
|
from liteeth.mac.common import *
|
||||||
|
from liteeth.mac import preamble, crc, last_be
|
||||||
|
|
||||||
from liteethernet.common import *
|
class LiteEthMACCore(Module, AutoCSR):
|
||||||
from liteethernet.mac.common import *
|
def __init__(self, phy, dw, endianness="be", with_hw_preamble_crc=True):
|
||||||
from liteethernet.mac.preamble import PreambleInserter, PreambleChecker
|
if dw > phy.dw:
|
||||||
from liteethernet.mac.crc import CRC32Inserter, CRC32Checker
|
raise ValueError("Core data width must be larger than PHY data width")
|
||||||
from liteethernet.mac.last_be import TXLastBE, RXLastBE
|
|
||||||
|
|
||||||
class LiteEthernetMACCore(Module, AutoCSR):
|
|
||||||
def __init__(self, phy, with_hw_preamble_crc=True, endianness="be"):
|
|
||||||
# Preamble / CRC (optional)
|
# Preamble / CRC (optional)
|
||||||
if with_hw_preamble_crc:
|
if with_hw_preamble_crc:
|
||||||
self._hw_preamble_crc = CSRStatus(reset=1)
|
self._hw_preamble_crc = CSRStatus(reset=1)
|
||||||
# Preamble insert/check
|
# Preamble insert/check
|
||||||
preamble_inserter = PreambleInserter(phy.dw)
|
preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
|
||||||
preamble_checker = PreambleChecker(phy.dw)
|
preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
|
||||||
self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
|
self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
|
||||||
self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
|
self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
|
||||||
|
|
||||||
# CRC insert/check
|
# CRC insert/check
|
||||||
crc32_inserter = CRC32Inserter(eth_description(phy.dw))
|
crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_description(phy.dw))
|
||||||
crc32_checker = CRC32Checker(eth_description(phy.dw))
|
crc32_checker = crc.LiteEthMACCRC32Checker(eth_description(phy.dw))
|
||||||
self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
|
self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
|
||||||
self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
|
self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
|
||||||
|
|
||||||
# Delimiters
|
# Delimiters
|
||||||
tx_last_be = TXLastBE(phy.dw)
|
tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
|
||||||
rx_last_be = RXLastBE(phy.dw)
|
rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
|
||||||
self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
|
self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
|
||||||
self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
|
self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
|
||||||
|
|
||||||
# Converters
|
# Converters
|
||||||
reverse = endianness == "be"
|
reverse = endianness == "be"
|
||||||
tx_converter = Converter(eth_description(32), eth_description(phy.dw), reverse=reverse)
|
tx_converter = Converter(eth_description(dw), eth_description(phy.dw), reverse=reverse)
|
||||||
rx_converter = Converter(eth_description(phy.dw), eth_description(32), reverse=reverse)
|
rx_converter = Converter(eth_description(phy.dw), eth_description(dw), reverse=reverse)
|
||||||
self.submodules += RenameClockDomains(tx_converter, "eth_tx")
|
self.submodules += RenameClockDomains(tx_converter, "eth_tx")
|
||||||
self.submodules += RenameClockDomains(rx_converter, "eth_rx")
|
self.submodules += RenameClockDomains(rx_converter, "eth_rx")
|
||||||
|
|
||||||
# Cross Domain Crossing
|
# Cross Domain Crossing
|
||||||
tx_cdc = AsyncFIFO(eth_description(32), 4)
|
tx_cdc = AsyncFIFO(eth_description(dw), 4)
|
||||||
rx_cdc = AsyncFIFO(eth_description(32), 4)
|
rx_cdc = AsyncFIFO(eth_description(dw), 4)
|
||||||
self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
|
self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
|
||||||
self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
|
self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from liteeth.common import *
|
||||||
from migen.genlib.fsm import FSM, NextState
|
from liteeth.mac.common import *
|
||||||
from migen.genlib.record import *
|
|
||||||
from migen.genlib.misc import optree, chooser
|
|
||||||
from migen.genlib.crc import *
|
|
||||||
from migen.flow.actor import Sink, Source
|
|
||||||
from migen.actorlib.fifo import SyncFIFO
|
|
||||||
|
|
||||||
from collections import OrderedDict
|
class LiteEthMACCRCEngine(Module):
|
||||||
|
|
||||||
class CRCEngine(Module):
|
|
||||||
"""Cyclic Redundancy Check Engine
|
"""Cyclic Redundancy Check Engine
|
||||||
|
|
||||||
Compute next CRC value from last CRC value and data input using
|
Compute next CRC value from last CRC value and data input using
|
||||||
|
@ -78,7 +71,7 @@ class CRCEngine(Module):
|
||||||
|
|
||||||
@DecorateModule(InsertReset)
|
@DecorateModule(InsertReset)
|
||||||
@DecorateModule(InsertCE)
|
@DecorateModule(InsertCE)
|
||||||
class CRC32(Module):
|
class LiteEthMACCRC32(Module):
|
||||||
"""IEEE 802.3 CRC
|
"""IEEE 802.3 CRC
|
||||||
|
|
||||||
Implement an IEEE 802.3 CRC generator/checker.
|
Implement an IEEE 802.3 CRC generator/checker.
|
||||||
|
@ -108,7 +101,7 @@ class CRC32(Module):
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
self.submodules.engine = CRCEngine(dat_width, self.width, self.polynom)
|
self.submodules.engine = LiteEthCRCEngine(dat_width, self.width, self.polynom)
|
||||||
reg = Signal(self.width, reset=self.init)
|
reg = Signal(self.width, reset=self.init)
|
||||||
self.sync += reg.eq(self.engine.next)
|
self.sync += reg.eq(self.engine.next)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
|
@ -119,7 +112,7 @@ class CRC32(Module):
|
||||||
self.error.eq(self.engine.next != self.check)
|
self.error.eq(self.engine.next != self.check)
|
||||||
]
|
]
|
||||||
|
|
||||||
class CRCInserter(Module):
|
class LiteEthMACCRCInserter(Module):
|
||||||
"""CRC Inserter
|
"""CRC Inserter
|
||||||
|
|
||||||
Append a CRC at the end of each packet.
|
Append a CRC at the end of each packet.
|
||||||
|
@ -193,11 +186,11 @@ class CRCInserter(Module):
|
||||||
)
|
)
|
||||||
self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
|
self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
|
||||||
|
|
||||||
class CRC32Inserter(CRCInserter):
|
class LiteEthMACCRC32Inserter(CRCInserter):
|
||||||
def __init__(self, layout):
|
def __init__(self, layout):
|
||||||
CRCInserter.__init__(self, CRC32, layout)
|
LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, layout)
|
||||||
|
|
||||||
class CRCChecker(Module):
|
class LiteEthMACCRCChecker(Module):
|
||||||
"""CRC Checker
|
"""CRC Checker
|
||||||
|
|
||||||
Check CRC at the end of each packet.
|
Check CRC at the end of each packet.
|
||||||
|
@ -279,6 +272,6 @@ class CRCChecker(Module):
|
||||||
)
|
)
|
||||||
self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
|
self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
|
||||||
|
|
||||||
class CRC32Checker(CRCChecker):
|
class LiteEthMACCRC32Checker(CRCChecker):
|
||||||
def __init__(self, layout):
|
def __init__(self, layout):
|
||||||
CRCChecker.__init__(self, CRC32, layout)
|
LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, layout)
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from liteeth.common import *
|
||||||
from migen.genlib.record import *
|
from liteeth.mac.common import *
|
||||||
from migen.flow.actor import Sink, Source
|
|
||||||
|
|
||||||
from liteethernet.common import *
|
class LiteEthMACTXLastBE(Module):
|
||||||
from liteethernet.mac.common import *
|
|
||||||
|
|
||||||
class TXLastBE(Module):
|
|
||||||
def __init__(self, d_w):
|
def __init__(self, d_w):
|
||||||
self.sink = sink = Sink(eth_description(d_w))
|
self.sink = sink = Sink(eth_description(d_w))
|
||||||
self.source = source = Source(eth_description(d_w))
|
self.source = source = Source(eth_description(d_w))
|
||||||
|
@ -27,7 +23,7 @@ class TXLastBE(Module):
|
||||||
self.source.stb.eq(self.sink.stb & (self.sink.sop | ongoing))
|
self.source.stb.eq(self.sink.stb & (self.sink.sop | ongoing))
|
||||||
]
|
]
|
||||||
|
|
||||||
class RXLastBE(Module):
|
class LiteEthMACRXLastBE(Module):
|
||||||
def __init__(self, d_w):
|
def __init__(self, d_w):
|
||||||
self.sink = sink = Sink(eth_description(d_w))
|
self.sink = sink = Sink(eth_description(d_w))
|
||||||
self.source = source = Source(eth_description(d_w))
|
self.source = source = Source(eth_description(d_w))
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from liteeth.common import *
|
||||||
from migen.genlib.fsm import FSM, NextState
|
from liteeth.mac.common import *
|
||||||
from migen.genlib.misc import chooser
|
|
||||||
from migen.genlib.record import *
|
|
||||||
from migen.flow.actor import Sink, Source
|
|
||||||
|
|
||||||
from liteethernet.common import *
|
class LiteEthMACPreambleInserter(Module):
|
||||||
from liteethernet.ethmac.common import *
|
|
||||||
|
|
||||||
class PreambleInserter(Module):
|
|
||||||
def __init__(self, d_w):
|
def __init__(self, d_w):
|
||||||
self.sink = Sink(eth_description(d_w))
|
self.sink = Sink(eth_description(d_w))
|
||||||
self.source = Source(eth_description(d_w))
|
self.source = Source(eth_description(d_w))
|
||||||
|
@ -56,7 +50,7 @@ class PreambleInserter(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
class PreambleChecker(Module):
|
class LiteEthMACPreambleChecker(Module):
|
||||||
def __init__(self, d_w):
|
def __init__(self, d_w):
|
||||||
self.sink = Sink(eth_description(d_w))
|
self.sink = Sink(eth_description(d_w))
|
||||||
self.source = Source(eth_description(d_w))
|
self.source = Source(eth_description(d_w))
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
from migen.fhdl.std import *
|
from liteeth.common import *
|
||||||
from migen.genlib.fifo import SyncFIFO
|
from liteeth.mac.common import *
|
||||||
from migen.genlib.fsm import FSM, NextState
|
|
||||||
from migen.genlib.misc import chooser
|
|
||||||
from migen.flow.actor import Sink, Source
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.bank.eventmanager import *
|
|
||||||
|
|
||||||
from liteethernet.common import *
|
class LiteEthMACSRAMWriter(Module, AutoCSR):
|
||||||
from liteethernet.mac.common import *
|
def __init__(self, dw, depth, nslots=2):
|
||||||
|
self.sink = sink = Sink(eth_description(dw))
|
||||||
class SRAMWriter(Module, AutoCSR):
|
|
||||||
def __init__(self, depth, nslots=2):
|
|
||||||
self.sink = sink = Sink(eth_description(32))
|
|
||||||
self.crc_error = Signal()
|
self.crc_error = Signal()
|
||||||
|
|
||||||
slotbits = max(log2_int(nslots), 1)
|
slotbits = max(log2_int(nslots), 1)
|
||||||
|
@ -117,7 +109,7 @@ class SRAMWriter(Module, AutoCSR):
|
||||||
mems = [None]*nslots
|
mems = [None]*nslots
|
||||||
ports = [None]*nslots
|
ports = [None]*nslots
|
||||||
for n in range(nslots):
|
for n in range(nslots):
|
||||||
mems[n] = Memory(32, depth)
|
mems[n] = Memory(dw, depth)
|
||||||
ports[n] = mems[n].get_port(write_capable=True)
|
ports[n] = mems[n].get_port(write_capable=True)
|
||||||
self.specials += ports[n]
|
self.specials += ports[n]
|
||||||
self.mems = mems
|
self.mems = mems
|
||||||
|
@ -134,9 +126,9 @@ class SRAMWriter(Module, AutoCSR):
|
||||||
self.comb += Case(slot, cases)
|
self.comb += Case(slot, cases)
|
||||||
|
|
||||||
|
|
||||||
class SRAMReader(Module, AutoCSR):
|
class LiteEthMACSRAMReader(Module, AutoCSR):
|
||||||
def __init__(self, depth, nslots=2):
|
def __init__(self, dw, depth, nslots=2):
|
||||||
self.source = source = Source(eth_description(32))
|
self.source = source = Source(eth_description(dw))
|
||||||
|
|
||||||
slotbits = max(log2_int(nslots), 1)
|
slotbits = max(log2_int(nslots), 1)
|
||||||
lengthbits = log2_int(depth*4) # length in bytes
|
lengthbits = log2_int(depth*4) # length in bytes
|
||||||
|
@ -240,7 +232,7 @@ class SRAMReader(Module, AutoCSR):
|
||||||
mems = [None]*nslots
|
mems = [None]*nslots
|
||||||
ports = [None]*nslots
|
ports = [None]*nslots
|
||||||
for n in range(nslots):
|
for n in range(nslots):
|
||||||
mems[n] = Memory(32, depth)
|
mems[n] = Memory(dw, depth)
|
||||||
ports[n] = mems[n].get_port()
|
ports[n] = mems[n].get_port()
|
||||||
self.specials += ports[n]
|
self.specials += ports[n]
|
||||||
self.mems = mems
|
self.mems = mems
|
||||||
|
@ -250,3 +242,10 @@ class SRAMReader(Module, AutoCSR):
|
||||||
self.comb += ports[n].adr.eq(cnt[2:])
|
self.comb += ports[n].adr.eq(cnt[2:])
|
||||||
cases[n] = [source.d.eq(port.dat_r)]
|
cases[n] = [source.d.eq(port.dat_r)]
|
||||||
self.comb += Case(rd_slot, cases)
|
self.comb += Case(rd_slot, cases)
|
||||||
|
|
||||||
|
class LiteMACEthMACSRAM(Module, AutoCSR):
|
||||||
|
def __init__(self, dw, depth, nrxslots, ntxslots):
|
||||||
|
self.submodules.writer = LiteEthSRAMWriter(dw, depth, nrxslots)
|
||||||
|
self.submodules.reader = LiteEthSRAMReader(dw, depth, ntxslots)
|
||||||
|
self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
|
||||||
|
self.sink, self.source = self.witer.sink, self.reader.source
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
from liteethernet.common import *
|
from liteeth.common import *
|
||||||
from liteethernet.mac import LiteEthernetMAC
|
from liteeth.mac.common import *
|
||||||
|
from liteeth.mac.frontend import sram
|
||||||
|
|
||||||
class LiteEthernetMACWishboneInterface(Module, AutoCSR):
|
class LiteEthMACWishboneInterface(Module, AutoCSR):
|
||||||
def __init__(self, nrxslots=2, ntxslots=2):
|
def __init__(self, dw, nrxslots=2, ntxslots=2):
|
||||||
self.sink = Sink(mac_description(dw))
|
self.sink = Sink(mac_description(dw))
|
||||||
self.source = Source(max_description(dw))
|
self.source = Source(max_description(dw))
|
||||||
self.bus = wishbone.Interface()
|
self.bus = wishbone.Interface()
|
||||||
|
|
||||||
###
|
###
|
||||||
|
# storage in SRAM
|
||||||
# SRAM Storage
|
sram_depth = buffer_depth//(dw//8)
|
||||||
sram_depth = buffer_depth//(32//8)
|
self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots)
|
||||||
self.submodules.sram_writer = SRAMWriter(sram_depth, nrxslots)
|
|
||||||
self.submodules.sram_reader = SRAMReader(sram_depth, ntxslots)
|
|
||||||
self.submodules.ev = SharedIRQ(self.sram_writer.ev, self.sram_reader.ev)
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
Record.connect(self.sink, self.sram_writer.sink),
|
Record.connect(self.sink, self.sram.sink),
|
||||||
Record.connect(self.sram_reader.source, self.source)
|
Record.connect(self.sram.source, self.source)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Interface
|
# Wishbone interface
|
||||||
wb_rx_sram_ifs = [wishbone.SRAM(self.sram_writer.mems[n], read_only=True)
|
wb_rx_sram_ifs = [wishbone.SRAM(self.sram_writer.mems[n], read_only=True)
|
||||||
for n in range(nrxslots)]
|
for n in range(nrxslots)]
|
||||||
# TODO: FullMemoryWE should move to Mibuild
|
# TODO: FullMemoryWE should move to Mibuild
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
MSCDIR = ../../../
|
|
||||||
PYTHON = python3
|
|
||||||
|
|
||||||
CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
|
|
||||||
|
|
||||||
crc_tb:
|
|
||||||
$(CMD) crc_tb.py
|
|
||||||
|
|
||||||
preamble_tb:
|
|
||||||
$(CMD) preamble_tb.py
|
|
||||||
|
|
||||||
ethmac_tb:
|
|
||||||
$(CMD) ethmac_tb.py
|
|
|
@ -1,83 +0,0 @@
|
||||||
from migen.fhdl.std import *
|
|
||||||
from migen.actorlib.crc import *
|
|
||||||
|
|
||||||
from misoclib.ethmac.common import *
|
|
||||||
from misoclib.ethmac.test.common import *
|
|
||||||
|
|
||||||
payload = [
|
|
||||||
0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12,
|
|
||||||
0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00,
|
|
||||||
0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11,
|
|
||||||
0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00,
|
|
||||||
0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C,
|
|
||||||
0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
|
||||||
0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
|
||||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
|
|
||||||
]
|
|
||||||
|
|
||||||
crc = [
|
|
||||||
0x7A, 0xD5, 0x6B, 0xB3
|
|
||||||
]
|
|
||||||
|
|
||||||
mux = {
|
|
||||||
"inserter": 0,
|
|
||||||
"checker": 1,
|
|
||||||
"both": 2
|
|
||||||
}
|
|
||||||
|
|
||||||
class TB(Module):
|
|
||||||
def __init__(self, random_level=50):
|
|
||||||
sm = self.submodules
|
|
||||||
sm.streamer = PacketStreamer(eth_description(8))
|
|
||||||
sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level)
|
|
||||||
sm.logger = PacketLogger(eth_description(8))
|
|
||||||
sm.logger_randomizer = AckRandomizer(eth_description(8), random_level)
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
self.streamer.source.connect(self.streamer_randomizer.sink),
|
|
||||||
self.logger_randomizer.source.connect(self.logger.sink)
|
|
||||||
]
|
|
||||||
|
|
||||||
sm.crc32_inserter = CRC32Inserter(eth_description(8))
|
|
||||||
sm.crc32_checker = CRC32Checker(eth_description(8))
|
|
||||||
|
|
||||||
self.mux = Signal(2)
|
|
||||||
self.comb += [
|
|
||||||
If(self.mux == mux["inserter"],
|
|
||||||
self.streamer_randomizer.source.connect(self.crc32_inserter.sink),
|
|
||||||
self.crc32_inserter.source.connect(self.logger_randomizer.sink)
|
|
||||||
).Elif(self.mux == mux["checker"],
|
|
||||||
self.streamer_randomizer.source.connect(self.crc32_checker.sink),
|
|
||||||
self.crc32_checker.source.connect(self.logger_randomizer.sink)
|
|
||||||
).Elif(self.mux == mux["both"],
|
|
||||||
self.streamer_randomizer.source.connect(self.crc32_inserter.sink),
|
|
||||||
self.crc32_inserter.source.connect(self.crc32_checker.sink),
|
|
||||||
self.crc32_checker.source.connect(self.logger_randomizer.sink)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
def gen_simulation(self, selfp):
|
|
||||||
selfp.mux = mux["inserter"]
|
|
||||||
print("streamer --> crc32_inserter --> logger:")
|
|
||||||
self.streamer.send(Packet(payload))
|
|
||||||
yield from self.logger.receive()
|
|
||||||
s, l, e = check(payload+crc, self.logger.packet)
|
|
||||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
|
||||||
|
|
||||||
selfp.mux = mux["checker"]
|
|
||||||
print("streamer --> crc32_checker --> logger:")
|
|
||||||
self.streamer.send(Packet(payload+crc))
|
|
||||||
yield from self.logger.receive()
|
|
||||||
s, l, e = check(payload, self.logger.packet)
|
|
||||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
|
||||||
|
|
||||||
selfp.mux = mux["both"]
|
|
||||||
print("streamer --> crc32_inserter --> crc32_checker --> logger:")
|
|
||||||
self.streamer.send(Packet(payload))
|
|
||||||
yield from self.logger.receive()
|
|
||||||
s, l, e = check(payload, self.logger.packet)
|
|
||||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
from migen.sim.generic import run_simulation
|
|
||||||
run_simulation(TB(), ncycles=1000, vcd_name="my.vcd")
|
|
|
@ -1,75 +0,0 @@
|
||||||
[*]
|
|
||||||
[*] GTKWave Analyzer v3.3.46 (w)1999-2012 BSI
|
|
||||||
[*] Fri Oct 31 11:20:55 2014
|
|
||||||
[*]
|
|
||||||
[dumpfile] "/home/florent/Dev/misoc/misoclib/ethmac/test/my.vcd"
|
|
||||||
[dumpfile_mtime] "Fri Oct 31 11:20:07 2014"
|
|
||||||
[dumpfile_size] 5152269
|
|
||||||
[savefile] "/home/florent/Dev/misoc/misoclib/ethmac/test/ethmac_tb.gtkw"
|
|
||||||
[timestart] 0
|
|
||||||
[size] 1548 849
|
|
||||||
[pos] 101 171
|
|
||||||
*-25.000000 34300000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
|
||||||
[treeopen] top.
|
|
||||||
[sst_width] 379
|
|
||||||
[signals_width] 464
|
|
||||||
[sst_expanded] 1
|
|
||||||
[sst_vpaned_height] 485
|
|
||||||
@200
|
|
||||||
-WISHBONE
|
|
||||||
@28
|
|
||||||
top.dut.bus_ack
|
|
||||||
@22
|
|
||||||
top.dut.bus_adr[29:0]
|
|
||||||
@28
|
|
||||||
top.dut.bus_bte[1:0]
|
|
||||||
top.dut.bus_cti[2:0]
|
|
||||||
top.dut.bus_cyc
|
|
||||||
@22
|
|
||||||
top.dut.bus_dat_r[31:0]
|
|
||||||
top.dut.bus_dat_w[31:0]
|
|
||||||
@28
|
|
||||||
top.dut.bus_err
|
|
||||||
@22
|
|
||||||
top.dut.bus_sel[3:0]
|
|
||||||
@28
|
|
||||||
top.dut.bus_stb
|
|
||||||
top.dut.bus_we
|
|
||||||
@200
|
|
||||||
-SRAM_READER --> PHYTx
|
|
||||||
@28
|
|
||||||
top.dut.sram_reader_source_ack
|
|
||||||
top.dut.sram_reader_source_eop
|
|
||||||
@22
|
|
||||||
top.dut.sram_reader_source_payload_d[31:0]
|
|
||||||
top.dut.sram_reader_source_payload_error[3:0]
|
|
||||||
top.dut.sram_reader_source_payload_last_be[3:0]
|
|
||||||
@28
|
|
||||||
top.dut.sram_reader_source_sop
|
|
||||||
top.dut.sram_reader_source_stb
|
|
||||||
@200
|
|
||||||
-LOOPBACK
|
|
||||||
@28
|
|
||||||
top.dut.phy_source_ack
|
|
||||||
top.dut.phy_source_eop
|
|
||||||
@22
|
|
||||||
top.dut.phy_source_payload_d[7:0]
|
|
||||||
@28
|
|
||||||
top.dut.phy_source_payload_error
|
|
||||||
top.dut.phy_source_payload_last_be
|
|
||||||
top.dut.phy_source_sop
|
|
||||||
top.dut.phy_source_stb
|
|
||||||
@200
|
|
||||||
-PHYRx --> SRAM_WRITER
|
|
||||||
@28
|
|
||||||
top.dut.sram_writer_sink_ack
|
|
||||||
top.dut.sram_writer_sink_eop
|
|
||||||
@22
|
|
||||||
top.dut.sram_writer_sink_payload_d[31:0]
|
|
||||||
top.dut.sram_writer_sink_payload_error[3:0]
|
|
||||||
top.dut.sram_writer_sink_payload_last_be[3:0]
|
|
||||||
@28
|
|
||||||
top.dut.sram_writer_sink_sop
|
|
||||||
top.dut.sram_writer_sink_stb
|
|
||||||
[pattern_trace] 1
|
|
||||||
[pattern_trace] 0
|
|
|
@ -1,82 +0,0 @@
|
||||||
from migen.fhdl.std import *
|
|
||||||
|
|
||||||
from misoclib.ethmac.common import *
|
|
||||||
from misoclib.ethmac.preamble import *
|
|
||||||
from misoclib.ethmac.test.common import *
|
|
||||||
|
|
||||||
preamble = [
|
|
||||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5
|
|
||||||
]
|
|
||||||
|
|
||||||
payload = [
|
|
||||||
0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12,
|
|
||||||
0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00,
|
|
||||||
0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11,
|
|
||||||
0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00,
|
|
||||||
0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C,
|
|
||||||
0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
|
||||||
0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
|
||||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
|
|
||||||
]
|
|
||||||
|
|
||||||
mux = {
|
|
||||||
"inserter": 0,
|
|
||||||
"checker": 1,
|
|
||||||
"both": 2
|
|
||||||
}
|
|
||||||
|
|
||||||
class TB(Module):
|
|
||||||
def __init__(self, random_level=50):
|
|
||||||
sm = self.submodules
|
|
||||||
sm.streamer = PacketStreamer(eth_description(8))
|
|
||||||
sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level)
|
|
||||||
sm.logger = PacketLogger(eth_description(8))
|
|
||||||
sm.logger_randomizer = AckRandomizer(eth_description(8), random_level)
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
self.streamer.source.connect(self.streamer_randomizer.sink),
|
|
||||||
self.logger_randomizer.source.connect(self.logger.sink)
|
|
||||||
]
|
|
||||||
|
|
||||||
sm.preamble_inserter = PreambleInserter(8)
|
|
||||||
sm.preamble_checker = PreambleChecker(8)
|
|
||||||
|
|
||||||
self.mux = Signal(2)
|
|
||||||
self.comb += [
|
|
||||||
If(self.mux == mux["inserter"],
|
|
||||||
self.streamer_randomizer.source.connect(self.preamble_inserter.sink),
|
|
||||||
self.preamble_inserter.source.connect(self.logger_randomizer.sink)
|
|
||||||
).Elif(self.mux == mux["checker"],
|
|
||||||
self.streamer_randomizer.source.connect(self.preamble_checker.sink),
|
|
||||||
self.preamble_checker.source.connect(self.logger_randomizer.sink)
|
|
||||||
).Elif(self.mux == mux["both"],
|
|
||||||
self.streamer_randomizer.source.connect(self.preamble_inserter.sink),
|
|
||||||
self.preamble_inserter.source.connect(self.preamble_checker.sink),
|
|
||||||
self.preamble_checker.source.connect(self.logger_randomizer.sink)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
def gen_simulation(self, selfp):
|
|
||||||
selfp.mux = mux["inserter"]
|
|
||||||
print("streamer --> preamble_inserter --> logger:")
|
|
||||||
self.streamer.send(Packet(payload))
|
|
||||||
yield from self.logger.receive()
|
|
||||||
s, l, e = check(preamble+payload, self.logger.packet)
|
|
||||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
|
||||||
|
|
||||||
selfp.mux = mux["checker"]
|
|
||||||
print("streamer --> preamble_checker --> logger:")
|
|
||||||
self.streamer.send(Packet(preamble+payload))
|
|
||||||
yield from self.logger.receive()
|
|
||||||
s, l, e = check(payload, self.logger.packet)
|
|
||||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
|
||||||
|
|
||||||
selfp.mux = mux["both"]
|
|
||||||
print("streamer --> preamble_inserter --> preamble_checker --> logger:")
|
|
||||||
self.streamer.send(Packet(payload))
|
|
||||||
yield from self.logger.receive()
|
|
||||||
s, l, e = check(payload, self.logger.packet)
|
|
||||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
from migen.sim.generic import run_simulation
|
|
||||||
run_simulation(TB(), ncycles=1000, vcd_name="my.vcd")
|
|
|
@ -1,11 +1,6 @@
|
||||||
from migen.fhdl.std import *
|
from liteeth.common import *
|
||||||
from migen.flow.actor import Sink, Source
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
||||||
|
|
||||||
from liteethernet.common import *
|
class LiteEthPHYGMIITX(Module):
|
||||||
|
|
||||||
class GMIIPHYTX(Module):
|
|
||||||
def __init__(self, pads):
|
def __init__(self, pads):
|
||||||
self.sink = sink = Sink(eth_description(8))
|
self.sink = sink = Sink(eth_description(8))
|
||||||
###
|
###
|
||||||
|
@ -16,7 +11,7 @@ class GMIIPHYTX(Module):
|
||||||
]
|
]
|
||||||
self.comb += sink.ack.eq(1)
|
self.comb += sink.ack.eq(1)
|
||||||
|
|
||||||
class GMIIPHYRX(Module):
|
class LiteEthPHYGMIIRX(Module):
|
||||||
def __init__(self, pads):
|
def __init__(self, pads):
|
||||||
self.source = source = Source(eth_description(8))
|
self.source = source = Source(eth_description(8))
|
||||||
###
|
###
|
||||||
|
@ -38,7 +33,7 @@ class GMIIPHYRX(Module):
|
||||||
|
|
||||||
# CRG is the only Xilinx specific module.
|
# CRG is the only Xilinx specific module.
|
||||||
# TODO: use generic code or add support for others vendors
|
# TODO: use generic code or add support for others vendors
|
||||||
class GMIIPHYCRG(Module, AutoCSR):
|
class LiteEthPHYGMIICRG(Module, AutoCSR):
|
||||||
def __init__(self, clock_pads, pads):
|
def __init__(self, clock_pads, pads):
|
||||||
self._reset = CSRStorage()
|
self._reset = CSRStorage()
|
||||||
###
|
###
|
||||||
|
@ -61,10 +56,10 @@ class GMIIPHYCRG(Module, AutoCSR):
|
||||||
AsyncResetSynchronizer(self.cd_eth_rx, reset),
|
AsyncResetSynchronizer(self.cd_eth_rx, reset),
|
||||||
]
|
]
|
||||||
|
|
||||||
class GMIIPHY(Module, AutoCSR):
|
class LiteEthPHYMII(Module, AutoCSR):
|
||||||
def __init__(self, clock_pads, pads):
|
def __init__(self, clock_pads, pads):
|
||||||
self.dw = 8
|
self.dw = 8
|
||||||
self.submodules.crg = GMIIPHYCRG(clock_pads, pads)
|
self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads)
|
||||||
self.submodules.tx = RenameClockDomains(GMIIPHYTX(pads), "eth_tx")
|
self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads), "eth_tx")
|
||||||
self.submodules.rx = RenameClockDomains(GMIIPHYRX(pads), "eth_rx")
|
self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads), "eth_rx")
|
||||||
self.sink, self.source = self.tx.sink, self.rx.source
|
self.sink, self.source = self.tx.sink, self.rx.source
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
from migen.fhdl.std import *
|
from liteeth.common import *
|
||||||
from migen.flow.actor import Sink, Source
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.genlib.record import *
|
|
||||||
|
|
||||||
from liteethernet.common import *
|
class LiteEthPHYLoopbackCRG(Module, AutoCSR):
|
||||||
|
|
||||||
class LoopbackPHYCRG(Module, AutoCSR):
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._reset = CSRStorage()
|
self._reset = CSRStorage()
|
||||||
###
|
###
|
||||||
|
@ -22,10 +17,10 @@ class LoopbackPHYCRG(Module, AutoCSR):
|
||||||
self.cd_eth_tx.rst.eq(reset)
|
self.cd_eth_tx.rst.eq(reset)
|
||||||
]
|
]
|
||||||
|
|
||||||
class LoopbackPHY(Module, AutoCSR):
|
class LiteEthPHYLoopback(Module, AutoCSR):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.dw = 8
|
self.dw = 8
|
||||||
self.submodules.crg = LoopbackPHYCRG()
|
self.submodules.crg = LiteEthLoopbackPHYCRG()
|
||||||
self.sink = sink = Sink(eth_description(8))
|
self.sink = sink = Sink(eth_description(8))
|
||||||
self.source = source = Source(eth_description(8))
|
self.source = source = Source(eth_description(8))
|
||||||
self.comb += Record.connect(self.sink, self.source)
|
self.comb += Record.connect(self.sink, self.source)
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
from migen.fhdl.std import *
|
from liteeth.common import *
|
||||||
from migen.genlib.fsm import FSM, NextState
|
|
||||||
from migen.flow.actor import Sink, Source
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
||||||
|
|
||||||
from liteethernet.common import *
|
class LiteEthPHYMIITX(Module):
|
||||||
|
|
||||||
class MIIPHYTX(Module):
|
|
||||||
def __init__(self, pads):
|
def __init__(self, pads):
|
||||||
self.sink = sink = Sink(eth_description(8))
|
self.sink = sink = Sink(eth_description(8))
|
||||||
###
|
###
|
||||||
|
@ -43,7 +37,7 @@ class MIIPHYTX(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
class MIIPHYRX(Module):
|
class LiteEthPHYMIIRX(Module):
|
||||||
def __init__(self, pads):
|
def __init__(self, pads):
|
||||||
self.source = source = Source(eth_description(8))
|
self.source = source = Source(eth_description(8))
|
||||||
###
|
###
|
||||||
|
@ -95,7 +89,7 @@ class MIIPHYRX(Module):
|
||||||
NextState("LOAD_LO")
|
NextState("LOAD_LO")
|
||||||
)
|
)
|
||||||
|
|
||||||
class MIIPHYCRG(Module, AutoCSR):
|
class LiteEthPHYMIICRG(Module, AutoCSR):
|
||||||
def __init__(self, clock_pads, pads):
|
def __init__(self, clock_pads, pads):
|
||||||
self._reset = CSRStorage()
|
self._reset = CSRStorage()
|
||||||
###
|
###
|
||||||
|
@ -113,10 +107,10 @@ class MIIPHYCRG(Module, AutoCSR):
|
||||||
AsyncResetSynchronizer(self.cd_eth_rx, reset),
|
AsyncResetSynchronizer(self.cd_eth_rx, reset),
|
||||||
]
|
]
|
||||||
|
|
||||||
class MIIPHY(Module, AutoCSR):
|
class LiteEthPHYMII(Module, AutoCSR):
|
||||||
def __init__(self, clock_pads, pads):
|
def __init__(self, clock_pads, pads):
|
||||||
self.dw = 8
|
self.dw = 8
|
||||||
self.submodules.crg = MIIPHYCRG(clock_pads, pads)
|
self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads)
|
||||||
self.submodules.tx = RenameClockDomains(MIIPHYTX(pads), "eth_tx")
|
self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx")
|
||||||
self.submodules.rx = RenameClockDomains(MIIPHYRX(pads), "eth_rx")
|
self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx")
|
||||||
self.sink, self.source = self.tx.sink, self.rx.source
|
self.sink, self.source = self.tx.sink, self.rx.source
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
LEDIR = ../../
|
||||||
|
PYTHON = python3
|
||||||
|
|
||||||
|
CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
|
||||||
|
|
||||||
|
mac_crc_tb:
|
||||||
|
$(CMD) mac_crc_tb.py
|
||||||
|
|
||||||
|
mac_preamble_tb:
|
||||||
|
$(CMD) mac_preamble_preamble_tb.py
|
||||||
|
|
||||||
|
ethmac_tb:
|
||||||
|
$(CMD) ethmac_tb.py
|
|
@ -0,0 +1,123 @@
|
||||||
|
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.phy import loopback
|
||||||
|
|
||||||
|
from misoclib.ethmac.test.common import *
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0]
|
||||||
|
|
||||||
|
errors = 0
|
||||||
|
|
||||||
|
for slot in range(2):
|
||||||
|
print("slot {}:".format(slot))
|
||||||
|
# fill tx memory
|
||||||
|
for i in range(length//4+1):
|
||||||
|
dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big")
|
||||||
|
yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat)
|
||||||
|
|
||||||
|
# send tx payload & 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 payload (loopback on PHY Model)
|
||||||
|
rx_payload = []
|
||||||
|
for i in range(length//4+1):
|
||||||
|
yield from wishbone_master.read(sram_writer_slots_offset[slot]+i)
|
||||||
|
dat = wishbone_master.dat
|
||||||
|
rx_payload += list(dat.to_bytes(4, byteorder='big'))
|
||||||
|
|
||||||
|
# check results
|
||||||
|
s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))])
|
||||||
|
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_simulation(TB(), vcd_name="my.vcd")
|
Loading…
Reference in New Issue