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):
|
||||
layout = _layout_from_header(arp_header) + [
|
||||
("data", dw),
|
||||
("last_be", dw//8),
|
||||
("error", dw//8)
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
@ -101,7 +100,6 @@ def eth_arp_description(dw):
|
|||
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)
|
||||
|
@ -109,8 +107,56 @@ def eth_ipv4_description(dw):
|
|||
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)
|
||||
|
|
|
@ -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