forked from M-Labs/artiq-zynq
FIQ_issue
This commit is contained in:
parent
f8f6dcef14
commit
adaecf87a8
|
@ -231,6 +231,7 @@ class GenericMaster(SoCCore):
|
|||
pads=data_pads,
|
||||
clk_freq=clk_freq)
|
||||
self.csr_devices.append("gt_drtio")
|
||||
self.config["RTIO_FREQUENCY"] = str(clk_freq/1e6)
|
||||
self.config["CLOCK_FREQUENCY"] = int(clk_freq)
|
||||
|
||||
txout_buf = Signal()
|
||||
|
@ -259,10 +260,17 @@ class GenericMaster(SoCCore):
|
|||
|
||||
if with_wrpll:
|
||||
self.submodules.wrpll_refclk = wrpll.SMAFrequencyMultiplier(platform.request("sma_clkin"))
|
||||
self.csr_devices.append("wrpll_refclk")
|
||||
|
||||
self.submodules.main_dcxo = si549.Si549(platform.request("ddmtd_main_dcxo_i2c"))
|
||||
self.submodules.helper_dcxo = si549.Si549(platform.request("ddmtd_helper_dcxo_i2c"))
|
||||
self.submodules.wrpll = wrpll.WRPLL(
|
||||
cd_ref=self.wrpll_refclk.cd_ref,
|
||||
main_dcxo_pads=platform.request("cdr_clk_clean_fabric"),
|
||||
helper_dcxo_pads=platform.request("ddmtd_helper_clk"))
|
||||
self.csr_devices.append("wrpll_refclk")
|
||||
self.csr_devices.append("main_dcxo")
|
||||
self.csr_devices.append("helper_dcxo")
|
||||
self.csr_devices.append("wrpll")
|
||||
self.comb += self.ps7.core.core0.nfiq.eq(self.wrpll.ev.irq)
|
||||
self.config["HAS_SI549"] = None
|
||||
self.config["WRPLL_REF_CLK"] = "SMA_CLKIN"
|
||||
else:
|
||||
|
@ -612,7 +620,7 @@ def main():
|
|||
help="build gateware into the specified directory")
|
||||
parser.add_argument("--acpki", default=False, action="store_true",
|
||||
help="enable ACPKI")
|
||||
parser.add_argument("--with-wrpll", default=False, action="store_true",
|
||||
parser.add_argument("--with-wrpll", default=True, action="store_true",
|
||||
help="enable WRPLL")
|
||||
parser.add_argument("description", metavar="DESCRIPTION",
|
||||
help="JSON system description file")
|
||||
|
|
|
@ -60,7 +60,7 @@ class WRPLL(Module, AutoCSR):
|
|||
|
||||
# # #
|
||||
|
||||
self.helper_reset = CSRStorage(reset=1)
|
||||
self.helper_reset = CSRStorage()
|
||||
self.clock_domains.cd_helper = ClockDomain()
|
||||
self.specials += [
|
||||
Instance("IBUFGDS",
|
||||
|
@ -131,6 +131,7 @@ class SMAFrequencyMultiplier(Module, AutoCSR):
|
|||
freq = 125e6
|
||||
period = 1e9/freq # ns
|
||||
|
||||
sma_clkin_se = Signal()
|
||||
mmcm_locked = Signal()
|
||||
mmcm_fb_clk = Signal()
|
||||
ref_clk = Signal()
|
||||
|
@ -150,6 +151,9 @@ class SMAFrequencyMultiplier(Module, AutoCSR):
|
|||
# # #
|
||||
|
||||
self.specials += [
|
||||
Instance("IBUFDS",
|
||||
i_I=sma_clkin.p, i_IB=sma_clkin.n,
|
||||
o_O=sma_clkin_se),
|
||||
# MMCME2 is capable to accept 10Mhz input while PLLE2 only support down to 19Mhz input (DS191)
|
||||
Instance("MMCME2_ADV",
|
||||
p_BANDWIDTH="LOW", # lower jitter
|
||||
|
@ -157,7 +161,7 @@ class SMAFrequencyMultiplier(Module, AutoCSR):
|
|||
i_RST=self.mmcm_reset.storage,
|
||||
|
||||
p_CLKIN1_PERIOD=period,
|
||||
i_CLKIN1=ClockSignal("sys"),
|
||||
i_CLKIN1=sma_clkin_se,
|
||||
i_CLKINSEL=1, # 1=CLKIN1 0=CLKIN2
|
||||
|
||||
# VCO @ 1.25Ghz
|
||||
|
@ -178,7 +182,4 @@ class SMAFrequencyMultiplier(Module, AutoCSR):
|
|||
),
|
||||
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)
|
||||
]
|
||||
|
|
|
@ -7,12 +7,14 @@ use crate::pl::csr;
|
|||
#[cfg(feature = "target_kasli_soc")]
|
||||
const ADDRESS: u8 = 0x67;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct DividerConfig {
|
||||
pub hsdiv: u16,
|
||||
pub lsdiv: u8,
|
||||
pub fbdiv: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct FrequencySetting {
|
||||
pub main: DividerConfig,
|
||||
#[cfg(has_wrpll)]
|
||||
|
@ -272,6 +274,7 @@ pub fn main_setup(timer: &mut GlobalTimer, settings: FrequencySetting) -> Result
|
|||
#[cfg(has_wrpll)]
|
||||
pub mod wrpll {
|
||||
|
||||
use embedded_hal::blocking::delay::DelayMs;
|
||||
use libcortex_a9::mutex::Mutex;
|
||||
|
||||
use super::*;
|
||||
|
@ -376,6 +379,8 @@ pub mod wrpll {
|
|||
csr::helper_dcxo::bitbang_enable_write(0);
|
||||
}
|
||||
info!("Helper Si549 started");
|
||||
|
||||
timer.delay_ms(5_000);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -446,12 +451,15 @@ pub mod wrpll {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_freq_counts(timer: &mut GlobalTimer) -> (u32, u32) {
|
||||
pub fn get_freq_counts(timer: &mut GlobalTimer) -> (u32, u32) {
|
||||
unsafe {
|
||||
csr::wrpll::frequency_counter_update_en_write(1);
|
||||
timer.delay_us(150_000); // 8ns << TIMER_WIDTH
|
||||
csr::wrpll::frequency_counter_update_en_write(0);
|
||||
let ref_count = csr::wrpll::frequency_counter_counter_gtx0_rtio_rx_read();
|
||||
#[cfg(wrpll_ref_clk = "GTX_CDR")]
|
||||
let ref_count = csr::wrpll::frequency_counter_counter_rtio_rx0_read();
|
||||
#[cfg(wrpll_ref_clk = "SMA_CLKIN")]
|
||||
let ref_count = csr::wrpll::frequency_counter_counter_ref_read();
|
||||
let main_count = csr::wrpll::frequency_counter_counter_sys_read();
|
||||
|
||||
(ref_count, main_count)
|
||||
|
@ -500,6 +508,21 @@ pub mod wrpll {
|
|||
}
|
||||
|
||||
fn helper_pll() -> Result<(), &'static str> {
|
||||
// unsafe {
|
||||
// use libboard_zynq::println;
|
||||
|
||||
// ERR_ARR[COUNTER] = tag_collector::get_period_error();
|
||||
|
||||
// if COUNTER == SIZE - 1 {
|
||||
// for i in 0..SIZE {
|
||||
// println!("{}", ERR_ARR[i])
|
||||
// }
|
||||
// COUNTER = 0;
|
||||
// let mut timer = GlobalTimer::get();
|
||||
// timer.delay_us(20_000_000);
|
||||
// }
|
||||
// COUNTER += 1;
|
||||
// }
|
||||
let period_err = tag_collector::get_period_error();
|
||||
let mut integrator_lock = H_INTEGRATOR.lock();
|
||||
|
||||
|
@ -512,7 +535,29 @@ pub mod wrpll {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
const SIZE: usize = 2000;
|
||||
static mut COUNTER: usize = 0;
|
||||
static mut ERR_ARR: [i32; SIZE] = [0; SIZE];
|
||||
static mut FIN_ADPLL: i32 = 0;
|
||||
|
||||
fn main_pll() -> Result<(), &'static str> {
|
||||
// unsafe {
|
||||
// use libboard_zynq::println;
|
||||
|
||||
// ERR_ARR[COUNTER] = tag_collector::get_phase_error();
|
||||
|
||||
// if COUNTER == SIZE - 1 {
|
||||
// for i in 0..SIZE {
|
||||
// println!("{}", ERR_ARR[i])
|
||||
// }
|
||||
// println!("{:>3} Zero crossing adpll = {:>5}", SIZE, FIN_ADPLL);
|
||||
// COUNTER = 0;
|
||||
// let mut timer = GlobalTimer::get();
|
||||
// timer.delay_us(20_000_000);
|
||||
// }
|
||||
// COUNTER += 1;
|
||||
// }
|
||||
|
||||
let phase_err = tag_collector::get_phase_error();
|
||||
let mut integrator_lock = M_INTEGRATOR.lock();
|
||||
|
||||
|
@ -522,6 +567,12 @@ pub mod wrpll {
|
|||
m_adpll = m_adpll.clamp(-ADPLL_MAX, ADPLL_MAX);
|
||||
set_adpll(i2c::DCXO::Main, m_adpll)?;
|
||||
|
||||
unsafe {
|
||||
if ERR_ARR[COUNTER] == 0 {
|
||||
FIN_ADPLL = m_adpll;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -532,18 +583,50 @@ pub mod wrpll {
|
|||
tag_collector::reset();
|
||||
reset_plls().expect("failed to reset main and helper PLL");
|
||||
|
||||
info!("warming up GTX CDR...");
|
||||
// gtx need a couple seconds for freq counter to read it properly
|
||||
timer.delay_us(20_000_000);
|
||||
info!("warming up refclk...");
|
||||
// refclk need a couple seconds for freq counter to read it properly
|
||||
// timer.delay_us(20_000_000);
|
||||
set_base_adpll(timer).expect("failed to set base adpll");
|
||||
|
||||
let ppm = 0.0;
|
||||
*BASE_ADPLL.lock() += (ppm / 0.0001164) as i32;
|
||||
timer.delay_us(200);
|
||||
info!("KP = {}, KI = {}", KP, KI);
|
||||
info!("adding {}ppm to main & helper base adpll ({})", ppm, *BASE_ADPLL.lock());
|
||||
|
||||
// clear gateware pending flag
|
||||
clear_pending(FIQ::RefTag);
|
||||
clear_pending(FIQ::MainTag);
|
||||
|
||||
unsafe {
|
||||
info!("ref tag = {} ", csr::wrpll::ref_tag_read());
|
||||
info!("main tag = {} ", csr::wrpll::main_tag_read());
|
||||
}
|
||||
|
||||
// use nFIQ to avoid IRQ being disabled by mutex lock and mess up PLL
|
||||
set_fiq(true);
|
||||
info!("WRPLL interrupt enabled");
|
||||
|
||||
timer.delay_ms(500);
|
||||
unsafe {
|
||||
info!("main_tag_ev_enable_read() = {}", csr::wrpll::main_tag_ev_enable_read());
|
||||
info!("main_tag_ev_status_read() = {}", csr::wrpll::main_tag_ev_status_read());
|
||||
info!("ref_tag_ev_enable_read() = {}", csr::wrpll::ref_tag_ev_enable_read());
|
||||
info!("ref_tag_ev_status_read() = {}", csr::wrpll::ref_tag_ev_status_read());
|
||||
|
||||
// loop {
|
||||
// if is_pending(FIQ::RefTag) {
|
||||
// info!("REF tag is pending")
|
||||
// }
|
||||
// if is_pending(FIQ::MainTag) {
|
||||
// info!("Main tag is pending")
|
||||
// }
|
||||
|
||||
// // info!("ref tag = {} ", csr::wrpll::ref_tag_read());
|
||||
// // info!("main tag = {} ", csr::wrpll::main_tag_read());
|
||||
// timer.delay_ms(500);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -671,13 +754,25 @@ pub mod wrpll_refclk {
|
|||
if !locked {
|
||||
return Err("failed to generate 125Mhz ref clock from SMA CLKIN");
|
||||
}
|
||||
|
||||
// const TIMER_WIDTH: u32 = 24;
|
||||
// const COUNTER_DIV: u32 = 2;
|
||||
|
||||
// let (ref_count, main_count) = wrpll::get_freq_counts(timer);
|
||||
|
||||
// let f_sys = 125e6;
|
||||
|
||||
// info!(
|
||||
// "ref counter = {} freq = {}",
|
||||
// ref_count,
|
||||
// (ref_count as f64 * f_sys) as f64 / (1 << (TIMER_WIDTH - COUNTER_DIV)) as f64
|
||||
// );
|
||||
// info!(
|
||||
// "Main counter = {} freq = {}",
|
||||
// main_count,
|
||||
// (main_count as f64 * f_sys) as f64 / (1 << (TIMER_WIDTH - COUNTER_DIV)) as f64
|
||||
// );
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use libcortex_a9::{interrupt_handler, regs::MPIDR};
|
|||
use libregister::RegisterR;
|
||||
|
||||
interrupt_handler!(FIQ, fiq, __irq_stack0_start, __irq_stack1_start, {
|
||||
// println!("hello?");
|
||||
match MPIDR.read().cpu_id() {
|
||||
0 => {
|
||||
// nFIQ is driven directly and bypass GIC
|
||||
|
|
|
@ -6,6 +6,8 @@ use libboard_artiq::pl;
|
|||
use libboard_artiq::si5324;
|
||||
#[cfg(has_si549)]
|
||||
use libboard_artiq::si549;
|
||||
#[cfg(has_wrpll)]
|
||||
use libboard_artiq::si549::wrpll_refclk;
|
||||
#[cfg(has_si5324)]
|
||||
use libboard_zynq::i2c::I2c;
|
||||
use libboard_zynq::timer::GlobalTimer;
|
||||
|
@ -262,46 +264,137 @@ fn setup_si5324(i2c: &mut I2c, timer: &mut GlobalTimer, clk: RtioClock) {
|
|||
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 {
|
||||
#[cfg(has_wrpll)]
|
||||
fn wrpll_setup(timer: &mut GlobalTimer, clk: RtioClock, si549_settings: si549::FrequencySetting) {
|
||||
let mmcm_setting = match clk {
|
||||
RtioClock::Ext0_Synth0_10to125 => si549::wrpll_refclk::MmcmSetting {
|
||||
clkout0_reg1: 0x1083,
|
||||
clkout0_reg2: 0x0080,
|
||||
clkfbout_reg1: 0x179e,
|
||||
clkfbout_reg2: 0x4c00,
|
||||
div_reg: 0x1041,
|
||||
lock_reg1: 0x00fa,
|
||||
lock_reg2: 0x7c01,
|
||||
lock_reg3: 0xffe9,
|
||||
power_reg: 0x9900,
|
||||
filt_reg1: 0x0808,
|
||||
filt_reg2: 0x0800,
|
||||
},
|
||||
RtioClock::Ext0_Synth0_80to125 => si549::wrpll_refclk::MmcmSetting {
|
||||
clkout0_reg1: 0x1145,
|
||||
clkout0_reg2: 0x0000,
|
||||
clkfbout_reg1: 0x11c7,
|
||||
clkfbout_reg2: 0x5880,
|
||||
div_reg: 0x1041,
|
||||
lock_reg1: 0x028a,
|
||||
lock_reg2: 0x7c01,
|
||||
lock_reg3: 0xffe9,
|
||||
power_reg: 0x9900,
|
||||
filt_reg1: 0x0808,
|
||||
filt_reg2: 0x9800,
|
||||
},
|
||||
RtioClock::Ext0_Synth0_100to125 => si549::wrpll_refclk::MmcmSetting {
|
||||
clkout0_reg1: 0x1145,
|
||||
clkout0_reg2: 0x0000,
|
||||
clkfbout_reg1: 0x1145,
|
||||
clkfbout_reg2: 0x4c00,
|
||||
div_reg: 0x1041,
|
||||
lock_reg1: 0x0339,
|
||||
lock_reg2: 0x7c01,
|
||||
lock_reg3: 0xffe9,
|
||||
power_reg: 0x9900,
|
||||
filt_reg1: 0x0808,
|
||||
filt_reg2: 0x9800,
|
||||
},
|
||||
RtioClock::Ext0_Synth0_125to125 => si549::wrpll_refclk::MmcmSetting {
|
||||
clkout0_reg1: 0x1145,
|
||||
clkout0_reg2: 0x0000,
|
||||
clkfbout_reg1: 0x1145,
|
||||
clkfbout_reg2: 0x0000,
|
||||
div_reg: 0x1041,
|
||||
lock_reg1: 0x03e8,
|
||||
lock_reg2: 0x7001,
|
||||
lock_reg3: 0xf3e9,
|
||||
power_reg: 0x0100,
|
||||
filt_reg1: 0x0808,
|
||||
filt_reg2: 0x1100,
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
si549::main_setup(timer, si549_settings).expect("cannot initialize main Si549");
|
||||
si549::wrpll::helper_setup(timer, si549_settings).expect("cannot initialize helper Si549");
|
||||
|
||||
si549::wrpll_refclk::setup(timer, mmcm_setting).expect("cannot initialize ref clk for wrpll");
|
||||
// si549::wrpll::select_recovered_clock(true, timer);
|
||||
}
|
||||
|
||||
fn get_si549_setting(clk: RtioClock) -> si549::FrequencySetting {
|
||||
match clk {
|
||||
RtioClock::Ext0_Synth0_10to125 => {
|
||||
info!("using 10MHz reference to make 125MHz RTIO clock with WRPLL");
|
||||
}
|
||||
RtioClock::Ext0_Synth0_80to125 => {
|
||||
info!("using 80MHz reference to make 125MHz RTIO clock with WRPLL");
|
||||
}
|
||||
RtioClock::Ext0_Synth0_100to125 => {
|
||||
info!("using 100MHz reference to make 125MHz RTIO clock with WRPLL");
|
||||
}
|
||||
RtioClock::Ext0_Synth0_125to125 => {
|
||||
info!("using 125MHz reference to make 125MHz RTIO clock with WRPLL");
|
||||
}
|
||||
RtioClock::Int_150 => {
|
||||
info!("using internal 150MHz RTIO clock");
|
||||
}
|
||||
RtioClock::Int_100 => {
|
||||
info!("using internal 100MHz RTIO clock");
|
||||
}
|
||||
RtioClock::Int_125 => {
|
||||
info!("using internal 125MHz RTIO clock");
|
||||
}
|
||||
_ => {
|
||||
warn!(
|
||||
"rtio_clock setting '{:?}' is unsupported. Falling back to default internal 125MHz RTIO clock.",
|
||||
clk
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
match clk {
|
||||
RtioClock::Int_100 => {
|
||||
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,
|
||||
#[cfg(has_wrpll)]
|
||||
helper: si549::DividerConfig {
|
||||
// 100Mhz*32767/32768
|
||||
hsdiv: 0x06C,
|
||||
lsdiv: 0,
|
||||
fbdiv: 0x04815791F25,
|
||||
fbdiv: 0x046C5670BBD,
|
||||
},
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// same setting as Int_125, but fallback to default
|
||||
warn!(
|
||||
"rtio_clock setting '{:?}' is unsupported. Falling back to default 125MHz RTIO clock.",
|
||||
clk
|
||||
);
|
||||
// Everything else use 125Mhz
|
||||
si549::FrequencySetting {
|
||||
main: si549::DividerConfig {
|
||||
hsdiv: 0x058,
|
||||
lsdiv: 0,
|
||||
fbdiv: 0x04815791F25,
|
||||
},
|
||||
#[cfg(has_wrpll)]
|
||||
helper: si549::DividerConfig {
|
||||
// 125Mhz*32767/32768
|
||||
hsdiv: 0x058,
|
||||
lsdiv: 0,
|
||||
fbdiv: 0x04814E8F442,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
si549::main_setup(timer, si549_settings).expect("cannot initialize main Si549");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
|
||||
|
@ -317,10 +410,23 @@ pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
|
|||
_ => setup_si5324(i2c, timer, clk),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(has_si549)]
|
||||
{
|
||||
si549::sma_pll::setup(timer);
|
||||
setup_si549(timer, clk);
|
||||
let si549_settings = get_si549_setting(clk);
|
||||
|
||||
match clk {
|
||||
RtioClock::Ext0_Synth0_10to125
|
||||
| RtioClock::Ext0_Synth0_80to125
|
||||
| RtioClock::Ext0_Synth0_100to125
|
||||
| RtioClock::Ext0_Synth0_125to125 => {
|
||||
wrpll_setup(timer, clk, si549_settings);
|
||||
}
|
||||
_ => {
|
||||
wrpll_setup(timer, RtioClock::Ext0_Synth0_125to125, si549_settings);
|
||||
// si549::main_setup(timer, si549_settings).expect("cannot initialize main Si549");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
|
@ -328,4 +434,7 @@ pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
|
|||
|
||||
#[cfg(not(has_drtio))]
|
||||
init_rtio(timer);
|
||||
|
||||
// !! move back to cfg after testing
|
||||
si549::wrpll::select_recovered_clock(true, timer);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue