forked from M-Labs/artiq-zynq
cxp: add trig to upconn & remove tx_command_packet
This commit is contained in:
parent
6d421a1041
commit
d84c7c9523
|
@ -8,8 +8,6 @@ from cxp_pipeline import *
|
||||||
|
|
||||||
class CXP(Module, AutoCSR):
|
class CXP(Module, AutoCSR):
|
||||||
def __init__(self, refclk, downconn_pads, upconn_pads, sys_clk_freq, debug_sma, pmod_pads):
|
def __init__(self, refclk, downconn_pads, upconn_pads, sys_clk_freq, debug_sma, pmod_pads):
|
||||||
self.submodules.trig = TX_Trigger(cxp_phy_layout())
|
|
||||||
|
|
||||||
self.submodules.upconn = UpConn_Interface(upconn_pads, sys_clk_freq, debug_sma, pmod_pads)
|
self.submodules.upconn = UpConn_Interface(upconn_pads, sys_clk_freq, debug_sma, pmod_pads)
|
||||||
|
|
||||||
self.submodules.downconn = CXP_DownConn(refclk, downconn_pads, sys_clk_freq, debug_sma, pmod_pads)
|
self.submodules.downconn = CXP_DownConn(refclk, downconn_pads, sys_clk_freq, debug_sma, pmod_pads)
|
||||||
|
@ -17,9 +15,6 @@ class CXP(Module, AutoCSR):
|
||||||
|
|
||||||
# TODO: add link layer
|
# TODO: add link layer
|
||||||
|
|
||||||
# TODO: remove this and put it in upconn_interface
|
|
||||||
def cxp_phy_layout():
|
|
||||||
return [("data", 8), ("k", 1)]
|
|
||||||
|
|
||||||
class UpConn_Interface(Module, AutoCSR):
|
class UpConn_Interface(Module, AutoCSR):
|
||||||
def __init__(self, upconn_pads, sys_clk_freq, debug_sma, pmod_pads, fifos_depth=64):
|
def __init__(self, upconn_pads, sys_clk_freq, debug_sma, pmod_pads, fifos_depth=64):
|
||||||
|
@ -31,7 +26,9 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
self.submodules.upconn_phy = upconn_phy = CXP_UpConn_PHY(upconn_pads, sys_clk_freq, debug_sma, pmod_pads, cxp_phy_layout(), fifos_depth)
|
layout = [("data", 8), ("k", 1)]
|
||||||
|
|
||||||
|
self.submodules.upconn_phy = upconn_phy = CXP_UpConn_PHY(upconn_pads, sys_clk_freq, debug_sma, pmod_pads, layout, fifos_depth)
|
||||||
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
upconn_phy.bitrate2x_enable.eq(self.bitrate2x_enable.storage),
|
upconn_phy.bitrate2x_enable.eq(self.bitrate2x_enable.storage),
|
||||||
|
@ -45,8 +42,36 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
|
|
||||||
|
|
||||||
# Packet FIFOs with transmission priority
|
# Packet FIFOs with transmission priority
|
||||||
# 0: Trigger packet
|
# NOTE: 0 Trigger packet
|
||||||
|
self.submodules.trig = trig = TX_Trigger(layout)
|
||||||
|
|
||||||
|
# DEBUG: INPUT
|
||||||
|
self.trig_stb = CSR()
|
||||||
|
self.trig_delay = CSRStorage(8)
|
||||||
|
self.linktrigger = CSRStorage(2)
|
||||||
|
|
||||||
|
self.sync += [
|
||||||
|
trig.trig_stb.eq(self.trig_stb.re),
|
||||||
|
trig.delay.eq(self.trig_delay.storage),
|
||||||
|
trig.linktrig_mode.eq(self.linktrigger.storage),
|
||||||
|
]
|
||||||
|
|
||||||
|
# DEBUG: OUTPUT
|
||||||
|
self.submodules.trig_out = trig_out = stream.SyncFIFO(layout, 64)
|
||||||
|
self.comb += trig.source.connect(trig_out.sink)
|
||||||
|
self.trig_inc = CSR()
|
||||||
|
self.trig_dout_pak = CSRStatus(8)
|
||||||
|
self.trig_kout_pak = CSRStatus()
|
||||||
|
self.trig_dout_valid = CSRStatus()
|
||||||
|
|
||||||
|
self.sync += [
|
||||||
|
# output
|
||||||
|
trig_out.source.ack.eq(self.trig_inc.re),
|
||||||
|
self.trig_dout_pak.status.eq(trig_out.source.data),
|
||||||
|
self.trig_kout_pak.status.eq(trig_out.source.k),
|
||||||
|
self.trig_dout_valid.status.eq(trig_out.source.stb),
|
||||||
|
]
|
||||||
|
|
||||||
self.symbol0 = CSR(9)
|
self.symbol0 = CSR(9)
|
||||||
self.sync += [
|
self.sync += [
|
||||||
upconn_phy.tx_fifos.sink[0].stb.eq(self.symbol0.re),
|
upconn_phy.tx_fifos.sink[0].stb.eq(self.symbol0.re),
|
||||||
|
@ -55,9 +80,9 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# 1: IO acknowledgment for trigger packet
|
# NOTE: 1 IO acknowledgment for trigger packet
|
||||||
|
|
||||||
self.submodules.trig_ack = trig_ack = Trigger_ACK(cxp_phy_layout())
|
self.submodules.trig_ack = trig_ack = Trigger_ACK(layout)
|
||||||
|
|
||||||
# DEBUG: INPUT
|
# DEBUG: INPUT
|
||||||
self.ack = CSR()
|
self.ack = CSR()
|
||||||
|
@ -66,7 +91,7 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
]
|
]
|
||||||
|
|
||||||
# DEBUG: OUTPUT
|
# DEBUG: OUTPUT
|
||||||
self.submodules.trig_ack_out = trig_ack_out = stream.SyncFIFO(cxp_phy_layout(), 64)
|
self.submodules.trig_ack_out = trig_ack_out = stream.SyncFIFO(layout, 64)
|
||||||
self.comb += trig_ack.source.connect(trig_ack_out.sink)
|
self.comb += trig_ack.source.connect(trig_ack_out.sink)
|
||||||
self.trig_ack_inc = CSR()
|
self.trig_ack_inc = CSR()
|
||||||
self.trig_ack_dout_pak = CSRStatus(8)
|
self.trig_ack_dout_pak = CSRStatus(8)
|
||||||
|
@ -88,7 +113,7 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
upconn_phy.tx_fifos.sink[1].k.eq(self.symbol1.r[8]),
|
upconn_phy.tx_fifos.sink[1].k.eq(self.symbol1.r[8]),
|
||||||
]
|
]
|
||||||
|
|
||||||
# 2: All other packets
|
# NOTE: 2 All other packets
|
||||||
# Control is not timing dependent, all the link layer is done in firmware
|
# Control is not timing dependent, all the link layer is done in firmware
|
||||||
|
|
||||||
# Table 54 (CXP-001-2021)
|
# Table 54 (CXP-001-2021)
|
||||||
|
@ -99,11 +124,11 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
# section 9.6.1.2 (CXP-001-2021)
|
# section 9.6.1.2 (CXP-001-2021)
|
||||||
# tags implementation is on firmware
|
# tags implementation is on firmware
|
||||||
|
|
||||||
self.submodules.command = command = TX_Command_Packet(pmod_pads)
|
self.submodules.command = command = TX_Command_Packet(layout, pmod_pads)
|
||||||
|
|
||||||
|
|
||||||
# DEBUG: OUTPUT
|
# DEBUG: OUTPUT
|
||||||
self.submodules.command_out = command_out = stream.SyncFIFO(cxp_phy_layout(), 64)
|
self.submodules.command_out = command_out = stream.SyncFIFO(layout, 64)
|
||||||
self.comb += command.source.connect(command_out.sink)
|
self.comb += command.source.connect(command_out.sink)
|
||||||
|
|
||||||
self.command_inc = CSR()
|
self.command_inc = CSR()
|
||||||
|
@ -138,129 +163,3 @@ class UpConn_Interface(Module, AutoCSR):
|
||||||
upconn_phy.tx_fifos.sink[2].data.eq(self.symbol2.r[:8]),
|
upconn_phy.tx_fifos.sink[2].data.eq(self.symbol2.r[:8]),
|
||||||
upconn_phy.tx_fifos.sink[2].k.eq(self.symbol2.r[8]),
|
upconn_phy.tx_fifos.sink[2].k.eq(self.symbol2.r[8]),
|
||||||
]
|
]
|
||||||
|
|
||||||
def K(x, y):
|
|
||||||
return ((y << 5) | x)
|
|
||||||
|
|
||||||
# TODO: move this to cxp_pipeline, since it used K(x, y) :<
|
|
||||||
class TX_Trigger(Module, AutoCSR):
|
|
||||||
def __init__(self, layout):
|
|
||||||
# This module is mostly control by gateware
|
|
||||||
|
|
||||||
self.trig_stb = Signal()
|
|
||||||
self.delay = Signal(8) # FIXME: use source instead
|
|
||||||
self.linktrig_mode = Signal(max=4)
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
|
|
||||||
self.submodules.code_src = code_src = Code_Source(layout, counts=3)
|
|
||||||
self.comb += [
|
|
||||||
code_src.stb.eq(self.trig_stb),
|
|
||||||
code_src.data.eq(self.delay),
|
|
||||||
code_src.k.eq(0)
|
|
||||||
]
|
|
||||||
|
|
||||||
self.submodules.inserter_once = inserter_once = Code_Inserter(layout, counts=1)
|
|
||||||
self.submodules.inserter_twice = inserter_twice = Code_Inserter(layout, counts=2)
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
inserter_once.k.eq(1),
|
|
||||||
inserter_twice.k.eq(1),
|
|
||||||
If((self.linktrig_mode == 0) | (self.linktrig_mode == 2),
|
|
||||||
inserter_once.data.eq(K(28, 2)),
|
|
||||||
inserter_twice.data.eq(K(28, 4)),
|
|
||||||
).Else(
|
|
||||||
inserter_once.data.eq(K(28, 4)),
|
|
||||||
inserter_twice.data.eq(K(28, 2)),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
self.submodules.buf_out = buf_out = stream.SyncFIFO(layout, 64)
|
|
||||||
|
|
||||||
tx_pipeline = [ code_src, inserter_twice, inserter_once, buf_out]
|
|
||||||
|
|
||||||
for s, d in zip(tx_pipeline, tx_pipeline[1:]):
|
|
||||||
self.comb += s.source.connect(d.sink)
|
|
||||||
|
|
||||||
self.source = tx_pipeline[-1].source
|
|
||||||
|
|
||||||
|
|
||||||
# DEBUG: INPUT
|
|
||||||
self.stb = CSR()
|
|
||||||
self.trig_delay = CSRStorage(8)
|
|
||||||
self.linktrigger = CSRStorage(2)
|
|
||||||
|
|
||||||
self.sync += [
|
|
||||||
self.trig_stb.eq(self.stb.re),
|
|
||||||
self.delay.eq(self.trig_delay.storage),
|
|
||||||
self.linktrig_mode.eq(self.linktrigger.storage),
|
|
||||||
]
|
|
||||||
|
|
||||||
# DEBUG: OUTPUT
|
|
||||||
self.inc = CSR()
|
|
||||||
self.dout_pak = CSRStatus(8)
|
|
||||||
self.kout_pak = CSRStatus()
|
|
||||||
self.dout_valid = CSRStatus()
|
|
||||||
|
|
||||||
self.sync += [
|
|
||||||
# output
|
|
||||||
buf_out.source.ack.eq(self.inc.re),
|
|
||||||
self.dout_pak.status.eq(buf_out.source.data),
|
|
||||||
self.kout_pak.status.eq(buf_out.source.k),
|
|
||||||
self.dout_valid.status.eq(buf_out.source.stb),
|
|
||||||
]
|
|
||||||
|
|
||||||
class TX_Command_Packet(Module, AutoCSR):
|
|
||||||
def __init__(self, pmod_pads):
|
|
||||||
self.packet_type = CSRStorage(8)
|
|
||||||
|
|
||||||
self.din_len = CSRStorage(6)
|
|
||||||
self.din_data = CSR(8)
|
|
||||||
self.din_k = CSRStorage()
|
|
||||||
self.din_ready = CSRStatus()
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
|
|
||||||
# a buf is used to simulated a proper endpoint which hold source.stb high as long as data is available
|
|
||||||
# otherwise, CSR.re only hold when CSR is written to and it cannot act as a proper source
|
|
||||||
self.submodules.buf_in = buf_in = stream.SyncFIFO(cxp_phy_layout(), 2)
|
|
||||||
|
|
||||||
self.submodules.crc_inserter = crc_inserters = CXPCRC32Inserter(cxp_phy_layout())
|
|
||||||
self.submodules.pak_type = pak_type = Code_Inserter(cxp_phy_layout())
|
|
||||||
self.submodules.pak_wrp = pak_wrp = Packet_Wrapper(cxp_phy_layout())
|
|
||||||
|
|
||||||
len = Signal(6, reset=1)
|
|
||||||
self.sync += [
|
|
||||||
self.din_ready.status.eq(buf_in.sink.ack),
|
|
||||||
buf_in.sink.stb.eq(0),
|
|
||||||
If(self.din_data.re,
|
|
||||||
If(len == self.din_len.storage,
|
|
||||||
len.eq(len.reset),
|
|
||||||
buf_in.sink.eop.eq(1),
|
|
||||||
).Else(
|
|
||||||
len.eq(len + 1),
|
|
||||||
buf_in.sink.eop.eq(0),
|
|
||||||
),
|
|
||||||
buf_in.sink.stb.eq(1),
|
|
||||||
buf_in.sink.data.eq(self.din_data.r),
|
|
||||||
buf_in.sink.k.eq(self.din_k.storage),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
pak_type.data.eq(self.packet_type.storage),
|
|
||||||
pak_type.k.eq(0),
|
|
||||||
]
|
|
||||||
|
|
||||||
tx_pipeline = [ buf_in, crc_inserters, pak_type, pak_wrp]
|
|
||||||
|
|
||||||
for s, d in zip(tx_pipeline, tx_pipeline[1:]):
|
|
||||||
self.comb += s.source.connect(d.sink)
|
|
||||||
|
|
||||||
self.source = tx_pipeline[-1].source
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue