reorganize core (to add crossbar to ip)
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 5 Feb 2015 23:38:56 +0000 (00:38 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 5 Feb 2015 23:38:56 +0000 (00:38 +0100)
liteeth/core/arp.py [deleted file]
liteeth/core/arp/__init__.py [new file with mode: 0644]
liteeth/core/ip.py [deleted file]
liteeth/core/ip/__init__.py [new file with mode: 0644]
liteeth/core/udp.py [deleted file]
liteeth/core/udp/__init__.py [new file with mode: 0644]

diff --git a/liteeth/core/arp.py b/liteeth/core/arp.py
deleted file mode 100644 (file)
index d7fd26d..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-from liteeth.common import *
-from liteeth.generic.depacketizer import LiteEthDepacketizer
-from liteeth.generic.packetizer import LiteEthPacketizer
-
-_arp_table_layout = [
-               ("reply", 1),
-               ("request", 1),
-               ("ip_address", 32),
-               ("mac_address", 48)
-       ]
-
-class LiteEthARPDepacketizer(LiteEthDepacketizer):
-       def __init__(self):
-               LiteEthDepacketizer.__init__(self,
-                       eth_mac_description(8),
-                       eth_arp_description(8),
-                       arp_header,
-                       arp_header_len)
-
-class LiteEthARPPacketizer(LiteEthPacketizer):
-       def __init__(self):
-               LiteEthPacketizer.__init__(self,
-                       eth_arp_description(8),
-                       eth_mac_description(8),
-                       arp_header,
-                       arp_header_len)
-
-class LiteEthARPTX(Module):
-       def __init__(self, mac_address, ip_address):
-               self.sink = sink = Sink(_arp_table_layout)
-               self.source = Source(eth_mac_description(8))
-               ###
-               packetizer = LiteEthARPPacketizer()
-               self.submodules += packetizer
-               source = packetizer.sink
-
-               counter = Counter(max=max(arp_header_len, eth_min_len))
-               self.submodules += counter
-
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       counter.reset.eq(1),
-                       If(sink.stb,
-                               sink.ack.eq(0),
-                               NextState("SEND")
-                       )
-               )
-               self.comb += [
-                       source.sop.eq(counter.value == 0),
-                       source.eop.eq(counter.value == max(arp_header_len, eth_min_len)-1),
-                       source.hwtype.eq(arp_hwtype_ethernet),
-                       source.proto.eq(arp_proto_ip),
-                       source.hwsize.eq(6),
-                       source.protosize.eq(4),
-                       source.sender_mac.eq(mac_address),
-                       source.sender_ip.eq(ip_address),
-                       If(sink.reply,
-                               source.opcode.eq(arp_opcode_reply),
-                               source.target_mac.eq(sink.mac_address),
-                               source.target_ip.eq(sink.ip_address)
-                       ).Elif(sink.request,
-                               source.opcode.eq(arp_opcode_request),
-                               source.target_mac.eq(0xffffffffffff),
-                               source.target_ip.eq(sink.ip_address)
-                       )
-               ]
-               fsm.act("SEND",
-                       source.stb.eq(1),
-                       Record.connect(packetizer.source, self.source),
-                       self.source.target_mac.eq(source.target_mac),
-                       self.source.sender_mac.eq(mac_address),
-                       self.source.ethernet_type.eq(ethernet_type_arp),
-                       If(self.source.stb & self.source.ack,
-                               sink.ack.eq(source.eop),
-                               counter.ce.eq(1),
-                               If(self.source.eop,
-                                       NextState("IDLE")
-                               )
-                       )
-               )
-
-class LiteEthARPRX(Module):
-       def __init__(self, mac_address, ip_address):
-               self.sink = Sink(eth_mac_description(8))
-               self.source = source = Source(_arp_table_layout)
-               ###
-               depacketizer = LiteEthARPDepacketizer()
-               self.submodules += depacketizer
-               self.comb += Record.connect(self.sink, depacketizer.sink)
-               sink = depacketizer.source
-
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("CHECK")
-                       )
-               )
-               valid = Signal()
-               self.comb += valid.eq(
-                       sink.stb &
-                       (sink.hwtype == arp_hwtype_ethernet) &
-                       (sink.proto == arp_proto_ip) &
-                       (sink.hwsize == 6) &
-                       (sink.protosize == 4) &
-                       (sink.target_ip == ip_address)
-               )
-               reply = Signal()
-               request = Signal()
-               self.comb += Case(sink.opcode, {
-                       arp_opcode_request      :       [request.eq(1)],
-                       arp_opcode_reply        :       [reply.eq(1)],
-                       "default"                       :       []
-                       })
-               self.comb += [
-                       source.ip_address.eq(sink.sender_ip),
-                       source.mac_address.eq(sink.sender_mac)
-               ]
-               fsm.act("CHECK",
-                       If(valid,
-                               source.stb.eq(1),
-                               source.reply.eq(reply),
-                               source.request.eq(request)
-                       ),
-                       NextState("TERMINATE")
-               ),
-               fsm.act("TERMINATE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.eop,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthARPTable(Module):
-       def __init__(self, clk_freq, max_requests=8):
-               self.sink = sink = Sink(_arp_table_layout)                      # from arp_rx
-               self.source = source = Source(_arp_table_layout)        # to arp_tx
-
-               # Request/Response interface
-               self.request = request = Sink(arp_table_request_layout)
-               self.response = response = Source(arp_table_response_layout)
-               ###
-               request_timeout = Timeout(clk_freq//10)
-               request_counter = Counter(max=max_requests)
-               request_pending = FlipFlop()
-               request_ip_address = FlipFlop(32)
-               self.submodules += request_timeout, request_counter, request_pending, request_ip_address
-               self.comb += [
-                       request_timeout.ce.eq(request_pending.q),
-                       request_pending.d.eq(1),
-                       request_ip_address.d.eq(request.ip_address)
-               ]
-
-               # Note: Only store 1 IP/MAC couple, can be improved with a real
-               # table in the future to improve performance when packet are
-               # targeting multiple destinations.
-               update = Signal()
-               cached_valid = Signal()
-               cached_ip_address = Signal(32)
-               cached_mac_address = Signal(48)
-               cached_timeout = Timeout(clk_freq*10)
-               self.submodules += cached_timeout
-
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-               fsm.act("IDLE",
-                       # Note: for simplicicy, if APR table is busy response from arp_rx
-                       # is lost. This is compensated by the protocol (retry)
-                       If(sink.stb & sink.request,
-                               NextState("SEND_REPLY")
-                       ).Elif(sink.stb & sink.reply & request_pending.q,
-                               NextState("UPDATE_TABLE"),
-                       ).Elif(request_counter.value == max_requests-1,
-                               NextState("PRESENT_RESPONSE")
-                       ).Elif(request.stb | (request_pending.q & request_timeout.reached),
-                               NextState("CHECK_TABLE")
-                       )
-               )
-               fsm.act("SEND_REPLY",
-                       source.stb.eq(1),
-                       source.reply.eq(1),
-                       source.ip_address.eq(sink.ip_address),
-                       If(source.ack,
-                               NextState("IDLE")
-                       )
-               )
-               fsm.act("UPDATE_TABLE",
-                       request_pending.reset.eq(1),
-                       update.eq(1),
-                       NextState("CHECK_TABLE")
-               )
-               self.sync += [
-                       If(update,
-                               cached_valid.eq(1),
-                               cached_ip_address.eq(sink.ip_address),
-                               cached_mac_address.eq(sink.mac_address),
-                               cached_timeout.reset.eq(1)
-                       ).Else(
-                               cached_timeout.ce.eq(1),
-                               If(cached_timeout.reached,
-                                       cached_valid.eq(0)
-                               )
-                       )
-               ]
-               found = Signal()
-               fsm.act("CHECK_TABLE",
-                       If(cached_valid,
-                               If(request_ip_address.q == cached_ip_address,
-                                       request_ip_address.reset.eq(1),
-                                       NextState("PRESENT_RESPONSE"),
-                               ).Elif(request.ip_address == cached_ip_address,
-                                       request.ack.eq(request.stb),
-                                       NextState("PRESENT_RESPONSE"),
-                               ).Else(
-                                       request_ip_address.ce.eq(request.stb),
-                                       NextState("SEND_REQUEST")
-                               )
-                       ).Else(
-                               request_ip_address.ce.eq(request.stb),
-                               NextState("SEND_REQUEST")
-                       )
-               )
-               fsm.act("SEND_REQUEST",
-                       source.stb.eq(1),
-                       source.request.eq(1),
-                       source.ip_address.eq(request_ip_address.q),
-                       If(source.ack,
-                               request_timeout.reset.eq(1),
-                               request_counter.reset.eq(request.stb),
-                               request_counter.ce.eq(1),
-                               request_pending.ce.eq(1),
-                               request.ack.eq(1),
-                               NextState("IDLE")
-                       )
-               )
-               self.comb += [
-                       If(request_counter == max_requests-1,
-                               response.failed.eq(1),
-                               request_counter.reset.eq(1),
-                               request_pending.reset.eq(1)
-                       ),
-                       response.mac_address.eq(cached_mac_address)
-               ]
-               fsm.act("PRESENT_RESPONSE",
-                       response.stb.eq(1),
-                       If(response.ack,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthARP(Module):
-       def __init__(self, mac, mac_address, ip_address, clk_freq):
-               self.submodules.tx = LiteEthARPTX(mac_address, ip_address)
-               self.submodules.rx = LiteEthARPRX(mac_address, ip_address)
-               self.submodules.table = LiteEthARPTable(clk_freq)
-               self.comb += [
-                       Record.connect(self.rx.source, self.table.sink),
-                       Record.connect(self.table.source, self.tx.sink)
-               ]
-               mac_port = mac.crossbar.get_port(ethernet_type_arp)
-               self.comb += [
-                       Record.connect(self.tx.source, mac_port.sink),
-                       Record.connect(mac_port.source, self.rx.sink)
-               ]
diff --git a/liteeth/core/arp/__init__.py b/liteeth/core/arp/__init__.py
new file mode 100644 (file)
index 0000000..d7fd26d
--- /dev/null
@@ -0,0 +1,265 @@
+from liteeth.common import *
+from liteeth.generic.depacketizer import LiteEthDepacketizer
+from liteeth.generic.packetizer import LiteEthPacketizer
+
+_arp_table_layout = [
+               ("reply", 1),
+               ("request", 1),
+               ("ip_address", 32),
+               ("mac_address", 48)
+       ]
+
+class LiteEthARPDepacketizer(LiteEthDepacketizer):
+       def __init__(self):
+               LiteEthDepacketizer.__init__(self,
+                       eth_mac_description(8),
+                       eth_arp_description(8),
+                       arp_header,
+                       arp_header_len)
+
+class LiteEthARPPacketizer(LiteEthPacketizer):
+       def __init__(self):
+               LiteEthPacketizer.__init__(self,
+                       eth_arp_description(8),
+                       eth_mac_description(8),
+                       arp_header,
+                       arp_header_len)
+
+class LiteEthARPTX(Module):
+       def __init__(self, mac_address, ip_address):
+               self.sink = sink = Sink(_arp_table_layout)
+               self.source = Source(eth_mac_description(8))
+               ###
+               packetizer = LiteEthARPPacketizer()
+               self.submodules += packetizer
+               source = packetizer.sink
+
+               counter = Counter(max=max(arp_header_len, eth_min_len))
+               self.submodules += counter
+
+               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       counter.reset.eq(1),
+                       If(sink.stb,
+                               sink.ack.eq(0),
+                               NextState("SEND")
+                       )
+               )
+               self.comb += [
+                       source.sop.eq(counter.value == 0),
+                       source.eop.eq(counter.value == max(arp_header_len, eth_min_len)-1),
+                       source.hwtype.eq(arp_hwtype_ethernet),
+                       source.proto.eq(arp_proto_ip),
+                       source.hwsize.eq(6),
+                       source.protosize.eq(4),
+                       source.sender_mac.eq(mac_address),
+                       source.sender_ip.eq(ip_address),
+                       If(sink.reply,
+                               source.opcode.eq(arp_opcode_reply),
+                               source.target_mac.eq(sink.mac_address),
+                               source.target_ip.eq(sink.ip_address)
+                       ).Elif(sink.request,
+                               source.opcode.eq(arp_opcode_request),
+                               source.target_mac.eq(0xffffffffffff),
+                               source.target_ip.eq(sink.ip_address)
+                       )
+               ]
+               fsm.act("SEND",
+                       source.stb.eq(1),
+                       Record.connect(packetizer.source, self.source),
+                       self.source.target_mac.eq(source.target_mac),
+                       self.source.sender_mac.eq(mac_address),
+                       self.source.ethernet_type.eq(ethernet_type_arp),
+                       If(self.source.stb & self.source.ack,
+                               sink.ack.eq(source.eop),
+                               counter.ce.eq(1),
+                               If(self.source.eop,
+                                       NextState("IDLE")
+                               )
+                       )
+               )
+
+class LiteEthARPRX(Module):
+       def __init__(self, mac_address, ip_address):
+               self.sink = Sink(eth_mac_description(8))
+               self.source = source = Source(_arp_table_layout)
+               ###
+               depacketizer = LiteEthARPDepacketizer()
+               self.submodules += depacketizer
+               self.comb += Record.connect(self.sink, depacketizer.sink)
+               sink = depacketizer.source
+
+               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("CHECK")
+                       )
+               )
+               valid = Signal()
+               self.comb += valid.eq(
+                       sink.stb &
+                       (sink.hwtype == arp_hwtype_ethernet) &
+                       (sink.proto == arp_proto_ip) &
+                       (sink.hwsize == 6) &
+                       (sink.protosize == 4) &
+                       (sink.target_ip == ip_address)
+               )
+               reply = Signal()
+               request = Signal()
+               self.comb += Case(sink.opcode, {
+                       arp_opcode_request      :       [request.eq(1)],
+                       arp_opcode_reply        :       [reply.eq(1)],
+                       "default"                       :       []
+                       })
+               self.comb += [
+                       source.ip_address.eq(sink.sender_ip),
+                       source.mac_address.eq(sink.sender_mac)
+               ]
+               fsm.act("CHECK",
+                       If(valid,
+                               source.stb.eq(1),
+                               source.reply.eq(reply),
+                               source.request.eq(request)
+                       ),
+                       NextState("TERMINATE")
+               ),
+               fsm.act("TERMINATE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.eop,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthARPTable(Module):
+       def __init__(self, clk_freq, max_requests=8):
+               self.sink = sink = Sink(_arp_table_layout)                      # from arp_rx
+               self.source = source = Source(_arp_table_layout)        # to arp_tx
+
+               # Request/Response interface
+               self.request = request = Sink(arp_table_request_layout)
+               self.response = response = Source(arp_table_response_layout)
+               ###
+               request_timeout = Timeout(clk_freq//10)
+               request_counter = Counter(max=max_requests)
+               request_pending = FlipFlop()
+               request_ip_address = FlipFlop(32)
+               self.submodules += request_timeout, request_counter, request_pending, request_ip_address
+               self.comb += [
+                       request_timeout.ce.eq(request_pending.q),
+                       request_pending.d.eq(1),
+                       request_ip_address.d.eq(request.ip_address)
+               ]
+
+               # Note: Only store 1 IP/MAC couple, can be improved with a real
+               # table in the future to improve performance when packet are
+               # targeting multiple destinations.
+               update = Signal()
+               cached_valid = Signal()
+               cached_ip_address = Signal(32)
+               cached_mac_address = Signal(48)
+               cached_timeout = Timeout(clk_freq*10)
+               self.submodules += cached_timeout
+
+               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       # Note: for simplicicy, if APR table is busy response from arp_rx
+                       # is lost. This is compensated by the protocol (retry)
+                       If(sink.stb & sink.request,
+                               NextState("SEND_REPLY")
+                       ).Elif(sink.stb & sink.reply & request_pending.q,
+                               NextState("UPDATE_TABLE"),
+                       ).Elif(request_counter.value == max_requests-1,
+                               NextState("PRESENT_RESPONSE")
+                       ).Elif(request.stb | (request_pending.q & request_timeout.reached),
+                               NextState("CHECK_TABLE")
+                       )
+               )
+               fsm.act("SEND_REPLY",
+                       source.stb.eq(1),
+                       source.reply.eq(1),
+                       source.ip_address.eq(sink.ip_address),
+                       If(source.ack,
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("UPDATE_TABLE",
+                       request_pending.reset.eq(1),
+                       update.eq(1),
+                       NextState("CHECK_TABLE")
+               )
+               self.sync += [
+                       If(update,
+                               cached_valid.eq(1),
+                               cached_ip_address.eq(sink.ip_address),
+                               cached_mac_address.eq(sink.mac_address),
+                               cached_timeout.reset.eq(1)
+                       ).Else(
+                               cached_timeout.ce.eq(1),
+                               If(cached_timeout.reached,
+                                       cached_valid.eq(0)
+                               )
+                       )
+               ]
+               found = Signal()
+               fsm.act("CHECK_TABLE",
+                       If(cached_valid,
+                               If(request_ip_address.q == cached_ip_address,
+                                       request_ip_address.reset.eq(1),
+                                       NextState("PRESENT_RESPONSE"),
+                               ).Elif(request.ip_address == cached_ip_address,
+                                       request.ack.eq(request.stb),
+                                       NextState("PRESENT_RESPONSE"),
+                               ).Else(
+                                       request_ip_address.ce.eq(request.stb),
+                                       NextState("SEND_REQUEST")
+                               )
+                       ).Else(
+                               request_ip_address.ce.eq(request.stb),
+                               NextState("SEND_REQUEST")
+                       )
+               )
+               fsm.act("SEND_REQUEST",
+                       source.stb.eq(1),
+                       source.request.eq(1),
+                       source.ip_address.eq(request_ip_address.q),
+                       If(source.ack,
+                               request_timeout.reset.eq(1),
+                               request_counter.reset.eq(request.stb),
+                               request_counter.ce.eq(1),
+                               request_pending.ce.eq(1),
+                               request.ack.eq(1),
+                               NextState("IDLE")
+                       )
+               )
+               self.comb += [
+                       If(request_counter == max_requests-1,
+                               response.failed.eq(1),
+                               request_counter.reset.eq(1),
+                               request_pending.reset.eq(1)
+                       ),
+                       response.mac_address.eq(cached_mac_address)
+               ]
+               fsm.act("PRESENT_RESPONSE",
+                       response.stb.eq(1),
+                       If(response.ack,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthARP(Module):
+       def __init__(self, mac, mac_address, ip_address, clk_freq):
+               self.submodules.tx = LiteEthARPTX(mac_address, ip_address)
+               self.submodules.rx = LiteEthARPRX(mac_address, ip_address)
+               self.submodules.table = LiteEthARPTable(clk_freq)
+               self.comb += [
+                       Record.connect(self.rx.source, self.table.sink),
+                       Record.connect(self.table.source, self.tx.sink)
+               ]
+               mac_port = mac.crossbar.get_port(ethernet_type_arp)
+               self.comb += [
+                       Record.connect(self.tx.source, mac_port.sink),
+                       Record.connect(mac_port.source, self.rx.sink)
+               ]
diff --git a/liteeth/core/ip.py b/liteeth/core/ip.py
deleted file mode 100644 (file)
index 04be1ce..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-from liteeth.common import *
-from liteeth.generic.depacketizer import LiteEthDepacketizer
-from liteeth.generic.packetizer import LiteEthPacketizer
-
-class LiteEthIPV4Depacketizer(LiteEthDepacketizer):
-       def __init__(self):
-               LiteEthDepacketizer.__init__(self,
-                       eth_mac_description(8),
-                       eth_ipv4_description(8),
-                       ipv4_header,
-                       ipv4_header_len)
-
-class LiteEthIPV4Packetizer(LiteEthPacketizer):
-       def __init__(self):
-               LiteEthPacketizer.__init__(self,
-                       eth_ipv4_description(8),
-                       eth_mac_description(8),
-                       ipv4_header,
-                       ipv4_header_len)
-
-class LiteEthIPV4Checksum(Module):
-       def __init__(self, skip_header=False):
-               self.header = Signal(ipv4_header_len*8)
-               self.value = Signal(16)
-
-               s = Signal(17)
-               r = Signal(17)
-               for i in range(ipv4_header_len//2):
-                       if skip_header and i == 5:
-                               pass
-                       else:
-                               s_next = Signal(17)
-                               r_next = Signal(17)
-                               self.comb += [
-                                       s_next.eq(r + self.header[i*16:(i+1)*16]),
-                                       r_next.eq(Cat(s_next[:16]+s_next[16], Signal()))
-                               ]
-                               s, r = s_next, r_next
-               self.comb += self.value.eq(~Cat(r[8:16], r[:8]))
-
-class LiteEthIPTX(Module):
-       def __init__(self, mac_address, ip_address, arp_table):
-               self.sink = Sink(eth_ipv4_user_description(8))
-               self.source = Source(eth_mac_description(8))
-               self.target_unreachable = Signal()
-               ###
-               packetizer = LiteEthIPV4Packetizer()
-               self.submodules += packetizer
-               self.comb += [
-                       packetizer.sink.stb.eq(self.sink.stb),
-                       packetizer.sink.sop.eq(self.sink.sop),
-                       packetizer.sink.eop.eq(self.sink.eop),
-                       self.sink.ack.eq(packetizer.sink.ack),
-                       packetizer.sink.target_ip.eq(self.sink.ip_address),
-                       packetizer.sink.protocol.eq(self.sink.protocol),
-                       packetizer.sink.total_length.eq(self.sink.length + (0x5*4)),
-                       packetizer.sink.version.eq(0x4),        # ipv4
-                       packetizer.sink.ihl.eq(0x5),            # 20 bytes
-                       packetizer.sink.identification.eq(0),
-                       packetizer.sink.ttl.eq(0x80),
-                       packetizer.sink.sender_ip.eq(ip_address),
-                       packetizer.sink.data.eq(self.sink.data)
-               ]
-               sink = packetizer.source
-
-               checksum = LiteEthIPV4Checksum(skip_header=True)
-               self.submodules += checksum
-               self.comb += [
-                       checksum.header.eq(packetizer.header),
-                       packetizer.sink.checksum.eq(checksum.value)
-               ]
-
-               target_mac = Signal(48)
-
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("SEND_MAC_ADDRESS_REQUEST")
-                       )
-               )
-               self.comb += arp_table.request.ip_address.eq(self.sink.ip_address)
-               fsm.act("SEND_MAC_ADDRESS_REQUEST",
-                       arp_table.request.stb.eq(1),
-                       If(arp_table.request.stb & arp_table.request.ack,
-                               NextState("WAIT_MAC_ADDRESS_RESPONSE")
-                       )
-               )
-               fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
-                       If(arp_table.response.stb,
-                               arp_table.response.ack.eq(1),
-                               If(arp_table.response.failed,
-                                       self.target_unreachable.eq(1),
-                                       NextState("DROP"),
-                               ).Else(
-                                       NextState("SEND")
-                               )
-                       )
-               )
-               self.sync += If(arp_table.response.stb, target_mac.eq(arp_table.response.mac_address))
-               fsm.act("SEND",
-                       Record.connect(packetizer.source, self.source),
-                       self.source.ethernet_type.eq(ethernet_type_ip),
-                       self.source.target_mac.eq(target_mac),
-                       self.source.sender_mac.eq(mac_address),
-                       If(self.source.stb & self.source.eop & self.source.ack,
-                               NextState("IDLE")
-                       )
-               )
-               fsm.act("DROP",
-                       packetizer.source.ack.eq(1),
-                       If(packetizer.source.stb & packetizer.source.eop & packetizer.source.ack,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthIPRX(Module):
-       def __init__(self, mac_address, ip_address):
-               self.sink = Sink(eth_mac_description(8))
-               self.source = source = Source(eth_ipv4_user_description(8))
-               ###
-               depacketizer = LiteEthIPV4Depacketizer()
-               self.submodules += depacketizer
-               self.comb += Record.connect(self.sink, depacketizer.sink)
-               sink = depacketizer.source
-
-               checksum = LiteEthIPV4Checksum(skip_header=False)
-               self.submodules += checksum
-               self.comb += checksum.header.eq(depacketizer.header)
-
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("CHECK")
-                       )
-               )
-               valid = Signal()
-               self.comb += valid.eq(
-                       sink.stb &
-                       (sink.target_ip == ip_address) &
-                       (sink.version == 0x4) &
-                       (sink.ihl == 0x5) &
-                       (checksum.value == 0)
-               )
-
-               fsm.act("CHECK",
-                       If(valid,
-                               NextState("PRESENT")
-                       ).Else(
-                               NextState("DROP")
-                       )
-               )
-               self.comb += [
-                       source.sop.eq(sink.sop),
-                       source.eop.eq(sink.eop),
-                       source.length.eq(sink.total_length - (sink.ihl*4)),
-                       source.protocol.eq(sink.protocol),
-                       source.ip_address.eq(sink.target_ip),
-                       source.data.eq(sink.data),
-                       source.error.eq(sink.error)
-               ]
-               fsm.act("PRESENT",
-                       source.stb.eq(sink.stb),
-                       sink.ack.eq(source.ack),
-                       If(source.stb & source.eop & source.ack,
-                               NextState("IDLE")
-                       )
-               )
-               fsm.act("DROP",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.eop & sink.ack,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthIP(Module):
-       def __init__(self, mac, mac_address, ip_address, arp_table):
-               self.submodules.tx = LiteEthIPTX(mac_address, ip_address, arp_table)
-               self.submodules.rx = LiteEthIPRX(mac_address, ip_address)
-               mac_port = mac.crossbar.get_port(ethernet_type_ip)
-               self.comb += [
-                       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
diff --git a/liteeth/core/ip/__init__.py b/liteeth/core/ip/__init__.py
new file mode 100644 (file)
index 0000000..04be1ce
--- /dev/null
@@ -0,0 +1,188 @@
+from liteeth.common import *
+from liteeth.generic.depacketizer import LiteEthDepacketizer
+from liteeth.generic.packetizer import LiteEthPacketizer
+
+class LiteEthIPV4Depacketizer(LiteEthDepacketizer):
+       def __init__(self):
+               LiteEthDepacketizer.__init__(self,
+                       eth_mac_description(8),
+                       eth_ipv4_description(8),
+                       ipv4_header,
+                       ipv4_header_len)
+
+class LiteEthIPV4Packetizer(LiteEthPacketizer):
+       def __init__(self):
+               LiteEthPacketizer.__init__(self,
+                       eth_ipv4_description(8),
+                       eth_mac_description(8),
+                       ipv4_header,
+                       ipv4_header_len)
+
+class LiteEthIPV4Checksum(Module):
+       def __init__(self, skip_header=False):
+               self.header = Signal(ipv4_header_len*8)
+               self.value = Signal(16)
+
+               s = Signal(17)
+               r = Signal(17)
+               for i in range(ipv4_header_len//2):
+                       if skip_header and i == 5:
+                               pass
+                       else:
+                               s_next = Signal(17)
+                               r_next = Signal(17)
+                               self.comb += [
+                                       s_next.eq(r + self.header[i*16:(i+1)*16]),
+                                       r_next.eq(Cat(s_next[:16]+s_next[16], Signal()))
+                               ]
+                               s, r = s_next, r_next
+               self.comb += self.value.eq(~Cat(r[8:16], r[:8]))
+
+class LiteEthIPTX(Module):
+       def __init__(self, mac_address, ip_address, arp_table):
+               self.sink = Sink(eth_ipv4_user_description(8))
+               self.source = Source(eth_mac_description(8))
+               self.target_unreachable = Signal()
+               ###
+               packetizer = LiteEthIPV4Packetizer()
+               self.submodules += packetizer
+               self.comb += [
+                       packetizer.sink.stb.eq(self.sink.stb),
+                       packetizer.sink.sop.eq(self.sink.sop),
+                       packetizer.sink.eop.eq(self.sink.eop),
+                       self.sink.ack.eq(packetizer.sink.ack),
+                       packetizer.sink.target_ip.eq(self.sink.ip_address),
+                       packetizer.sink.protocol.eq(self.sink.protocol),
+                       packetizer.sink.total_length.eq(self.sink.length + (0x5*4)),
+                       packetizer.sink.version.eq(0x4),        # ipv4
+                       packetizer.sink.ihl.eq(0x5),            # 20 bytes
+                       packetizer.sink.identification.eq(0),
+                       packetizer.sink.ttl.eq(0x80),
+                       packetizer.sink.sender_ip.eq(ip_address),
+                       packetizer.sink.data.eq(self.sink.data)
+               ]
+               sink = packetizer.source
+
+               checksum = LiteEthIPV4Checksum(skip_header=True)
+               self.submodules += checksum
+               self.comb += [
+                       checksum.header.eq(packetizer.header),
+                       packetizer.sink.checksum.eq(checksum.value)
+               ]
+
+               target_mac = Signal(48)
+
+               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("SEND_MAC_ADDRESS_REQUEST")
+                       )
+               )
+               self.comb += arp_table.request.ip_address.eq(self.sink.ip_address)
+               fsm.act("SEND_MAC_ADDRESS_REQUEST",
+                       arp_table.request.stb.eq(1),
+                       If(arp_table.request.stb & arp_table.request.ack,
+                               NextState("WAIT_MAC_ADDRESS_RESPONSE")
+                       )
+               )
+               fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
+                       If(arp_table.response.stb,
+                               arp_table.response.ack.eq(1),
+                               If(arp_table.response.failed,
+                                       self.target_unreachable.eq(1),
+                                       NextState("DROP"),
+                               ).Else(
+                                       NextState("SEND")
+                               )
+                       )
+               )
+               self.sync += If(arp_table.response.stb, target_mac.eq(arp_table.response.mac_address))
+               fsm.act("SEND",
+                       Record.connect(packetizer.source, self.source),
+                       self.source.ethernet_type.eq(ethernet_type_ip),
+                       self.source.target_mac.eq(target_mac),
+                       self.source.sender_mac.eq(mac_address),
+                       If(self.source.stb & self.source.eop & self.source.ack,
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("DROP",
+                       packetizer.source.ack.eq(1),
+                       If(packetizer.source.stb & packetizer.source.eop & packetizer.source.ack,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthIPRX(Module):
+       def __init__(self, mac_address, ip_address):
+               self.sink = Sink(eth_mac_description(8))
+               self.source = source = Source(eth_ipv4_user_description(8))
+               ###
+               depacketizer = LiteEthIPV4Depacketizer()
+               self.submodules += depacketizer
+               self.comb += Record.connect(self.sink, depacketizer.sink)
+               sink = depacketizer.source
+
+               checksum = LiteEthIPV4Checksum(skip_header=False)
+               self.submodules += checksum
+               self.comb += checksum.header.eq(depacketizer.header)
+
+               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("CHECK")
+                       )
+               )
+               valid = Signal()
+               self.comb += valid.eq(
+                       sink.stb &
+                       (sink.target_ip == ip_address) &
+                       (sink.version == 0x4) &
+                       (sink.ihl == 0x5) &
+                       (checksum.value == 0)
+               )
+
+               fsm.act("CHECK",
+                       If(valid,
+                               NextState("PRESENT")
+                       ).Else(
+                               NextState("DROP")
+                       )
+               )
+               self.comb += [
+                       source.sop.eq(sink.sop),
+                       source.eop.eq(sink.eop),
+                       source.length.eq(sink.total_length - (sink.ihl*4)),
+                       source.protocol.eq(sink.protocol),
+                       source.ip_address.eq(sink.target_ip),
+                       source.data.eq(sink.data),
+                       source.error.eq(sink.error)
+               ]
+               fsm.act("PRESENT",
+                       source.stb.eq(sink.stb),
+                       sink.ack.eq(source.ack),
+                       If(source.stb & source.eop & source.ack,
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("DROP",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.eop & sink.ack,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthIP(Module):
+       def __init__(self, mac, mac_address, ip_address, arp_table):
+               self.submodules.tx = LiteEthIPTX(mac_address, ip_address, arp_table)
+               self.submodules.rx = LiteEthIPRX(mac_address, ip_address)
+               mac_port = mac.crossbar.get_port(ethernet_type_ip)
+               self.comb += [
+                       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
diff --git a/liteeth/core/udp.py b/liteeth/core/udp.py
deleted file mode 100644 (file)
index 7a6c503..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-from liteeth.common import *
-from liteeth.generic.depacketizer import LiteEthDepacketizer
-from liteeth.generic.packetizer import LiteEthPacketizer
-
-class LiteEthUDPDepacketizer(LiteEthDepacketizer):
-       def __init__(self):
-               LiteEthDepacketizer.__init__(self,
-                       eth_ipv4_user_description(8),
-                       eth_udp_description(8),
-                       udp_header,
-                       udp_header_len)
-
-class LiteEthUDPPacketizer(LiteEthPacketizer):
-       def __init__(self):
-               LiteEthPacketizer.__init__(self,
-                       eth_udp_description(8),
-                       eth_ipv4_user_description(8),
-                       udp_header,
-                       udp_header_len)
-
-class LiteEthUDPTX(Module):
-       def __init__(self, ip_address):
-               self.sink = Sink(eth_udp_user_description(8))
-               self.source = Source(eth_ipv4_user_description(8))
-               ###
-               packetizer = LiteEthUDPPacketizer()
-               self.submodules += packetizer
-               self.comb += [
-                       packetizer.sink.stb.eq(self.sink.stb),
-                       packetizer.sink.sop.eq(self.sink.sop),
-                       packetizer.sink.eop.eq(self.sink.eop),
-                       self.sink.ack.eq(packetizer.sink.ack),
-                       packetizer.sink.src_port.eq(self.sink.src_port),
-                       packetizer.sink.dst_port.eq(self.sink.dst_port),
-                       packetizer.sink.length.eq(self.sink.length + udp_header_len),
-                       packetizer.sink.checksum.eq(0),
-                       packetizer.sink.data.eq(self.sink.data)
-               ]
-               sink = packetizer.source
-
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("SEND")
-                       )
-               )
-               fsm.act("SEND",
-                       Record.connect(packetizer.source, self.source),
-                       self.source.length.eq(packetizer.sink.length + ipv4_header_len),
-                       self.source.protocol.eq(udp_protocol),
-                       self.source.ip_address.eq(self.sink.ip_address),
-                       If(self.source.stb & self.source.eop & self.source.ack,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthUDPRX(Module):
-       def __init__(self, ip_address):
-               self.sink = Sink(eth_ipv4_user_description(8))
-               self.source = source = Source(eth_udp_user_description(8))
-               ###
-               depacketizer = LiteEthUDPDepacketizer()
-               self.submodules += depacketizer
-               self.comb += Record.connect(self.sink, depacketizer.sink)
-               sink = depacketizer.source
-
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("CHECK")
-                       )
-               )
-               valid = Signal()
-               self.comb += valid.eq(
-                       sink.stb &
-                       (self.sink.protocol == udp_protocol) &
-                       (self.sink.ip_address == ip_address)
-               )
-
-               fsm.act("CHECK",
-                       If(valid,
-                               NextState("PRESENT")
-                       ).Else(
-                               NextState("DROP")
-                       )
-               )
-               self.comb += [
-                       source.sop.eq(sink.sop),
-                       source.eop.eq(sink.eop),
-                       source.src_port.eq(sink.src_port),
-                       source.dst_port.eq(sink.dst_port),
-                       source.ip_address.eq(0),
-                       source.length.eq(sink.length - udp_header_len),
-                       source.data.eq(sink.data),
-                       source.error.eq(sink.error)
-               ]
-               fsm.act("PRESENT",
-                       source.stb.eq(sink.stb),
-                       sink.ack.eq(source.ack),
-                       If(source.stb & source.eop & source.ack,
-                               NextState("IDLE")
-                       )
-               )
-               fsm.act("DROP",
-                       sink.ack.eq(1),
-                       If(source.stb & source.eop & source.ack,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthUDP(Module):
-       def __init__(self, ip, ip_address):
-               self.submodules.tx = LiteEthUDPTX(ip_address)
-               self.submodules.rx = LiteEthUDPRX(ip_address)
-               self.comb += [
-                       Record.connect(self.tx.source, ip.sink),
-                       Record.connect(ip.source, self.rx.sink)
-               ]
-               self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/liteeth/core/udp/__init__.py b/liteeth/core/udp/__init__.py
new file mode 100644 (file)
index 0000000..7a6c503
--- /dev/null
@@ -0,0 +1,123 @@
+from liteeth.common import *
+from liteeth.generic.depacketizer import LiteEthDepacketizer
+from liteeth.generic.packetizer import LiteEthPacketizer
+
+class LiteEthUDPDepacketizer(LiteEthDepacketizer):
+       def __init__(self):
+               LiteEthDepacketizer.__init__(self,
+                       eth_ipv4_user_description(8),
+                       eth_udp_description(8),
+                       udp_header,
+                       udp_header_len)
+
+class LiteEthUDPPacketizer(LiteEthPacketizer):
+       def __init__(self):
+               LiteEthPacketizer.__init__(self,
+                       eth_udp_description(8),
+                       eth_ipv4_user_description(8),
+                       udp_header,
+                       udp_header_len)
+
+class LiteEthUDPTX(Module):
+       def __init__(self, ip_address):
+               self.sink = Sink(eth_udp_user_description(8))
+               self.source = Source(eth_ipv4_user_description(8))
+               ###
+               packetizer = LiteEthUDPPacketizer()
+               self.submodules += packetizer
+               self.comb += [
+                       packetizer.sink.stb.eq(self.sink.stb),
+                       packetizer.sink.sop.eq(self.sink.sop),
+                       packetizer.sink.eop.eq(self.sink.eop),
+                       self.sink.ack.eq(packetizer.sink.ack),
+                       packetizer.sink.src_port.eq(self.sink.src_port),
+                       packetizer.sink.dst_port.eq(self.sink.dst_port),
+                       packetizer.sink.length.eq(self.sink.length + udp_header_len),
+                       packetizer.sink.checksum.eq(0),
+                       packetizer.sink.data.eq(self.sink.data)
+               ]
+               sink = packetizer.source
+
+               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("SEND")
+                       )
+               )
+               fsm.act("SEND",
+                       Record.connect(packetizer.source, self.source),
+                       self.source.length.eq(packetizer.sink.length + ipv4_header_len),
+                       self.source.protocol.eq(udp_protocol),
+                       self.source.ip_address.eq(self.sink.ip_address),
+                       If(self.source.stb & self.source.eop & self.source.ack,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthUDPRX(Module):
+       def __init__(self, ip_address):
+               self.sink = Sink(eth_ipv4_user_description(8))
+               self.source = source = Source(eth_udp_user_description(8))
+               ###
+               depacketizer = LiteEthUDPDepacketizer()
+               self.submodules += depacketizer
+               self.comb += Record.connect(self.sink, depacketizer.sink)
+               sink = depacketizer.source
+
+               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("CHECK")
+                       )
+               )
+               valid = Signal()
+               self.comb += valid.eq(
+                       sink.stb &
+                       (self.sink.protocol == udp_protocol) &
+                       (self.sink.ip_address == ip_address)
+               )
+
+               fsm.act("CHECK",
+                       If(valid,
+                               NextState("PRESENT")
+                       ).Else(
+                               NextState("DROP")
+                       )
+               )
+               self.comb += [
+                       source.sop.eq(sink.sop),
+                       source.eop.eq(sink.eop),
+                       source.src_port.eq(sink.src_port),
+                       source.dst_port.eq(sink.dst_port),
+                       source.ip_address.eq(0),
+                       source.length.eq(sink.length - udp_header_len),
+                       source.data.eq(sink.data),
+                       source.error.eq(sink.error)
+               ]
+               fsm.act("PRESENT",
+                       source.stb.eq(sink.stb),
+                       sink.ack.eq(source.ack),
+                       If(source.stb & source.eop & source.ack,
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("DROP",
+                       sink.ack.eq(1),
+                       If(source.stb & source.eop & source.ack,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthUDP(Module):
+       def __init__(self, ip, ip_address):
+               self.submodules.tx = LiteEthUDPTX(ip_address)
+               self.submodules.rx = LiteEthUDPRX(ip_address)
+               self.comb += [
+                       Record.connect(self.tx.source, ip.sink),
+                       Record.connect(ip.source, self.rx.sink)
+               ]
+               self.sink, self.source = self.tx.sink, self.rx.source