From 384fc3c868212af0933a15c0a9731246746c8962 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 11 Feb 2015 18:37:59 +0100 Subject: [PATCH] etherbone: record wip --- liteeth/common.py | 25 ++++- liteeth/core/etherbone/record.py | 157 ++++++++++++++++++++++--------- 2 files changed, 131 insertions(+), 51 deletions(-) diff --git a/liteeth/common.py b/liteeth/common.py index dcfb0516..3142beb7 100644 --- a/liteeth/common.py +++ b/liteeth/common.py @@ -274,6 +274,17 @@ def eth_etherbone_record_description(dw): param_layout = _layout_from_header(etherbone_record_header) 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 class Port: def connect(self, port): @@ -377,10 +388,9 @@ class PacketBuffer(Module): return EndpointDescription(layout) cmd_fifo = SyncFIFO(cmd_description(), cmd_depth) self.submodules += cmd_fifo - self.comb += [ - cmd_fifo.sink.stb.eq(sink_status.done), - cmd_fifo.sink.error.eq(sink.error) - ] + self.comb += cmd_fifo.sink.stb.eq(sink_status.done) + if hasattr(sink, "error"): + self.comb += cmd_fifo.sink.error.eq(sink.error) # data data_fifo = SyncFIFO(description, data_depth, buffered=True) @@ -406,9 +416,14 @@ class PacketBuffer(Module): NextState("OUTPUT") ) ) + if hasattr(source, "error"): + source_error = self.source.error + else: + source_error = Signal() + fsm.act("OUTPUT", 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, cmd_fifo.source.ack.eq(1), NextState("IDLE") diff --git a/liteeth/core/etherbone/record.py b/liteeth/core/etherbone/record.py index 6eec7730..7b033253 100644 --- a/liteeth/core/etherbone/record.py +++ b/liteeth/core/etherbone/record.py @@ -6,83 +6,148 @@ class LiteEthEtherboneRecordPacketizer(LiteEthPacketizer): def __init__(self): LiteEthPacketizer.__init__(self, eth_etherbone_record_description(32), - eth_raw_description(32), + eth_etherbone_packet_user_description(32), etherbone_record_header, etherbone_record_header_len) -class LiteEthEtherboneRecordTX(Module): +class LiteEthEtherboneRecordDepacketizer(LiteEthDepacketizer): + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_etherbone_packet_user_description(32), + eth_etherbone_record_description(32), + etherbone_record_header, + etherbone_record_header_len) + +class LiteEthEtherboneRecordReceiver(Module): def __init__(self): self.sink = sink = Sink(eth_etherbone_record_description(32)) - self.source = source = Source(eth_raw_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.packetizer = packetizer = LiteEthEtherboneRecordPacketizer() - self.comb += Record.connect(sink, packetizer.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") fsm.act("IDLE", - packetizer.source.ack.eq(1), - If(packetizer.source.stb & packetizer.source.sop, - packetizer.source.ack.eq(0), - NextState("SEND") + sink.ack.eq(1), + counter.reset.eq(1), + If(sink.stb & sink.sop, + base_addr.ce.eq(1), + If(sink.wcount, + NextState("RECEIVE_READS") + ).Elif(sink.rcount, + NextState("RECEIVE_READS") + ) ) ) - fsm.act("SEND", - Record.connect(packetizer.source, source), - If(source.stb & source.eop & source.ack, - NextState("IDLE") + fsm.act("RECEIVE_WRITES", + write_source.stb.eq(sink.stb), + write_source.sop.eq(counter.value == 0), + write_source.eop.eq(counter.value == sink.wcount-1), + write_source.count.eq(sink.wcount), + write_source.base_addr.eq(base_addr.q), + 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("RECEIVE_BASE_RET_ADDR", + 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") + ) ) ) -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): +# Note: for now only support writes from the FPGA +class LiteEthEtherboneRecordSender(Module): def __init__(self): - self.sink = sink = Sink(eth_raw_description(32)) + 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.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer() - self.comb += Record.connect(sink, depacketizer.sink) + 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", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.sop, - depacketizer.source.ack.eq(0), - NextState("CHECK") + 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") ) ) - valid = Signal() - self.sync += valid.eq(1) # XXX - fsm.act("CHECK", - If(valid, - NextState("PRESENT") - ).Else( - NextState("DROP") + 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("PRESENT", - Record.connect(depacketizer.source, source), + 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, 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): 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() + self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer() + 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) + ] -- 2.30.2