etherbone: add record depacketizer/packetizer (wip)

This commit is contained in:
Florent Kermarrec 2015-02-11 16:21:06 +01:00
parent 247c30ae26
commit abe6d87438
9 changed files with 203 additions and 62 deletions

View File

@ -141,6 +141,13 @@ def _remove_from_layout(layout, *args):
r.append(f)
return r
def eth_raw_description(dw):
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, packetized=True)
def eth_phy_description(dw):
payload_layout = [
("data", dw),
@ -250,14 +257,20 @@ def eth_etherbone_packet_description(dw):
return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_etherbone_packet_user_description(dw):
payload_layout = [("data", dw)]
payload_layout = [
("data", dw),
("error", dw//8)
]
param_layout = _layout_from_header(etherbone_packet_header)
param_layout = _remove_from_layout(param_layout, "magic", "portsize", "addrsize", "version")
param_layout += eth_udp_user_description(dw).param_layout
return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_etherbone_record_description(dw):
payload_layout = [("data", dw)]
payload_layout = [
("data", dw),
("error", dw//8)
]
param_layout = _layout_from_header(etherbone_record_header)
return EndpointDescription(payload_layout, param_layout, packetized=True)

View File

@ -1,30 +1,21 @@
from liteeth.common import *
from liteeth.core.etherbone import common
from liteeth.generic.arbiter import Arbiter
from liteeth.generic.dispatcher import Dispatcher
from liteeth.core.etherbone.packet import *
from liteeth.core.etherbone.probe import *
from liteeth.core.etherbone.record import *
class LiteEthEtherbone(Module):
def __init__(self, udp, udp_port):
self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port)
self.submodules.probe = probe = LiteEthEtherboneProbe()
self.submodules.record = record = LiteEthEtherboneRecord()
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
packet.source.ack.eq(1),
If(packet.source.stb & packet.source.sop,
If(packet.source.pf,
packet.source.ack.eq(0),
NextState("SEND_PROBE_RESPONSE")
)
)
)
fsm.act("SEND_PROBE_RESPONSE",
packet.sink.stb.eq(1),
packet.sink.sop.eq(1),
packet.sink.eop.eq(1),
packet.sink.pr.eq(1),
packet.sink.ip_address.eq(packet.source.ip_address),
packet.sink.length.eq(0),
If(packet.sink.ack,
packet.source.ack.eq(1),
NextState("IDLE")
)
)
dispatcher = Dispatcher(packet.source, [probe.sink, record.sink])
self.comb += dispatcher.sel.eq(~packet.source.pf)
self.submodules += dispatcher
arbiter = Arbiter([probe.source, record.source], packet.sink)
self.submodules += arbiter

View File

@ -1 +0,0 @@
from liteeth.common import *

View File

@ -1,5 +1,4 @@
from liteeth.common import *
from liteeth.core.etherbone import common
class LiteEthEtherboneWishboneMaster(Module):
def __init__(self):

View File

@ -1,7 +1,6 @@
from liteeth.common import *
from liteeth.generic.depacketizer import LiteEthDepacketizer
from liteeth.generic.packetizer import LiteEthPacketizer
from liteeth.core.etherbone import common
class LiteEthEtherbonePacketPacketizer(LiteEthPacketizer):
def __init__(self):

View File

@ -0,0 +1,24 @@
from liteeth.common import *
class LiteEthEtherboneProbe(Module):
def __init__(self):
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
self.source = source = Source(eth_etherbone_packet_user_description(32))
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
sink.ack.eq(1),
If(sink.stb & sink.sop,
sink.ack.eq(0),
NextState("PROBE_RESPONSE")
)
)
fsm.act("PROBE_RESPONSE",
Record.connect(sink, source),
source.pf.eq(0),
source.pr.eq(1),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)

View File

@ -0,0 +1,88 @@
from liteeth.common import *
from liteeth.generic.depacketizer import LiteEthDepacketizer
from liteeth.generic.packetizer import LiteEthPacketizer
class LiteEthEtherboneRecordPacketizer(LiteEthPacketizer):
def __init__(self):
LiteEthPacketizer.__init__(self,
eth_etherbone_record_description(32),
eth_raw_description(32),
etherbone_record_header,
etherbone_record_header_len)
class LiteEthEtherboneRecordTX(Module):
def __init__(self):
self.sink = sink = Sink(eth_etherbone_record_description(32))
self.source = source = Source(eth_raw_description(32))
###
self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer()
self.comb += Record.connect(sink, packetizer.sink)
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
packetizer.source.ack.eq(1),
If(packetizer.source.stb & packetizer.source.sop,
packetizer.source.ack.eq(0),
NextState("SEND")
)
)
fsm.act("SEND",
Record.connect(packetizer.source, source),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)
class LiteEthEtherboneRecordDepacketizer(LiteEthDepacketizer):
def __init__(self):
LiteEthDepacketizer.__init__(self,
eth_raw_description(32),
eth_etherbone_record_description(32),
etherbone_record_header,
etherbone_record_header_len)
class LiteEthEtherboneRecordRX(Module):
def __init__(self):
self.sink = sink = Sink(eth_raw_description(32))
self.source = source = Source(eth_etherbone_record_description(32))
###
self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer()
self.comb += Record.connect(sink, depacketizer.sink)
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
depacketizer.source.ack.eq(1),
If(depacketizer.source.stb & depacketizer.source.sop,
depacketizer.source.ack.eq(0),
NextState("CHECK")
)
)
valid = Signal()
self.sync += valid.eq(1) # XXX
fsm.act("CHECK",
If(valid,
NextState("PRESENT")
).Else(
NextState("DROP")
)
)
fsm.act("PRESENT",
Record.connect(depacketizer.source, source),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)
fsm.act("DROP",
depacketizer.source.ack.eq(1),
If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack,
NextState("IDLE")
)
)
class LiteEthEtherboneRecord(Module):
def __init__(self):
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
self.source = source = Sink(eth_etherbone_packet_user_description(32))
###
self.submodules.record_tx = record_tx = LiteEthEtherboneRecordTX()
self.submodules.record_rx = record_rx = LiteEthEtherboneRecordRX()

View File

@ -16,10 +16,18 @@ class LiteEthDepacketizer(Module):
###
dw = flen(sink.data)
header_words = (header_length*8)//dw
shift = Signal()
counter = Counter(max=header_length//(dw//8))
counter = Counter(max=max(header_words, 2))
self.submodules += counter
if header_words == 1:
self.sync += \
If(shift,
self.header.eq(sink.data)
)
else:
self.sync += \
If(shift,
self.header.eq(Cat(self.header[dw:], sink.data))
@ -28,20 +36,26 @@ class LiteEthDepacketizer(Module):
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
if header_words == 1:
idle_next_state = "COPY"
else:
idle_next_state = "RECEIVE_HEADER"
fsm.act("IDLE",
sink.ack.eq(1),
counter.reset.eq(1),
If(sink.stb,
shift.eq(1),
NextState("RECEIVE_HEADER")
NextState(idle_next_state)
)
)
if header_words != 1:
fsm.act("RECEIVE_HEADER",
sink.ack.eq(1),
If(sink.stb,
counter.ce.eq(1),
shift.eq(1),
If(counter.value == header_length//(dw//8)-2,
If(counter.value == header_words-2,
NextState("COPY")
)
)

View File

@ -17,12 +17,20 @@ class LiteEthPacketizer(Module):
dw = flen(self.sink.data)
header_reg = Signal(header_length*8)
header_words = (header_length*8)//dw
load = Signal()
shift = Signal()
counter = Counter(max=header_length//(dw//8))
counter = Counter(max=max(header_words, 2))
self.submodules += counter
self.comb += _encode_header(header_type, self.header, sink)
if header_words == 1:
self.sync += [
If(load,
header_reg.eq(self.header)
)
]
else:
self.sync += [
If(load,
header_reg.eq(self.header)
@ -34,6 +42,11 @@ class LiteEthPacketizer(Module):
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
if header_words == 1:
idle_next_state = "COPY"
else:
idle_next_state = "SEND_HEADER"
fsm.act("IDLE",
sink.ack.eq(1),
counter.reset.eq(1),
@ -45,19 +58,20 @@ class LiteEthPacketizer(Module):
source.data.eq(self.header[:dw]),
If(source.stb & source.ack,
load.eq(1),
NextState("SEND_HEADER"),
NextState(idle_next_state)
)
)
)
if header_words != 1:
fsm.act("SEND_HEADER",
source.stb.eq(1),
source.sop.eq(0),
source.eop.eq(sink.eop & (counter.value == header_length//(dw//8)-2)),
source.eop.eq(sink.eop & (counter.value == header_words-2)),
source.data.eq(header_reg[dw:2*dw]),
If(source.stb & source.ack,
shift.eq(1),
counter.ce.eq(1),
If(counter.value == header_length//(dw//8)-2,
If(counter.value == header_words-2,
NextState("COPY")
)
)