-from liteeth.common import *
-from liteeth.mac import LiteEthMAC
-from liteeth.arp import LiteEthARP
-from liteeth.ip import LiteEthIP
-
-class LiteEthIPStack(Module, AutoCSR):
- def __init__(self, phy, mac_address, ip_address):
- self.phy = phy
- self.submodules.mac = mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
- self.submodules.arp = arp = LiteEthARP(mac, mac_address, ip_address)
- self.submodules.ip = ip = LiteEthIP(mac, mac_address, ip_address, arp.table)
- self.sink, self.source = self.ip.sink, self.ip.source
+++ /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=arp_packet_length)
- self.submodules += counter
-
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- sink.ack.eq(1),
- counter.reset.eq(1),
- If(sink.stb,
- sink.ack.eq(0),
- NextState("SEND")
- )
- )
- self.comb += [
- source.hardware_type.eq(arp_hwtype_ethernet),
- source.protocol_type.eq(arp_proto_ip),
- source.hardware_address_length.eq(6),
- source.protocol_address_length.eq(4),
- source.source_mac_address.eq(mac_address),
- source.source_ip_address.eq(ip_address),
- If(sink.reply,
- source.operation.eq(arp_opcode_reply),
- source.destination_mac_address.eq(sink.mac_address),
- source.destination_ip_address.eq(sink.ip_address)
- ).Elif(sink.request,
- source.operation.eq(arp_opcode_request),
- source.destination_mac_address.eq(0xffffffffffff),
- source.destination_ip_address.eq(sink.ip_address)
- )
- ]
- fsm.act("SEND",
- source.stb.eq(1),
- source.sop.eq(counter.value == 0),
- source.eop.eq(counter.value == arp_packet_length-1),
- Record.connect(packetizer.source, self.source),
- self.source.destination_mac_address.eq(source.destination_mac_address),
- self.source.source_mac_address.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
-
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- 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.hardware_type == arp_hwtype_ethernet) &
- (sink.protocol_type == arp_proto_ip) &
- (sink.hardware_address_length == 6) &
- (sink.protocol_address_length == 4) &
- (sink.destination_ip_address == ip_address)
- )
- reply = Signal()
- request = Signal()
- self.comb += Case(sink.operation, {
- arp_opcode_request : [request.eq(1)],
- arp_opcode_reply : [reply.eq(1)],
- "default" : []
- })
- self.comb += [
- source.ip_address.eq(sink.source_ip_address),
- source.mac_address.eq(sink.source_mac_address)
- ]
- 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):
- 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(512) # XXX fix me 100ms?
- request_pending = FlipFlop()
- request_ip_address = FlipFlop(32, reset=0xffffffff) # XXX add cached_valid?
- self.submodules += request_timeout, 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: Store only one ip/mac couple, replace this with
- # a real ARP table
- update = Signal()
- cached_ip_address = Signal(32)
- cached_mac_address = Signal(48)
-
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- # Note: for simplicicy, if APR table is busy response from arp_rx
- # is lost. This is compensated by the protocol (retrys)
- If(sink.stb & sink.request,
- NextState("SEND_REPLY")
- ).Elif(sink.stb & sink.reply & request_pending.q,
- NextState("UPDATE_TABLE"),
- ).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_ip_address.eq(sink.ip_address),
- cached_mac_address.eq(sink.mac_address)
- )
- ]
- found = Signal()
- fsm.act("CHECK_TABLE",
- # XXX: add a live time for cached_mac_address
- 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(1),
- NextState("SEND_REQUEST")
- )
- )
- fsm.act("SEND_REQUEST",
- source.stb.eq(1),
- source.request.eq(1),
- source.ip_address.eq(request.ip_address),
- If(source.ack,
- request_timeout.reset.eq(1),
- request_pending.ce.eq(1),
- request.ack.eq(1),
- NextState("IDLE")
- )
- )
- fsm.act("PRESENT_RESPONSE",
- response.stb.eq(1),
- response.failed.eq(0), # XXX add timeout to trigger failed
- response.mac_address.eq(cached_mac_address),
- If(response.ack,
- NextState("IDLE")
- )
- )
-
-class LiteEthARP(Module):
- def __init__(self, mac, mac_address, ip_address):
- self.submodules.tx = LiteEthARPTX(mac_address, ip_address)
- self.submodules.rx = LiteEthARPRX(mac_address, ip_address)
- self.submodules.table = LiteEthARPTable()
- 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.mac import LiteEthMAC
+from liteeth.core.arp import LiteEthARP
+from liteeth.core.ip import LiteEthIP
+
+class LiteEthIPCore(Module, AutoCSR):
+ def __init__(self, phy, mac_address, ip_address):
+ self.phy = phy
+ self.submodules.mac = mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
+ self.submodules.arp = arp = LiteEthARP(mac, mac_address, ip_address)
+ self.submodules.ip = ip = LiteEthIP(mac, mac_address, ip_address, arp.table)
+ self.sink, self.source = self.ip.sink, self.ip.source
--- /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=arp_packet_length)
+ self.submodules += counter
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ counter.reset.eq(1),
+ If(sink.stb,
+ sink.ack.eq(0),
+ NextState("SEND")
+ )
+ )
+ self.comb += [
+ source.hardware_type.eq(arp_hwtype_ethernet),
+ source.protocol_type.eq(arp_proto_ip),
+ source.hardware_address_length.eq(6),
+ source.protocol_address_length.eq(4),
+ source.source_mac_address.eq(mac_address),
+ source.source_ip_address.eq(ip_address),
+ If(sink.reply,
+ source.operation.eq(arp_opcode_reply),
+ source.destination_mac_address.eq(sink.mac_address),
+ source.destination_ip_address.eq(sink.ip_address)
+ ).Elif(sink.request,
+ source.operation.eq(arp_opcode_request),
+ source.destination_mac_address.eq(0xffffffffffff),
+ source.destination_ip_address.eq(sink.ip_address)
+ )
+ ]
+ fsm.act("SEND",
+ source.stb.eq(1),
+ source.sop.eq(counter.value == 0),
+ source.eop.eq(counter.value == arp_packet_length-1),
+ Record.connect(packetizer.source, self.source),
+ self.source.destination_mac_address.eq(source.destination_mac_address),
+ self.source.source_mac_address.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
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ 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.hardware_type == arp_hwtype_ethernet) &
+ (sink.protocol_type == arp_proto_ip) &
+ (sink.hardware_address_length == 6) &
+ (sink.protocol_address_length == 4) &
+ (sink.destination_ip_address == ip_address)
+ )
+ reply = Signal()
+ request = Signal()
+ self.comb += Case(sink.operation, {
+ arp_opcode_request : [request.eq(1)],
+ arp_opcode_reply : [reply.eq(1)],
+ "default" : []
+ })
+ self.comb += [
+ source.ip_address.eq(sink.source_ip_address),
+ source.mac_address.eq(sink.source_mac_address)
+ ]
+ 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):
+ 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(512) # XXX fix me 100ms?
+ request_pending = FlipFlop()
+ request_ip_address = FlipFlop(32, reset=0xffffffff) # XXX add cached_valid?
+ self.submodules += request_timeout, 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: Store only one ip/mac couple, replace this with
+ # a real ARP table
+ update = Signal()
+ cached_ip_address = Signal(32)
+ cached_mac_address = Signal(48)
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ # Note: for simplicicy, if APR table is busy response from arp_rx
+ # is lost. This is compensated by the protocol (retrys)
+ If(sink.stb & sink.request,
+ NextState("SEND_REPLY")
+ ).Elif(sink.stb & sink.reply & request_pending.q,
+ NextState("UPDATE_TABLE"),
+ ).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_ip_address.eq(sink.ip_address),
+ cached_mac_address.eq(sink.mac_address)
+ )
+ ]
+ found = Signal()
+ fsm.act("CHECK_TABLE",
+ # XXX: add a live time for cached_mac_address
+ 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(1),
+ NextState("SEND_REQUEST")
+ )
+ )
+ fsm.act("SEND_REQUEST",
+ source.stb.eq(1),
+ source.request.eq(1),
+ source.ip_address.eq(request.ip_address),
+ If(source.ack,
+ request_timeout.reset.eq(1),
+ request_pending.ce.eq(1),
+ request.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+ fsm.act("PRESENT_RESPONSE",
+ response.stb.eq(1),
+ response.failed.eq(0), # XXX add timeout to trigger failed
+ response.mac_address.eq(cached_mac_address),
+ If(response.ack,
+ NextState("IDLE")
+ )
+ )
+
+class LiteEthARP(Module):
+ def __init__(self, mac, mac_address, ip_address):
+ self.submodules.tx = LiteEthARPTX(mac_address, ip_address)
+ self.submodules.rx = LiteEthARPRX(mac_address, ip_address)
+ self.submodules.table = LiteEthARPTable()
+ 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))
+ ###
+ 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.eq(packetizer.sink.ack),
+ packetizer.sink.destination_ip_address.eq(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.dscp.eq(0),
+ packetizer.sink.ecn.eq(0),
+ packetizer.sink.identification.eq(0),
+ packetizer.sink.flags.eq(0),
+ packetizer.sink.fragment_offset.eq(0),
+ packetizer.sink.time_to_live.eq(0x80),
+ packetizer.sink.source_ip_address.eq(ip_address)
+ ]
+ sink = packetizer.source
+
+ checksum = LiteEthIPV4Checksum(skip_header=True)
+ self.submodules += checksum
+ self.comb += [
+ checksum.header.eq(packetizer.header),
+ packetizer.sink.header_checksum.eq(checksum.value)
+ ]
+
+ destination_mac_address = Signal(48)
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ If(sink.stb & sink.sop,
+ sink.ack.eq(0),
+ NextState("SEND_MAC_ADDRESS_REQUEST")
+ )
+ )
+ fsm.act("SEND_MAC_ADDRESS_REQUEST",
+ arp_table.request.stb.eq(1),
+ arp_table.request.ip_address.eq(self.sink.ip_address),
+ If(arp_table.request.stb & arp_table.request.ack,
+ NextState("WAIT_MAC_ADDRESS_RESPONSE")
+ )
+ )
+ fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
+ # XXX add timeout
+ If(arp_table.response.stb,
+ arp_table.response.ack.eq(1),
+ # XXX manage failed
+ NextState("SEND")
+ )
+ )
+ self.sync += If(arp_table.response.stb, destination_mac_address.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.destination_mac_address.eq(destination_mac_address),
+ self.source.source_mac_address.eq(mac_address),
+ # XXX compute check sum
+ If(self.source.stb & self.source.eop & self.source.ack,
+ # XXX manage failed
+ 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)
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ 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.destination_ip_address == ip_address) &
+ (sink.version == 0x4) &
+ (sink.ihl == 0x5) &
+ (checksum.value == 0)
+ )
+
+ fsm.act("CHECK",
+ If(valid,
+ NextState("PRESENT")
+ ).Else(
+ NextState("DROP")
+ )
+ ),
+ fsm.act("PRESENT",
+ source.stb.eq(sink.stb),
+ source.sop.eq(sink.sop),
+ source.eop.eq(sink.eop),
+ sink.ack.eq(source.ack),
+ source.length.eq(sink.total_length - (sink.ihl*4)),
+ source.protocol.eq(sink.protocol),
+ source.ip_address.eq(sink.destination_ip_address),
+ source.data.eq(sink.data),
+ source.error.eq(sink.error),
+ 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 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_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_description(8),
+ udp_header,
+ udp_header_len)
+++ /dev/null
-# This file is Copyright (c) 2014 Robert Jordens <jordens@gmail.com>
-# License: BSD
-
-import struct
-from collections import namedtuple
-
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.record import Record
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.fifo import SyncFIFO
-from migen.genlib.misc import optree
-from migen.actorlib.structuring import Cast, Pack, Unpack, pack_layout
-from migen.actorlib.sim import SimActor
-from migen.bus.transactions import TRead, TWrite
-from migen.flow.transactions import Token
-from migen.flow.actor import Source, Sink
-from migen.flow.network import DataFlowGraph, CompositeActor
-
-
-_eb_width = 32 # addr and data
-_eb_queue_len = 32
-_eb_magic = 0x4e6f
-_eb_ver = 1
-_eb_hdr = [
- ("magic", 16),
- ("ver", 4),
- ("res1", 1),
- ("no_response", 1),
- ("probe_res", 1),
- ("probe", 1),
- ("addr_size", 4),
- ("data_size", 4),
- ][::-1] # big-endian
-
-_eb_rec_hdr = [
- ("bca_cfg", 1),
- ("rca_cfg", 1),
- ("rd_fifo", 1),
- ("res1", 1),
- ("drop_cyc", 1),
- ("wca_cfg", 1),
- ("wr_fifo", 1),
- ("res2", 1),
- ("sel", 8),
- ("wr_cnt", 8),
- ("rd_cnt", 8),
- ][::-1] # big-endian
-
-_eb_layout = [("data", _eb_width)]
-
-
-class Config(Module):
- def __init__(self, sdb_addr):
- self.errreg = Signal(8*8)
- mach = Signal(4*8, reset=0xd15e)
- macl = Signal(4*8, reset=0xa5edbeef)
- self.mac = Signal(6*8)
- self.comb += self.mac.eq(Cat(macl, mach))
- self.ip = Signal(4*8, reset=0xc0a80064)
- self.port = Signal(4*8, reset=0xebd0)
-
- self.bus = bus = wishbone.Interface()
- self.submodules.fifo = SyncFIFO(3, _eb_queue_len)
-
- read_mux = Array([self.errreg[32:], self.errreg[:32], 0,
- sdb_addr, mach, macl, self.ip, self.port])
- write_mux = Array([mach, macl, self.ip, self.port])[bus.adr - 4]
-
- self.dout = read_mux[self.fifo.dout]
- self.comb += [
- bus.ack.eq(bus.cyc & bus.stb),
- bus.dat_r.eq(read_mux[bus.adr[:3]]),
- ]
- self.sync += [
- If(bus.cyc & bus.stb & bus.we & optree("|",
- [bus.adr[:3] == i for i in (4, 5, 6, 7)]),
- write_mux.eq(bus.dat_w),
- )]
-
-class WishboneMaster(Module):
- def __init__(self, timeout):
- self.bus = bus = wishbone.Interface()
- self.submodules.fifo = SyncFIFO(_eb_width + 1, _eb_queue_len)
-
- self.active = Signal()
- inflight = Signal(max=_eb_queue_len)
- queued = Signal(max=_eb_queue_len)
- self.sync += [
- inflight.eq(inflight + self.active - self.fifo.we),
- queued.eq(queued + self.active - self.fifo.re),
- ]
-
- self.busy = Signal()
- self.full = Signal()
- self.comb += [
- self.busy.eq(inflight != 0),
- self.full.eq(queued == _eb_queue_len - 1),
- ]
-
- kill_ack = Signal()
- time = Signal(max=timeout)
- self.comb += kill_ack.eq(time == timeout - 1)
- self.sync += [
- If(self.fifo.we | ~self.busy,
- time.eq(0),
- ).Else(
- time.eq(time + 1),
- )]
-
- self.comb += [
- self.fifo.we.eq(bus.ack | bus.err | kill_ack),
- self.fifo.din.eq(Cat(bus.dat_r, ~bus.ack)),
- ]
-
- self.errreg = Signal(64)
- self.sync += [
- If(self.fifo.re,
- self.errreg.eq(Cat(self.fifo.dout[-1], self.errreg)),
- )]
-
-class Transmit(Module):
- def __init__(self, pas, cfg, wbm, tag, tags):
- self.tx = Source(_eb_layout)
-
- data = Signal(_eb_width)
- re = Signal(4)
- self.tx_cyc = Signal()
- self.tx_skip = Signal()
- last_tx_cyc = Signal()
- last_tx_skip = Signal()
- readable = Signal()
-
- self.sync += [
- last_tx_cyc.eq(self.tx_cyc),
- last_tx_skip.eq(self.tx_skip),
- ]
-
- self.comb += [
- readable.eq(Cat(tag.readable, pas.readable,
- cfg.fifo.readable, wbm.readable) & re == re),
- self.tx.stb.eq(readable & (re[1:] != 0)),
- self.tx.payload.data.eq(data),
- Case(tag.dout, {
- tags["PASS_TX"]: [re.eq(0b0011), data.eq(pas.dout)],
- tags["PASS_ON"]: [re.eq(0b0011), data.eq(pas.dout)],
- tags["CFG_REQ"]: [re.eq(0b0101), data.eq(cfg.dout)],
- tags["CFG_IGN"]: [re.eq(0b0111), data.eq(pas.dout)],
- tags["WBM_REQ"]: [re.eq(0b1001), data.eq(wbm.dout)],
- tags["WBM_IGN"]: [re.eq(0b1011), data.eq(pas.dout)],
- "default": [re.eq(0b0001)],
- }),
- If(readable & (self.tx.ack | (re[1:] == 0)),
- Cat(tag.re, pas.re, cfg.fifo.re, wbm.re).eq(re),
- ),
- If(tag.readable,
- If(tag.dout == tags["PASS_TX"],
- self.tx_cyc.eq(1),
- self.tx_skip.eq(0),
- ).Elif(tag.dout == tags["SKIP_TX"],
- self.tx_cyc.eq(0),
- self.tx_skip.eq(1),
- ).Elif(tag.dout == tags["DROP_TX"],
- self.tx_cyc.eq(0),
- self.tx_skip.eq(0),
- ).Else(
- self.tx_cyc.eq(last_tx_cyc),
- self.tx_skip.eq(last_tx_skip),
- ),
- ).Else(
- self.tx_cyc.eq(last_tx_cyc),
- self.tx_skip.eq(last_tx_skip),
- ),
- ]
-
-class Receive(Module):
- def __init__(self, pas, cfg, wbm, tag, tags):
- self.rx = Sink(_eb_layout)
-
- rx_rec_hdr = Record(_eb_rec_hdr)
- tx_rec_hdr = Record(_eb_rec_hdr)
- rx_eb_hdr = Record(_eb_hdr)
- tx_eb_hdr = Record(_eb_hdr)
- self.comb += [
- rx_eb_hdr.raw_bits().eq(self.rx.payload.data),
- tx_eb_hdr.magic.eq(rx_eb_hdr.magic),
- tx_eb_hdr.ver.eq(_eb_ver),
- tx_eb_hdr.no_response.eq(1),
- tx_eb_hdr.addr_size.eq(4),
- tx_eb_hdr.data_size.eq(4),
- tx_eb_hdr.probe_res.eq(rx_eb_hdr.probe),
-
- rx_rec_hdr.raw_bits().eq(self.rx.payload.data),
- tx_rec_hdr.wca_cfg.eq(rx_rec_hdr.bca_cfg),
- tx_rec_hdr.wr_fifo.eq(rx_rec_hdr.rd_fifo),
- tx_rec_hdr.wr_cnt.eq(rx_rec_hdr.rd_cnt),
- tx_rec_hdr.sel.eq(rx_rec_hdr.sel),
- tx_rec_hdr.drop_cyc.eq(rx_rec_hdr.drop_cyc),
- ]
-
- do_rx = Signal()
- self.rx_cyc = Signal()
- self.comb += [
- wbm.bus.sel.eq(rx_rec_hdr.sel),
- do_rx.eq(tag.writable & # tag is always written/read
- self.rx_cyc & self.rx.stb & # have data
- (wbm.fifo.we | ~wbm.bus.stb) & # stb finished or idle
- (wbm.bus.cyc | ~wbm.busy)), # in-cycle or idle
- self.rx.ack.eq(do_rx),
- cfg.fifo.din.eq(wbm.bus.adr),
- # no eb-cfg write support yet
- #cfg.dat_w.eq(wbm.bus.dat_w),
- #cfg.we.eq(wbm.bus.we),
- cfg.errreg.eq(wbm.errreg),
- ]
-
- cur_rx_rec_hdr = Record(_eb_rec_hdr)
- cur_tx_rec_hdr = Record(_eb_rec_hdr)
- do_rec = Signal()
- do_adr = Signal()
- do_write = Signal()
- do_read = Signal()
- wr_adr = Signal(flen(wbm.bus.adr))
- old_rx_cyc = Signal()
- self.sync += [
- wbm.bus.stb.eq(wbm.bus.stb & ~wbm.fifo.we),
- wbm.bus.cyc.eq(wbm.bus.cyc & (
- ~cur_rx_rec_hdr.drop_cyc |
- (cur_rx_rec_hdr.wr_cnt > 0) |
- (cur_rx_rec_hdr.rd_cnt > 0))),
- If(do_rec,
- cur_rx_rec_hdr.eq(rx_rec_hdr),
- cur_tx_rec_hdr.eq(tx_rec_hdr),
- ),
- If(do_adr,
- wr_adr.eq(self.rx.payload.data[2:]),
- ),
- If(do_write,
- If(cur_rx_rec_hdr.wca_cfg,
- cfg.fifo.we.eq(1),
- ).Else(
- wbm.bus.cyc.eq(1),
- wbm.bus.stb.eq(1),
- ),
- wbm.bus.we.eq(1),
- wbm.bus.adr.eq(wr_adr),
- wbm.bus.dat_w.eq(self.rx.payload.data),
- If(~cur_rx_rec_hdr.wr_fifo,
- wr_adr.eq(wr_adr + 1),
- ),
- cur_rx_rec_hdr.wr_cnt.eq(cur_rx_rec_hdr.wr_cnt - 1),
- ),
- If(do_read,
- If(cur_rx_rec_hdr.rca_cfg,
- cfg.fifo.we.eq(1),
- ).Else(
- wbm.bus.cyc.eq(1),
- wbm.bus.stb.eq(1),
- ),
- wbm.bus.we.eq(0),
- wbm.bus.adr.eq(self.rx.payload.data[2:]),
- cur_rx_rec_hdr.rd_cnt.eq(cur_rx_rec_hdr.rd_cnt - 1),
- ),
- If(~self.rx_cyc,
- wbm.bus.cyc.eq(0),
- ),
- old_rx_cyc.eq(self.rx_cyc),
- ]
-
- fsm = self.submodules.fsm = FSM()
- fsm.reset_state = "EB_HDR"
- fsm.act("EB_HDR",
- If(do_rx,
- tag.we.eq(1),
- If((rx_eb_hdr.magic != _eb_magic) |
- (rx_eb_hdr.ver !=_eb_ver),
- tag.din.eq(tags["SKIP_TX"]),
- NextState("DROP"),
- ).Else(
- If(rx_eb_hdr.no_response,
- tag.din.eq(tags["SKIP_TX"]),
- ).Else(
- tag.din.eq(tags["PASS_TX"]),
- pas.we.eq(1),
- pas.din.eq(tx_eb_hdr.raw_bits()),
- ),
- If(rx_eb_hdr.probe,
- If(rx_eb_hdr.addr_size[2] &
- rx_eb_hdr.data_size[2],
- NextState("PROBE_ID"),
- ).Else(
- NextState("PROBE_DROP"),
- ),
- ).Else(
- If((rx_eb_hdr.addr_size == 4) &
- (rx_eb_hdr.data_size == 4),
- NextState("CYC_HDR"),
- ).Else(
- NextState("DROP"),
- ),
- ),
- ),
- ))
- fsm.act("PROBE_DROP",
- If(do_rx,
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- pas.din.eq(self.rx.payload.data),
- NextState("DROP"),
- ))
- fsm.act("PROBE_ID",
- If(do_rx,
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- pas.din.eq(self.rx.payload.data),
- NextState("CYC_HDR"),
- ))
- fsm.act("CYC_HDR",
- If(do_rx,
- do_rec.eq(1),
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- If(rx_rec_hdr.wr_cnt != 0,
- NextState("WR_ADR"),
- ).Else(
- pas.din.eq(tx_rec_hdr.raw_bits()),
- If(rx_rec_hdr.rd_cnt != 0,
- NextState("RD_ADR"),
- ).Else(
- NextState("CYC_HDR"),
- ),
- ),
- ))
- fsm.act("WR_ADR",
- If(do_rx,
- do_adr.eq(1),
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- NextState("WRITE"),
- ))
- fsm.act("WRITE",
- If(do_rx,
- do_write.eq(1),
- tag.we.eq(1),
- If(cur_rx_rec_hdr.wca_cfg,
- tag.din.eq(tags["CFG_IGN"]),
- ).Else(
- wbm.active.eq(1),
- tag.din.eq(tags["WBM_IGN"]),
- ),
- pas.we.eq(1),
- If(cur_rx_rec_hdr.wr_cnt == 1,
- pas.din.eq(cur_tx_rec_hdr.raw_bits()),
- If(cur_rx_rec_hdr.rd_cnt != 0,
- NextState("RD_ADR"),
- ).Else(
- NextState("CYC_HDR"),
- ),
- ),
- ))
- fsm.act("RD_ADR",
- If(do_rx,
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- pas.din.eq(self.rx.payload.data),
- NextState("READ"),
- ))
- fsm.act("READ",
- If(do_rx,
- do_read.eq(1),
- tag.we.eq(1),
- If(cur_rx_rec_hdr.rca_cfg,
- tag.din.eq(tags["CFG_REQ"]),
- ).Else(
- wbm.active.eq(1),
- tag.din.eq(tags["WBM_REQ"]),
- ),
- If(cur_rx_rec_hdr.rd_cnt == 1,
- NextState("CYC_HDR"),
- ),
- ))
- fsm.act("DROP",
- #If(do_rx,
- # tag.we.eq(1),
- # tag.din.eq(tags["PASS_ON"]),
- # pas.we.eq(1),
- #)
- )
- for state in fsm.actions:
- fsm.act(state, If(~self.rx_cyc, NextState("EB_HDR")))
- self.comb += [
- If(~self.rx_cyc,
- Cat(do_rec, do_adr, do_write, do_read).eq(0),
- Cat(wbm.active, pas.we).eq(0),
- If(old_rx_cyc,
- tag.we.eq(1),
- tag.din.eq(tags["DROP_TX"]),
- ),
- )]
-
-class Slave(Module):
- def __init__(self, sdb_addr, timeout):
- tags = dict((k, i) for i, k in enumerate(
- "DROP_TX SKIP_TX PASS_TX PASS_ON CFG_REQ "
- "CFG_IGN WBM_REQ WBM_IGN".split()))
- tag_width = flen(Signal(max=len(tags)))
-
- self.submodules.pas = SyncFIFO(_eb_width, _eb_queue_len)
- self.submodules.cfg = Config(sdb_addr)
- self.submodules.wbm = WishboneMaster(timeout)
- self.submodules.tag = SyncFIFO(tag_width, _eb_queue_len)
-
- self.submodules.rxfsm = Receive(self.pas, self.cfg,
- self.wbm, self.tag, tags)
- self.rx = self.rxfsm.rx
- self.rx_cyc = self.rxfsm.rx_cyc
- self.submodules.txmux = Transmit(self.pas, self.cfg,
- self.wbm.fifo, self.tag, tags)
- self.tx = self.txmux.tx
- self.tx_skip = self.txmux.tx_skip
- self.tx_cyc = self.txmux.tx_cyc
- self.busy = self.wbm.busy
-
-class Converter(Module):
- def __init__(self, raw_width, graph, **slave_kwargs):
- raw_layout = [("data", raw_width)]
- pack_factor = _eb_width//raw_width
-
- self.rx = Sink(raw_layout)
- rx_pack = Pack(raw_layout, pack_factor)
- rx_cast = Cast(pack_layout(raw_layout, pack_factor), _eb_layout)
- self.submodules.slave = Slave(**slave_kwargs)
- tx_cast = Cast(_eb_layout, pack_layout(raw_layout, pack_factor))
- tx_unpack = Unpack(pack_factor, raw_layout)
- self.tx = Source(raw_layout)
-
- graph.add_connection(self.rx, rx_pack)
- graph.add_connection(rx_pack, rx_cast)
- graph.add_connection(rx_cast, self.slave.rx)
- graph.add_connection(self.slave.tx, tx_cast)
- graph.add_connection(tx_cast, tx_unpack)
- graph.add_connection(tx_unpack, self.tx)
-
-class SimTx(SimActor):
- def __init__(self, data):
- self.tx = Source(_eb_layout)
- SimActor.__init__(self, self.gen(data))
-
- def gen(self, data):
- for i in data:
- yield Token("tx", {"data": i})
- print("eb tx", hex(i))
-
-class SimRx(SimActor):
- def __init__(self):
- self.rx = Sink(_eb_layout)
- self.recv = []
- SimActor.__init__(self, self.gen())
-
- def gen(self):
- while True:
- t = Token("rx")
- yield t
- print("eb rx", hex(t.value["data"]))
- self.recv.append(t.value["data"])
-
-class TB(Module):
- def __init__(self, data):
- ebm_tx = SimTx(data)
- ebm_rx = SimRx()
- self.slave = Slave(0x200, 10)
- g = DataFlowGraph()
- g.add_connection(ebm_tx, self.slave)
- g.add_connection(self.slave, ebm_rx)
- self.submodules.graph = CompositeActor(g)
- self.submodules.cfg_master = wishbone.Initiator(self.gen_cfg_reads())
- self.submodules.cfg_tap = wishbone.Tap(self.slave.cfg.bus,
- lambda l: print("cfg", l))
- self.submodules.wbm_tap = wishbone.Tap(self.slave.wbm.bus,
- lambda l: print("wbm", l))
- self.submodules.xbar = wishbone.Crossbar(
- [self.cfg_master.bus, self.slave.wbm.bus],
- [
- (lambda a: a[6:] == 0x0, wishbone.Target(
- wishbone.TargetModel()).bus),
- (lambda a: a[6:] == 0x1, self.slave.cfg.bus),
- ])
-
- def gen_cfg_reads(self):
- for a in range(0x40, 0x40+4):
- t = TRead(a)
- yield t
-
- def do_simulation(self, s):
- #s.interrupt = self.cfg_master.done
- s.wr(self.slave.rx_cyc, int(s.cycle_counter < 200))
-
-class MyStruct(object):
- _data = None
- _fmt = "!"
-
- def __init__(self, **kwargs):
- self.data = self._data(**kwargs)
-
- def __bytes__(self):
- return struct.pack(self._fmt, *self.data)
-
-class EbHeader(MyStruct):
- _data = namedtuple("eb_hdr", "magic ver size")
- _fmt = "!HBB"
-
- def __init__(self, probe_id=None, addr_size=4, data_size=4, records=[]):
- no_response = not any(r.read for r in records)
- probe = probe_id is not None
- probe_res = False
- MyStruct.__init__(self, magic=_eb_magic, ver=(_eb_ver<<4) |
- (no_response<<2) | (probe_res<<1) | (probe<<0),
- size=(addr_size<<4) | (data_size<<0))
- self.probe = struct.pack("!I", probe_id) if probe else b""
- self.records = records
-
- def __bytes__(self):
- return (MyStruct.__bytes__(self) + self.probe +
- b"".join(map(bytes, self.records)))
-
-class EbRecord(MyStruct):
- _data = namedtuple("eb_rec", "flags sel wr_cnt rd_cnt")
- _fmt = "!BBBB"
-
- def __init__(self, sel=0xf, wr_adr=0, rd_adr=0, write=[], read=[],
- bca_cfg=False, rca_cfg=False, rd_fifo=False, drop_cyc=False,
- wca_cfg=False, wr_fifo=False):
- MyStruct.__init__(self, sel=sel, wr_cnt=len(write),
- rd_cnt=len(read), flags=(bca_cfg<<7) | (rca_cfg<<6) |
- (rd_fifo<<5) | (drop_cyc<<3) | (wca_cfg<<2) |
- (wr_fifo>>1))
- self.wr_adr = wr_adr
- self.write = write
- self.rd_adr = rd_adr
- self.read = read
-
- def __bytes__(self):
- b = MyStruct.__bytes__(self)
- if self.write:
- b += struct.pack("!I" + "I"*len(self.write), self.wr_adr,
- *self.write)
- if self.read:
- b += struct.pack("!I" + "I"*len(self.read), self.rd_adr,
- *self.read)
- return b
-
-def main():
- from migen.sim.generic import Simulator, TopLevel
-
- #from migen.fhdl import verilog
- #s = Slave(0, 10)
- #print(verilog.convert(s, ios={s.rx.payload.data, s.tx.payload.data,
- # s.rx.stb, s.rx.ack, s.tx.stb, s.tx.ack}))
-
- eb_pkt = EbHeader(records=[
- EbRecord(wr_adr=0x10, write=[0x20, 0x21],
- rd_adr=0x30, read=range(0, 8, 4)),
- EbRecord(rd_adr=0x40, read=range(0x100, 0x100+32, 4),
- drop_cyc=True),
- EbRecord(rca_cfg=True, bca_cfg=True, rd_adr=0x50,
- read=range(0, 0+8, 4), drop_cyc=True),
- ])
- eb_pkt = bytes(eb_pkt)
- eb_pkt = struct.unpack("!" + "I"*(len(eb_pkt)//4), eb_pkt)
- tb = TB(eb_pkt)
- sim = Simulator(tb, TopLevel("etherbone.vcd"))
- sim.run(500)
-
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
--- /dev/null
+# This file is Copyright (c) 2014 Robert Jordens <jordens@gmail.com>
+# License: BSD
+
+import struct
+from collections import namedtuple
+
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.record import Record
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.fifo import SyncFIFO
+from migen.genlib.misc import optree
+from migen.actorlib.structuring import Cast, Pack, Unpack, pack_layout
+from migen.actorlib.sim import SimActor
+from migen.bus.transactions import TRead, TWrite
+from migen.flow.transactions import Token
+from migen.flow.actor import Source, Sink
+from migen.flow.network import DataFlowGraph, CompositeActor
+
+
+_eb_width = 32 # addr and data
+_eb_queue_len = 32
+_eb_magic = 0x4e6f
+_eb_ver = 1
+_eb_hdr = [
+ ("magic", 16),
+ ("ver", 4),
+ ("res1", 1),
+ ("no_response", 1),
+ ("probe_res", 1),
+ ("probe", 1),
+ ("addr_size", 4),
+ ("data_size", 4),
+ ][::-1] # big-endian
+
+_eb_rec_hdr = [
+ ("bca_cfg", 1),
+ ("rca_cfg", 1),
+ ("rd_fifo", 1),
+ ("res1", 1),
+ ("drop_cyc", 1),
+ ("wca_cfg", 1),
+ ("wr_fifo", 1),
+ ("res2", 1),
+ ("sel", 8),
+ ("wr_cnt", 8),
+ ("rd_cnt", 8),
+ ][::-1] # big-endian
+
+_eb_layout = [("data", _eb_width)]
+
+
+class Config(Module):
+ def __init__(self, sdb_addr):
+ self.errreg = Signal(8*8)
+ mach = Signal(4*8, reset=0xd15e)
+ macl = Signal(4*8, reset=0xa5edbeef)
+ self.mac = Signal(6*8)
+ self.comb += self.mac.eq(Cat(macl, mach))
+ self.ip = Signal(4*8, reset=0xc0a80064)
+ self.port = Signal(4*8, reset=0xebd0)
+
+ self.bus = bus = wishbone.Interface()
+ self.submodules.fifo = SyncFIFO(3, _eb_queue_len)
+
+ read_mux = Array([self.errreg[32:], self.errreg[:32], 0,
+ sdb_addr, mach, macl, self.ip, self.port])
+ write_mux = Array([mach, macl, self.ip, self.port])[bus.adr - 4]
+
+ self.dout = read_mux[self.fifo.dout]
+ self.comb += [
+ bus.ack.eq(bus.cyc & bus.stb),
+ bus.dat_r.eq(read_mux[bus.adr[:3]]),
+ ]
+ self.sync += [
+ If(bus.cyc & bus.stb & bus.we & optree("|",
+ [bus.adr[:3] == i for i in (4, 5, 6, 7)]),
+ write_mux.eq(bus.dat_w),
+ )]
+
+class WishboneMaster(Module):
+ def __init__(self, timeout):
+ self.bus = bus = wishbone.Interface()
+ self.submodules.fifo = SyncFIFO(_eb_width + 1, _eb_queue_len)
+
+ self.active = Signal()
+ inflight = Signal(max=_eb_queue_len)
+ queued = Signal(max=_eb_queue_len)
+ self.sync += [
+ inflight.eq(inflight + self.active - self.fifo.we),
+ queued.eq(queued + self.active - self.fifo.re),
+ ]
+
+ self.busy = Signal()
+ self.full = Signal()
+ self.comb += [
+ self.busy.eq(inflight != 0),
+ self.full.eq(queued == _eb_queue_len - 1),
+ ]
+
+ kill_ack = Signal()
+ time = Signal(max=timeout)
+ self.comb += kill_ack.eq(time == timeout - 1)
+ self.sync += [
+ If(self.fifo.we | ~self.busy,
+ time.eq(0),
+ ).Else(
+ time.eq(time + 1),
+ )]
+
+ self.comb += [
+ self.fifo.we.eq(bus.ack | bus.err | kill_ack),
+ self.fifo.din.eq(Cat(bus.dat_r, ~bus.ack)),
+ ]
+
+ self.errreg = Signal(64)
+ self.sync += [
+ If(self.fifo.re,
+ self.errreg.eq(Cat(self.fifo.dout[-1], self.errreg)),
+ )]
+
+class Transmit(Module):
+ def __init__(self, pas, cfg, wbm, tag, tags):
+ self.tx = Source(_eb_layout)
+
+ data = Signal(_eb_width)
+ re = Signal(4)
+ self.tx_cyc = Signal()
+ self.tx_skip = Signal()
+ last_tx_cyc = Signal()
+ last_tx_skip = Signal()
+ readable = Signal()
+
+ self.sync += [
+ last_tx_cyc.eq(self.tx_cyc),
+ last_tx_skip.eq(self.tx_skip),
+ ]
+
+ self.comb += [
+ readable.eq(Cat(tag.readable, pas.readable,
+ cfg.fifo.readable, wbm.readable) & re == re),
+ self.tx.stb.eq(readable & (re[1:] != 0)),
+ self.tx.payload.data.eq(data),
+ Case(tag.dout, {
+ tags["PASS_TX"]: [re.eq(0b0011), data.eq(pas.dout)],
+ tags["PASS_ON"]: [re.eq(0b0011), data.eq(pas.dout)],
+ tags["CFG_REQ"]: [re.eq(0b0101), data.eq(cfg.dout)],
+ tags["CFG_IGN"]: [re.eq(0b0111), data.eq(pas.dout)],
+ tags["WBM_REQ"]: [re.eq(0b1001), data.eq(wbm.dout)],
+ tags["WBM_IGN"]: [re.eq(0b1011), data.eq(pas.dout)],
+ "default": [re.eq(0b0001)],
+ }),
+ If(readable & (self.tx.ack | (re[1:] == 0)),
+ Cat(tag.re, pas.re, cfg.fifo.re, wbm.re).eq(re),
+ ),
+ If(tag.readable,
+ If(tag.dout == tags["PASS_TX"],
+ self.tx_cyc.eq(1),
+ self.tx_skip.eq(0),
+ ).Elif(tag.dout == tags["SKIP_TX"],
+ self.tx_cyc.eq(0),
+ self.tx_skip.eq(1),
+ ).Elif(tag.dout == tags["DROP_TX"],
+ self.tx_cyc.eq(0),
+ self.tx_skip.eq(0),
+ ).Else(
+ self.tx_cyc.eq(last_tx_cyc),
+ self.tx_skip.eq(last_tx_skip),
+ ),
+ ).Else(
+ self.tx_cyc.eq(last_tx_cyc),
+ self.tx_skip.eq(last_tx_skip),
+ ),
+ ]
+
+class Receive(Module):
+ def __init__(self, pas, cfg, wbm, tag, tags):
+ self.rx = Sink(_eb_layout)
+
+ rx_rec_hdr = Record(_eb_rec_hdr)
+ tx_rec_hdr = Record(_eb_rec_hdr)
+ rx_eb_hdr = Record(_eb_hdr)
+ tx_eb_hdr = Record(_eb_hdr)
+ self.comb += [
+ rx_eb_hdr.raw_bits().eq(self.rx.payload.data),
+ tx_eb_hdr.magic.eq(rx_eb_hdr.magic),
+ tx_eb_hdr.ver.eq(_eb_ver),
+ tx_eb_hdr.no_response.eq(1),
+ tx_eb_hdr.addr_size.eq(4),
+ tx_eb_hdr.data_size.eq(4),
+ tx_eb_hdr.probe_res.eq(rx_eb_hdr.probe),
+
+ rx_rec_hdr.raw_bits().eq(self.rx.payload.data),
+ tx_rec_hdr.wca_cfg.eq(rx_rec_hdr.bca_cfg),
+ tx_rec_hdr.wr_fifo.eq(rx_rec_hdr.rd_fifo),
+ tx_rec_hdr.wr_cnt.eq(rx_rec_hdr.rd_cnt),
+ tx_rec_hdr.sel.eq(rx_rec_hdr.sel),
+ tx_rec_hdr.drop_cyc.eq(rx_rec_hdr.drop_cyc),
+ ]
+
+ do_rx = Signal()
+ self.rx_cyc = Signal()
+ self.comb += [
+ wbm.bus.sel.eq(rx_rec_hdr.sel),
+ do_rx.eq(tag.writable & # tag is always written/read
+ self.rx_cyc & self.rx.stb & # have data
+ (wbm.fifo.we | ~wbm.bus.stb) & # stb finished or idle
+ (wbm.bus.cyc | ~wbm.busy)), # in-cycle or idle
+ self.rx.ack.eq(do_rx),
+ cfg.fifo.din.eq(wbm.bus.adr),
+ # no eb-cfg write support yet
+ #cfg.dat_w.eq(wbm.bus.dat_w),
+ #cfg.we.eq(wbm.bus.we),
+ cfg.errreg.eq(wbm.errreg),
+ ]
+
+ cur_rx_rec_hdr = Record(_eb_rec_hdr)
+ cur_tx_rec_hdr = Record(_eb_rec_hdr)
+ do_rec = Signal()
+ do_adr = Signal()
+ do_write = Signal()
+ do_read = Signal()
+ wr_adr = Signal(flen(wbm.bus.adr))
+ old_rx_cyc = Signal()
+ self.sync += [
+ wbm.bus.stb.eq(wbm.bus.stb & ~wbm.fifo.we),
+ wbm.bus.cyc.eq(wbm.bus.cyc & (
+ ~cur_rx_rec_hdr.drop_cyc |
+ (cur_rx_rec_hdr.wr_cnt > 0) |
+ (cur_rx_rec_hdr.rd_cnt > 0))),
+ If(do_rec,
+ cur_rx_rec_hdr.eq(rx_rec_hdr),
+ cur_tx_rec_hdr.eq(tx_rec_hdr),
+ ),
+ If(do_adr,
+ wr_adr.eq(self.rx.payload.data[2:]),
+ ),
+ If(do_write,
+ If(cur_rx_rec_hdr.wca_cfg,
+ cfg.fifo.we.eq(1),
+ ).Else(
+ wbm.bus.cyc.eq(1),
+ wbm.bus.stb.eq(1),
+ ),
+ wbm.bus.we.eq(1),
+ wbm.bus.adr.eq(wr_adr),
+ wbm.bus.dat_w.eq(self.rx.payload.data),
+ If(~cur_rx_rec_hdr.wr_fifo,
+ wr_adr.eq(wr_adr + 1),
+ ),
+ cur_rx_rec_hdr.wr_cnt.eq(cur_rx_rec_hdr.wr_cnt - 1),
+ ),
+ If(do_read,
+ If(cur_rx_rec_hdr.rca_cfg,
+ cfg.fifo.we.eq(1),
+ ).Else(
+ wbm.bus.cyc.eq(1),
+ wbm.bus.stb.eq(1),
+ ),
+ wbm.bus.we.eq(0),
+ wbm.bus.adr.eq(self.rx.payload.data[2:]),
+ cur_rx_rec_hdr.rd_cnt.eq(cur_rx_rec_hdr.rd_cnt - 1),
+ ),
+ If(~self.rx_cyc,
+ wbm.bus.cyc.eq(0),
+ ),
+ old_rx_cyc.eq(self.rx_cyc),
+ ]
+
+ fsm = self.submodules.fsm = FSM()
+ fsm.reset_state = "EB_HDR"
+ fsm.act("EB_HDR",
+ If(do_rx,
+ tag.we.eq(1),
+ If((rx_eb_hdr.magic != _eb_magic) |
+ (rx_eb_hdr.ver !=_eb_ver),
+ tag.din.eq(tags["SKIP_TX"]),
+ NextState("DROP"),
+ ).Else(
+ If(rx_eb_hdr.no_response,
+ tag.din.eq(tags["SKIP_TX"]),
+ ).Else(
+ tag.din.eq(tags["PASS_TX"]),
+ pas.we.eq(1),
+ pas.din.eq(tx_eb_hdr.raw_bits()),
+ ),
+ If(rx_eb_hdr.probe,
+ If(rx_eb_hdr.addr_size[2] &
+ rx_eb_hdr.data_size[2],
+ NextState("PROBE_ID"),
+ ).Else(
+ NextState("PROBE_DROP"),
+ ),
+ ).Else(
+ If((rx_eb_hdr.addr_size == 4) &
+ (rx_eb_hdr.data_size == 4),
+ NextState("CYC_HDR"),
+ ).Else(
+ NextState("DROP"),
+ ),
+ ),
+ ),
+ ))
+ fsm.act("PROBE_DROP",
+ If(do_rx,
+ tag.we.eq(1),
+ tag.din.eq(tags["PASS_ON"]),
+ pas.we.eq(1),
+ pas.din.eq(self.rx.payload.data),
+ NextState("DROP"),
+ ))
+ fsm.act("PROBE_ID",
+ If(do_rx,
+ tag.we.eq(1),
+ tag.din.eq(tags["PASS_ON"]),
+ pas.we.eq(1),
+ pas.din.eq(self.rx.payload.data),
+ NextState("CYC_HDR"),
+ ))
+ fsm.act("CYC_HDR",
+ If(do_rx,
+ do_rec.eq(1),
+ tag.we.eq(1),
+ tag.din.eq(tags["PASS_ON"]),
+ pas.we.eq(1),
+ If(rx_rec_hdr.wr_cnt != 0,
+ NextState("WR_ADR"),
+ ).Else(
+ pas.din.eq(tx_rec_hdr.raw_bits()),
+ If(rx_rec_hdr.rd_cnt != 0,
+ NextState("RD_ADR"),
+ ).Else(
+ NextState("CYC_HDR"),
+ ),
+ ),
+ ))
+ fsm.act("WR_ADR",
+ If(do_rx,
+ do_adr.eq(1),
+ tag.we.eq(1),
+ tag.din.eq(tags["PASS_ON"]),
+ pas.we.eq(1),
+ NextState("WRITE"),
+ ))
+ fsm.act("WRITE",
+ If(do_rx,
+ do_write.eq(1),
+ tag.we.eq(1),
+ If(cur_rx_rec_hdr.wca_cfg,
+ tag.din.eq(tags["CFG_IGN"]),
+ ).Else(
+ wbm.active.eq(1),
+ tag.din.eq(tags["WBM_IGN"]),
+ ),
+ pas.we.eq(1),
+ If(cur_rx_rec_hdr.wr_cnt == 1,
+ pas.din.eq(cur_tx_rec_hdr.raw_bits()),
+ If(cur_rx_rec_hdr.rd_cnt != 0,
+ NextState("RD_ADR"),
+ ).Else(
+ NextState("CYC_HDR"),
+ ),
+ ),
+ ))
+ fsm.act("RD_ADR",
+ If(do_rx,
+ tag.we.eq(1),
+ tag.din.eq(tags["PASS_ON"]),
+ pas.we.eq(1),
+ pas.din.eq(self.rx.payload.data),
+ NextState("READ"),
+ ))
+ fsm.act("READ",
+ If(do_rx,
+ do_read.eq(1),
+ tag.we.eq(1),
+ If(cur_rx_rec_hdr.rca_cfg,
+ tag.din.eq(tags["CFG_REQ"]),
+ ).Else(
+ wbm.active.eq(1),
+ tag.din.eq(tags["WBM_REQ"]),
+ ),
+ If(cur_rx_rec_hdr.rd_cnt == 1,
+ NextState("CYC_HDR"),
+ ),
+ ))
+ fsm.act("DROP",
+ #If(do_rx,
+ # tag.we.eq(1),
+ # tag.din.eq(tags["PASS_ON"]),
+ # pas.we.eq(1),
+ #)
+ )
+ for state in fsm.actions:
+ fsm.act(state, If(~self.rx_cyc, NextState("EB_HDR")))
+ self.comb += [
+ If(~self.rx_cyc,
+ Cat(do_rec, do_adr, do_write, do_read).eq(0),
+ Cat(wbm.active, pas.we).eq(0),
+ If(old_rx_cyc,
+ tag.we.eq(1),
+ tag.din.eq(tags["DROP_TX"]),
+ ),
+ )]
+
+class Slave(Module):
+ def __init__(self, sdb_addr, timeout):
+ tags = dict((k, i) for i, k in enumerate(
+ "DROP_TX SKIP_TX PASS_TX PASS_ON CFG_REQ "
+ "CFG_IGN WBM_REQ WBM_IGN".split()))
+ tag_width = flen(Signal(max=len(tags)))
+
+ self.submodules.pas = SyncFIFO(_eb_width, _eb_queue_len)
+ self.submodules.cfg = Config(sdb_addr)
+ self.submodules.wbm = WishboneMaster(timeout)
+ self.submodules.tag = SyncFIFO(tag_width, _eb_queue_len)
+
+ self.submodules.rxfsm = Receive(self.pas, self.cfg,
+ self.wbm, self.tag, tags)
+ self.rx = self.rxfsm.rx
+ self.rx_cyc = self.rxfsm.rx_cyc
+ self.submodules.txmux = Transmit(self.pas, self.cfg,
+ self.wbm.fifo, self.tag, tags)
+ self.tx = self.txmux.tx
+ self.tx_skip = self.txmux.tx_skip
+ self.tx_cyc = self.txmux.tx_cyc
+ self.busy = self.wbm.busy
+
+class Converter(Module):
+ def __init__(self, raw_width, graph, **slave_kwargs):
+ raw_layout = [("data", raw_width)]
+ pack_factor = _eb_width//raw_width
+
+ self.rx = Sink(raw_layout)
+ rx_pack = Pack(raw_layout, pack_factor)
+ rx_cast = Cast(pack_layout(raw_layout, pack_factor), _eb_layout)
+ self.submodules.slave = Slave(**slave_kwargs)
+ tx_cast = Cast(_eb_layout, pack_layout(raw_layout, pack_factor))
+ tx_unpack = Unpack(pack_factor, raw_layout)
+ self.tx = Source(raw_layout)
+
+ graph.add_connection(self.rx, rx_pack)
+ graph.add_connection(rx_pack, rx_cast)
+ graph.add_connection(rx_cast, self.slave.rx)
+ graph.add_connection(self.slave.tx, tx_cast)
+ graph.add_connection(tx_cast, tx_unpack)
+ graph.add_connection(tx_unpack, self.tx)
+
+class SimTx(SimActor):
+ def __init__(self, data):
+ self.tx = Source(_eb_layout)
+ SimActor.__init__(self, self.gen(data))
+
+ def gen(self, data):
+ for i in data:
+ yield Token("tx", {"data": i})
+ print("eb tx", hex(i))
+
+class SimRx(SimActor):
+ def __init__(self):
+ self.rx = Sink(_eb_layout)
+ self.recv = []
+ SimActor.__init__(self, self.gen())
+
+ def gen(self):
+ while True:
+ t = Token("rx")
+ yield t
+ print("eb rx", hex(t.value["data"]))
+ self.recv.append(t.value["data"])
+
+class TB(Module):
+ def __init__(self, data):
+ ebm_tx = SimTx(data)
+ ebm_rx = SimRx()
+ self.slave = Slave(0x200, 10)
+ g = DataFlowGraph()
+ g.add_connection(ebm_tx, self.slave)
+ g.add_connection(self.slave, ebm_rx)
+ self.submodules.graph = CompositeActor(g)
+ self.submodules.cfg_master = wishbone.Initiator(self.gen_cfg_reads())
+ self.submodules.cfg_tap = wishbone.Tap(self.slave.cfg.bus,
+ lambda l: print("cfg", l))
+ self.submodules.wbm_tap = wishbone.Tap(self.slave.wbm.bus,
+ lambda l: print("wbm", l))
+ self.submodules.xbar = wishbone.Crossbar(
+ [self.cfg_master.bus, self.slave.wbm.bus],
+ [
+ (lambda a: a[6:] == 0x0, wishbone.Target(
+ wishbone.TargetModel()).bus),
+ (lambda a: a[6:] == 0x1, self.slave.cfg.bus),
+ ])
+
+ def gen_cfg_reads(self):
+ for a in range(0x40, 0x40+4):
+ t = TRead(a)
+ yield t
+
+ def do_simulation(self, s):
+ #s.interrupt = self.cfg_master.done
+ s.wr(self.slave.rx_cyc, int(s.cycle_counter < 200))
+
+class MyStruct(object):
+ _data = None
+ _fmt = "!"
+
+ def __init__(self, **kwargs):
+ self.data = self._data(**kwargs)
+
+ def __bytes__(self):
+ return struct.pack(self._fmt, *self.data)
+
+class EbHeader(MyStruct):
+ _data = namedtuple("eb_hdr", "magic ver size")
+ _fmt = "!HBB"
+
+ def __init__(self, probe_id=None, addr_size=4, data_size=4, records=[]):
+ no_response = not any(r.read for r in records)
+ probe = probe_id is not None
+ probe_res = False
+ MyStruct.__init__(self, magic=_eb_magic, ver=(_eb_ver<<4) |
+ (no_response<<2) | (probe_res<<1) | (probe<<0),
+ size=(addr_size<<4) | (data_size<<0))
+ self.probe = struct.pack("!I", probe_id) if probe else b""
+ self.records = records
+
+ def __bytes__(self):
+ return (MyStruct.__bytes__(self) + self.probe +
+ b"".join(map(bytes, self.records)))
+
+class EbRecord(MyStruct):
+ _data = namedtuple("eb_rec", "flags sel wr_cnt rd_cnt")
+ _fmt = "!BBBB"
+
+ def __init__(self, sel=0xf, wr_adr=0, rd_adr=0, write=[], read=[],
+ bca_cfg=False, rca_cfg=False, rd_fifo=False, drop_cyc=False,
+ wca_cfg=False, wr_fifo=False):
+ MyStruct.__init__(self, sel=sel, wr_cnt=len(write),
+ rd_cnt=len(read), flags=(bca_cfg<<7) | (rca_cfg<<6) |
+ (rd_fifo<<5) | (drop_cyc<<3) | (wca_cfg<<2) |
+ (wr_fifo>>1))
+ self.wr_adr = wr_adr
+ self.write = write
+ self.rd_adr = rd_adr
+ self.read = read
+
+ def __bytes__(self):
+ b = MyStruct.__bytes__(self)
+ if self.write:
+ b += struct.pack("!I" + "I"*len(self.write), self.wr_adr,
+ *self.write)
+ if self.read:
+ b += struct.pack("!I" + "I"*len(self.read), self.rd_adr,
+ *self.read)
+ return b
+
+def main():
+ from migen.sim.generic import Simulator, TopLevel
+
+ #from migen.fhdl import verilog
+ #s = Slave(0, 10)
+ #print(verilog.convert(s, ios={s.rx.payload.data, s.tx.payload.data,
+ # s.rx.stb, s.rx.ack, s.tx.stb, s.tx.ack}))
+
+ eb_pkt = EbHeader(records=[
+ EbRecord(wr_adr=0x10, write=[0x20, 0x21],
+ rd_adr=0x30, read=range(0, 8, 4)),
+ EbRecord(rd_adr=0x40, read=range(0x100, 0x100+32, 4),
+ drop_cyc=True),
+ EbRecord(rca_cfg=True, bca_cfg=True, rd_adr=0x50,
+ read=range(0, 0+8, 4), drop_cyc=True),
+ ])
+ eb_pkt = bytes(eb_pkt)
+ eb_pkt = struct.unpack("!" + "I"*(len(eb_pkt)//4), eb_pkt)
+ tb = TB(eb_pkt)
+ sim = Simulator(tb, TopLevel("etherbone.vcd"))
+ sim.run(500)
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
+++ /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))
- ###
- 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.eq(packetizer.sink.ack),
- packetizer.sink.destination_ip_address.eq(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.dscp.eq(0),
- packetizer.sink.ecn.eq(0),
- packetizer.sink.identification.eq(0),
- packetizer.sink.flags.eq(0),
- packetizer.sink.fragment_offset.eq(0),
- packetizer.sink.time_to_live.eq(0x80),
- packetizer.sink.source_ip_address.eq(ip_address)
- ]
- sink = packetizer.source
-
- checksum = LiteEthIPV4Checksum(skip_header=True)
- self.submodules += checksum
- self.comb += [
- checksum.header.eq(packetizer.header),
- packetizer.sink.header_checksum.eq(checksum.value)
- ]
-
- destination_mac_address = Signal(48)
-
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- sink.ack.eq(1),
- If(sink.stb & sink.sop,
- sink.ack.eq(0),
- NextState("SEND_MAC_ADDRESS_REQUEST")
- )
- )
- fsm.act("SEND_MAC_ADDRESS_REQUEST",
- arp_table.request.stb.eq(1),
- arp_table.request.ip_address.eq(self.sink.ip_address),
- If(arp_table.request.stb & arp_table.request.ack,
- NextState("WAIT_MAC_ADDRESS_RESPONSE")
- )
- )
- fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
- # XXX add timeout
- If(arp_table.response.stb,
- arp_table.response.ack.eq(1),
- # XXX manage failed
- NextState("SEND")
- )
- )
- self.sync += If(arp_table.response.stb, destination_mac_address.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.destination_mac_address.eq(destination_mac_address),
- self.source.source_mac_address.eq(mac_address),
- # XXX compute check sum
- If(self.source.stb & self.source.eop & self.source.ack,
- # XXX manage failed
- 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)
-
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- 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.destination_ip_address == ip_address) &
- (sink.version == 0x4) &
- (sink.ihl == 0x5) &
- (checksum.value == 0)
- )
-
- fsm.act("CHECK",
- If(valid,
- NextState("PRESENT")
- ).Else(
- NextState("DROP")
- )
- ),
- fsm.act("PRESENT",
- source.stb.eq(sink.stb),
- source.sop.eq(sink.sop),
- source.eop.eq(sink.eop),
- sink.ack.eq(source.ack),
- source.length.eq(sink.total_length - (sink.ihl*4)),
- source.protocol.eq(sink.protocol),
- source.ip_address.eq(sink.destination_ip_address),
- source.data.eq(sink.data),
- source.error.eq(sink.error),
- 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 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
from liteeth.common import *
from liteeth.mac import LiteEthMAC
-from liteeth.arp import LiteEthARP
+from liteeth.core.arp import LiteEthARP
from liteeth.test.common import *
from liteeth.test.model import phy, mac, arp
class TB(Module):
def __init__(self):
- self.submodules.phy_model = phy.PHY(8, debug=True)
+ self.submodules.phy_model = phy.PHY(8, debug=False)
self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
from migen.sim.generic import run_simulation
from liteeth.common import *
-from liteeth import LiteEthIPStack
+from liteeth.core import LiteEthIPCore
from liteeth.test.common import *
from liteeth.test.model import phy, mac, arp, ip
self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=True)
- self.submodules.ip = LiteEthIPStack(self.phy_model, mac_address, ip_address)
+ self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address)
# use sys_clk for each clock_domain
self.clock_domains.cd_eth_rx = ClockDomain()
+++ /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_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_description(8),
- udp_header,
- udp_header_len)