mac: add packetizer/depacketizer (untested)

This commit is contained in:
Florent Kermarrec 2015-01-29 00:02:50 +01:00
parent 6249209f94
commit dc5e1aa1ad
3 changed files with 185 additions and 3 deletions

View File

@ -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)

View File

@ -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")
)
)

View File

@ -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")
)
)
)