forked from M-Labs/artiq-zynq
cxp GW: fix read ptr not restarting with rx
cxp GW: express size in bytes instead of bits
This commit is contained in:
parent
aa4594d84a
commit
30cc069a29
|
@ -16,29 +16,32 @@ class CXP_PHYS(Module, AutoCSR):
|
||||||
@FullMemoryWE()
|
@FullMemoryWE()
|
||||||
class CXP_Interface(Module, AutoCSR):
|
class CXP_Interface(Module, AutoCSR):
|
||||||
def __init__(self, upconn_phy, downconn_phy, debug_sma, pmod_pads):
|
def __init__(self, upconn_phy, downconn_phy, debug_sma, pmod_pads):
|
||||||
# TODO: move all transceiver csr into a transceiver interface submodule
|
# TODO: add rtio interface io
|
||||||
|
|
||||||
self.submodules.upconn = UpConn_Interface(upconn_phy, debug_sma, pmod_pads)
|
self.submodules.upconn = UpConn_Interface(upconn_phy, debug_sma, pmod_pads)
|
||||||
|
|
||||||
self.submodules.downconn = DownConn_Interface(downconn_phy, debug_sma, pmod_pads)
|
self.submodules.downconn = DownConn_Interface(downconn_phy, debug_sma, pmod_pads)
|
||||||
|
|
||||||
def get_tx_port(self):
|
def get_tx_port(self):
|
||||||
return self.upconn.command.mem.get_port(write_capable=True)
|
return self.upconn.bootstrap.mem.get_port(write_capable=True)
|
||||||
|
|
||||||
def get_tx_mem_size(self):
|
def get_tx_mem_size(self):
|
||||||
return self.upconn.command.mem.depth*self.upconn.command.mem.width
|
# FIXME: if tx mem size is same as rx, for some reason when rx mem is writen, tx mem cannot be access anymore
|
||||||
|
# and each time tx mem is read, CPU will return rx mem instead
|
||||||
|
return self.upconn.bootstrap.mem.depth*self.upconn.bootstrap.mem.width // 8
|
||||||
|
# return self.downconn.bootstrap.mem.depth*self.downconn.bootstrap.mem.width // 8
|
||||||
|
|
||||||
def get_rx_port(self):
|
def get_rx_port(self):
|
||||||
return self.downconn.packet_decoder.mem.get_port(write_capable=False)
|
return self.downconn.bootstrap.mem.get_port(write_capable=False)
|
||||||
|
|
||||||
def get_rx_mem_size(self):
|
def get_rx_mem_size(self):
|
||||||
return self.downconn.packet_decoder.mem.depth*self.downconn.packet_decoder.mem.width
|
return self.downconn.bootstrap.mem.depth*self.downconn.bootstrap.mem.width // 8
|
||||||
|
|
||||||
def get_loopback_tx_port(self):
|
def get_loopback_tx_port(self):
|
||||||
return self.downconn.command.mem.get_port(write_capable=True)
|
return self.downconn.bootstrap_loopback.mem.get_port(write_capable=True)
|
||||||
|
|
||||||
def get_loopback_tx_mem_size(self):
|
def get_loopback_tx_mem_size(self):
|
||||||
return self.downconn.command.mem.depth*self.downconn.command.mem.width
|
return self.downconn.bootstrap_loopback.mem.depth*self.downconn.bootstrap_loopback.mem.width // 8
|
||||||
|
|
||||||
class DownConn_Interface(Module, AutoCSR):
|
class DownConn_Interface(Module, AutoCSR):
|
||||||
def __init__(self, phy, debug_sma, pmod_pads):
|
def __init__(self, phy, debug_sma, pmod_pads):
|
||||||
|
@ -149,17 +152,17 @@ class DownConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
# DEBUG: Transmission Pipeline
|
# DEBUG: Transmission Pipeline
|
||||||
#
|
#
|
||||||
# test pak ----+
|
# rtio pak ----+
|
||||||
# from gw | 32 32
|
# from gw | 32 32
|
||||||
# |---/---> mux -----> packet -----> trigger ack ---/---> PHY
|
# mux---/---> packet -----> trigger ack ---/---> PHY
|
||||||
# | wrapper inserter
|
# | wrapper inserter
|
||||||
# data pak ----+
|
# data/test ----+
|
||||||
# from fw
|
# pak from fw
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
# DEBUG: TX pipeline
|
# DEBUG: TX pipeline
|
||||||
self.submodules.command = command = TX_Command_Packet()
|
self.submodules.bootstrap_loopback = bootstrap_loopback = TX_Bootstrap()
|
||||||
self.submodules.testseq = testseq = TX_Test_Packet()
|
|
||||||
self.submodules.mux = mux = stream.Multiplexer(word_layout, 2)
|
self.submodules.mux = mux = stream.Multiplexer(word_layout, 2)
|
||||||
self.submodules.pak_wrp = pak_wrp = Packet_Wrapper()
|
self.submodules.pak_wrp = pak_wrp = Packet_Wrapper()
|
||||||
self.submodules.trig_ack = trig_ack = Trigger_ACK_Inserter()
|
self.submodules.trig_ack = trig_ack = Trigger_ACK_Inserter()
|
||||||
|
@ -169,8 +172,7 @@ class DownConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
self.sync += trig_ack.stb.eq(self.ack.re),
|
self.sync += trig_ack.stb.eq(self.ack.re),
|
||||||
self.comb += [
|
self.comb += [
|
||||||
command.source.connect(mux.sink0),
|
bootstrap_loopback.source.connect(mux.sink0),
|
||||||
testseq.source.connect(mux.sink1),
|
|
||||||
mux.sel.eq(self.mux_sel.storage),
|
mux.sel.eq(self.mux_sel.storage),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -207,36 +209,36 @@ class DownConn_Interface(Module, AutoCSR):
|
||||||
]
|
]
|
||||||
|
|
||||||
# Priority level 2 packet - data, test packet
|
# Priority level 2 packet - data, test packet
|
||||||
self.submodules.packet_decoder = packet_decoder = cdr(CXP_Data_Packet_Decode())
|
self.submodules.bootstrap = bootstrap = cdr(RX_Bootstrap())
|
||||||
|
|
||||||
self.decoder_error = CSR()
|
self.bootstrap_decoder_err = CSR()
|
||||||
self.test_error = CSR()
|
self.bootstrap_test_err = CSR()
|
||||||
self.buffer_error = CSR()
|
self.boostrap_buffer_err = CSR()
|
||||||
|
|
||||||
decode_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys")
|
decode_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys")
|
||||||
test_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys")
|
test_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys")
|
||||||
buffer_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys")
|
buffer_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys")
|
||||||
self.submodules += decode_err_ps, test_err_ps, buffer_err_ps
|
self.submodules += decode_err_ps, test_err_ps, buffer_err_ps
|
||||||
self.comb += [
|
self.comb += [
|
||||||
decode_err_ps.i.eq(packet_decoder.decode_err),
|
decode_err_ps.i.eq(bootstrap.decode_err),
|
||||||
test_err_ps.i.eq(packet_decoder.test_err),
|
test_err_ps.i.eq(bootstrap.test_err),
|
||||||
buffer_err_ps.i.eq(packet_decoder.buffer_err),
|
buffer_err_ps.i.eq(bootstrap.buffer_err),
|
||||||
]
|
]
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(decode_err_ps.o,
|
If(decode_err_ps.o,
|
||||||
self.decoder_error.w.eq(1),
|
self.bootstrap_decoder_err.w.eq(1),
|
||||||
).Elif(self.decoder_error.re,
|
).Elif(self.bootstrap_decoder_err.re,
|
||||||
self.decoder_error.w.eq(0),
|
self.bootstrap_decoder_err.w.eq(0),
|
||||||
),
|
),
|
||||||
If(test_err_ps.o,
|
If(test_err_ps.o,
|
||||||
self.test_error.w.eq(1),
|
self.bootstrap_test_err.w.eq(1),
|
||||||
).Elif(self.test_error.re,
|
).Elif(self.bootstrap_test_err.re,
|
||||||
self.test_error.w.eq(0),
|
self.bootstrap_test_err.w.eq(0),
|
||||||
),
|
),
|
||||||
If(buffer_err_ps.o,
|
If(buffer_err_ps.o,
|
||||||
self.buffer_error.w.eq(1),
|
self.boostrap_buffer_err.w.eq(1),
|
||||||
).Elif(self.test_error.re,
|
).Elif(self.bootstrap_test_err.re,
|
||||||
self.buffer_error.w.eq(0),
|
self.boostrap_buffer_err.w.eq(0),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -247,12 +249,14 @@ class DownConn_Interface(Module, AutoCSR):
|
||||||
self.read_ptr = CSRStatus(log2_int(buffer_count))
|
self.read_ptr = CSRStatus(log2_int(buffer_count))
|
||||||
|
|
||||||
self.specials += [
|
self.specials += [
|
||||||
MultiReg(packet_decoder.packet_type, self.packet_type.status),
|
MultiReg(bootstrap.packet_type, self.packet_type.status),
|
||||||
MultiReg(self.read_ptr.status, packet_decoder.read_ptr_rx, odomain="cxp_gtx_rx"),
|
MultiReg(self.read_ptr.status, bootstrap.read_ptr_rx, odomain="cxp_gtx_rx"),
|
||||||
]
|
]
|
||||||
self.sync += [
|
self.sync += [
|
||||||
self.pending_packet.w.eq(self.read_ptr.status != packet_decoder.write_ptr_sys),
|
self.pending_packet.w.eq(self.read_ptr.status != bootstrap.write_ptr_sys),
|
||||||
If(self.pending_packet.re & self.pending_packet.w,
|
If(self.rx_restart.re,
|
||||||
|
self.read_ptr.status.eq(0),
|
||||||
|
).Elif(self.pending_packet.re & self.pending_packet.w,
|
||||||
self.read_ptr.status.eq(self.read_ptr.status + 1),
|
self.read_ptr.status.eq(self.read_ptr.status + 1),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
@ -263,8 +267,18 @@ class DownConn_Interface(Module, AutoCSR):
|
||||||
self.submodules += ClockDomainsRenamer({"write": "cxp_gtx_rx", "read": "sys"})(cdc_fifo)
|
self.submodules += ClockDomainsRenamer({"write": "cxp_gtx_rx", "read": "sys"})(cdc_fifo)
|
||||||
self.submodules.debug_out = debug_out = RX_Debug_Buffer()
|
self.submodules.debug_out = debug_out = RX_Debug_Buffer()
|
||||||
|
|
||||||
|
self.dmux_sel = CSRStorage()
|
||||||
|
self.submodules.dmux = dmux = stream.Demultiplexer(word_layout, 2)
|
||||||
|
|
||||||
rx_pipeline = [phy, trig_ack_checker, packet_decoder, cdc_fifo, debug_out]
|
|
||||||
|
self.comb += [
|
||||||
|
dmux.source0.connect(bootstrap.sink),
|
||||||
|
dmux.source1.connect(cdc_fifo.sink),
|
||||||
|
cdc_fifo.source.connect(debug_out.sink),
|
||||||
|
dmux.sel.eq(self.dmux_sel.storage),
|
||||||
|
]
|
||||||
|
|
||||||
|
rx_pipeline = [phy, trig_ack_checker, dmux]
|
||||||
for s, d in zip(rx_pipeline, rx_pipeline[1:]):
|
for s, d in zip(rx_pipeline, rx_pipeline[1:]):
|
||||||
self.comb += s.source.connect(d.sink)
|
self.comb += s.source.connect(d.sink)
|
||||||
|
|
||||||
|
@ -278,14 +292,14 @@ class DownConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
pak_start = Signal()
|
pak_start = Signal()
|
||||||
self.sync += [
|
self.sync += [
|
||||||
pak_start.eq(packet_decoder.sink.data == 0xFBFBFBFB),
|
pak_start.eq(bootstrap.sink.data == 0xFBFBFBFB),
|
||||||
]
|
]
|
||||||
|
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("OBUF", i_I=phy.gtx.cd_cxp_gtx_rx.clk, o_O=debug_sma.p_tx),
|
Instance("OBUF", i_I=phy.gtx.cd_cxp_gtx_rx.clk, o_O=debug_sma.p_tx),
|
||||||
# Instance("OBUF", i_I=, o_O=debug_sma.p_rx),
|
# Instance("OBUF", i_I=, o_O=debug_sma.p_rx),
|
||||||
# # pmod 0-7 pin
|
# # pmod 0-7 pin
|
||||||
Instance("OBUF", i_I=packet_decoder.test_err, o_O=pmod_pads[0]),
|
Instance("OBUF", i_I=bootstrap.test_err, o_O=pmod_pads[0]),
|
||||||
Instance("OBUF", i_I=pak_start, o_O=pmod_pads[1]),
|
Instance("OBUF", i_I=pak_start, o_O=pmod_pads[1]),
|
||||||
# Instance("OBUF", i_I=fifo_in.source.ack, o_O=pmod_pads[2]),
|
# Instance("OBUF", i_I=fifo_in.source.ack, o_O=pmod_pads[2]),
|
||||||
# Instance("OBUF", i_I=gtx.comma_checker.aligner_en, o_O=pmod_pads[3]),
|
# Instance("OBUF", i_I=gtx.comma_checker.aligner_en, o_O=pmod_pads[3]),
|
||||||
|
@ -301,11 +315,7 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
self.clk_reset = CSRStorage(reset=1)
|
self.clk_reset = CSRStorage(reset=1)
|
||||||
self.bitrate2x_enable = CSRStorage()
|
self.bitrate2x_enable = CSRStorage()
|
||||||
self.tx_enable = CSRStorage()
|
self.tx_enable = CSRStorage()
|
||||||
|
self.tx_mux = CSRStorage()
|
||||||
# TODO: add busy condition
|
|
||||||
self.tx_busy = CSRStatus()
|
|
||||||
|
|
||||||
self.tx_testmode_en = CSRStorage()
|
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
|
@ -317,13 +327,10 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
|
|
||||||
# Transmission Pipeline
|
# Transmission Pipeline
|
||||||
#
|
#
|
||||||
# test pak ----+
|
# 32 32 8
|
||||||
# from gw | 32 32 8
|
# ctrl/test ---/---> packet -----> idle word -----> trigger ack ---/--> conv ---/---> trigger -----> PHY
|
||||||
# |---/---> mux -----> packet -----> idle word -----> trigger ack ---/--> conv ---/---> trigger -----> PHY
|
# packet wrapper inserter inserter inserter
|
||||||
# | wrapper inserter inserter inserter
|
|
||||||
# data pak ----+
|
|
||||||
# from fw
|
|
||||||
#
|
#
|
||||||
# Equivalent transmission priority:
|
# Equivalent transmission priority:
|
||||||
# trigger > trigger ack > idle > test/data packet
|
# trigger > trigger ack > idle > test/data packet
|
||||||
|
@ -362,20 +369,9 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
# 2: All other packets (data & test packet)
|
# 2: All other packets (data & test packet)
|
||||||
# Control is not timing dependent, all the data packets are handled in firmware
|
# Control is not timing dependent, all the data packets are handled in firmware
|
||||||
|
self.submodules.bootstrap = bootstrap = TX_Bootstrap()
|
||||||
self.submodules.command = command = TX_Command_Packet()
|
|
||||||
self.submodules.testseq = testseq = TX_Test_Packet()
|
|
||||||
self.submodules.mux = mux = stream.Multiplexer(word_layout, 2)
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
command.source.connect(mux.sink0),
|
|
||||||
testseq.source.connect(mux.sink1),
|
|
||||||
mux.sel.eq(self.tx_testmode_en.storage),
|
|
||||||
]
|
|
||||||
|
|
||||||
self.submodules.pak_wrp = pak_wrp = Packet_Wrapper()
|
self.submodules.pak_wrp = pak_wrp = Packet_Wrapper()
|
||||||
|
|
||||||
# IDLE Word
|
|
||||||
self.submodules.idle = idle = Idle_Word_Inserter()
|
self.submodules.idle = idle = Idle_Word_Inserter()
|
||||||
|
|
||||||
# Section 9.2.5.1 (CXP-001-2021)
|
# Section 9.2.5.1 (CXP-001-2021)
|
||||||
|
@ -394,6 +390,6 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
self.submodules.converter = converter = stream.StrideConverter(word_layout, char_layout)
|
self.submodules.converter = converter = stream.StrideConverter(word_layout, char_layout)
|
||||||
|
|
||||||
tx_pipeline = [mux, pak_wrp, idle, trig_ack, converter, trig, phy]
|
tx_pipeline = [bootstrap, pak_wrp, idle, trig_ack, converter, trig, phy]
|
||||||
for s, d in zip(tx_pipeline, tx_pipeline[1:]):
|
for s, d in zip(tx_pipeline, tx_pipeline[1:]):
|
||||||
self.comb += s.source.connect(d.sink)
|
self.comb += s.source.connect(d.sink)
|
||||||
|
|
Loading…
Reference in New Issue