eth_mac_description(8),
eth_arp_description(8),
arp_header,
- arp_header_length)
+ arp_header_len)
-class LiteEthARPPacketizer(LiteEthDepacketizer):
+class LiteEthARPPacketizer(LiteEthPacketizer):
def __init__(self):
- LiteEthDepacketizer.__init__(self,
+ LiteEthPacketizer.__init__(self,
eth_arp_description(8),
eth_mac_description(8),
arp_header,
- arp_header_length)
+ arp_header_len)
class LiteSATACommandTX(Module):
def __init__(self, transport):
self.sink = sink = Sink(_arp_table_description())
self.source = Source(eth_mac_description(8))
###
- packetiser = LiteEthARPPacketizer()
+ 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),
- If(sink.stb & sink.sop,
+ counter.reset.eq(1),
+ If(sink.stb,
+ sink.ack.eq(0),
NextState("SEND")
)
)
source.destination_ip_address.eq(sink.ip_address)
)
]
- fsm.act("SEND_REQUEST",
+ 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),
- If(self.source.stb & self.source.eop & self.source.ack,
- NextState("IDLE")
+ 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(1),
+ counter.ce.eq(1),
+ If(self.source.eop,
+ NextState("IDLE")
+ )
)
)
self.sink = Sink(eth_mac_description(8))
self.source = source = Source(_arp_table_description())
###
- depacketiser = LiteEthARPDepacketizer()
+ depacketizer = LiteEthARPDepacketizer()
self.submodules += depacketizer
self.comb += Record.connect(self.sink, depacketizer.sink)
sink = depacketizer.source
source.reply.eq(reply),
source.request.eq(request)
),
- NextState.eq("TERMINATE")
+ NextState("TERMINATE")
),
fsm.act("TERMINATE",
sink.ack.eq(1),
- If(sink.stb & sink.source.eop & sink.source.ack,
+ If(sink.stb & sink.eop,
NextState("IDLE")
)
)
fsm.act("CHECK_TABLE",
# XXX add a kind of CAM?
If(found,
- NexState.eq("PRESENT_RESPONSE")
+ NextState("PRESENT_RESPONSE")
).Else(
- NextState.eq("SEND_REQUEST")
+ NextState("SEND_REQUEST")
)
)
fsm.act("SEND_REQUEST",
source.sop.eq(0)
)
self.comb += [
- source.sop.eq(sop),
source.eop.eq(sink.eop),
source.data.eq(sink.data),
source.error.eq(sink.error),
from liteeth.common import *
+import math
+
+def reverse_bytes(v):
+ n = math.ceil(flen(v)//8)
+ r = []
+ for i in reversed(range(n)):
+ r.append(v[i*8:min((i+1)*8, flen(v))])
+ return Cat(iter(r))
def _encode_header(h_dict, h_signal, obj):
r = []
for k, v in sorted(h_dict.items()):
- start = v.word*32+v.offset
+ start = v.byte*8+v.offset
end = start+v.width
- r.append(h_signal[start:end].eq(getattr(obj, k)))
+ r.append(h_signal[start:end].eq(reverse_bytes(getattr(obj, k))))
return r
class LiteEthPacketizer(Module):
counter = Counter(max=header_length)
self.submodules += counter
- self.comb += header.eq(_encode_header(header_type, header, sink))
+ self.comb += _encode_header(header_type, header, sink)
self.sync += [
If(load,
header_reg.eq(header)
fsm.act("IDLE",
sink.ack.eq(1),
+ counter.reset.eq(1),
If(sink.stb & sink.sop,
- load.eq(1),
sink.ack.eq(0),
source.stb.eq(1),
source.sop.eq(1),
source.eop.eq(0),
source.data.eq(header[:8]),
If(source.stb & source.ack,
+ load.eq(1),
NextState("SEND_HEADER"),
)
)
source.eop.eq(sink.eop),
source.data.eq(header_reg[8:16]),
If(source.stb & source.ack,
- sink.ack.eq(1),
- If(counter == header_length-2,
+ shift.eq(1),
+ counter.ce.eq(1),
+ If(counter.value == header_length-2,
NextState("COPY")
)
)
fsm.act("COPY",
source.stb.eq(sink.stb),
source.sop.eq(0),
- source.eop.eq(sink_eop),
+ source.eop.eq(sink.eop),
source.data.eq(sink.data),
source.error.eq(sink.error),
If(source.stb & source.ack,
eth_mac_description(8),
eth_ipv4_description(8),
ipv4_header,
- ipv4_header_length)
+ ipv4_header_len)
-class LiteEthIPV4Packetizer(LiteEthDepacketizer):
+class LiteEthIPV4Packetizer(LiteEthPacketizer):
def __init__(self):
- LiteEthDepacketizer.__init__(self,
+ LiteEthPacketizer.__init__(self,
eth_ipv4_description(8),
eth_mac_description(8),
ipv4_header,
- ipv4_header_length)
+ ipv4_header_len)
eth_phy_description(8),
eth_mac_description(8),
mac_header,
- mac_header_length)
+ mac_header_len)
-class LiteEthMACPacketizer(LiteEthDepacketizer):
+class LiteEthMACPacketizer(LiteEthPacketizer):
def __init__(self):
- LiteEthDepacketizer.__init__(self,
+ LiteEthPacketizer.__init__(self,
eth_mac_description(8),
eth_phy_description(8),
mac_header,
- mac_header_length)
+ mac_header_len)
class LiteEthMAC(Module, AutoCSR):
def __init__(self, phy, dw, interface="mac", endianness="be",
Record.connect(self.core.source, depacketizer.sink)
]
self.sink, self.source = packetizer.sink, depacketizer.source
+ pass
elif interface == "wishbone":
self.submodules.interface = wishbone.LiteEthMACWishboneInterface(dw, 2, 2)
self.comb += [
def __init__(self, phy, dw, endianness="be", with_hw_preamble_crc=True):
if dw < phy.dw:
raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw))
+
+ rx_pipeline = [phy]
+ tx_pipeline = [phy]
+
# Preamble / CRC (optional)
if with_hw_preamble_crc:
self._hw_preamble_crc = CSRStatus(reset=1)
self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
- # Delimiters
- tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
- rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
- self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
- self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
+ tx_pipeline += [preamble_inserter, crc32_inserter]
+ rx_pipeline += [preamble_checker, crc32_checker]
+
+ if dw != phy.dw:
+ # Delimiters
+ tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
+ rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
+ self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
+ self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
- # Converters
- reverse = endianness == "be"
- tx_converter = Converter(eth_phy_description(dw), eth_phy_description(phy.dw), reverse=reverse)
- rx_converter = Converter(eth_phy_description(phy.dw), eth_phy_description(dw), reverse=reverse)
- self.submodules += RenameClockDomains(tx_converter, "eth_tx")
- self.submodules += RenameClockDomains(rx_converter, "eth_rx")
+ # Converters
+ reverse = endianness == "be"
+ tx_converter = Converter(eth_phy_description(dw), eth_phy_description(phy.dw), reverse=reverse)
+ rx_converter = Converter(eth_phy_description(phy.dw), eth_phy_description(dw), reverse=reverse)
+ self.submodules += RenameClockDomains(tx_converter, "eth_tx")
+ self.submodules += RenameClockDomains(rx_converter, "eth_rx")
+
+ tx_pipeline += [tx_last_be, tx_converter]
+ rx_pipeline += [rx_last_be, rx_converter]
# Cross Domain Crossing
tx_cdc = AsyncFIFO(eth_phy_description(dw), 4)
self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
+ tx_pipeline += [tx_cdc]
+ rx_pipeline += [rx_cdc]
+
# Graph
- if with_hw_preamble_crc:
- rx_pipeline = [phy, preamble_checker, crc32_checker, rx_last_be, rx_converter, rx_cdc]
- tx_pipeline = [tx_cdc, tx_converter, tx_last_be, crc32_inserter, preamble_inserter, phy]
- else:
- rx_pipeline = [phy, rx_last_be, rx_converter, rx_cdc]
- tx_pipeline = [tx_cdc, tx_converter, tx_last_be, phy]
+ self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
- self.submodules.tx_pipeline = Pipeline(*tx_pipeline)
self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
mac_wishbone_tb:
$(CMD) mac_wishbone_tb.py
+
+arp_tb:
+ $(CMD) arp_tb.py
--- /dev/null
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.bus.transactions import *
+from migen.sim.generic import run_simulation
+
+from liteeth.common import *
+from liteeth.mac import LiteEthMAC
+from liteeth.arp import LiteEthARP
+
+from liteeth.test.common import *
+from liteeth.test.model import phy, mac, arp
+
+ip_address = 0x12345678
+mac_address = 0x12345678abcd
+
+class TB(Module):
+ def __init__(self):
+ self.submodules.phy_model = phy.PHY(8, debug=True)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=True, loopback=False)
+ self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=True)
+
+ self.submodules.core = LiteEthMAC(phy=self.phy_model, dw=8, with_hw_preamble_crc=True)
+ self.submodules.arp = LiteEthARP(mac_address, ip_address)
+
+ # use sys_clk for each clock_domain
+ self.clock_domains.cd_eth_rx = ClockDomain()
+ self.clock_domains.cd_eth_tx = ClockDomain()
+ self.comb += [
+ self.cd_eth_rx.clk.eq(ClockSignal()),
+ self.cd_eth_rx.rst.eq(ResetSignal()),
+ self.cd_eth_tx.clk.eq(ClockSignal()),
+ self.cd_eth_tx.rst.eq(ResetSignal()),
+ ]
+
+ self.comb += [
+ Record.connect(self.arp.source, self.core.sink),
+ Record.connect(self.core.source, self.arp.sink)
+ ]
+
+ def gen_simulation(self, selfp):
+ selfp.cd_eth_rx.rst = 1
+ selfp.cd_eth_tx.rst = 1
+ yield
+ selfp.cd_eth_rx.rst = 0
+ selfp.cd_eth_tx.rst = 0
+
+ for i in range(100):
+ yield
+
+ selfp.arp.table.request.ip_address = 0x12345678
+ selfp.arp.table.request.stb = 1
+
+if __name__ == "__main__":
+ run_simulation(TB(), ncycles=256, vcd_name="my.vcd", keep_files=True)
from liteeth.mac.common import *
from liteeth.test.common import *
+from liteeth.test.model import mac
+
def print_arp(s):
print_with_prefix(s, "[ARP]")
return r
class ARP(Module):
- def __init__(self, mac, ip_address, mac_address, debug=False):
+ def __init__(self, mac, mac_address, ip_address, debug=False):
self.mac = mac
+ self.mac_address = mac_address
self.ip_address = ip_address
- self.mac_address = mac_addres
self.debug = debug
self.tx_packets = []
self.tx_packet = ARPPacket()
self.mac.set_arp_callback(self.callback)
def send(self, packet):
+ packet.encode()
if self.debug:
print_arp(">>>>>>>>")
print_arp(packet)
- packet.encode()
- self.mac.send(MACPacket(packet))
+ mac_packet = mac.MACPacket(packet)
+ mac_packet.destination_mac_address = packet.destination_mac_address
+ mac_packet.source_mac_address = packet.source_mac_address
+ mac_packet.ethernet_type = ethernet_type_arp
+ self.mac.send(mac_packet)
def callback(self, packet):
- packet = ARPPacket(datas)
+ packet = ARPPacket(packet)
packet.decode()
if self.debug:
print_arp("<<<<<<<<")
print_arp(packet)
- self.process_packet()
+ self.process(packet)
def process(self, packet):
- if len(packet) != arp_packet_length-arp_header_length:
+ if len(packet) != arp_packet_length-arp_header_len:
raise ValueError
if packet.hardware_type != arp_hwtype_ethernet:
raise ValueError
def process_request(self, request):
if request.destination_ip_address == self.ip_address:
- reply = ARPPacket([0]*(arp_packet_length-arp_header_length))
+ reply = ARPPacket([0]*(arp_packet_length-arp_header_len))
reply.hardware_type = arp_hwtype_ethernet
reply.protocol_type = arp_proto_ip
+ reply.operation = arp_opcode_reply
reply.hardware_address_length = 6
reply.protocol_address_length = 4
reply.source_mac_address = self.mac_address
self.table[reply.source_ip_address] = reply.source_mac_address
def request(self, ip_address):
- request = ARPPacket([0]*(arp_packet_length-arp_header_length))
+ request = ARPPacket([0]*(arp_packet_length-arp_header_len))
request.hardware_type = arp_hwtype_ethernet
request.protocol_type = arp_proto_ip
+ request.operation = arp_opcode_request
request.hardware_address_length = 6
request.protocol_address_length = 4
request.source_mac_address = self.mac_address
if self.loopback:
self.send(packet)
else:
- if self.ethernet_type == ethernet_type_ip:
+ if packet.ethernet_type == ethernet_type_ip:
if self.ip_callback is not None:
self.ip_callback(packet)
- elif self.ethernet_type == ethernet_type_arp:
+ elif packet.ethernet_type == ethernet_type_arp:
if self.arp_callback is not None:
self.arp_callback(packet)
else:
eth_ipv4_description(8),
eth_udp_description(8),
udp_header,
- udp_header_length)
+ udp_header_len)
-class LiteEthUDPPacketizer(LiteEthDepacketizer):
+class LiteEthUDPPacketizer(LiteEthPacketizer):
def __init__(self):
- LiteEthDepacketizer.__init__(self,
+ LiteEthPacketizer.__init__(self,
eth_udp_description(8),
eth_ipv4_description(8),
udp_header,
- udp_header_length)
+ udp_header_len)