continue code refactoring

This commit is contained in:
Florent Kermarrec 2015-01-28 09:14:01 +01:00
parent 4cd73fc9da
commit 8a2b65f21d
21 changed files with 239 additions and 439 deletions

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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"})

View File

@ -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)

View File

@ -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))

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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

13
liteeth/test/Makefile Normal file
View File

@ -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

View File

@ -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")