1
0
Fork 0

Compare commits

..

No commits in common. "b471db8567644c08ab841644b5d0863244c13416" and "675c535812bd203908fba56676acbcd860b2e6f4" have entirely different histories.

11 changed files with 151 additions and 254 deletions

View File

@ -1,58 +0,0 @@
"""
Non-realtime drivers for CXP.
"""
# TODO: add api calls for CTRL packet similar i2c
# TODO: add timing critical trigger ack
from artiq.language.core import syscall, kernel
from artiq.language.types import TBool, TInt32, TNone
from artiq.coredevice.rtio import rtio_output
from artiq.experiment import *
class CoaXPress:
def __init__(self, channel, core_device="core"):
# __device_mgr is private
# self.core = dmgr.get(core_device)
# you can get the channel via `print(len(rtio_channels))` before calling
# `rtio_channels.append(rtio.Channel.from_phy(cxp_interface))`
self.channel = channel
# the first 8 bits is reserved for the rtlink.OInterface.addr not for channel no.
self.target_o = channel << 8
@staticmethod
def get_rtio_channels(channel, **kwargs):
return [(channel, None)]
@kernel
def trigger(self, linktrig, trigdelay):
rtio_output(self.target_o, linktrig | trigdelay << 1)
@syscall(flags={"nounwind", "nowrite"})
def cxp_readu32(channel: TInt32, addr: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"})
def cxp_writeu32(channel: TInt32, addr: TInt32, val: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
class IdleKernel(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("led0")
# declare the class before using it in kernel
self.cxp = CoaXPress(0x0)
@kernel
def run(self):
self.core.reset()
# cxp_readu32(0, 3)
# cxp_writeu32(0, 0, 0xABCD)
self.cxp.trigger(1, 10)

View File

@ -2,8 +2,6 @@ from migen import *
from migen.genlib.cdc import MultiReg, PulseSynchronizer from migen.genlib.cdc import MultiReg, PulseSynchronizer
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
from artiq.gateware.rtio import rtlink
from cxp_downconn import CXP_DownConn_PHYS from cxp_downconn import CXP_DownConn_PHYS
from cxp_upconn import CXP_UpConn_PHYS from cxp_upconn import CXP_UpConn_PHYS
from cxp_pipeline import * from cxp_pipeline import *
@ -12,14 +10,16 @@ from cxp_pipeline import *
class CXP_PHYS(Module, AutoCSR): class CXP_PHYS(Module, AutoCSR):
def __init__(self, refclk, upconn_pads, downconn_pads, sys_clk_freq, debug_sma, pmod_pads): def __init__(self, refclk, upconn_pads, downconn_pads, sys_clk_freq, debug_sma, pmod_pads):
assert len(upconn_pads) == len(downconn_pads) assert len(upconn_pads) == len(downconn_pads)
self.submodules.upconn = CXP_UpConn_PHYS(upconn_pads, sys_clk_freq, debug_sma, pmod_pads) self.submodules.upconn = CXP_UpConn_PHYS(upconn_pads, sys_clk_freq, debug_sma, pmod_pads)
self.submodules.downconn = CXP_DownConn_PHYS(refclk, downconn_pads, sys_clk_freq, debug_sma, pmod_pads) self.submodules.downconn = CXP_DownConn_PHYS(refclk, downconn_pads, sys_clk_freq, debug_sma, pmod_pads)
@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: 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):
@ -43,34 +43,6 @@ class CXP_Interface(Module, AutoCSR):
def get_loopback_tx_mem_size(self): def get_loopback_tx_mem_size(self):
return self.downconn.bootstrap_loopback.mem.depth*self.downconn.bootstrap_loopback.mem.width // 8 return self.downconn.bootstrap_loopback.mem.depth*self.downconn.bootstrap_loopback.mem.width // 8
class CXP_Master(CXP_Interface):
def __init__(self, upconn_phy, downconn_phy, debug_sma, pmod_pads):
CXP_Interface.__init__(self, upconn_phy, downconn_phy, debug_sma, pmod_pads)
nbit_trigdelay = 8
nbit_linktrig = 1
self.rtlink = rtlink.Interface(
rtlink.OInterface(nbit_trigdelay + nbit_linktrig),
rtlink.IInterface(word_dw, timestamped=False)
)
self.sync.rio += [
If(self.rtlink.o.stb,
self.upconn.trig.delay.eq(self.rtlink.o.data[nbit_linktrig:]),
self.upconn.trig.linktrig_mode.eq(self.rtlink.o.data[:nbit_linktrig]),
),
self.upconn.trig.stb.eq(self.rtlink.o.stb),
]
# DEBUG: out
self.specials += Instance("OBUF", i_I=self.rtlink.o.stb, o_O=debug_sma.p_tx),
# self.specials += Instance("OBUF", i_I=self.rtlink.o.stb, o_O=debug_sma.n_rx),
class CXP_Extension(CXP_Interface):
def __init__(self, upconn_phy, downconn_phy, debug_sma, pmod_pads):
CXP_Interface.__init__(self, upconn_phy, downconn_phy, debug_sma, pmod_pads)
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):
self.rx_start_init = CSRStorage() self.rx_start_init = CSRStorage()
@ -123,14 +95,22 @@ class DownConn_Interface(Module, AutoCSR):
self.comb += gtx.dclk.eq(ClockSignal("sys")) self.comb += gtx.dclk.eq(ClockSignal("sys"))
self.sync += [ self.sync += [
gtx.den.eq(0),
gtx.dwen.eq(0),
If(self.gtx_dread.re,
gtx.den.eq(1),
gtx.daddr.eq(self.gtx_daddr.storage),
).Elif(self.gtx_din_stb.re,
gtx.den.eq(1),
gtx.dwen.eq(1),
gtx.daddr.eq(self.gtx_daddr.storage), gtx.daddr.eq(self.gtx_daddr.storage),
gtx.den.eq(self.gtx_dread.re | self.gtx_din_stb.re),
gtx.dwen.eq(self.gtx_din_stb.re),
gtx.din.eq(self.gtx_din.storage), gtx.din.eq(self.gtx_din.storage),
),
If(gtx.dready, If(gtx.dready,
self.gtx_dready.w.eq(1), self.gtx_dready.w.eq(1),
self.gtx_dout.status.eq(gtx.dout), self.gtx_dout.status.eq(gtx.dout),
).Elif(self.gtx_dready.re, ),
If(self.gtx_dready.re,
self.gtx_dready.w.eq(0), self.gtx_dready.w.eq(0),
), ),
] ]
@ -274,7 +254,7 @@ class DownConn_Interface(Module, AutoCSR):
] ]
self.sync += [ self.sync += [
self.pending_packet.w.eq(self.read_ptr.status != bootstrap.write_ptr_sys), self.pending_packet.w.eq(self.read_ptr.status != bootstrap.write_ptr_sys),
If(~gtx.rx_ready, If(self.rx_restart.re,
self.read_ptr.status.eq(0), self.read_ptr.status.eq(0),
).Elif(self.pending_packet.re & self.pending_packet.w, ).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),
@ -316,7 +296,7 @@ class DownConn_Interface(Module, AutoCSR):
] ]
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=bootstrap.test_err, o_O=pmod_pads[0]), Instance("OBUF", i_I=bootstrap.test_err, o_O=pmod_pads[0]),
@ -332,6 +312,20 @@ class DownConn_Interface(Module, AutoCSR):
class UpConn_Interface(Module, AutoCSR): class UpConn_Interface(Module, AutoCSR):
def __init__(self, phy, debug_sma, pmod_pads): def __init__(self, phy, debug_sma, pmod_pads):
self.clk_reset = CSRStorage(reset=1)
self.bitrate2x_enable = CSRStorage()
self.tx_enable = CSRStorage()
self.tx_mux = CSRStorage()
# # #
self.sync += [
phy.bitrate2x_enable.eq(self.bitrate2x_enable.storage),
phy.tx_enable.eq(self.tx_enable.storage),
phy.clk_reset.eq(self.clk_reset.re),
]
# Transmission Pipeline # Transmission Pipeline
# #
# 32 32 8 # 32 32 8
@ -356,13 +350,13 @@ class UpConn_Interface(Module, AutoCSR):
# # DEBUG: INPUT # # DEBUG: INPUT
self.trig_stb = CSR() self.trig_stb = CSR()
self.trig_delay = CSRStorage(8) self.trig_delay = CSRStorage(8)
self.linktrigger = CSRStorage() self.linktrigger = CSRStorage(2)
# self.sync += [ self.sync += [
# trig.stb.eq(self.trig_stb.re), trig.stb.eq(self.trig_stb.re),
# trig.delay.eq(self.trig_delay.storage), trig.delay.eq(self.trig_delay.storage),
# trig.linktrig_mode.eq(self.linktrigger.storage), trig.linktrig_mode.eq(self.linktrigger.storage),
# ] ]
# 1: IO acknowledgment for trigger packet # 1: IO acknowledgment for trigger packet

View File

@ -40,15 +40,6 @@ class CXP_DownConn_PHYS(Module, AutoCSR):
# checkout channel interfaces & drtio_gtx # checkout channel interfaces & drtio_gtx
# GTPTXPhaseAlignement for inspiration # GTPTXPhaseAlignement for inspiration
# Connect slave i's `cxp_gtx_rx` clock to `cxp_gtx_rxi` clock
for rx in self.rx_phys:
name = "cd_cxp_gtx_rx" + str(i)
setattr(self.clock_domains, name, ClockDomain(name=name))
self.comb += [
getattr(self, name).clk.eq(rx.gtx.cd_cxp_gtx_rx.clk),
getattr(self, name).rst.eq(rx.gtx.cd_cxp_gtx_rx.rst)
]
class Receiver(Module): class Receiver(Module):
def __init__(self, qpll, pad, sys_clk_freq, tx_mode, rx_mode, debug_sma, pmod_pads): def __init__(self, qpll, pad, sys_clk_freq, tx_mode, rx_mode, debug_sma, pmod_pads):
@ -60,8 +51,8 @@ class Receiver(Module):
self.source.stb.eq(0), self.source.stb.eq(0),
If(gtx.rx_ready & self.source.ack & ~((gtx.decoders[0].d == 0xBC) & (gtx.decoders[0].k == 1)), If(gtx.rx_ready & self.source.ack & ~((gtx.decoders[0].d == 0xBC) & (gtx.decoders[0].k == 1)),
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Cat(gtx.decoders[i].d for i in range(4))), self.source.data.eq(Cat(gtx.decoders[0].d, gtx.decoders[1].d, gtx.decoders[2].d, gtx.decoders[3].d)),
self.source.k.eq(Cat(gtx.decoders[i].k for i in range(4))), self.source.k.eq(Cat(gtx.decoders[0].k, gtx.decoders[1].k, gtx.decoders[2].k, gtx.decoders[3].k)),
) )
] ]

View File

@ -47,7 +47,7 @@ class Packet_Wrapper(Module):
self.sink.ack.eq(0), self.sink.ack.eq(0),
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Replicate(KCode["pak_start"], 4)), self.source.data.eq(Replicate(KCode["pak_start"], 4)),
self.source.k.eq(Replicate(1, 4)), self.source.k.eq(0b1111),
If(self.source.ack, NextState("COPY")), If(self.source.ack, NextState("COPY")),
) )
@ -63,7 +63,7 @@ class Packet_Wrapper(Module):
self.sink.ack.eq(0), self.sink.ack.eq(0),
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Replicate(KCode["pak_end"], 4)), self.source.data.eq(Replicate(KCode["pak_end"], 4)),
self.source.k.eq(Replicate(1, 4)), self.source.k.eq(0b1111),
self.source.eop.eq(1), self.source.eop.eq(1),
If(self.source.ack, NextState("IDLE")), If(self.source.ack, NextState("IDLE")),
) )
@ -72,7 +72,7 @@ class TX_Trigger(Module):
def __init__(self): def __init__(self):
self.stb = Signal() self.stb = Signal()
self.delay = Signal(char_width) self.delay = Signal(char_width)
self.linktrig_mode = Signal() self.linktrig_mode = Signal(max=4)
# # # # # #
@ -85,14 +85,14 @@ class TX_Trigger(Module):
trig_packet = [Signal(char_width), Signal(char_width), Signal(char_width), self.delay, self.delay, self.delay] trig_packet = [Signal(char_width), Signal(char_width), Signal(char_width), self.delay, self.delay, self.delay]
trig_packet_k = [1, 1, 1, 0, 0, 0] trig_packet_k = [1, 1, 1, 0, 0, 0]
self.comb += [ self.comb += [
If(self.linktrig_mode, If((self.linktrig_mode == 0) | (self.linktrig_mode == 2),
trig_packet[0].eq(KCode["trig_indic_28_4"]),
trig_packet[1].eq(KCode["trig_indic_28_2"]),
trig_packet[2].eq(KCode["trig_indic_28_2"]),
).Else(
trig_packet[0].eq(KCode["trig_indic_28_2"]), trig_packet[0].eq(KCode["trig_indic_28_2"]),
trig_packet[1].eq(KCode["trig_indic_28_4"]), trig_packet[1].eq(KCode["trig_indic_28_4"]),
trig_packet[2].eq(KCode["trig_indic_28_4"]), trig_packet[2].eq(KCode["trig_indic_28_4"]),
).Else(
trig_packet[0].eq(KCode["trig_indic_28_4"]),
trig_packet[1].eq(KCode["trig_indic_28_2"]),
trig_packet[2].eq(KCode["trig_indic_28_2"]),
), ),
] ]
@ -140,7 +140,7 @@ class Idle_Word_Inserter(Module):
self.sink.ack.eq(0), self.sink.ack.eq(0),
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Cat(KCode["idle_comma"], KCode["idle_alignment"], KCode["idle_alignment"], C(0xB5, char_width))), self.source.data.eq(Cat(KCode["idle_comma"], KCode["idle_alignment"], KCode["idle_alignment"], C(0xB5, char_width))),
self.source.k.eq(Cat(1, 1, 1, 0)), self.source.k.eq(0b1110),
If(self.source.ack, NextState("COPY")), If(self.source.ack, NextState("COPY")),
) )
@ -166,7 +166,7 @@ class Trigger_ACK_Inserter(Module):
self.sink.ack.eq(0), self.sink.ack.eq(0),
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Replicate(KCode["io_ack"], 4)), self.source.data.eq(Replicate(KCode["io_ack"], 4)),
self.source.k.eq(Replicate(1, 4)), self.source.k.eq(0b1111),
If(self.source.ack, NextState("WRITE_ACK1")), If(self.source.ack, NextState("WRITE_ACK1")),
) )
@ -174,7 +174,7 @@ class Trigger_ACK_Inserter(Module):
self.sink.ack.eq(0), self.sink.ack.eq(0),
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Replicate(C(0x01, char_width), 4)), self.source.data.eq(Replicate(C(0x01, char_width), 4)),
self.source.k.eq(Replicate(0, 4)), self.source.k.eq(0b0000),
If(self.source.ack, NextState("COPY")), If(self.source.ack, NextState("COPY")),
) )
@ -240,14 +240,14 @@ class TX_Bootstrap(Module, AutoCSR):
fsm.act("WRITE_TEST_PACKET_TYPE", fsm.act("WRITE_TEST_PACKET_TYPE",
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Replicate(C(0x04, char_width), 4)), self.source.data.eq(Replicate(C(0x04, char_width), 4)),
self.source.k.eq(Replicate(0, 4)), self.source.k.eq(0b0000),
If(self.source.ack,NextState("WRITE_TEST_COUNTER")) If(self.source.ack,NextState("WRITE_TEST_COUNTER"))
) )
fsm.act("WRITE_TEST_COUNTER", fsm.act("WRITE_TEST_COUNTER",
self.source.stb.eq(1), self.source.stb.eq(1),
self.source.data.eq(Cat(cnt[:8], cnt[:8]+1, cnt[:8]+2, cnt[:8]+3)), self.source.data.eq(Cat(cnt[:8], cnt[:8]+1, cnt[:8]+2, cnt[:8]+3)),
self.source.k.eq(Cat(0, 0, 0, 0)), self.source.k.eq(0b0000),
If(self.source.ack, If(self.source.ack,
If(cnt == 0xFFF-3, If(cnt == 0xFFF-3,
self.source.eop.eq(1), self.source.eop.eq(1),
@ -405,7 +405,6 @@ class RX_Bootstrap(Module):
self.comb += [ self.comb += [
mem_port.adr[:addr_nbits].eq(addr), mem_port.adr[:addr_nbits].eq(addr),
mem_port.adr[addr_nbits:].eq(write_ptr), mem_port.adr[addr_nbits:].eq(write_ptr),
mem_port.dat_w.eq(self.sink.data),
] ]
# For control ack, event packet # For control ack, event packet
@ -417,7 +416,9 @@ class RX_Bootstrap(Module):
NextState("MOVE_BUFFER_PTR"), NextState("MOVE_BUFFER_PTR"),
).Else( ).Else(
mem_port.we.eq(1), mem_port.we.eq(1),
mem_port.dat_w.eq(self.sink.data),
NextValue(addr, addr + 1), NextValue(addr, addr + 1),
If(addr == buffer_depth - 1, If(addr == buffer_depth - 1,
# discard the packet # discard the packet
self.buffer_err.eq(1), self.buffer_err.eq(1),

View File

@ -180,7 +180,7 @@ class Transmitter(Module, AutoCSR):
self.specials += [ self.specials += [
# # debug sma # # debug sma
# Instance("OBUF", i_I=serdes.o, o_O=debug_sma.p_tx), # Instance("OBUF", i_I=serdes.o, o_O=debug_sma.p_tx),
Instance("OBUF", i_I=serdes.o, o_O=debug_sma.n_rx), # Instance("OBUF", i_I=cg.clk_10x, o_O=debug_sma.n_rx),
@ -205,20 +205,8 @@ class Transmitter(Module, AutoCSR):
class CXP_UpConn_PHYS(Module, AutoCSR): class CXP_UpConn_PHYS(Module, AutoCSR):
def __init__(self, pads, sys_clk_freq, debug_sma, pmod_pads): def __init__(self, pads, sys_clk_freq, debug_sma, pmod_pads):
self.clk_reset = CSR()
self.bitrate2x_enable = CSRStorage()
self.tx_enable = CSRStorage()
# # #
self.tx_phys = [] self.tx_phys = []
for i, pad in enumerate(pads): for i, pad in enumerate(pads):
tx = Transmitter(pad, sys_clk_freq, debug_sma, pmod_pads) tx = Transmitter(pad, sys_clk_freq, debug_sma, pmod_pads)
self.tx_phys.append(tx) self.tx_phys.append(tx)
setattr(self.submodules, "tx"+str(i), tx) setattr(self.submodules, "tx"+str(i), tx)
self.sync += [
tx.clk_reset.eq(self.clk_reset.re),
tx.bitrate2x_enable.eq(self.bitrate2x_enable.storage),
tx.tx_enable.eq(self.tx_enable.storage),
]

View File

@ -704,7 +704,6 @@ class CXP_FMC():
self.csr_devices.append("cxp_phys") self.csr_devices.append("cxp_phys")
rtio_channels = []
cxp_csr_group = [] cxp_csr_group = []
cxp_tx_mem_group = [] cxp_tx_mem_group = []
cxp_rx_mem_group = [] cxp_rx_mem_group = []
@ -712,25 +711,13 @@ class CXP_FMC():
for i, (tx, rx) in enumerate(zip(cxp_phys.upconn.tx_phys, cxp_phys.downconn.rx_phys)): for i, (tx, rx) in enumerate(zip(cxp_phys.upconn.tx_phys, cxp_phys.downconn.rx_phys)):
cxp_name = "cxp" + str(i) cxp_name = "cxp" + str(i)
cdr = ClockDomainsRenamer({"cxp_gtx_rx": "cxp_gtx_rx" + str(i)}) # TODO: cdr = ClockDomainsRenamer({"cxp_gtx_rx": "cxp_gtx_rx" + str(i)})
if i == 0:
cxp_interface = cdr(cxp.CXP_Master(tx, rx, debug_sma_pad, pmod_pads))
# Add rtlink for Master Connection only
print("CoaXPress at RTIO channel 0x{:06x}".format(len(rtio_channels)))
rtio_channels.append(rtio.Channel.from_phy(cxp_interface))
else:
cxp_interface = cdr(cxp.CXP_Extension(tx, rx, debug_sma_pad, pmod_pads))
cxp_interface = cxp.CXP_Interface(tx, rx, debug_sma_pad, pmod_pads)
setattr(self.submodules, cxp_name, cxp_interface ) setattr(self.submodules, cxp_name, cxp_interface )
self.csr_devices.append(cxp_name) self.csr_devices.append(cxp_name)
cxp_csr_group.append(cxp_name) cxp_csr_group.append(cxp_name)
# Add memory group
rx_mem_name = "cxp_rx" + str(i) + "_mem" rx_mem_name = "cxp_rx" + str(i) + "_mem"
rx_mem_size = cxp_interface.get_rx_mem_size() rx_mem_size = cxp_interface.get_rx_mem_size()
cxp_rx_mem_group.append(rx_mem_name) cxp_rx_mem_group.append(rx_mem_name)
@ -764,6 +751,7 @@ class CXP_FMC():
# constraint the CLK path # constraint the CLK path
platform.add_false_path_constraints(self.sys_crg.cd_sys.clk, rx.gtx.cd_cxp_gtx_tx.clk, rx.gtx.cd_cxp_gtx_rx.clk) platform.add_false_path_constraints(self.sys_crg.cd_sys.clk, rx.gtx.cd_cxp_gtx_tx.clk, rx.gtx.cd_cxp_gtx_rx.clk)
rtio_channels = []
# FIXME remove this placeholder RTIO channel # FIXME remove this placeholder RTIO channel
# There are too few RTIO channels and cannot be compiled (adr width issue of the lane distributor) # There are too few RTIO channels and cannot be compiled (adr width issue of the lane distributor)
# see https://github.com/m-labs/artiq/pull/2158 for similar issue # see https://github.com/m-labs/artiq/pull/2158 for similar issue

View File

@ -6,7 +6,7 @@ use crate::{cxp_phys, cxp_proto, pl::csr::CXP};
pub fn loopback_testing(channel: usize, timer: &mut GlobalTimer, speed: cxp_phys::CXP_SPEED) { pub fn loopback_testing(channel: usize, timer: &mut GlobalTimer, speed: cxp_phys::CXP_SPEED) {
println!("=============================================================================="); println!("==============================================================================");
cxp_phys::change_linerate(speed); cxp_phys::change_linerate(channel, timer, speed);
unsafe { unsafe {
info!("waiting for tx&rx setup..."); info!("waiting for tx&rx setup...");

View File

@ -4,8 +4,6 @@ use log::info;
use crate::pl::{csr, csr::CXP}; use crate::pl::{csr, csr::CXP};
const CHANNEL_LEN: usize = csr::CXP_LEN;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub enum CXP_SPEED { pub enum CXP_SPEED {
@ -21,35 +19,36 @@ pub enum CXP_SPEED {
pub fn setup(timer: &mut GlobalTimer) { pub fn setup(timer: &mut GlobalTimer) {
down_conn::setup(timer); down_conn::setup(timer);
up_conn::setup(); up_conn::setup();
change_linerate(CXP_SPEED::CXP_1);
} }
pub fn change_linerate(speed: CXP_SPEED) { pub fn change_linerate(channel: usize, timer: &mut GlobalTimer, speed: CXP_SPEED) {
info!("Changing all channels datarate to {:?}", speed); info!("Changing channel {}'s datarate to {:?}", channel, speed);
down_conn::change_linerate(speed); down_conn::change_linerate(channel, timer, speed);
up_conn::change_linerate(speed); up_conn::change_linerate(channel, speed);
} }
mod up_conn { mod up_conn {
use super::*; use super::*;
pub fn setup() { pub fn setup() {
// TODO: do a for loop for channel?
let channel: usize = 0;
unsafe { unsafe {
csr::cxp_phys::upconn_tx_enable_write(1); change_linerate(channel, CXP_SPEED::CXP_1);
(CXP[channel].upconn_tx_enable_write)(1);
} }
} }
pub fn change_linerate(speed: CXP_SPEED) { pub fn change_linerate(channel: usize, speed: CXP_SPEED) {
unsafe { unsafe {
(CXP[channel].upconn_clk_reset_write)(1);
match speed { match speed {
CXP_SPEED::CXP_1 | CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 | CXP_SPEED::CXP_5 | CXP_SPEED::CXP_6 => {
csr::cxp_phys::upconn_bitrate2x_enable_write(0);
}
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => { CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => {
csr::cxp_phys::upconn_bitrate2x_enable_write(1); (CXP[channel].upconn_bitrate2x_enable_write)(1);
} }
_ => {}
}; };
csr::cxp_phys::upconn_clk_reset_write(1); (CXP[channel].upconn_clk_reset_write)(0);
} }
} }
} }
@ -58,11 +57,11 @@ mod down_conn {
use super::*; use super::*;
pub fn setup(timer: &mut GlobalTimer) { pub fn setup(timer: &mut GlobalTimer) {
// TODO: do a for loop for channel?
let channel: usize = 0;
unsafe { unsafe {
info!("turning on pmc loopback mode..."); info!("turning on pmc loopback mode...");
for channel in 0..CHANNEL_LEN {
(CXP[channel].downconn_loopback_mode_write)(0b010); // Near-End PMA Loopback (CXP[channel].downconn_loopback_mode_write)(0b010); // Near-End PMA Loopback
}
// QPLL setup // QPLL setup
csr::cxp_phys::downconn_qpll_reset_write(1); csr::cxp_phys::downconn_qpll_reset_write(1);
@ -70,46 +69,43 @@ mod down_conn {
while csr::cxp_phys::downconn_qpll_locked_read() != 1 {} while csr::cxp_phys::downconn_qpll_locked_read() != 1 {}
info!("QPLL locked"); info!("QPLL locked");
for channel in 0..CHANNEL_LEN {
// tx/rx setup // tx/rx setup
(CXP[channel].downconn_tx_start_init_write)(1); (CXP[channel].downconn_tx_start_init_write)(1);
(CXP[channel].downconn_rx_start_init_write)(1); (CXP[channel].downconn_rx_start_init_write)(1);
}
// DEBUG: printout
info!("waiting for tx & rx setup..."); info!("waiting for tx & rx setup...");
timer.delay_us(50_000); timer.delay_us(50_000);
for channel in 0..CHANNEL_LEN {
info!( info!(
"tx_phaligndone = {} | rx_phaligndone = {}", "tx_phaligndone = {} | rx_phaligndone = {}",
(CXP[channel].downconn_txinit_phaligndone_read)(), (CXP[channel].downconn_txinit_phaligndone_read)(),
(CXP[channel].downconn_rxinit_phaligndone_read)(), (CXP[channel].downconn_rxinit_phaligndone_read)(),
); );
} }
}
change_linerate(channel, timer, CXP_SPEED::CXP_1);
} }
pub fn change_linerate(speed: CXP_SPEED) { pub fn change_linerate(channel: usize, timer: &mut GlobalTimer, speed: CXP_SPEED) {
// DEBUG: DRP pll for TXUSRCLK = freq(linerate)/20 // DEBUG: DRP pll for TXUSRCLK = freq(linerate)/20
let settings = txusrclk::get_txusrclk_config(speed); let settings = txusrclk::get_txusrclk_config(speed);
txusrclk::setup(settings); txusrclk::setup(channel, timer, settings);
change_qpll_fb_divider(speed); change_qpll_fb_divider(speed);
change_gtx_divider(speed); change_gtx_divider(channel, speed);
change_cdr_cfg(speed); change_cdr_cfg(channel, speed);
unsafe { unsafe {
csr::cxp_phys::downconn_qpll_reset_write(1); csr::cxp_phys::downconn_qpll_reset_write(1);
info!("waiting for QPLL/CPLL to lock..."); info!("waiting for QPLL/CPLL to lock...");
while csr::cxp_phys::downconn_qpll_locked_read() != 1 {} while csr::cxp_phys::downconn_qpll_locked_read() != 1 {}
info!("QPLL locked"); info!("QPLL locked");
}
for channel in 0..CHANNEL_LEN { unsafe {
(CXP[channel].downconn_tx_restart_write)(1); (CXP[channel].downconn_tx_restart_write)(1);
(CXP[channel].downconn_rx_restart_write)(1); (CXP[channel].downconn_rx_restart_write)(1);
} }
} }
}
fn change_qpll_fb_divider(speed: CXP_SPEED) { fn change_qpll_fb_divider(speed: CXP_SPEED) {
let qpll_div_reg = match speed { let qpll_div_reg = match speed {
@ -122,7 +118,7 @@ mod down_conn {
println!("0x36 = {:#06x}", qpll_read(0x36)); println!("0x36 = {:#06x}", qpll_read(0x36));
} }
fn change_gtx_divider(speed: CXP_SPEED) { fn change_gtx_divider(channel: usize, speed: CXP_SPEED) {
let div_reg = match speed { let div_reg = match speed {
CXP_SPEED::CXP_1 => 0x33, // RXOUT_DIV = 8 CXP_SPEED::CXP_1 => 0x33, // RXOUT_DIV = 8
CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 => 0x22, // RXOUT_DIV = 4 CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 => 0x22, // RXOUT_DIV = 4
@ -130,14 +126,12 @@ mod down_conn {
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => 0x00, // RXOUT_DIV = 1 CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => 0x00, // RXOUT_DIV = 1
}; };
for channel in 0..CHANNEL_LEN { println!("0x88 = {:#06x}", gtx_read(channel, 0x88));
println!("channel {}, 0x88 = {:#06x}", channel, gtx_read(channel, 0x88));
gtx_write(channel, 0x88, div_reg); gtx_write(channel, 0x88, div_reg);
println!("channel {}, 0x88 = {:#06x}", channel, gtx_read(channel, 0x88)); println!("0x88 = {:#06x}", gtx_read(channel, 0x88));
}
} }
fn change_cdr_cfg(speed: CXP_SPEED) { fn change_cdr_cfg(channel: usize, speed: CXP_SPEED) {
struct CdrConfig { struct CdrConfig {
pub cfg_reg0: u16, // addr = 0xA8 pub cfg_reg0: u16, // addr = 0xA8
pub cfg_reg1: u16, // addr = 0xA9 pub cfg_reg1: u16, // addr = 0xA9
@ -181,14 +175,12 @@ mod down_conn {
}, },
}; };
for channel in 0..CHANNEL_LEN {
gtx_write(channel, 0x0A8, cdr_cfg.cfg_reg0); gtx_write(channel, 0x0A8, cdr_cfg.cfg_reg0);
gtx_write(channel, 0x0A9, cdr_cfg.cfg_reg1); gtx_write(channel, 0x0A9, cdr_cfg.cfg_reg1);
gtx_write(channel, 0x0AA, cdr_cfg.cfg_reg2); gtx_write(channel, 0x0AA, cdr_cfg.cfg_reg2);
gtx_write(channel, 0x0AB, cdr_cfg.cfg_reg3); gtx_write(channel, 0x0AB, cdr_cfg.cfg_reg3);
gtx_write(channel, 0x0AC, cdr_cfg.cfg_reg4); gtx_write(channel, 0x0AC, cdr_cfg.cfg_reg4);
} }
}
#[allow(dead_code)] #[allow(dead_code)]
fn gtx_read(channel: usize, address: u16) -> u16 { fn gtx_read(channel: usize, address: u16) -> u16 {
@ -232,7 +224,6 @@ mod down_conn {
pub mod txusrclk { pub mod txusrclk {
use super::*; use super::*;
#[derive(Copy, Clone)]
pub struct PLLSetting { pub struct PLLSetting {
pub clkout0_reg1: u16, //0x08 pub clkout0_reg1: u16, //0x08
pub clkout0_reg2: u16, //0x09 pub clkout0_reg2: u16, //0x09
@ -326,8 +317,7 @@ mod down_conn {
} }
} }
pub fn setup(settings: PLLSetting) { pub fn setup(channel: usize, timer: &mut GlobalTimer, settings: PLLSetting) {
for channel in 0..CHANNEL_LEN {
if false { if false {
info!("0x08 = {:#06x}", read(channel, 0x08)); info!("0x08 = {:#06x}", read(channel, 0x08));
info!("0x09 = {:#06x}", read(channel, 0x09)); info!("0x09 = {:#06x}", read(channel, 0x09));
@ -357,10 +347,11 @@ mod down_conn {
write(channel, 0x4F, settings.filt_reg2); write(channel, 0x4F, settings.filt_reg2);
reset(channel, false); reset(channel, false);
info!("waiting for PLL of txusrclk to lock..."); // wait for the pll to lock
while unsafe { (CXP[channel].downconn_txpll_locked_read)() == 0 } {} timer.delay_us(100);
info!("txusrclk locked :D");
} let locked = unsafe { (CXP[channel].downconn_txpll_locked_read)() == 1 };
info!("txusrclk locked = {}", locked);
} }
} }

View File

@ -7,7 +7,7 @@ use io::Cursor;
use libboard_zynq::println; use libboard_zynq::println;
use crate::{mem::mem::{CXP_LOOPBACK_MEM, CXP_RX_MEM, CXP_TX_MEM}, use crate::{mem::mem::{CXP_LOOPBACK_MEM, CXP_RX_MEM, CXP_TX_MEM},
pl::{csr, csr::CXP}}; pl::csr::CXP};
const BUF_LEN: usize = 0x800; const BUF_LEN: usize = 0x800;
const DATA_MAXSIZE: usize = 48; const DATA_MAXSIZE: usize = 48;
@ -448,7 +448,7 @@ impl UpConnPacket {
} }
pub fn send(channel: usize, packet: &UpConnPacket) -> Result<(), Error> { pub fn send(channel: usize, packet: &UpConnPacket) -> Result<(), Error> {
if unsafe { csr::cxp_phys::upconn_tx_enable_read() } == 0 { if unsafe { (CXP[channel].upconn_tx_enable_read)() } == 0 {
Err(Error::LinkDown)? Err(Error::LinkDown)?
} }
@ -465,8 +465,6 @@ fn send_data_packet(channel: usize, packet: &UpConnPacket) -> Result<(), Error>
let mut writer = Cursor::new(slice::from_raw_parts_mut(ptr as *mut u8, BUF_LEN)); let mut writer = Cursor::new(slice::from_raw_parts_mut(ptr as *mut u8, BUF_LEN));
packet.write_to(&mut writer)?; packet.write_to(&mut writer)?;
println!("TX MEM after writing");
print_packet(&writer.get_ref()[0..40]);
(CXP[channel].upconn_bootstrap_tx_word_len_write)(writer.position() as u16 / 4); (CXP[channel].upconn_bootstrap_tx_word_len_write)(writer.position() as u16 / 4);
(CXP[channel].upconn_bootstrap_tx_write)(1); (CXP[channel].upconn_bootstrap_tx_write)(1);

View File

@ -24,7 +24,7 @@ pub fn tx_test(channel: usize, timer: &mut GlobalTimer) {
// CXP[channel].upconn_ack_write(1); // CXP[channel].upconn_ack_write(1);
timer.delay_us(20); timer.delay_us(20);
csr::cxp_phys::upconn_tx_enable_write(0); (CXP[channel].upconn_tx_enable_write)(0);
// Collect data // Collect data
let mut i: usize = 0; let mut i: usize = 0;

View File

@ -158,7 +158,11 @@ pub fn main_core0() {
// cxp_downconn::loopback_testing(0, &mut timer, cxp_phys::CXP_SPEED::CXP_6); // cxp_downconn::loopback_testing(0, &mut timer, cxp_phys::CXP_SPEED::CXP_6);
// cxp_downconn::loopback_testing(0, &mut timer, cxp_phys::CXP_SPEED::CXP_10); // cxp_downconn::loopback_testing(0, &mut timer, cxp_phys::CXP_SPEED::CXP_10);
// cxp_downconn::loopback_testing(0, &mut timer, cxp_phys::CXP_SPEED::CXP_12); // cxp_downconn::loopback_testing(0, &mut timer, cxp_phys::CXP_SPEED::CXP_12);
// loop {
// use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayUs;
// cxp_upconn::tx_test(0, &mut timer); // cxp_upconn::tx_test(0, &mut timer);
// timer.delay_us(5_000_000);
// }
comms::main(timer, cfg); comms::main(timer, cfg);
} }