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):
|
||||
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.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: remove this and put it in upconn_interface
|
||||
def cxp_phy_layout():
|
||||
return [("data", 8), ("k", 1)]
|
||||
|
||||
class UpConn_Interface(Module, AutoCSR):
|
||||
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 += [
|
||||
upconn_phy.bitrate2x_enable.eq(self.bitrate2x_enable.storage),
|
||||
|
@ -45,8 +42,36 @@ class UpConn_Interface(Module, AutoCSR):
|
|||
|
||||
|
||||
# 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.sync += [
|
||||
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
|
||||
self.ack = CSR()
|
||||
|
@ -66,7 +91,7 @@ class UpConn_Interface(Module, AutoCSR):
|
|||
]
|
||||
|
||||
# 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.trig_ack_inc = CSR()
|
||||
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]),
|
||||
]
|
||||
|
||||
# 2: All other packets
|
||||
# NOTE: 2 All other packets
|
||||
# Control is not timing dependent, all the link layer is done in firmware
|
||||
|
||||
# Table 54 (CXP-001-2021)
|
||||
|
@ -99,11 +124,11 @@ class UpConn_Interface(Module, AutoCSR):
|
|||
# section 9.6.1.2 (CXP-001-2021)
|
||||
# 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
|
||||
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.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].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