master WRPLL: init
gw: add rtio_frequency gw: add wrpll ref clock config gw: add mmcm and expose mmcm config port fw: add mmcm read fw: add CLK_SEL to expander
This commit is contained in:
parent
9d5d883b1b
commit
c7df09b6a3
@ -224,8 +224,6 @@ class GenericMaster(SoCCore):
|
|||||||
|
|
||||||
self.config["HW_REV"] = description["hw_rev"]
|
self.config["HW_REV"] = description["hw_rev"]
|
||||||
|
|
||||||
self.submodules += SMAClkinForward(self.platform)
|
|
||||||
|
|
||||||
data_pads = [platform.request("sfp", i) for i in range(4)]
|
data_pads = [platform.request("sfp", i) for i in range(4)]
|
||||||
|
|
||||||
self.submodules.gt_drtio = gtx_7series.GTX(
|
self.submodules.gt_drtio = gtx_7series.GTX(
|
||||||
@ -259,6 +257,16 @@ class GenericMaster(SoCCore):
|
|||||||
self.comb += ext_async_rst.eq(self.sys_crg.clk_sw_fsm.o_clk_sw & ~gtx0.tx_init.done)
|
self.comb += ext_async_rst.eq(self.sys_crg.clk_sw_fsm.o_clk_sw & ~gtx0.tx_init.done)
|
||||||
self.specials += MultiReg(self.sys_crg.clk_sw_fsm.o_clk_sw & self.sys_crg.mmcm_locked, self.gt_drtio.clk_path_ready, odomain="bootstrap")
|
self.specials += MultiReg(self.sys_crg.clk_sw_fsm.o_clk_sw & self.sys_crg.mmcm_locked, self.gt_drtio.clk_path_ready, odomain="bootstrap")
|
||||||
|
|
||||||
|
if with_wrpll:
|
||||||
|
self.submodules.sma_pll = wrpll.SMA_PLL(platform.request("sma_clkin"))
|
||||||
|
self.csr_devices.append("sma_pll")
|
||||||
|
|
||||||
|
self.submodules.main_dcxo = si549.Si549(platform.request("ddmtd_main_dcxo_i2c"))
|
||||||
|
self.csr_devices.append("main_dcxo")
|
||||||
|
self.config["HAS_SI549"] = None
|
||||||
|
self.config["WRPLL_REF_CLK"] = "SMA_CLKIN"
|
||||||
|
else:
|
||||||
|
self.submodules += SMAClkinForward(self.platform)
|
||||||
self.config["HAS_SI5324"] = None
|
self.config["HAS_SI5324"] = None
|
||||||
self.config["SI5324_SOFT_RESET"] = None
|
self.config["SI5324_SOFT_RESET"] = None
|
||||||
|
|
||||||
@ -565,6 +573,7 @@ class GenericSatellite(SoCCore):
|
|||||||
self.csr_devices.append("wrpll")
|
self.csr_devices.append("wrpll")
|
||||||
self.comb += self.ps7.core.core0.nfiq.eq(self.wrpll.ev.irq)
|
self.comb += self.ps7.core.core0.nfiq.eq(self.wrpll.ev.irq)
|
||||||
self.config["HAS_SI549"] = None
|
self.config["HAS_SI549"] = None
|
||||||
|
self.config["WRPLL_REF_CLK"] = "GTX_CDR"
|
||||||
else:
|
else:
|
||||||
self.submodules.siphaser = SiPhaser7Series(
|
self.submodules.siphaser = SiPhaser7Series(
|
||||||
si5324_clkin=platform.request("cdr_clk"),
|
si5324_clkin=platform.request("cdr_clk"),
|
||||||
|
@ -124,3 +124,64 @@ class WRPLL(Module, AutoCSR):
|
|||||||
]
|
]
|
||||||
|
|
||||||
self.submodules.ev = SharedIRQ(self.ref_tag_ev, self.main_tag_ev)
|
self.submodules.ev = SharedIRQ(self.ref_tag_ev, self.main_tag_ev)
|
||||||
|
|
||||||
|
|
||||||
|
class SMA_PLL(Module, AutoCSR):
|
||||||
|
def __init__(self, sma_clkin):
|
||||||
|
freq = 125e9
|
||||||
|
period = 1e9/freq # ns
|
||||||
|
|
||||||
|
mmcm_locked = Signal()
|
||||||
|
mmcm_fb_clk = Signal()
|
||||||
|
ref_clk = Signal()
|
||||||
|
self.clock_domains.cd_ref = ClockDomain()
|
||||||
|
|
||||||
|
self.mmcm_locked = CSRStatus()
|
||||||
|
self.mmcm_reset = CSRStorage() #TODO for i_RST
|
||||||
|
|
||||||
|
self.drp_addr = CSRStorage(7)
|
||||||
|
self.drp_in = CSRStorage(16)
|
||||||
|
self.drp_w_en = CSRStorage()
|
||||||
|
self.drp_en = CSRStorage()
|
||||||
|
self.drp_clk = CSRStorage()
|
||||||
|
self.drp_out = CSRStatus(16)
|
||||||
|
self.drp_ready = CSRStatus()
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.specials += [
|
||||||
|
# MMCME2 is capable to accept 10Mhz input while PLLE2 only support down to 19Mhz input (DS191)
|
||||||
|
Instance("MMCME2_ADV",
|
||||||
|
p_BANDWIDTH="LOW", # lower jitter
|
||||||
|
o_LOCKED=self.mmcm_locked.status,
|
||||||
|
|
||||||
|
p_CLKIN1_PERIOD=period,
|
||||||
|
i_CLKIN1=ClockSignal("sys"),
|
||||||
|
i_RST=ResetSignal("sys"),
|
||||||
|
i_CLKINSEL=1, # 1=CLKIN1 0=CLKIN2
|
||||||
|
|
||||||
|
# VCO @ 1Ghz
|
||||||
|
p_CLKFBOUT_MULT_F=8.0,
|
||||||
|
# p_CLKFBOUT_MULT = 1.0, # M = p_CLKFBOUT_MULT_F/p_CLKFBOUT_MULT
|
||||||
|
p_DIVCLK_DIVIDE=1,
|
||||||
|
i_CLKFBIN=mmcm_fb_clk, o_CLKFBOUT=mmcm_fb_clk,
|
||||||
|
|
||||||
|
# 62.5MHz
|
||||||
|
p_CLKOUT0_DIVIDE_F=16, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=ref_clk,
|
||||||
|
|
||||||
|
# Dynamic Reconfiguration Port
|
||||||
|
i_DADDR = self.drp_addr.storage,
|
||||||
|
i_DI = self.drp_in.storage,
|
||||||
|
i_DWE = self.drp_w_en.storage,
|
||||||
|
i_DEN = self.drp_en.storage,
|
||||||
|
i_DCLK = self.drp_clk.storage,
|
||||||
|
o_DO = self.drp_out.status,
|
||||||
|
o_DRDY = self.drp_ready.status
|
||||||
|
),
|
||||||
|
Instance("BUFG", i_I=ref_clk, o_O=self.cd_ref.clk),
|
||||||
|
AsyncResetSynchronizer(self.cd_ref, ~self.mmcm_locked.status),
|
||||||
|
|
||||||
|
# debug output
|
||||||
|
Instance("OBUFDS", i_I=self.cd_ref.clk, o_O=sma_clkin.p, o_OB=sma_clkin.n)
|
||||||
|
]
|
||||||
|
|
||||||
|
@ -547,3 +547,64 @@ pub mod wrpll {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_sma_pll)]
|
||||||
|
pub mod sma_pll {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// Based on "DRP State Machine" section from XAPP888
|
||||||
|
mod mmcm {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn one_clock_cycle(timer: &mut GlobalTimer) {
|
||||||
|
unsafe {
|
||||||
|
csr::sma_pll::drp_clk_write(1);
|
||||||
|
timer.delay_us(1);
|
||||||
|
csr::sma_pll::drp_clk_write(0);
|
||||||
|
timer.delay_us(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_addr(address: u8) {
|
||||||
|
unsafe {
|
||||||
|
csr::sma_pll::drp_addr_write(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_enable(en: bool) {
|
||||||
|
unsafe {
|
||||||
|
let val = if en { 1 } else { 0 };
|
||||||
|
csr::sma_pll::drp_en_write(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_data() -> u16 {
|
||||||
|
unsafe { csr::sma_pll::drp_out_read() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drp_ready() -> bool {
|
||||||
|
unsafe { csr::sma_pll::drp_ready_read() == 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(timer: &mut GlobalTimer, address: u8) -> u16 {
|
||||||
|
set_addr(address);
|
||||||
|
set_enable(true);
|
||||||
|
// Set DADDR on the MMCM and assert DEN for one clock cycle
|
||||||
|
one_clock_cycle(timer);
|
||||||
|
set_enable(false);
|
||||||
|
while !drp_ready() {
|
||||||
|
// keep the clock signal until data is ready
|
||||||
|
one_clock_cycle(timer);
|
||||||
|
}
|
||||||
|
get_data()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(timer: &mut GlobalTimer) {
|
||||||
|
for addr in 7..12 {
|
||||||
|
info!("address = {:#x} | val = {:016b}", addr, mmcm::read(timer, addr));
|
||||||
|
}
|
||||||
|
info!("running SMA PLL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -104,6 +104,11 @@ pub fn main_core0() {
|
|||||||
io_expander1
|
io_expander1
|
||||||
.init(i2c_bus)
|
.init(i2c_bus)
|
||||||
.expect("I2C I/O expander #1 initialization failed");
|
.expect("I2C I/O expander #1 initialization failed");
|
||||||
|
|
||||||
|
// Drive CLK_SEL to true
|
||||||
|
#[cfg(has_si549)]
|
||||||
|
io_expander0.set(1, 7, true);
|
||||||
|
|
||||||
// Drive TX_DISABLE to false on SFP0..3
|
// Drive TX_DISABLE to false on SFP0..3
|
||||||
io_expander0.set(0, 1, false);
|
io_expander0.set(0, 1, false);
|
||||||
io_expander1.set(0, 1, false);
|
io_expander1.set(0, 1, false);
|
||||||
|
@ -4,6 +4,8 @@ use ksupport::i2c;
|
|||||||
use libboard_artiq::pl;
|
use libboard_artiq::pl;
|
||||||
#[cfg(has_si5324)]
|
#[cfg(has_si5324)]
|
||||||
use libboard_artiq::si5324;
|
use libboard_artiq::si5324;
|
||||||
|
#[cfg(has_si549)]
|
||||||
|
use libboard_artiq::si549;
|
||||||
#[cfg(has_si5324)]
|
#[cfg(has_si5324)]
|
||||||
use libboard_zynq::i2c::I2c;
|
use libboard_zynq::i2c::I2c;
|
||||||
use libboard_zynq::timer::GlobalTimer;
|
use libboard_zynq::timer::GlobalTimer;
|
||||||
@ -260,6 +262,48 @@ fn setup_si5324(i2c: &mut I2c, timer: &mut GlobalTimer, clk: RtioClock) {
|
|||||||
si5324::setup(i2c, &si5324_settings, si5324_ref_input, timer).expect("cannot initialize Si5324");
|
si5324::setup(i2c, &si5324_settings, si5324_ref_input, timer).expect("cannot initialize Si5324");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_si549)]
|
||||||
|
fn setup_si549(timer: &mut GlobalTimer, clk: RtioClock) {
|
||||||
|
let si549_settings = match clk {
|
||||||
|
RtioClock::Int_100 => {
|
||||||
|
info!("using internal 100MHz RTIO clock");
|
||||||
|
si549::FrequencySetting {
|
||||||
|
main: si549::DividerConfig {
|
||||||
|
hsdiv: 0x06C,
|
||||||
|
lsdiv: 0,
|
||||||
|
fbdiv: 0x046C5F49797,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RtioClock::Int_125 => {
|
||||||
|
info!("using internal 125MHz RTIO clock");
|
||||||
|
si549::FrequencySetting {
|
||||||
|
main: si549::DividerConfig {
|
||||||
|
hsdiv: 0x058,
|
||||||
|
lsdiv: 0,
|
||||||
|
fbdiv: 0x04815791F25,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// same setting as Int_125, but fallback to default
|
||||||
|
warn!(
|
||||||
|
"rtio_clock setting '{:?}' is unsupported. Falling back to default 125MHz RTIO clock.",
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
si549::FrequencySetting {
|
||||||
|
main: si549::DividerConfig {
|
||||||
|
hsdiv: 0x058,
|
||||||
|
lsdiv: 0,
|
||||||
|
fbdiv: 0x04815791F25,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
si549::main_setup(timer, si549_settings).expect("cannot initialize main Si549");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
|
pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
|
||||||
let clk = get_rtio_clock_cfg(cfg);
|
let clk = get_rtio_clock_cfg(cfg);
|
||||||
#[cfg(has_si5324)]
|
#[cfg(has_si5324)]
|
||||||
@ -273,6 +317,11 @@ pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
|
|||||||
_ => setup_si5324(i2c, timer, clk),
|
_ => setup_si5324(i2c, timer, clk),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(has_si549)]
|
||||||
|
{
|
||||||
|
si549::sma_pll::setup(timer);
|
||||||
|
setup_si549(timer, clk);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
init_drtio(timer);
|
init_drtio(timer);
|
||||||
|
Loading…
Reference in New Issue
Block a user