mac: add packetizer/depacketizer (untested)
This commit is contained in:
parent
6249209f94
commit
dc5e1aa1ad
|
@ -93,7 +93,6 @@ def eth_mac_description(dw):
|
||||||
def eth_arp_description(dw):
|
def eth_arp_description(dw):
|
||||||
layout = _layout_from_header(arp_header) + [
|
layout = _layout_from_header(arp_header) + [
|
||||||
("data", dw),
|
("data", dw),
|
||||||
("last_be", dw//8),
|
|
||||||
("error", dw//8)
|
("error", dw//8)
|
||||||
]
|
]
|
||||||
return EndpointDescription(layout, packetized=True)
|
return EndpointDescription(layout, packetized=True)
|
||||||
|
@ -101,7 +100,6 @@ def eth_arp_description(dw):
|
||||||
def eth_ipv4_description(dw):
|
def eth_ipv4_description(dw):
|
||||||
layout = _layout_from_header(ipv4_header) + [
|
layout = _layout_from_header(ipv4_header) + [
|
||||||
("data", dw),
|
("data", dw),
|
||||||
("last_be", dw//8),
|
|
||||||
("error", dw//8)
|
("error", dw//8)
|
||||||
]
|
]
|
||||||
return EndpointDescription(layout, packetized=True)
|
return EndpointDescription(layout, packetized=True)
|
||||||
|
@ -109,8 +107,56 @@ def eth_ipv4_description(dw):
|
||||||
def eth_udp_description(dw):
|
def eth_udp_description(dw):
|
||||||
layout = _layout_from_header(udp_header) + [
|
layout = _layout_from_header(udp_header) + [
|
||||||
("data", dw),
|
("data", dw),
|
||||||
("last_be", dw//8),
|
|
||||||
("error", dw//8)
|
("error", dw//8)
|
||||||
]
|
]
|
||||||
return EndpointDescription(layout, packetized=True)
|
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)
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
)
|
|
@ -0,0 +1,73 @@
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
Loading…
Reference in New Issue