forked from M-Labs/artiq-zynq
Compare commits
11 Commits
675c535812
...
b471db8567
Author | SHA1 | Date |
---|---|---|
morgan | b471db8567 | |
morgan | 4f9f90adbf | |
morgan | 9ec0d58652 | |
morgan | 2cb823493f | |
morgan | 9b9f76a8b8 | |
morgan | 87c0a27566 | |
morgan | ba3015bffd | |
morgan | 66fa70ef3c | |
morgan | 11b3842a7f | |
morgan | d73cd459f0 | |
morgan | 392f38ed7e |
|
@ -0,0 +1,58 @@
|
||||||
|
"""
|
||||||
|
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)
|
|
@ -2,6 +2,8 @@ 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 *
|
||||||
|
@ -10,16 +12,14 @@ 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,6 +43,34 @@ 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()
|
||||||
|
@ -95,23 +123,15 @@ 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.daddr.eq(self.gtx_daddr.storage),
|
||||||
gtx.dwen.eq(0),
|
gtx.den.eq(self.gtx_dread.re | self.gtx_din_stb.re),
|
||||||
If(self.gtx_dread.re,
|
gtx.dwen.eq(self.gtx_din_stb.re),
|
||||||
gtx.den.eq(1),
|
gtx.din.eq(self.gtx_din.storage),
|
||||||
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.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),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -254,7 +274,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(self.rx_restart.re,
|
If(~gtx.rx_ready,
|
||||||
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),
|
||||||
|
@ -296,7 +316,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]),
|
||||||
|
@ -312,20 +332,6 @@ 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
|
||||||
|
@ -350,13 +356,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(2)
|
self.linktrigger = CSRStorage()
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -40,6 +40,15 @@ 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):
|
||||||
|
@ -51,8 +60,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[0].d, gtx.decoders[1].d, gtx.decoders[2].d, gtx.decoders[3].d)),
|
self.source.data.eq(Cat(gtx.decoders[i].d 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)),
|
self.source.k.eq(Cat(gtx.decoders[i].k for i in range(4))),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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(0b1111),
|
self.source.k.eq(Replicate(1, 4)),
|
||||||
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(0b1111),
|
self.source.k.eq(Replicate(1, 4)),
|
||||||
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(max=4)
|
self.linktrig_mode = Signal()
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
|
@ -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 == 0) | (self.linktrig_mode == 2),
|
If(self.linktrig_mode,
|
||||||
trig_packet[0].eq(KCode["trig_indic_28_2"]),
|
|
||||||
trig_packet[1].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[0].eq(KCode["trig_indic_28_4"]),
|
||||||
trig_packet[1].eq(KCode["trig_indic_28_2"]),
|
trig_packet[1].eq(KCode["trig_indic_28_2"]),
|
||||||
trig_packet[2].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[1].eq(KCode["trig_indic_28_4"]),
|
||||||
|
trig_packet[2].eq(KCode["trig_indic_28_4"]),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -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(0b1110),
|
self.source.k.eq(Cat(1, 1, 1, 0)),
|
||||||
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(0b1111),
|
self.source.k.eq(Replicate(1, 4)),
|
||||||
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(0b0000),
|
self.source.k.eq(Replicate(0, 4)),
|
||||||
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(0b0000),
|
self.source.k.eq(Replicate(0, 4)),
|
||||||
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(0b0000),
|
self.source.k.eq(Cat(0, 0, 0, 0)),
|
||||||
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,6 +405,7 @@ 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
|
||||||
|
@ -416,9 +417,7 @@ 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),
|
||||||
|
|
|
@ -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=cg.clk_10x, o_O=debug_sma.n_rx),
|
Instance("OBUF", i_I=serdes.o, o_O=debug_sma.n_rx),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,8 +205,20 @@ 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),
|
||||||
|
]
|
||||||
|
|
|
@ -704,6 +704,7 @@ 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 = []
|
||||||
|
@ -711,13 +712,25 @@ 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)
|
||||||
|
|
||||||
# TODO: cdr = ClockDomainsRenamer({"cxp_gtx_rx": "cxp_gtx_rx" + str(i)})
|
cdr = ClockDomainsRenamer({"cxp_gtx_rx": "cxp_gtx_rx" + str(i)})
|
||||||
|
|
||||||
cxp_interface = cxp.CXP_Interface(tx, rx, debug_sma_pad, pmod_pads)
|
if i == 0:
|
||||||
setattr(self.submodules, cxp_name, cxp_interface )
|
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))
|
||||||
|
|
||||||
|
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)
|
||||||
|
@ -751,7 +764,6 @@ 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
|
||||||
|
|
|
@ -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(channel, timer, speed);
|
cxp_phys::change_linerate(speed);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
info!("waiting for tx&rx setup...");
|
info!("waiting for tx&rx setup...");
|
||||||
|
|
|
@ -4,6 +4,8 @@ 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 {
|
||||||
|
@ -19,36 +21,35 @@ 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(channel: usize, timer: &mut GlobalTimer, speed: CXP_SPEED) {
|
pub fn change_linerate(speed: CXP_SPEED) {
|
||||||
info!("Changing channel {}'s datarate to {:?}", channel, speed);
|
info!("Changing all channels datarate to {:?}", speed);
|
||||||
down_conn::change_linerate(channel, timer, speed);
|
down_conn::change_linerate(speed);
|
||||||
up_conn::change_linerate(channel, speed);
|
up_conn::change_linerate(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 {
|
||||||
change_linerate(channel, CXP_SPEED::CXP_1);
|
csr::cxp_phys::upconn_tx_enable_write(1);
|
||||||
(CXP[channel].upconn_tx_enable_write)(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_linerate(channel: usize, speed: CXP_SPEED) {
|
pub fn change_linerate(speed: CXP_SPEED) {
|
||||||
unsafe {
|
unsafe {
|
||||||
(CXP[channel].upconn_clk_reset_write)(1);
|
|
||||||
match speed {
|
match speed {
|
||||||
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => {
|
CXP_SPEED::CXP_1 | CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 | CXP_SPEED::CXP_5 | CXP_SPEED::CXP_6 => {
|
||||||
(CXP[channel].upconn_bitrate2x_enable_write)(1);
|
csr::cxp_phys::upconn_bitrate2x_enable_write(0);
|
||||||
|
}
|
||||||
|
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => {
|
||||||
|
csr::cxp_phys::upconn_bitrate2x_enable_write(1);
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
(CXP[channel].upconn_clk_reset_write)(0);
|
csr::cxp_phys::upconn_clk_reset_write(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,11 +58,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...");
|
||||||
(CXP[channel].downconn_loopback_mode_write)(0b010); // Near-End PMA Loopback
|
for channel in 0..CHANNEL_LEN {
|
||||||
|
(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);
|
||||||
|
@ -69,41 +70,44 @@ 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");
|
||||||
|
|
||||||
// tx/rx setup
|
for channel in 0..CHANNEL_LEN {
|
||||||
(CXP[channel].downconn_tx_start_init_write)(1);
|
// tx/rx setup
|
||||||
(CXP[channel].downconn_rx_start_init_write)(1);
|
(CXP[channel].downconn_tx_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);
|
||||||
info!(
|
for channel in 0..CHANNEL_LEN {
|
||||||
"tx_phaligndone = {} | rx_phaligndone = {}",
|
info!(
|
||||||
(CXP[channel].downconn_txinit_phaligndone_read)(),
|
"tx_phaligndone = {} | rx_phaligndone = {}",
|
||||||
(CXP[channel].downconn_rxinit_phaligndone_read)(),
|
(CXP[channel].downconn_txinit_phaligndone_read)(),
|
||||||
);
|
(CXP[channel].downconn_rxinit_phaligndone_read)(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
change_linerate(channel, timer, CXP_SPEED::CXP_1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_linerate(channel: usize, timer: &mut GlobalTimer, speed: CXP_SPEED) {
|
pub fn change_linerate(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(channel, timer, settings);
|
txusrclk::setup(settings);
|
||||||
|
|
||||||
change_qpll_fb_divider(speed);
|
change_qpll_fb_divider(speed);
|
||||||
change_gtx_divider(channel, speed);
|
change_gtx_divider(speed);
|
||||||
change_cdr_cfg(channel, speed);
|
change_cdr_cfg(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");
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
for channel in 0..CHANNEL_LEN {
|
||||||
(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +122,7 @@ mod down_conn {
|
||||||
println!("0x36 = {:#06x}", qpll_read(0x36));
|
println!("0x36 = {:#06x}", qpll_read(0x36));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_gtx_divider(channel: usize, speed: CXP_SPEED) {
|
fn change_gtx_divider(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
|
||||||
|
@ -126,12 +130,14 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("0x88 = {:#06x}", gtx_read(channel, 0x88));
|
for channel in 0..CHANNEL_LEN {
|
||||||
gtx_write(channel, 0x88, div_reg);
|
println!("channel {}, 0x88 = {:#06x}", channel, gtx_read(channel, 0x88));
|
||||||
println!("0x88 = {:#06x}", gtx_read(channel, 0x88));
|
gtx_write(channel, 0x88, div_reg);
|
||||||
|
println!("channel {}, 0x88 = {:#06x}", channel, gtx_read(channel, 0x88));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_cdr_cfg(channel: usize, speed: CXP_SPEED) {
|
fn change_cdr_cfg(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
|
||||||
|
@ -175,11 +181,13 @@ mod down_conn {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
gtx_write(channel, 0x0A8, cdr_cfg.cfg_reg0);
|
for channel in 0..CHANNEL_LEN {
|
||||||
gtx_write(channel, 0x0A9, cdr_cfg.cfg_reg1);
|
gtx_write(channel, 0x0A8, cdr_cfg.cfg_reg0);
|
||||||
gtx_write(channel, 0x0AA, cdr_cfg.cfg_reg2);
|
gtx_write(channel, 0x0A9, cdr_cfg.cfg_reg1);
|
||||||
gtx_write(channel, 0x0AB, cdr_cfg.cfg_reg3);
|
gtx_write(channel, 0x0AA, cdr_cfg.cfg_reg2);
|
||||||
gtx_write(channel, 0x0AC, cdr_cfg.cfg_reg4);
|
gtx_write(channel, 0x0AB, cdr_cfg.cfg_reg3);
|
||||||
|
gtx_write(channel, 0x0AC, cdr_cfg.cfg_reg4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -224,6 +232,7 @@ 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
|
||||||
|
@ -317,41 +326,41 @@ mod down_conn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(channel: usize, timer: &mut GlobalTimer, settings: PLLSetting) {
|
pub fn setup(settings: PLLSetting) {
|
||||||
if false {
|
for channel in 0..CHANNEL_LEN {
|
||||||
info!("0x08 = {:#06x}", read(channel, 0x08));
|
if false {
|
||||||
info!("0x09 = {:#06x}", read(channel, 0x09));
|
info!("0x08 = {:#06x}", read(channel, 0x08));
|
||||||
info!("0x14 = {:#06x}", read(channel, 0x14));
|
info!("0x09 = {:#06x}", read(channel, 0x09));
|
||||||
info!("0x15 = {:#06x}", read(channel, 0x15));
|
info!("0x14 = {:#06x}", read(channel, 0x14));
|
||||||
info!("0x16 = {:#06x}", read(channel, 0x16));
|
info!("0x15 = {:#06x}", read(channel, 0x15));
|
||||||
info!("0x18 = {:#06x}", read(channel, 0x18));
|
info!("0x16 = {:#06x}", read(channel, 0x16));
|
||||||
info!("0x19 = {:#06x}", read(channel, 0x19));
|
info!("0x18 = {:#06x}", read(channel, 0x18));
|
||||||
info!("0x1A = {:#06x}", read(channel, 0x1A));
|
info!("0x19 = {:#06x}", read(channel, 0x19));
|
||||||
info!("0x28 = {:#06x}", read(channel, 0x28));
|
info!("0x1A = {:#06x}", read(channel, 0x1A));
|
||||||
info!("0x4E = {:#06x}", read(channel, 0x4E));
|
info!("0x28 = {:#06x}", read(channel, 0x28));
|
||||||
info!("0x4F = {:#06x}", read(channel, 0x4F));
|
info!("0x4E = {:#06x}", read(channel, 0x4E));
|
||||||
} else {
|
info!("0x4F = {:#06x}", read(channel, 0x4F));
|
||||||
// Based on "DRP State Machine" from XAPP888
|
} else {
|
||||||
// hold reset HIGH during pll config
|
// Based on "DRP State Machine" from XAPP888
|
||||||
reset(channel, true);
|
// hold reset HIGH during pll config
|
||||||
write(channel, 0x08, settings.clkout0_reg1);
|
reset(channel, true);
|
||||||
write(channel, 0x09, settings.clkout0_reg2);
|
write(channel, 0x08, settings.clkout0_reg1);
|
||||||
write(channel, 0x14, settings.clkfbout_reg1);
|
write(channel, 0x09, settings.clkout0_reg2);
|
||||||
write(channel, 0x15, settings.clkfbout_reg2);
|
write(channel, 0x14, settings.clkfbout_reg1);
|
||||||
write(channel, 0x16, settings.div_reg);
|
write(channel, 0x15, settings.clkfbout_reg2);
|
||||||
write(channel, 0x18, settings.lock_reg1);
|
write(channel, 0x16, settings.div_reg);
|
||||||
write(channel, 0x19, settings.lock_reg2);
|
write(channel, 0x18, settings.lock_reg1);
|
||||||
write(channel, 0x1A, settings.lock_reg3);
|
write(channel, 0x19, settings.lock_reg2);
|
||||||
write(channel, 0x28, settings.power_reg);
|
write(channel, 0x1A, settings.lock_reg3);
|
||||||
write(channel, 0x4E, settings.filt_reg1);
|
write(channel, 0x28, settings.power_reg);
|
||||||
write(channel, 0x4F, settings.filt_reg2);
|
write(channel, 0x4E, settings.filt_reg1);
|
||||||
reset(channel, false);
|
write(channel, 0x4F, settings.filt_reg2);
|
||||||
|
reset(channel, false);
|
||||||
|
|
||||||
// wait for the pll to lock
|
info!("waiting for PLL of txusrclk to lock...");
|
||||||
timer.delay_us(100);
|
while unsafe { (CXP[channel].downconn_txpll_locked_read)() == 0 } {}
|
||||||
|
info!("txusrclk locked :D");
|
||||||
let locked = unsafe { (CXP[channel].downconn_txpll_locked_read)() == 1 };
|
}
|
||||||
info!("txusrclk locked = {}", locked);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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::CXP};
|
pl::{csr, 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 { (CXP[channel].upconn_tx_enable_read)() } == 0 {
|
if unsafe { csr::cxp_phys::upconn_tx_enable_read() } == 0 {
|
||||||
Err(Error::LinkDown)?
|
Err(Error::LinkDown)?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,6 +465,8 @@ 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);
|
||||||
|
|
|
@ -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);
|
||||||
(CXP[channel].upconn_tx_enable_write)(0);
|
csr::cxp_phys::upconn_tx_enable_write(0);
|
||||||
|
|
||||||
// Collect data
|
// Collect data
|
||||||
let mut i: usize = 0;
|
let mut i: usize = 0;
|
||||||
|
|
|
@ -158,11 +158,7 @@ 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 {
|
// cxp_upconn::tx_test(0, &mut timer);
|
||||||
// use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayUs;
|
|
||||||
// cxp_upconn::tx_test(0, &mut timer);
|
|
||||||
// timer.delay_us(5_000_000);
|
|
||||||
// }
|
|
||||||
|
|
||||||
comms::main(timer, cfg);
|
comms::main(timer, cfg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue