From: Florent Kermarrec Date: Thu, 29 Jan 2015 00:03:47 +0000 (+0100) Subject: create LiteEthIPStack skeleton X-Git-Tag: 24jan2021_ls180~2604^2~112 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=51c9f84ef024ac5b9ea8ba001d034d78b6cb3a7b;p=litex.git create LiteEthIPStack skeleton --- diff --git a/liteeth/__init__.py b/liteeth/__init__.py index e69de29b..a67e5b38 100644 --- a/liteeth/__init__.py +++ b/liteeth/__init__.py @@ -0,0 +1,29 @@ +from liteeth.common import * +from liteeth.generic.arbiter import Arbiter +from liteeth.generic.dispatcher import Dispatcher +from liteeth.mac import LiteEthMAC + +class LiteEthIPStack(Module, AutoCSR): + def __init__(self, phy): + self.phy = phy + self.submodules.mac = mac = LiteEthMAC(phy, 8, interface="mac", with_hw_preamble_crc=True) + self.submodules.arp = arp = LiteEthARP() + self.submodules.ip = ip = LiteEthMACIP() + + # MAC dispatch + self.submodules.unknown_sink = unknown_sink = Sink(eth_mac_description(8)) + self.comb += unknown_sink.ack.eq(1) + self.submodules.mac_dispatcher = mac_dispatcher = Dispatcher(mac.source, [arp.sink, ip.sink, unknown_sink]) + self.comb += [ + If(mac.source.eth_type == ethernet_type_arp, + mac_dispatcher.sel.eq(0) + ).Elif(mac.source.eth_type == ethernet_type_ip, + mac_dispatcher.sel.eq(1) + ).Else( + mac_dispatcher.sel.eq(2) # connect to unknown sink that always acknowledge data + ) + ] + # MAC arbitrate + self.submodules.mac_arbiter = mac_arbiter = Arbiter([arp.source, ip.source], mac.sink) + + diff --git a/liteeth/common.py b/liteeth/common.py index 2fc2660f..d66e7c19 100644 --- a/liteeth/common.py +++ b/liteeth/common.py @@ -29,6 +29,9 @@ mac_header = { "ethernet_type": HField(12, 0, 16) } +ethernet_type_ip = 0x800 +ethernet_type_arp = 0x806 + arp_header_len = 28 arp_header = { "hardware_type": HField( 0, 0, 16), diff --git a/liteeth/generic/arbiter.py b/liteeth/generic/arbiter.py new file mode 100644 index 00000000..f61182b5 --- /dev/null +++ b/liteeth/generic/arbiter.py @@ -0,0 +1,27 @@ +from migen.fhdl.std import * +from migen.genlib.roundrobin import * +from migen.genlib.record import * + +class Arbiter(Module): + def __init__(self, sources, sink): + if len(sources) == 0: + pass + elif len(sources) == 1: + self.grant = Signal() + self.comb += Record.connect(sources[0], sink) + else: + self.rr = RoundRobin(len(sources)) + self.grant = self.rr.grant + cases = {} + for i, source in enumerate(sources): + sop = Signal() + eop = Signal() + ongoing = Signal() + self.comb += [ + sop.eq(source.stb & source.sop), + eop.eq(source.stb & source.eop & source.ack), + ] + self.sync += ongoing.eq((sop | ongoing) & ~eop) + self.comb += self.rr.request[i].eq((sop | ongoing) & ~eop) + cases[i] = [Record.connect(source, sink)] + self.comb += Case(self.grant, cases) diff --git a/liteeth/generic/dispatcher.py b/liteeth/generic/dispatcher.py new file mode 100644 index 00000000..713dd617 --- /dev/null +++ b/liteeth/generic/dispatcher.py @@ -0,0 +1,39 @@ +from migen.fhdl.std import * +from migen.genlib.record import * + +class Dispatcher(Module): + def __init__(self, source, sinks, one_hot=False): + if len(sinks) == 0: + self.sel = Signal() + elif len(sinks) == 1: + self.comb += Record.connect(source, sinks[0]) + self.sel = Signal() + else: + if one_hot: + self.sel = Signal(len(sinks)) + else: + self.sel = Signal(max=len(sinks)) + ### + sop = Signal() + self.comb += sop.eq(source.stb & source.sop) + sel = Signal(max=len(sinks)) + sel_r = Signal(max=len(sinks)) + self.sync += \ + If(sop, + sel_r.eq(self.sel) + ) + self.comb += \ + If(sop, + sel.eq(self.sel) + ).Else( + sel.eq(sel_r) + ) + cases = {} + for i, sink in enumerate(sinks): + if one_hot: + idx = 2**i + else: + idx = i + cases[idx] = [Record.connect(source, sink)] + cases["default"] = [source.ack.eq(1)] + self.comb += Case(sel, cases) diff --git a/liteeth/mac/__init__.py b/liteeth/mac/__init__.py index a983c301..510faa77 100644 --- a/liteeth/mac/__init__.py +++ b/liteeth/mac/__init__.py @@ -21,12 +21,19 @@ class LiteEthMACPacketizer(LiteEthDepacketizer): mac_header_length) class LiteEthMAC(Module, AutoCSR): - def __init__(self, phy, dw, interface="core", endianness="be", + def __init__(self, phy, dw, interface="mac", endianness="be", with_hw_preamble_crc=True): self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_hw_preamble_crc) self.csrs = None - if interface == "core": - self.sink, self.source = self.core.sink, self.core.source + if interface == "mac": + packetizer = LiteEthMACPacketizer() + depacketizer = LiteEthMACDepacketizer() + self.submodules += packetizer, depacketizer + self.comb += [ + Record.connect(packetizer.source, self.core.sink), + Record.connect(self.core.source, depacketizer.sink) + ] + self.sink, self.source = packetizer.sink, depacketizer.source elif interface == "wishbone": self.submodules.interface = wishbone.LiteEthMACWishboneInterface(dw, 2, 2) self.comb += [ diff --git a/liteeth/test/mac_core_tb.py b/liteeth/test/mac_core_tb.py index fe1e4285..33680bec 100644 --- a/liteeth/test/mac_core_tb.py +++ b/liteeth/test/mac_core_tb.py @@ -4,7 +4,7 @@ from migen.bus.transactions import * from migen.sim.generic import run_simulation from liteeth.common import * -from liteeth.mac import LiteEthMAC +from liteeth.mac.core import LiteEthMACCore from liteeth.test.common import * from liteeth.test.model import phy, mac @@ -13,7 +13,7 @@ class TB(Module): def __init__(self): self.submodules.hostphy = phy.PHY(8, debug=False) self.submodules.hostmac = mac.MAC(self.hostphy, debug=False, loopback=True) - self.submodules.ethmac = LiteEthMAC(phy=self.hostphy, dw=32, interface="core", with_hw_preamble_crc=True) + self.submodules.core = LiteEthMACCore(phy=self.hostphy, dw=32, with_hw_preamble_crc=True) self.submodules.streamer = PacketStreamer(eth_phy_description(32), last_be=1) self.submodules.streamer_randomizer = AckRandomizer(eth_phy_description(32), level=50) @@ -33,8 +33,8 @@ class TB(Module): 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.streamer_randomizer.source, self.core.sink), + Record.connect(self.core.source, self.logger_randomizer.sink), Record.connect(self.logger_randomizer.source, self.logger.sink) ]