forked from M-Labs/artiq
DRTIO: RTIO/SYS clock merge, KC705
This commit is contained in:
parent
17efc28dbe
commit
3838dfc1d1
|
@ -63,40 +63,12 @@ fn get_rtio_clock_cfg() -> RtioClock {
|
||||||
|
|
||||||
#[cfg(has_rtio_crg)]
|
#[cfg(has_rtio_crg)]
|
||||||
pub mod crg {
|
pub mod crg {
|
||||||
#[cfg(has_rtio_clock_switch)]
|
|
||||||
use super::RtioClock;
|
|
||||||
use board_misoc::{clock, csr};
|
use board_misoc::{clock, csr};
|
||||||
|
|
||||||
pub fn check() -> bool {
|
pub fn check() -> bool {
|
||||||
unsafe { csr::rtio_crg::pll_locked_read() != 0 }
|
unsafe { csr::rtio_crg::pll_locked_read() != 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(has_rtio_clock_switch)]
|
|
||||||
pub fn init(clk: RtioClock) -> bool {
|
|
||||||
let clk_sel: u8 = match clk {
|
|
||||||
RtioClock::Ext0_Bypass => {
|
|
||||||
info!("Using external clock");
|
|
||||||
1
|
|
||||||
},
|
|
||||||
RtioClock::Int_125 => {
|
|
||||||
info!("Using internal RTIO clock");
|
|
||||||
0
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
warn!("rtio_clock setting '{:?}' is not supported. Using default internal RTIO clock instead", clk);
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
csr::rtio_crg::pll_reset_write(1);
|
|
||||||
csr::rtio_crg::clock_sel_write(clk_sel);
|
|
||||||
csr::rtio_crg::pll_reset_write(0);
|
|
||||||
}
|
|
||||||
clock::spin_us(150);
|
|
||||||
return check()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(has_rtio_clock_switch))]
|
|
||||||
pub fn init() -> bool {
|
pub fn init() -> bool {
|
||||||
info!("Using internal RTIO clock");
|
info!("Using internal RTIO clock");
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -223,7 +195,7 @@ fn setup_si5324(clock_cfg: RtioClock) {
|
||||||
#[cfg(soc_platform = "metlino")]
|
#[cfg(soc_platform = "metlino")]
|
||||||
let si5324_ext_input = si5324::Input::Ckin2;
|
let si5324_ext_input = si5324::Input::Ckin2;
|
||||||
#[cfg(soc_platform = "kc705")]
|
#[cfg(soc_platform = "kc705")]
|
||||||
let si5324_ext_input = si5324::Input::Ckin2;
|
let si5324_ext_input = si5324::Input::Ckin1;
|
||||||
match clock_cfg {
|
match clock_cfg {
|
||||||
RtioClock::Ext0_Bypass => {
|
RtioClock::Ext0_Bypass => {
|
||||||
info!("using external RTIO clock with PLL bypass");
|
info!("using external RTIO clock with PLL bypass");
|
||||||
|
@ -277,9 +249,6 @@ pub fn init() {
|
||||||
|
|
||||||
#[cfg(has_rtio_crg)]
|
#[cfg(has_rtio_crg)]
|
||||||
{
|
{
|
||||||
#[cfg(has_rtio_clock_switch)]
|
|
||||||
let result = crg::init(clock_cfg);
|
|
||||||
#[cfg(not(has_rtio_clock_switch))]
|
|
||||||
let result = crg::init();
|
let result = crg::init();
|
||||||
if !result {
|
if !result {
|
||||||
error!("RTIO clock failed");
|
error!("RTIO clock failed");
|
||||||
|
|
|
@ -426,19 +426,6 @@ fn hardware_tick(ts: &mut u64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(has_si5324, rtio_frequency = "150.0"))]
|
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
|
||||||
= si5324::FrequencySettings {
|
|
||||||
n1_hs : 6,
|
|
||||||
nc1_ls : 6,
|
|
||||||
n2_hs : 10,
|
|
||||||
n2_ls : 270,
|
|
||||||
n31 : 75,
|
|
||||||
n32 : 75,
|
|
||||||
bwsel : 4,
|
|
||||||
crystal_ref: true
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(all(has_si5324, rtio_frequency = "125.0"))]
|
#[cfg(all(has_si5324, rtio_frequency = "125.0"))]
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
const SI5324_SETTINGS: si5324::FrequencySettings
|
||||||
= si5324::FrequencySettings {
|
= si5324::FrequencySettings {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
from migen.genlib.cdc import MultiReg
|
||||||
|
|
||||||
from misoc.cores.code_8b10b import Encoder, Decoder
|
from misoc.cores.code_8b10b import Encoder, Decoder
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
|
@ -16,13 +17,12 @@ class GTX_20X(Module):
|
||||||
# * GTX PLL frequency @ 2.5GHz
|
# * GTX PLL frequency @ 2.5GHz
|
||||||
# * GTX line rate (TX & RX) @ 2.5Gb/s
|
# * GTX line rate (TX & RX) @ 2.5Gb/s
|
||||||
# * GTX TX/RX USRCLK @ 125MHz == coarse RTIO frequency
|
# * GTX TX/RX USRCLK @ 125MHz == coarse RTIO frequency
|
||||||
def __init__(self, refclk, pads, sys_clk_freq, rtio_clk_freq=125e6, tx_mode="single", rx_mode="single"):
|
def __init__(self, refclk, pads, clk_freq=125e6, tx_mode="single", rx_mode="single"):
|
||||||
assert tx_mode in ["single", "master", "slave"]
|
assert tx_mode in ["single", "master", "slave"]
|
||||||
assert rx_mode in ["single", "master", "slave"]
|
assert rx_mode in ["single", "master", "slave"]
|
||||||
|
|
||||||
self.txenable = Signal()
|
self.txenable = Signal()
|
||||||
self.submodules.encoder = ClockDomainsRenamer("rtio_tx")(
|
self.submodules.encoder = Encoder(2, True)
|
||||||
Encoder(2, True))
|
|
||||||
self.submodules.decoders = [ClockDomainsRenamer("rtio_rx")(
|
self.submodules.decoders = [ClockDomainsRenamer("rtio_rx")(
|
||||||
(Decoder(True))) for _ in range(2)]
|
(Decoder(True))) for _ in range(2)]
|
||||||
self.rx_ready = Signal()
|
self.rx_ready = Signal()
|
||||||
|
@ -36,11 +36,11 @@ class GTX_20X(Module):
|
||||||
|
|
||||||
cpllreset = Signal()
|
cpllreset = Signal()
|
||||||
cplllock = Signal()
|
cplllock = Signal()
|
||||||
# TX generates RTIO clock, init must be in system domain
|
# TX generates SYS clock, init must be in bootstrap domain
|
||||||
self.submodules.tx_init = tx_init = GTXInit(sys_clk_freq, False, mode=tx_mode)
|
self.submodules.tx_init = tx_init = ClockDomainsRenamer("bootstrap")(
|
||||||
# RX receives restart commands from RTIO domain
|
GTXInit(clk_freq, False, mode=tx_mode))
|
||||||
self.submodules.rx_init = rx_init = ClockDomainsRenamer("rtio_tx")(
|
# RX receives restart commands from SYS domain
|
||||||
GTXInit(rtio_clk_freq, True, mode=rx_mode))
|
self.submodules.rx_init = rx_init = GTXInit(clk_freq, True, mode=rx_mode)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
cpllreset.eq(tx_init.cpllreset),
|
cpllreset.eq(tx_init.cpllreset),
|
||||||
tx_init.cplllock.eq(cplllock),
|
tx_init.cplllock.eq(cplllock),
|
||||||
|
@ -113,8 +113,8 @@ class GTX_20X(Module):
|
||||||
i_TXCHARDISPMODE=Cat(txdata[9], txdata[19]),
|
i_TXCHARDISPMODE=Cat(txdata[9], txdata[19]),
|
||||||
i_TXCHARDISPVAL=Cat(txdata[8], txdata[18]),
|
i_TXCHARDISPVAL=Cat(txdata[8], txdata[18]),
|
||||||
i_TXDATA=Cat(txdata[:8], txdata[10:18]),
|
i_TXDATA=Cat(txdata[:8], txdata[10:18]),
|
||||||
i_TXUSRCLK=ClockSignal("rtio_tx"),
|
i_TXUSRCLK=ClockSignal("sys"),
|
||||||
i_TXUSRCLK2=ClockSignal("rtio_tx"),
|
i_TXUSRCLK2=ClockSignal("sys"),
|
||||||
|
|
||||||
# TX electrical
|
# TX electrical
|
||||||
i_TXBUFDIFFCTRL=0b100,
|
i_TXBUFDIFFCTRL=0b100,
|
||||||
|
@ -247,19 +247,10 @@ class GTX_20X(Module):
|
||||||
p_ES_EYE_SCAN_EN="TRUE", # Must be TRUE for GTX
|
p_ES_EYE_SCAN_EN="TRUE", # Must be TRUE for GTX
|
||||||
)
|
)
|
||||||
|
|
||||||
# TX clocking
|
|
||||||
tx_reset_deglitched = Signal()
|
|
||||||
tx_reset_deglitched.attr.add("no_retiming")
|
|
||||||
self.sync += tx_reset_deglitched.eq(~tx_init.done)
|
|
||||||
self.clock_domains.cd_rtio_tx = ClockDomain()
|
|
||||||
if tx_mode == "single" or tx_mode == "master":
|
|
||||||
self.specials += Instance("BUFG", i_I=self.txoutclk, o_O=self.cd_rtio_tx.clk)
|
|
||||||
self.specials += AsyncResetSynchronizer(self.cd_rtio_tx, tx_reset_deglitched)
|
|
||||||
|
|
||||||
# RX clocking
|
# RX clocking
|
||||||
rx_reset_deglitched = Signal()
|
rx_reset_deglitched = Signal()
|
||||||
rx_reset_deglitched.attr.add("no_retiming")
|
rx_reset_deglitched.attr.add("no_retiming")
|
||||||
self.sync.rtio += rx_reset_deglitched.eq(~rx_init.done)
|
self.sync += rx_reset_deglitched.eq(~rx_init.done)
|
||||||
self.clock_domains.cd_rtio_rx = ClockDomain()
|
self.clock_domains.cd_rtio_rx = ClockDomain()
|
||||||
if rx_mode == "single" or rx_mode == "master":
|
if rx_mode == "single" or rx_mode == "master":
|
||||||
self.specials += Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk),
|
self.specials += Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk),
|
||||||
|
@ -271,7 +262,7 @@ class GTX_20X(Module):
|
||||||
self.decoders[1].input.eq(rxdata[10:])
|
self.decoders[1].input.eq(rxdata[10:])
|
||||||
]
|
]
|
||||||
|
|
||||||
clock_aligner = BruteforceClockAligner(0b0101111100, rtio_clk_freq)
|
clock_aligner = BruteforceClockAligner(0b0101111100, clk_freq)
|
||||||
self.submodules += clock_aligner
|
self.submodules += clock_aligner
|
||||||
self.comb += [
|
self.comb += [
|
||||||
clock_aligner.rxdata.eq(rxdata),
|
clock_aligner.rxdata.eq(rxdata),
|
||||||
|
@ -282,17 +273,18 @@ class GTX_20X(Module):
|
||||||
|
|
||||||
|
|
||||||
class GTX(Module, TransceiverInterface):
|
class GTX(Module, TransceiverInterface):
|
||||||
def __init__(self, clock_pads, pads, sys_clk_freq, rtio_clk_freq=125e6, master=0):
|
def __init__(self, clock_pads, pads, clk_freq=125e6, master=0):
|
||||||
self.nchannels = nchannels = len(pads)
|
self.nchannels = nchannels = len(pads)
|
||||||
self.gtxs = []
|
self.gtxs = []
|
||||||
self.rtio_clk_freq = rtio_clk_freq
|
self.rtio_clk_freq = clk_freq
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
refclk = Signal()
|
refclk = Signal()
|
||||||
stable_clkin_n = Signal()
|
|
||||||
|
clk_enable = Signal()
|
||||||
self.specials += Instance("IBUFDS_GTE2",
|
self.specials += Instance("IBUFDS_GTE2",
|
||||||
i_CEB=stable_clkin_n,
|
i_CEB=~clk_enable,
|
||||||
i_I=clock_pads.p,
|
i_I=clock_pads.p,
|
||||||
i_IB=clock_pads.n,
|
i_IB=clock_pads.n,
|
||||||
o_O=refclk,
|
o_O=refclk,
|
||||||
|
@ -301,7 +293,6 @@ class GTX(Module, TransceiverInterface):
|
||||||
p_CLKSWING_CFG="0b11"
|
p_CLKSWING_CFG="0b11"
|
||||||
)
|
)
|
||||||
|
|
||||||
rtio_tx_clk = Signal()
|
|
||||||
channel_interfaces = []
|
channel_interfaces = []
|
||||||
for i in range(nchannels):
|
for i in range(nchannels):
|
||||||
if nchannels == 1:
|
if nchannels == 1:
|
||||||
|
@ -309,12 +300,7 @@ class GTX(Module, TransceiverInterface):
|
||||||
else:
|
else:
|
||||||
mode = "master" if i == master else "slave"
|
mode = "master" if i == master else "slave"
|
||||||
# Note: RX phase alignment is to be done on individual lanes, not multi-lane.
|
# Note: RX phase alignment is to be done on individual lanes, not multi-lane.
|
||||||
gtx = GTX_20X(refclk, pads[i], sys_clk_freq, rtio_clk_freq=rtio_clk_freq, tx_mode=mode, rx_mode="single")
|
gtx = GTX_20X(refclk, pads[i], clk_freq, tx_mode=mode, rx_mode="single")
|
||||||
# Fan-out (to slave) / Fan-in (from master) of the TXUSRCLK
|
|
||||||
if mode == "slave":
|
|
||||||
self.comb += gtx.cd_rtio_tx.clk.eq(rtio_tx_clk)
|
|
||||||
else:
|
|
||||||
self.comb += rtio_tx_clk.eq(gtx.cd_rtio_tx.clk)
|
|
||||||
self.gtxs.append(gtx)
|
self.gtxs.append(gtx)
|
||||||
setattr(self.submodules, "gtx"+str(i), gtx)
|
setattr(self.submodules, "gtx"+str(i), gtx)
|
||||||
channel_interface = ChannelInterface(gtx.encoder, gtx.decoders)
|
channel_interface = ChannelInterface(gtx.encoder, gtx.decoders)
|
||||||
|
@ -326,15 +312,16 @@ class GTX(Module, TransceiverInterface):
|
||||||
TransceiverInterface.__init__(self, channel_interfaces)
|
TransceiverInterface.__init__(self, channel_interfaces)
|
||||||
for n, gtx in enumerate(self.gtxs):
|
for n, gtx in enumerate(self.gtxs):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
stable_clkin_n.eq(~self.stable_clkin.storage),
|
gtx.txenable.eq(self.txenable.storage[n]),
|
||||||
gtx.txenable.eq(self.txenable.storage[n])
|
gtx.tx_init.stable_clkin.eq(clk_enable)
|
||||||
]
|
]
|
||||||
|
# rx_init is in SYS domain, rather than bootstrap
|
||||||
|
self.specials += MultiReg(clk_enable, gtx.rx_init.stable_clkin)
|
||||||
|
|
||||||
|
# stable_clkin resets after reboot since it's in SYS domain
|
||||||
|
# still need to keep clk_enable high after this
|
||||||
|
self.sync.bootstrap += clk_enable.eq(self.stable_clkin.storage | self.gtxs[0].tx_init.done)
|
||||||
|
|
||||||
# Connect master's `rtio_tx` clock to `rtio` clock
|
|
||||||
self.comb += [
|
|
||||||
self.cd_rtio.clk.eq(self.gtxs[master].cd_rtio_tx.clk),
|
|
||||||
self.cd_rtio.rst.eq(reduce(or_, [gtx.cd_rtio_tx.rst for gtx in self.gtxs]))
|
|
||||||
]
|
|
||||||
# Connect slave i's `rtio_rx` clock to `rtio_rxi` clock
|
# Connect slave i's `rtio_rx` clock to `rtio_rxi` clock
|
||||||
for i in range(nchannels):
|
for i in range(nchannels):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
|
|
|
@ -11,11 +11,13 @@ class GTXInit(Module):
|
||||||
# Choose between Auto Mode and Manual Mode for TX/RX phase alignment with buffer bypassed:
|
# Choose between Auto Mode and Manual Mode for TX/RX phase alignment with buffer bypassed:
|
||||||
# * Auto Mode: When only single lane is involved, as suggested by Xilinx (AR59612)
|
# * Auto Mode: When only single lane is involved, as suggested by Xilinx (AR59612)
|
||||||
# * Manual Mode: When only multi-lane is involved, as suggested by Xilinx (AR59612)
|
# * Manual Mode: When only multi-lane is involved, as suggested by Xilinx (AR59612)
|
||||||
def __init__(self, sys_clk_freq, rx, mode="single"):
|
def __init__(self, clk_freq, rx, mode="single"):
|
||||||
assert isinstance(rx, bool)
|
assert isinstance(rx, bool)
|
||||||
assert mode in ["single", "master", "slave"]
|
assert mode in ["single", "master", "slave"]
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
|
self.stable_clkin = Signal()
|
||||||
|
|
||||||
self.done = Signal()
|
self.done = Signal()
|
||||||
self.restart = Signal()
|
self.restart = Signal()
|
||||||
|
|
||||||
|
@ -83,13 +85,13 @@ class GTXInit(Module):
|
||||||
|
|
||||||
# After configuration, transceiver resets have to stay low for
|
# After configuration, transceiver resets have to stay low for
|
||||||
# at least 500ns (see AR43482)
|
# at least 500ns (see AR43482)
|
||||||
startup_cycles = ceil(500*sys_clk_freq/1000000000)
|
startup_cycles = ceil(500*clk_freq/1000000000)
|
||||||
startup_timer = WaitTimer(startup_cycles)
|
startup_timer = WaitTimer(startup_cycles)
|
||||||
self.submodules += startup_timer
|
self.submodules += startup_timer
|
||||||
|
|
||||||
# PLL reset should be 1 period of refclk
|
# PLL reset should be 1 period of refclk
|
||||||
# (i.e. 1/(125MHz) for the case of RTIO @ 125MHz)
|
# (i.e. 1/(125MHz) for the case of RTIO @ 125MHz)
|
||||||
pll_reset_cycles = ceil(sys_clk_freq/125e6)
|
pll_reset_cycles = ceil(clk_freq/125e6)
|
||||||
pll_reset_timer = WaitTimer(pll_reset_cycles)
|
pll_reset_timer = WaitTimer(pll_reset_cycles)
|
||||||
self.submodules += pll_reset_timer
|
self.submodules += pll_reset_timer
|
||||||
|
|
||||||
|
@ -108,7 +110,7 @@ class GTXInit(Module):
|
||||||
|
|
||||||
startup_fsm.act("INITIAL",
|
startup_fsm.act("INITIAL",
|
||||||
startup_timer.wait.eq(1),
|
startup_timer.wait.eq(1),
|
||||||
If(startup_timer.done, NextState("RESET_ALL"))
|
If(startup_timer.done & self.stable_clkin, NextState("RESET_ALL"))
|
||||||
)
|
)
|
||||||
startup_fsm.act("RESET_ALL",
|
startup_fsm.act("RESET_ALL",
|
||||||
gtXxreset.eq(1),
|
gtXxreset.eq(1),
|
||||||
|
|
|
@ -24,65 +24,20 @@ from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer
|
||||||
from artiq.gateware.drtio import *
|
from artiq.gateware.drtio import *
|
||||||
from artiq.build_soc import *
|
from artiq.build_soc import *
|
||||||
|
|
||||||
|
class SMAClkinForward(Module):
|
||||||
class _RTIOCRG(Module, AutoCSR):
|
def __init__(self, platform):
|
||||||
def __init__(self, platform, rtio_internal_clk, use_sma=True):
|
sma_clkin = platform.request("user_sma_clock")
|
||||||
self._clock_sel = CSRStorage()
|
sma_clkin_se = Signal()
|
||||||
self._pll_reset = CSRStorage(reset=1)
|
sma_clkin_buffered = Signal()
|
||||||
self._pll_locked = CSRStatus()
|
cdr_clk_se = Signal()
|
||||||
self.clock_domains.cd_rtio = ClockDomain()
|
cdr_clk = platform.request("si5324_clkin_33")
|
||||||
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
|
||||||
|
|
||||||
# 100 MHz when using 125MHz input
|
|
||||||
self.clock_domains.cd_ext_clkout = ClockDomain(reset_less=True)
|
|
||||||
platform.add_period_constraint(self.cd_ext_clkout.clk, 5.0)
|
|
||||||
if use_sma:
|
|
||||||
ext_clkout = platform.request("user_sma_gpio_p_33")
|
|
||||||
self.sync.ext_clkout += ext_clkout.eq(~ext_clkout)
|
|
||||||
|
|
||||||
rtio_external_clk = Signal()
|
|
||||||
if use_sma:
|
|
||||||
user_sma_clock = platform.request("user_sma_clock")
|
|
||||||
platform.add_period_constraint(user_sma_clock.p, 8.0)
|
|
||||||
self.specials += Instance("IBUFDS",
|
|
||||||
i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
|
|
||||||
o_O=rtio_external_clk)
|
|
||||||
|
|
||||||
pll_locked = Signal()
|
|
||||||
rtio_clk = Signal()
|
|
||||||
rtiox4_clk = Signal()
|
|
||||||
ext_clkout_clk = Signal()
|
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("PLLE2_ADV",
|
Instance("IBUFDS", i_I=sma_clkin.p, i_IB=sma_clkin.n, o_O=sma_clkin_se),
|
||||||
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
Instance("BUFG", i_I=sma_clkin_se, o_O=sma_clkin_buffered),
|
||||||
|
Instance("ODDR", i_C=sma_clkin_buffered, i_CE=1, i_D1=0, i_D2=1, o_Q=cdr_clk_se),
|
||||||
p_REF_JITTER1=0.01,
|
Instance("OBUFDS", i_I=cdr_clk_se, o_O=cdr_clk.p, o_OB=cdr_clk.n)
|
||||||
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
|
||||||
i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk,
|
|
||||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
|
||||||
i_CLKINSEL=~self._clock_sel.storage,
|
|
||||||
|
|
||||||
# VCO @ 1GHz when using 125MHz input
|
|
||||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
|
||||||
i_CLKFBIN=self.cd_rtio.clk,
|
|
||||||
i_RST=self._pll_reset.storage,
|
|
||||||
|
|
||||||
o_CLKFBOUT=rtio_clk,
|
|
||||||
|
|
||||||
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
|
||||||
o_CLKOUT0=rtiox4_clk,
|
|
||||||
|
|
||||||
p_CLKOUT1_DIVIDE=5, p_CLKOUT1_PHASE=0.0,
|
|
||||||
o_CLKOUT1=ext_clkout_clk),
|
|
||||||
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
|
||||||
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
|
||||||
Instance("BUFG", i_I=ext_clkout_clk, o_O=self.cd_ext_clkout.clk),
|
|
||||||
|
|
||||||
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
|
||||||
MultiReg(pll_locked, self._pll_locked.status)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# The default voltage for these signals on KC705 is 2.5V, and the Migen platform
|
# The default voltage for these signals on KC705 is 2.5V, and the Migen platform
|
||||||
# follows this default. But since the SMAs are on the same bank as the DDS,
|
# follows this default. But since the SMAs are on the same bank as the DDS,
|
||||||
# which is set to 3.3V by reprogramming the KC705 power ICs, we need to
|
# which is set to 3.3V by reprogramming the KC705 power ICs, we need to
|
||||||
|
@ -138,6 +93,7 @@ class _StandaloneBase(MiniSoC, AMPSoC):
|
||||||
integrated_sram_size=8192,
|
integrated_sram_size=8192,
|
||||||
ethmac_nrxslots=4,
|
ethmac_nrxslots=4,
|
||||||
ethmac_ntxslots=4,
|
ethmac_ntxslots=4,
|
||||||
|
rtio_sys_merge=True,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
AMPSoC.__init__(self)
|
AMPSoC.__init__(self)
|
||||||
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
||||||
|
@ -149,6 +105,31 @@ class _StandaloneBase(MiniSoC, AMPSoC):
|
||||||
if isinstance(self.platform.toolchain, XilinxISEToolchain):
|
if isinstance(self.platform.toolchain, XilinxISEToolchain):
|
||||||
self.platform.toolchain.bitgen_opt += " -g compress"
|
self.platform.toolchain.bitgen_opt += " -g compress"
|
||||||
|
|
||||||
|
self.platform.add_extension(_reprogrammed3v3_io)
|
||||||
|
|
||||||
|
cdr_clk_out = self.platform.request("si5324_clkout")
|
||||||
|
cdr_clk = Signal()
|
||||||
|
cdr_clk_buf = Signal()
|
||||||
|
|
||||||
|
self.config["HAS_SI5324"] = None
|
||||||
|
self.config["SI5324_AS_SYNTHESIZER"] = None
|
||||||
|
self.submodules.si5324_rst_n = gpio.GPIOOut(self.platform.request("si5324_33").rst_n)
|
||||||
|
self.csr_devices.append("si5324_rst_n")
|
||||||
|
self.specials += [
|
||||||
|
Instance("IBUFDS_GTE2",
|
||||||
|
i_CEB=0,
|
||||||
|
i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n,
|
||||||
|
o_O=cdr_clk,
|
||||||
|
p_CLKCM_CFG=1,
|
||||||
|
p_CLKRCV_TRST=1,
|
||||||
|
p_CLKSWING_CFG="2'b11"),
|
||||||
|
Instance("BUFG", i_I=cdr_clk, o_O=cdr_clk_buf)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.crg.configure(cdr_clk_buf)
|
||||||
|
|
||||||
|
self.submodules += SMAClkinForward(self.platform)
|
||||||
|
|
||||||
self.submodules.timer1 = timer.Timer()
|
self.submodules.timer1 = timer.Timer()
|
||||||
self.csr_devices.append("timer1")
|
self.csr_devices.append("timer1")
|
||||||
self.interrupt_devices.append("timer1")
|
self.interrupt_devices.append("timer1")
|
||||||
|
@ -158,7 +139,6 @@ class _StandaloneBase(MiniSoC, AMPSoC):
|
||||||
self.platform.request("user_led", 1)))
|
self.platform.request("user_led", 1)))
|
||||||
self.csr_devices.append("leds")
|
self.csr_devices.append("leds")
|
||||||
|
|
||||||
self.platform.add_extension(_reprogrammed3v3_io)
|
|
||||||
self.platform.add_extension(_ams101_dac)
|
self.platform.add_extension(_ams101_dac)
|
||||||
|
|
||||||
i2c = self.platform.request("i2c")
|
i2c = self.platform.request("i2c")
|
||||||
|
@ -169,9 +149,6 @@ class _StandaloneBase(MiniSoC, AMPSoC):
|
||||||
self.config["HAS_DDS"] = None
|
self.config["HAS_DDS"] = None
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels):
|
def add_rtio(self, rtio_channels):
|
||||||
self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk)
|
|
||||||
self.csr_devices.append("rtio_crg")
|
|
||||||
self.config["HAS_RTIO_CLOCK_SWITCH"] = None
|
|
||||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||||
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels)
|
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels)
|
||||||
self.csr_devices.append("rtio_core")
|
self.csr_devices.append("rtio_core")
|
||||||
|
@ -187,11 +164,6 @@ class _StandaloneBase(MiniSoC, AMPSoC):
|
||||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
||||||
self.csr_devices.append("rtio_moninj")
|
self.csr_devices.append("rtio_moninj")
|
||||||
|
|
||||||
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
|
||||||
self.platform.add_false_path_constraints(
|
|
||||||
self.crg.cd_sys.clk,
|
|
||||||
self.rtio_crg.cd_rtio.clk)
|
|
||||||
|
|
||||||
self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
||||||
self.get_native_sdram_if(), cpu_dw=self.cpu_dw)
|
self.get_native_sdram_if(), cpu_dw=self.cpu_dw)
|
||||||
self.csr_devices.append("rtio_analyzer")
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
@ -208,6 +180,7 @@ class _MasterBase(MiniSoC, AMPSoC):
|
||||||
mem_map.update(MiniSoC.mem_map)
|
mem_map.update(MiniSoC.mem_map)
|
||||||
|
|
||||||
def __init__(self, gateware_identifier_str=None, drtio_100mhz=False, **kwargs):
|
def __init__(self, gateware_identifier_str=None, drtio_100mhz=False, **kwargs):
|
||||||
|
clk_freq = 100e6 if drtio_100mhz else 125e6
|
||||||
MiniSoC.__init__(self,
|
MiniSoC.__init__(self,
|
||||||
cpu_type="vexriscv",
|
cpu_type="vexriscv",
|
||||||
cpu_bus_width=64,
|
cpu_bus_width=64,
|
||||||
|
@ -216,6 +189,8 @@ class _MasterBase(MiniSoC, AMPSoC):
|
||||||
integrated_sram_size=8192,
|
integrated_sram_size=8192,
|
||||||
ethmac_nrxslots=4,
|
ethmac_nrxslots=4,
|
||||||
ethmac_ntxslots=4,
|
ethmac_ntxslots=4,
|
||||||
|
clk_freq=clk_freq,
|
||||||
|
rtio_sys_merge=True,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
AMPSoC.__init__(self)
|
AMPSoC.__init__(self)
|
||||||
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
||||||
|
@ -236,14 +211,11 @@ class _MasterBase(MiniSoC, AMPSoC):
|
||||||
platform.request("sfp"), platform.request("user_sma_mgt")
|
platform.request("sfp"), platform.request("user_sma_mgt")
|
||||||
]
|
]
|
||||||
|
|
||||||
rtio_clk_freq = 100e6 if drtio_100mhz else 125e6
|
|
||||||
|
|
||||||
# 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock
|
# 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock
|
||||||
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
||||||
clock_pads=platform.request("si5324_clkout"),
|
clock_pads=platform.request("si5324_clkout"),
|
||||||
pads=data_pads,
|
pads=data_pads,
|
||||||
sys_clk_freq=self.clk_freq,
|
clk_freq=self.clk_freq)
|
||||||
rtio_clk_freq=rtio_clk_freq)
|
|
||||||
self.csr_devices.append("drtio_transceiver")
|
self.csr_devices.append("drtio_transceiver")
|
||||||
|
|
||||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||||
|
@ -292,29 +264,31 @@ class _MasterBase(MiniSoC, AMPSoC):
|
||||||
self.config["HAS_SI5324"] = None
|
self.config["HAS_SI5324"] = None
|
||||||
self.config["SI5324_AS_SYNTHESIZER"] = None
|
self.config["SI5324_AS_SYNTHESIZER"] = None
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")),
|
|
||||||
platform.request("user_sma_clock_n").eq(ClockSignal("rtio"))
|
|
||||||
]
|
|
||||||
|
|
||||||
rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq
|
rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq
|
||||||
# Constrain TX & RX timing for the first transceiver channel
|
# Constrain TX & RX timing for the first transceiver channel
|
||||||
# (First channel acts as master for phase alignment for all channels' TX)
|
# (First channel acts as master for phase alignment for all channels' TX)
|
||||||
gtx0 = self.drtio_transceiver.gtxs[0]
|
gtx0 = self.drtio_transceiver.gtxs[0]
|
||||||
|
|
||||||
|
txout_buf = Signal()
|
||||||
|
self.specials += Instance("BUFG", i_I=gtx0.txoutclk, o_O=txout_buf)
|
||||||
|
self.crg.configure(txout_buf, clk_sw=gtx0.tx_init.done)
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")),
|
||||||
|
platform.request("user_sma_clock_n").eq(gtx0.txoutclk)
|
||||||
|
]
|
||||||
|
|
||||||
platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period)
|
||||||
platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period)
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
self.crg.cd_sys.clk,
|
self.crg.cd_sys.clk, gtx0.rxoutclk)
|
||||||
gtx0.txoutclk, gtx0.rxoutclk)
|
|
||||||
# Constrain RX timing for the each transceiver channel
|
# Constrain RX timing for the each transceiver channel
|
||||||
# (Each channel performs single-lane phase alignment for RX)
|
# (Each channel performs single-lane phase alignment for RX)
|
||||||
for gtx in self.drtio_transceiver.gtxs[1:]:
|
for gtx in self.drtio_transceiver.gtxs[1:]:
|
||||||
platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period)
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
self.crg.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk)
|
self.crg.cd_sys.clk, gtx.rxoutclk)
|
||||||
|
|
||||||
self.submodules.rtio_crg = RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq)
|
|
||||||
self.csr_devices.append("rtio_crg")
|
|
||||||
fix_serdes_timing_path(platform)
|
fix_serdes_timing_path(platform)
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels):
|
def add_rtio(self, rtio_channels):
|
||||||
|
@ -345,12 +319,15 @@ class _SatelliteBase(BaseSoC):
|
||||||
mem_map.update(BaseSoC.mem_map)
|
mem_map.update(BaseSoC.mem_map)
|
||||||
|
|
||||||
def __init__(self, gateware_identifier_str=None, sma_as_sat=False, drtio_100mhz=False, **kwargs):
|
def __init__(self, gateware_identifier_str=None, sma_as_sat=False, drtio_100mhz=False, **kwargs):
|
||||||
|
clk_freq = 100e6 if drtio_100mhz else 125e6
|
||||||
BaseSoC.__init__(self,
|
BaseSoC.__init__(self,
|
||||||
cpu_type="vexriscv",
|
cpu_type="vexriscv",
|
||||||
cpu_bus_width=64,
|
cpu_bus_width=64,
|
||||||
sdram_controller_type="minicon",
|
sdram_controller_type="minicon",
|
||||||
l2_size=128*1024,
|
l2_size=128*1024,
|
||||||
integrated_sram_size=8192,
|
integrated_sram_size=8192,
|
||||||
|
clk_freq=clk_freq,
|
||||||
|
rtio_sys_merge=True,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
||||||
|
|
||||||
|
@ -372,14 +349,13 @@ class _SatelliteBase(BaseSoC):
|
||||||
if sma_as_sat:
|
if sma_as_sat:
|
||||||
data_pads = data_pads[::-1]
|
data_pads = data_pads[::-1]
|
||||||
|
|
||||||
rtio_clk_freq = 100e6 if drtio_100mhz else 125e6
|
rtio_clk_freq = clk_freq
|
||||||
|
|
||||||
# 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock
|
# 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock
|
||||||
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
||||||
clock_pads=platform.request("si5324_clkout"),
|
clock_pads=platform.request("si5324_clkout"),
|
||||||
pads=data_pads,
|
pads=data_pads,
|
||||||
sys_clk_freq=self.clk_freq,
|
clk_freq=self.clk_freq)
|
||||||
rtio_clk_freq=rtio_clk_freq)
|
|
||||||
self.csr_devices.append("drtio_transceiver")
|
self.csr_devices.append("drtio_transceiver")
|
||||||
|
|
||||||
self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3)
|
self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3)
|
||||||
|
@ -432,6 +408,7 @@ class _SatelliteBase(BaseSoC):
|
||||||
self.submodules.siphaser = SiPhaser7Series(
|
self.submodules.siphaser = SiPhaser7Series(
|
||||||
si5324_clkin=platform.request("si5324_clkin_33"),
|
si5324_clkin=platform.request("si5324_clkin_33"),
|
||||||
rx_synchronizer=self.rx_synchronizer,
|
rx_synchronizer=self.rx_synchronizer,
|
||||||
|
ref_clk=ClockSignal("bootstrap"),
|
||||||
ultrascale=False,
|
ultrascale=False,
|
||||||
rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq)
|
rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq)
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
|
@ -445,20 +422,22 @@ class _SatelliteBase(BaseSoC):
|
||||||
self.config["I2C_BUS_COUNT"] = 1
|
self.config["I2C_BUS_COUNT"] = 1
|
||||||
self.config["HAS_SI5324"] = None
|
self.config["HAS_SI5324"] = None
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")),
|
|
||||||
platform.request("user_sma_clock_n").eq(ClockSignal("rtio"))
|
|
||||||
]
|
|
||||||
|
|
||||||
rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq
|
rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq
|
||||||
# Constrain TX & RX timing for the first transceiver channel
|
# Constrain TX & RX timing for the first transceiver channel
|
||||||
# (First channel acts as master for phase alignment for all channels' TX)
|
# (First channel acts as master for phase alignment for all channels' TX)
|
||||||
gtx0 = self.drtio_transceiver.gtxs[0]
|
gtx0 = self.drtio_transceiver.gtxs[0]
|
||||||
|
|
||||||
|
txout_buf = Signal()
|
||||||
|
self.specials += Instance("BUFG", i_I=gtx0.txoutclk, o_O=txout_buf)
|
||||||
|
self.crg.configure(txout_buf, clk_sw=gtx0.tx_init.done)
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")),
|
||||||
|
platform.request("user_sma_clock_n").eq(gtx0.txoutclk)
|
||||||
|
]
|
||||||
|
|
||||||
platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period)
|
||||||
platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period)
|
||||||
platform.add_false_path_constraints(
|
|
||||||
self.crg.cd_sys.clk,
|
|
||||||
gtx0.txoutclk, gtx0.rxoutclk)
|
|
||||||
# Constrain RX timing for the each transceiver channel
|
# Constrain RX timing for the each transceiver channel
|
||||||
# (Each channel performs single-lane phase alignment for RX)
|
# (Each channel performs single-lane phase alignment for RX)
|
||||||
for gtx in self.drtio_transceiver.gtxs[1:]:
|
for gtx in self.drtio_transceiver.gtxs[1:]:
|
||||||
|
@ -466,8 +445,6 @@ class _SatelliteBase(BaseSoC):
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
self.crg.cd_sys.clk, gtx.rxoutclk)
|
self.crg.cd_sys.clk, gtx.rxoutclk)
|
||||||
|
|
||||||
self.submodules.rtio_crg = RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq)
|
|
||||||
self.csr_devices.append("rtio_crg")
|
|
||||||
fix_serdes_timing_path(platform)
|
fix_serdes_timing_path(platform)
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels):
|
def add_rtio(self, rtio_channels):
|
||||||
|
|
Loading…
Reference in New Issue