def eth_arp_description(dw):
layout = _layout_from_header(arp_header) + [
("data", dw),
- ("last_be", dw//8),
("error", dw//8)
]
return EndpointDescription(layout, packetized=True)
def eth_ipv4_description(dw):
layout = _layout_from_header(ipv4_header) + [
("data", dw),
- ("last_be", dw//8),
("error", dw//8)
]
return EndpointDescription(layout, packetized=True)
def eth_udp_description(dw):
layout = _layout_from_header(udp_header) + [
("data", dw),
- ("last_be", dw//8),
("error", dw//8)
]
return EndpointDescription(layout, packetized=True)
+# Generic modules
+@DecorateModule(InsertReset)
+@DecorateModule(InsertCE)
+class Counter(Module):
+ def __init__(self, signal=None, **kwargs):
+ if signal is None:
+ self.value = Signal(**kwargs)
+ else:
+ self.value = signal
+ self.width = flen(self.value)
+ self.sync += self.value.eq(self.value+1)
+
+@DecorateModule(InsertReset)
+@DecorateModule(InsertCE)
+class Timeout(Module):
+ def __init__(self, length):
+ self.reached = Signal()
+ ###
+ value = Signal(max=length)
+ self.sync += value.eq(value+1)
+ self.comb += self.reached.eq(value == length)
+
+class BufferizeEndpoints(ModuleDecorator):
+ def __init__(self, submodule, *args):
+ ModuleDecorator.__init__(self, submodule)
+
+ endpoints = get_endpoints(submodule)
+ sinks = {}
+ sources = {}
+ for name, endpoint in endpoints.items():
+ if name in args or len(args) == 0:
+ if isinstance(endpoint, Sink):
+ sinks.update({name : endpoint})
+ elif isinstance(endpoint, Source):
+ sources.update({name : endpoint})
+
+ # add buffer on sinks
+ for name, sink in sinks.items():
+ buf = Buffer(sink.description)
+ self.submodules += buf
+ setattr(self, name, buf.d)
+ self.comb += Record.connect(buf.q, sink)
+
+ # add buffer on sources
+ for name, source in sources.items():
+ buf = Buffer(source.description)
+ self.submodules += buf
+ self.comb += Record.connect(source, buf.d)
+ setattr(self, name, buf.q)
--- /dev/null
+import math
+
+from liteeth.common import *
+
+def _decode_header(h_dict, h_signal, obj):
+ r = []
+ for k, v in sorted(h_dict.items()):
+ start = v.byte*8+v.offset
+ end = start+v.width
+ r.append(getattr(obj, k).eq(h_signal[start:end]))
+ return r
+
+class LiteEthMACDepacketizer(Module):
+ def __init__(self):
+ self.sink = sink = Sink(eth_mac_description(8))
+ self.source = source = Source(eth_phy_description(8))
+ ###
+ shift = Signal()
+ header = Signal(mac_header_length*8)
+ counter = Counter(max=mac_header_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,
+ shift.eq(1),
+ NextState("RECEIVE_HEADER")
+ )
+ )
+ fsm.act("RECEIVE_HEADER",
+ sink.ack.eq(1),
+ If(sink.stb,
+ counter.ce.eq(1),
+ shift.eq(1),
+ If(counter.value == mac_header_length-2,
+ NextState("COPY")
+ )
+ )
+ )
+ self.sync += \
+ If(fsm.before_entering("COPY"),
+ source.sop.eq(1)
+ ).Elif(source.stb & source.ack,
+ 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),
+ _decode_header(mac_header, header, source)
+ ]
+ fsm.act("COPY",
+ sink.ack.eq(source.ack),
+ source.stb.eq(sink.stb),
+ If(source.stb & source.ack & source.eop,
+ NextState("IDLE")
+ )
+ )
--- /dev/null
+from liteeth.common import *
+
+def _encode_header(h_dict, h_signal, obj):
+ r = []
+ for k, v in sorted(h_dict.items()):
+ start = v.word*32+v.offset
+ end = start+v.width
+ r.append(h_signal[start:end].eq(getattr(obj, k)))
+ return r
+
+class LiteEthMACPacketizer(Module):
+ def __init__(self):
+ self.sink = sink = Sink(eth_phy_description(8))
+ self.source = source = Source(eth_mac_description(8))
+ ###
+ header = Signal(mac_header_length*8)
+ header_reg = Signal(mac_header_length*8)
+ load = Signal()
+ shift = Signal()
+ counter = Counter(max=mac_header_length)
+ self.submodules += counter
+
+ self.comb += header.eq(_encode_header(mac_header, header, sink))
+ self.sync += [
+ If(load,
+ header_reg.eq(header)
+ ).Elif(shift,
+ header_reg.eq(Cat(header_reg[8:], Signal(8)))
+ )
+ ]
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+
+ fsm.act("IDLE",
+ sink.ack.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,
+ NextState("SEND_HEADER"),
+ )
+ )
+ )
+ fsm.act("SEND_HEADER",
+ source.stb.eq(1),
+ source.sop.eq(0),
+ source.eop.eq(sink.eop),
+ source.data.eq(header_reg[8:16]),
+ If(source.stb & source.ack,
+ sink.ack.eq(1),
+ If(counter == mac_header_length-2,
+ NextState("COPY")
+ )
+ )
+ )
+ fsm.act("COPY",
+ source.stb.eq(sink.stb),
+ source.sop.eq(0),
+ source.eop.eq(sink_eop),
+ source.data.eq(sink.data),
+ source.error.eq(sink.error),
+ If(source.stb & source.ack,
+ sink.ack.eq(1),
+ If(source.eop,
+ NextState("IDLE")
+ )
+ )
+ )