mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
etherbone: record wip
This commit is contained in:
parent
abe6d87438
commit
384fc3c868
2 changed files with 136 additions and 56 deletions
|
@ -274,6 +274,17 @@ def eth_etherbone_record_description(dw):
|
||||||
param_layout = _layout_from_header(etherbone_record_header)
|
param_layout = _layout_from_header(etherbone_record_header)
|
||||||
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
||||||
|
|
||||||
|
def eth_etherbone_mmap_description(dw):
|
||||||
|
payload_layout = [
|
||||||
|
("data_addr", max(32, dw)),
|
||||||
|
]
|
||||||
|
param_layout = [
|
||||||
|
("count", 8),
|
||||||
|
("base_addr", 32),
|
||||||
|
("be", dw//8)
|
||||||
|
]
|
||||||
|
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
||||||
|
|
||||||
# Generic classes
|
# Generic classes
|
||||||
class Port:
|
class Port:
|
||||||
def connect(self, port):
|
def connect(self, port):
|
||||||
|
@ -377,10 +388,9 @@ class PacketBuffer(Module):
|
||||||
return EndpointDescription(layout)
|
return EndpointDescription(layout)
|
||||||
cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
|
cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
|
||||||
self.submodules += cmd_fifo
|
self.submodules += cmd_fifo
|
||||||
self.comb += [
|
self.comb += cmd_fifo.sink.stb.eq(sink_status.done)
|
||||||
cmd_fifo.sink.stb.eq(sink_status.done),
|
if hasattr(sink, "error"):
|
||||||
cmd_fifo.sink.error.eq(sink.error)
|
self.comb += cmd_fifo.sink.error.eq(sink.error)
|
||||||
]
|
|
||||||
|
|
||||||
# data
|
# data
|
||||||
data_fifo = SyncFIFO(description, data_depth, buffered=True)
|
data_fifo = SyncFIFO(description, data_depth, buffered=True)
|
||||||
|
@ -406,9 +416,14 @@ class PacketBuffer(Module):
|
||||||
NextState("OUTPUT")
|
NextState("OUTPUT")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if hasattr(source, "error"):
|
||||||
|
source_error = self.source.error
|
||||||
|
else:
|
||||||
|
source_error = Signal()
|
||||||
|
|
||||||
fsm.act("OUTPUT",
|
fsm.act("OUTPUT",
|
||||||
Record.connect(data_fifo.source, self.source),
|
Record.connect(data_fifo.source, self.source),
|
||||||
self.source.error.eq(cmd_fifo.source.error),
|
source_error.eq(cmd_fifo.source.error),
|
||||||
If(source_status.done,
|
If(source_status.done,
|
||||||
cmd_fifo.source.ack.eq(1),
|
cmd_fifo.source.ack.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
|
|
|
@ -6,83 +6,148 @@ class LiteEthEtherboneRecordPacketizer(LiteEthPacketizer):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
LiteEthPacketizer.__init__(self,
|
LiteEthPacketizer.__init__(self,
|
||||||
eth_etherbone_record_description(32),
|
eth_etherbone_record_description(32),
|
||||||
eth_raw_description(32),
|
eth_etherbone_packet_user_description(32),
|
||||||
etherbone_record_header,
|
etherbone_record_header,
|
||||||
etherbone_record_header_len)
|
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):
|
class LiteEthEtherboneRecordDepacketizer(LiteEthDepacketizer):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
LiteEthDepacketizer.__init__(self,
|
LiteEthDepacketizer.__init__(self,
|
||||||
eth_raw_description(32),
|
eth_etherbone_packet_user_description(32),
|
||||||
eth_etherbone_record_description(32),
|
eth_etherbone_record_description(32),
|
||||||
etherbone_record_header,
|
etherbone_record_header,
|
||||||
etherbone_record_header_len)
|
etherbone_record_header_len)
|
||||||
|
|
||||||
class LiteEthEtherboneRecordRX(Module):
|
class LiteEthEtherboneRecordReceiver(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sink = sink = Sink(eth_raw_description(32))
|
self.sink = sink = Sink(eth_etherbone_record_description(32))
|
||||||
self.source = source = Source(eth_etherbone_record_description(32))
|
self.write_source = write_source = Source(eth_etherbone_mmap_description(32))
|
||||||
|
self.read_source = read_source = Source(eth_etherbone_mmap_description(32))
|
||||||
###
|
###
|
||||||
self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer()
|
|
||||||
self.comb += Record.connect(sink, depacketizer.sink)
|
self.submodules.base_addr = base_addr = FlipFlop(32)
|
||||||
|
self.comb += base_addr.d.eq(sink.data)
|
||||||
|
|
||||||
|
self.submodules.counter = counter = Counter(max=512)
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
depacketizer.source.ack.eq(1),
|
sink.ack.eq(1),
|
||||||
If(depacketizer.source.stb & depacketizer.source.sop,
|
counter.reset.eq(1),
|
||||||
depacketizer.source.ack.eq(0),
|
If(sink.stb & sink.sop,
|
||||||
NextState("CHECK")
|
base_addr.ce.eq(1),
|
||||||
|
If(sink.wcount,
|
||||||
|
NextState("RECEIVE_READS")
|
||||||
|
).Elif(sink.rcount,
|
||||||
|
NextState("RECEIVE_READS")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
valid = Signal()
|
fsm.act("RECEIVE_WRITES",
|
||||||
self.sync += valid.eq(1) # XXX
|
write_source.stb.eq(sink.stb),
|
||||||
fsm.act("CHECK",
|
write_source.sop.eq(counter.value == 0),
|
||||||
If(valid,
|
write_source.eop.eq(counter.value == sink.wcount-1),
|
||||||
NextState("PRESENT")
|
write_source.count.eq(sink.wcount),
|
||||||
).Else(
|
write_source.base_addr.eq(base_addr.q),
|
||||||
NextState("DROP")
|
write_source.data_addr.eq(sink.data),
|
||||||
|
sink.ack.eq(write_source.ack),
|
||||||
|
If(write_source.stb & write_source.ack,
|
||||||
|
counter.ce.eq(1),
|
||||||
|
If(write_source.eop,
|
||||||
|
If(sink.rcount,
|
||||||
|
NextState("RECEIVE_BASE_RET_ADDR")
|
||||||
|
).Else(
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("PRESENT",
|
fsm.act("RECEIVE_BASE_RET_ADDR",
|
||||||
Record.connect(depacketizer.source, source),
|
counter.reset.eq(1),
|
||||||
|
If(sink.stb & sink.sop,
|
||||||
|
base_addr.ce.eq(1),
|
||||||
|
NextState("RECEIVE_READS")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("RECEIVE_READS",
|
||||||
|
read_source.stb.eq(sink.stb),
|
||||||
|
read_source.sop.eq(counter.value == 0),
|
||||||
|
read_source.eop.eq(counter.value == sink.rcount-1),
|
||||||
|
read_source.count.eq(sink.rcount),
|
||||||
|
read_source.base_addr.eq(base_addr.q),
|
||||||
|
read_source.data_addr.eq(sink.data),
|
||||||
|
sink.ack.eq(read_source.ack),
|
||||||
|
If(read_source.stb & read_source.ack,
|
||||||
|
counter.ce.eq(1),
|
||||||
|
If(read_source.eop,
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Note: for now only support writes from the FPGA
|
||||||
|
class LiteEthEtherboneRecordSender(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.wr_sink = wr_sink = Sink(eth_etherbone_mmap_description(32))
|
||||||
|
self.rd_sink = rd_sink = Sink(eth_etherbone_mmap_description(32))
|
||||||
|
self.source = source = Source(eth_etherbone_record_description(32))
|
||||||
|
###
|
||||||
|
self.submodules.wr_buffer = wr_buffer = PacketBuffer(eth_etherbone_mmap_description(32), 512)
|
||||||
|
self.comb += Record.connect(wr_sink, wr_buffer.sink)
|
||||||
|
|
||||||
|
self.submodules.base_addr = base_addr = FlipFlop(32)
|
||||||
|
self.comb += base_addr.d.eq(wr_buffer.source.data_addr)
|
||||||
|
|
||||||
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
|
fsm.act("IDLE",
|
||||||
|
wr_buffer.source.ack.eq(1),
|
||||||
|
If(wr_buffer.source.stb & wr_buffer.source.sop,
|
||||||
|
wr_buffer.source.ack.eq(0),
|
||||||
|
base_addr.ce.eq(1),
|
||||||
|
NextState("SEND_BASE_ADDRESS")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.comb += [
|
||||||
|
source.byte_enable.eq(wr_buffer.source.be),
|
||||||
|
source.wcount.eq(wr_buffer.source.count),
|
||||||
|
source.rcount.eq(0)
|
||||||
|
]
|
||||||
|
|
||||||
|
fsm.act("SEND_BASE_ADDRESS",
|
||||||
|
source.stb.eq(wr_buffer.source.stb),
|
||||||
|
source.sop.eq(1),
|
||||||
|
source.eop.eq(0),
|
||||||
|
source.data.eq(base_addr.q),
|
||||||
|
If(source.ack,
|
||||||
|
NextState("SEND_DATA")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("SEND_DATA",
|
||||||
|
source.stb.eq(wr_buffer.source.stb),
|
||||||
|
source.sop.eq(0),
|
||||||
|
source.eop.eq(wr_buffer.source.eop),
|
||||||
|
source.data.eq(wr_buffer.source.data_addr),
|
||||||
If(source.stb & source.eop & source.ack,
|
If(source.stb & source.eop & source.ack,
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("DROP",
|
|
||||||
depacketizer.source.ack.eq(1),
|
|
||||||
If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack,
|
|
||||||
NextState("IDLE")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# Note: for now only support 1 record per packet
|
||||||
class LiteEthEtherboneRecord(Module):
|
class LiteEthEtherboneRecord(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
|
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
|
||||||
self.source = source = 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.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer()
|
||||||
self.submodules.record_rx = record_rx = LiteEthEtherboneRecordRX()
|
self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver()
|
||||||
|
self.comb += [
|
||||||
|
Record.connect(sink, depacketizer.sink),
|
||||||
|
Record.connect(depacketizer.source, receiver.sink)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.submodules.sender = sender = LiteEthEtherboneRecordSender()
|
||||||
|
self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer()
|
||||||
|
self.comb += [
|
||||||
|
Record.connect(sender.source, packetizer.sink),
|
||||||
|
Record.connect(packetizer.source, source)
|
||||||
|
]
|
||||||
|
|
Loading…
Reference in a new issue