ip: add crossbar
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 5 Feb 2015 23:54:05 +0000 (00:54 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 5 Feb 2015 23:54:05 +0000 (00:54 +0100)
liteeth/core/__init__.py
liteeth/core/ip/__init__.py
liteeth/core/ip/common.py [new file with mode: 0644]
liteeth/core/ip/crossbar.py [new file with mode: 0644]
liteeth/core/udp/__init__.py
liteeth/mac/frontend/crossbar.py
liteeth/test/ip_tb.py

index 545b7a0fe44feee69a98cd4fc5aa15be5503797f..5fd6ac4d654e6c3ce7a5771ca34c09f198e5f1a4 100644 (file)
@@ -9,7 +9,6 @@ class LiteEthIPCore(Module, AutoCSR):
                self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
                self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq)
                self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table)
-               self.sink, self.source = self.ip.sink, self.ip.source
 
 class LiteEthUDPIPCore(LiteEthIPCore):
        def __init__(self, phy, mac_address, ip_address, clk_freq):
index 04be1ce7c7f4c5224b49b5f0d0fffb86881736b3..c22069bec498a5ab9791ffe7cbb0b3cdaa910468 100644 (file)
@@ -1,6 +1,7 @@
 from liteeth.common import *
 from liteeth.generic.depacketizer import LiteEthDepacketizer
 from liteeth.generic.packetizer import LiteEthPacketizer
+from liteeth.core.ip.crossbar import LiteEthIPV4Crossbar
 
 class LiteEthIPV4Depacketizer(LiteEthDepacketizer):
        def __init__(self):
@@ -185,4 +186,8 @@ class LiteEthIP(Module):
                        Record.connect(self.tx.source, mac_port.sink),
                        Record.connect(mac_port.source, self.rx.sink)
                ]
-               self.sink, self.source = self.tx.sink, self.rx.source
+               self.submodules.crossbar = LiteEthIPV4Crossbar()
+               self.comb += [
+                       Record.connect(self.crossbar.master.source, self.tx.sink),
+                       Record.connect(self.rx.source, self.crossbar.master.sink)
+               ]
diff --git a/liteeth/core/ip/common.py b/liteeth/core/ip/common.py
new file mode 100644 (file)
index 0000000..fef6d2d
--- /dev/null
@@ -0,0 +1,27 @@
+from liteeth.common import *
+
+class LiteEthIPV4MasterPort:
+       def __init__(self, dw):
+               self.source = Source(eth_ipv4_user_description(dw))
+               self.sink = Sink(eth_ipv4_user_description(dw))
+
+       def connect(self, slave):
+               return [
+                       Record.connect(self.source, slave.sink),
+                       Record.connect(slave.source, self.sink)
+               ]
+
+class LiteEthIPV4SlavePort:
+       def __init__(self, dw):
+               self.sink = Sink(eth_ipv4_user_description(dw))
+               self.source = Source(eth_ipv4_user_description(dw))
+
+       def connect(self, master):
+               return [
+                       Record.connect(self.sink, master.source),
+                       Record.connect(master.sink, self.source)
+               ]
+
+class LiteEthIPV4UserPort(LiteEthIPV4SlavePort):
+       def __init__(self, dw):
+               LiteEthIPV4SlavePort.__init__(self, dw)
diff --git a/liteeth/core/ip/crossbar.py b/liteeth/core/ip/crossbar.py
new file mode 100644 (file)
index 0000000..f7f676b
--- /dev/null
@@ -0,0 +1,33 @@
+from collections import OrderedDict
+
+from liteeth.common import *
+from liteeth.generic.arbiter import Arbiter
+from liteeth.generic.dispatcher import Dispatcher
+from liteeth.core.ip.common import *
+
+class LiteEthIPV4Crossbar(Module):
+       def __init__(self):
+               self.users = OrderedDict()
+               self.master = LiteEthIPV4MasterPort(8)
+
+       def get_port(self, protocol):
+               port = LiteEthIPV4UserPort(8)
+               if protocol in self.users.keys():
+                       raise ValueError("Protocol {} already used".format(protocol))
+               self.users[protocol] = port
+               return port
+
+       def do_finalize(self):
+               # TX arbitrate
+               sinks = [port.sink for port in self.users.values()]
+               self.submodules.ip_arbiter = Arbiter(sinks, self.master.source)
+
+               # RX dispatch
+               sources = [port.source for port in self.users.values()]
+               self.submodules.ip_dispatcher = Dispatcher(self.master.sink, sources, one_hot=True)
+               cases = {}
+               cases["default"] = self.ip_dispatcher.sel.eq(0)
+               for i, (k, v) in enumerate(self.users.items()):
+                       cases[k] = self.ip_dispatcher.sel.eq(2**i)
+               self.comb += \
+                       Case(self.master.sink.protocol, cases)
index 7a6c503fbb746b9d368b35bc656c893df27be487..59ea5cfd79c97adc2714edb74cbf2850a73707d0 100644 (file)
@@ -116,8 +116,9 @@ class LiteEthUDP(Module):
        def __init__(self, ip, ip_address):
                self.submodules.tx = LiteEthUDPTX(ip_address)
                self.submodules.rx = LiteEthUDPRX(ip_address)
+               ip_port = ip.crossbar.get_port(udp_protocol)
                self.comb += [
-                       Record.connect(self.tx.source, ip.sink),
-                       Record.connect(ip.source, self.rx.sink)
+                       Record.connect(self.tx.source, ip_port.sink),
+                       Record.connect(ip_port.source, self.rx.sink)
                ]
                self.sink, self.source = self.tx.sink, self.rx.source
index 696e353e8ca1bfc91995367f70c8a727aeb69f96..826db90bc9922a666172ce452e30e43cf89d083d 100644 (file)
@@ -13,7 +13,7 @@ class LiteEthMACCrossbar(Module):
        def get_port(self, ethernet_type):
                port = LiteEthMACUserPort(8)
                if ethernet_type in self.users.keys():
-                       raise ValueError("Ethernet type {} already used")
+                       raise ValueError("Ethernet type {} already used".format(ethernet_type))
                self.users[ethernet_type] = port
                return port
 
index eb68916fb6928a9f05b3e800cffdba04a741b7de..96b6d3418c27c3cef9f862754d27d285f1a2446c 100644 (file)
@@ -20,6 +20,7 @@ class TB(Module):
                self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=True)
 
                self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000)
+               self.ip_port = self.ip.ip.crossbar.get_port(udp_protocol)
 
                # use sys_clk for each clock_domain
                self.clock_domains.cd_eth_rx = ClockDomain()
@@ -42,15 +43,15 @@ class TB(Module):
                        yield
 
                while True:
-                       selfp.ip.sink.stb = 1
-                       selfp.ip.sink.sop = 1
-                       selfp.ip.sink.eop = 1
-                       selfp.ip.sink.ip_address = 0x12345678
-                       selfp.ip.sink.protocol = udp_protocol
-
-                       selfp.ip.source.ack = 1
-                       if selfp.ip.source.stb == 1 and selfp.ip.source.sop == 1:
-                               print("IP Packet / from ip_address %08x" %selfp.ip.sink.ip_address)
+                       selfp.ip_port.sink.stb = 1
+                       selfp.ip_port.sink.sop = 1
+                       selfp.ip_port.sink.eop = 1
+                       selfp.ip_port.sink.ip_address = 0x12345678
+                       selfp.ip_port.sink.protocol = udp_protocol
+
+                       selfp.ip_port.source.ack = 1
+                       if selfp.ip_port.source.stb == 1 and selfp.ip_port.source.sop == 1:
+                               print("IP Packet / from ip_address %08x" %selfp.ip_port.sink.ip_address)
 
                        yield