+++ /dev/null
-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)
- ]
--- /dev/null
+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)
+ ]
+++ /dev/null
-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
--- /dev/null
+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
+++ /dev/null
-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
--- /dev/null
+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