from migen.genlib.resetsync import AsyncResetSynchronizer
from migen.genlib.record import *
from migen.genlib.fsm import FSM, NextState
+from migen.genlib.misc import chooser
from migen.flow.actor import EndpointDescription
from migen.flow.actor import Sink, Source
from migen.actorlib.structuring import Converter, Pipeline
self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
# CRC insert/check
- crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_description(phy.dw))
- crc32_checker = crc.LiteEthMACCRC32Checker(eth_description(phy.dw))
+ crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw))
+ crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw))
self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
###
- self.submodules.engine = LiteEthCRCEngine(data_width, self.width, self.polynom)
+ self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom)
reg = Signal(self.width, reset=self.init)
self.sync += reg.eq(self.engine.next)
self.comb += [
NextState("IDLE"),
)
fsm.act("IDLE",
- crc.d.eq(sink.data),
+ crc.data.eq(sink.data),
If(sink.stb & sink.sop & sink.ack,
crc.ce.eq(1),
NextState("COPY")
)
)
fsm.act("COPY",
- crc.d.eq(sink.data),
+ crc.data.eq(sink.data),
If(sink.stb & sink.ack,
crc.ce.eq(1),
If(sink.eop,
LEDIR = ../../
PYTHON = python3
-CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
+CMD = PYTHONPATH=$(LEDIR) $(PYTHON)
mac_core_tb:
$(CMD) mac_core_tb.py
from migen.flow.actor import Sink, Source
from migen.genlib.record import *
-from misoclib.ethmac.common import *
+from liteeth.common import *
def print_with_prefix(s, prefix=""):
if not isinstance(s, str):
else:
return seed
+def comp(p1, p2):
+ r = True
+ for x, y in zip(p1, p2):
+ if x != y:
+ r = False
+ return r
+
def check(p1, p2):
p1 = copy.deepcopy(p1)
p2 = copy.deepcopy(p2)
self.append(data)
class PacketStreamer(Module):
- def __init__(self, description):
+ def __init__(self, description, last_be=None):
self.source = Source(description)
+ self.last_be = last_be
###
self.packets = []
self.packet = Packet()
- self.packet.done = 1
+ self.packet.done = True
def send(self, packet):
packet = copy.deepcopy(packet)
self.packets.append(packet)
+ while not packet.done:
+ yield
def do_simulation(self, selfp):
if len(self.packets) and self.packet.done:
if not self.packet.ongoing and not self.packet.done:
selfp.source.stb = 1
selfp.source.sop = 1
- selfp.source.d = self.packet.pop(0)
+ selfp.source.data = self.packet.pop(0)
self.packet.ongoing = True
elif selfp.source.stb == 1 and selfp.source.ack == 1:
selfp.source.sop = 0
- selfp.source.eop = (len(self.packet) == 1)
+ if len(self.packet) == 1:
+ selfp.source.eop = 1
+ if self.last_be is not None:
+ selfp.source.last_be = self.last_be
+ else:
+ selfp.source.eop = 0
+ selfp.source.last_be = 0
if len(self.packet) > 0:
selfp.source.stb = 1
- selfp.source.d = self.packet.pop(0)
+ selfp.source.data = self.packet.pop(0)
else:
- self.packet.done = 1
+ self.packet.done = True
selfp.source.stb = 0
class PacketLogger(Module):
self.packet = Packet()
def receive(self):
- self.packet.done = 0
- while self.packet.done == 0:
+ self.packet.done = False
+ while not self.packet.done:
yield
def do_simulation(self, selfp):
selfp.sink.ack = 1
if selfp.sink.stb == 1 and selfp.sink.sop == 1:
self.packet = Packet()
- self.packet.append(selfp.sink.d)
+ self.packet.append(selfp.sink.data)
elif selfp.sink.stb:
- self.packet.append(selfp.sink.d)
+ self.packet.append(selfp.sink.data)
if selfp.sink.stb == 1 and selfp.sink.eop == 1:
self.packet.done = True
from migen.bus.transactions import *
from migen.sim.generic import run_simulation
-from misoclib.ethmac import EthMAC
-from misoclib.ethmac.phy import loopback
+from liteeth.common import *
+from liteeth.mac import LiteEthMAC
-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
+from liteeth.test.common import *
+from liteeth.test.model import phy, mac
class TB(Module):
def __init__(self):
- self.submodules.ethphy = loopback.LoopbackPHY()
- self.submodules.ethmac = EthMAC(phy=self.ethphy, with_hw_preamble_crc=True)
+ self.submodules.hostphy = phy.PHY(8, debug=True)
+ self.submodules.hostmac = mac.MAC(self.hostphy, debug=True, random_level=0)
+ self.submodules.ethmac = LiteEthMAC(phy=self.hostphy, dw=32, interface="core", with_hw_preamble_crc=True)
+
+ self.submodules.streamer = PacketStreamer(eth_mac_description(32), last_be=1)
+ self.submodules.streamer_randomizer = AckRandomizer(eth_mac_description(32), level=0)
+
+ self.submodules.logger_randomizer = AckRandomizer(eth_mac_description(32), level=0)
+ self.submodules.logger = PacketLogger(eth_mac_description(32))
# use sys_clk for each clock_domain
self.clock_domains.cd_eth_rx = ClockDomain()
self.cd_eth_tx.rst.eq(ResetSignal()),
]
+ self.comb += [
+ Record.connect(self.streamer.source, self.streamer_randomizer.sink),
+ Record.connect(self.streamer_randomizer.source, self.ethmac.sink),
+ Record.connect(self.ethmac.source, self.logger_randomizer.sink),
+ Record.connect(self.logger_randomizer.source, self.logger.sink)
+ ]
+
def gen_simulation(self, selfp):
selfp.cd_eth_rx.rst = 1
selfp.cd_eth_tx.rst = 1
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))
+ for i in range(8):
+ streamer_packet = Packet([i for i in range(64)])
+ print(streamer_packet)
+ yield from self.streamer.send(streamer_packet)
if __name__ == "__main__":
- run_simulation(TB(), vcd_name="my.vcd")
+ run_simulation(TB(), ncycles=1000, vcd_name="my.vcd", keep_files=True)
--- /dev/null
+import binascii
+
+from liteeth.common import *
+from liteeth.mac.common import *
+from liteeth.test.common import *
+
+def crc32(l):
+ crc = []
+ crc_bytes = binascii.crc32(bytes(l)).to_bytes(4, byteorder="little")
+ for byte in crc_bytes:
+ crc.append(int(byte))
+ return crc
+
+# MAC model
+class MACPacket(list):
+ def __init__(self, init=[]):
+ self.ongoing = False
+ self.done = False
+ for byte in init:
+ self.append(byte)
+
+class MACRXPacket(MACPacket):
+ def check_remove_preamble(self):
+ if comp(self[0:8], [0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5]):
+ for i in range(8):
+ self.pop(0)
+ return False
+ else:
+ return True
+
+ def check_remove_crc(self):
+ if comp(self[-4:], crc32(self[:-4])):
+ for i in range(4):
+ self.pop()
+ return False
+ else:
+ return True
+
+class MACTXPacket(MACPacket):
+ def insert_crc(self):
+ return self
+
+ def insert_preamble(self):
+ return self
+
+class MAC(Module):
+ def __init__(self, phy, debug=False, random_level=0):
+ self.phy = phy
+ self.debug = debug
+ self.random_level = random_level
+ self.tx_packets = []
+ self.tx_packet = MACTXPacket()
+ self.rx_packet = MACRXPacket()
+
+ self.ip_callback = None
+
+ def set_ip_callback(self, callback):
+ self.ip_callback = callback
+
+ def send(self, datas):
+ tx_packet = MACTXPacket(datas)
+ tx_packet.insert_crc()
+ tx_packet.insert_preamble()
+ self.tx_packets.append(tx_packet)
+
+ def callback(self, datas):
+ rx_packet = MACRXPacket(datas)
+ preamble_error = rx_packet.check_remove_preamble()
+ crc_error = rx_packet.check_remove_crc()
+ if (not preamble_error) and (not crc_error):
+ if self.ip_callback is not None:
+ self.ip_callback(rx_packet)
+
+ def gen_simulation(self, selfp):
+ self.tx_packet.done = True
+ while True:
+ yield from self.phy.receive()
+ self.callback(self.phy.packet)
+ # XXX add full duplex
+ if len(self.tx_packets) != 0:
+ tx_packet = self.tx_packets.pop(0)
+ yield from self.phy.send(tx_packet)
self.dw = dw
self.debug = debug
- self.phy_source = PHYSource(dw)
- self.phy_sink = PHYSink(dw)
+ self.submodules.phy_source = PHYSource(dw)
+ self.submodules.phy_sink = PHYSink(dw)
self.source = self.phy_source.source
self.sink = self.phy_sink.sink
- def send(self, datas, blocking=True):
+ self.mac_callback = None
+
+ def set_mac_callback(self, callback):
+ self.mac_callback = callback
+
+ def send(self, datas):
packet = Packet(datas)
yield from self.phy_source.send(packet, blocking)