forked from M-Labs/artiq
wrpll: new frequency meter
As per Mattermost discussion with Tom.
This commit is contained in:
parent
9e15ff7e6a
commit
f57f235dca
@ -264,12 +264,25 @@ mod si549 {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_helper_frequency() -> u32 {
|
||||
unsafe { csr::wrpll::helper_frequency_start_write(1); }
|
||||
clock::spin_us(10_000);
|
||||
unsafe { csr::wrpll::helper_frequency_stop_write(1); }
|
||||
clock::spin_us(1);
|
||||
unsafe { csr::wrpll::helper_frequency_counter_read() }
|
||||
fn get_frequencies() -> (u32, u32, u32) {
|
||||
unsafe {
|
||||
csr::wrpll::frequency_counter_update_en_write(1);
|
||||
clock::spin_us(200_000); // wait for at least one update
|
||||
csr::wrpll::frequency_counter_update_en_write(0);
|
||||
clock::spin_us(1);
|
||||
let helper = csr::wrpll::frequency_counter_counter_helper_read();
|
||||
let main = csr::wrpll::frequency_counter_counter_rtio_read();
|
||||
let cdr = csr::wrpll::frequency_counter_counter_rtio_rx0_read();
|
||||
(helper, main, cdr)
|
||||
}
|
||||
}
|
||||
|
||||
fn log_frequencies() {
|
||||
let (f_helper, f_main, f_cdr) = get_frequencies();
|
||||
let conv_khz = |f| 4*(f as u64)*(csr::CONFIG_CLOCK_FREQUENCY as u64)/(1000*(1 << 23));
|
||||
info!("helper clock frequency: {}kHz ({})", conv_khz(f_helper), f_helper);
|
||||
info!("main clock frequency: {}kHz ({})", conv_khz(f_main), f_main);
|
||||
info!("CDR clock frequency: {}kHz ({})", conv_khz(f_cdr), f_cdr);
|
||||
}
|
||||
|
||||
fn get_ddmtd_main_tag() -> u16 {
|
||||
@ -309,7 +322,7 @@ pub fn init() {
|
||||
unsafe { csr::wrpll::helper_reset_write(0); }
|
||||
clock::spin_us(1);
|
||||
|
||||
info!("helper clock frequency: {}MHz", get_helper_frequency()/10000);
|
||||
log_frequencies();
|
||||
let mut tags = [0; 10];
|
||||
for i in 0..tags.len() {
|
||||
tags[i] = get_ddmtd_main_tag();
|
||||
@ -319,6 +332,7 @@ pub fn init() {
|
||||
|
||||
pub fn select_recovered_clock(rc: bool) {
|
||||
info!("select_recovered_clock: {}", rc);
|
||||
log_frequencies();
|
||||
if rc {
|
||||
let mut tags = [0; 10];
|
||||
for i in 0..tags.len() {
|
||||
|
@ -9,32 +9,43 @@ from artiq.gateware.drtio.wrpll import thls, filters
|
||||
|
||||
|
||||
class FrequencyCounter(Module, AutoCSR):
|
||||
def __init__(self):
|
||||
self.counter = CSRStatus(32)
|
||||
self.start = CSR()
|
||||
self.stop = CSR()
|
||||
def __init__(self, timer_width=23, counter_width=23, domains=["helper", "rtio", "rtio_rx0"]):
|
||||
for domain in domains:
|
||||
name = "counter_" + domain
|
||||
counter = CSRStatus(counter_width, name=name)
|
||||
setattr(self, name, counter)
|
||||
self.update_en = CSRStorage()
|
||||
|
||||
ps_start = PulseSynchronizer("sys", "helper")
|
||||
ps_stop = PulseSynchronizer("sys", "helper")
|
||||
self.submodules += ps_start, ps_stop
|
||||
timer = Signal(timer_width)
|
||||
timer_tick = Signal()
|
||||
self.sync += Cat(timer, timer_tick).eq(timer + 1)
|
||||
|
||||
self.comb += [
|
||||
ps_start.i.eq(self.start.re & self.start.r),
|
||||
ps_stop.i.eq(self.stop.re & self.stop.r)
|
||||
]
|
||||
for domain in domains:
|
||||
sync_domain = getattr(self.sync, domain)
|
||||
divider = Signal(2)
|
||||
sync_domain += divider.eq(divider + 1)
|
||||
|
||||
counter = Signal(32)
|
||||
self.specials += MultiReg(counter, self.counter.status)
|
||||
divided = Signal()
|
||||
divided.attr.add("no_retiming")
|
||||
sync_domain += divided.eq(divider[-1])
|
||||
divided_sys = Signal()
|
||||
self.specials += MultiReg(divided, divided_sys)
|
||||
|
||||
counting = Signal()
|
||||
self.sync.helper += [
|
||||
If(counting, counter.eq(counter + 1)),
|
||||
If(ps_start.o,
|
||||
counter.eq(0),
|
||||
counting.eq(1)
|
||||
),
|
||||
If(ps_stop.o, counting.eq(0))
|
||||
]
|
||||
divided_sys_r = Signal()
|
||||
divided_tick = Signal()
|
||||
self.sync += divided_sys_r.eq(divided_sys)
|
||||
self.comb += divided_tick.eq(divided_sys & ~divided_sys_r)
|
||||
|
||||
counter = Signal(counter_width)
|
||||
counter_csr = getattr(self, "counter_" + domain)
|
||||
self.sync += [
|
||||
If(timer_tick,
|
||||
If(self.update_en.storage, counter_csr.status.eq(counter)),
|
||||
counter.eq(0),
|
||||
).Else(
|
||||
If(divided_tick, counter.eq(counter + 1))
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class WRPLL(Module, AutoCSR):
|
||||
@ -52,7 +63,8 @@ class WRPLL(Module, AutoCSR):
|
||||
self.submodules.helper_dcxo = Si549(helper_dxco_i2c)
|
||||
self.submodules.main_dcxo = Si549(main_dcxo_i2c)
|
||||
|
||||
self.submodules.helper_frequency = FrequencyCounter() # for diagnostics
|
||||
# for diagnostics and PLL initialization
|
||||
self.submodules.frequency_counter = FrequencyCounter()
|
||||
|
||||
ddmtd_counter = Signal(N)
|
||||
self.sync.helper += ddmtd_counter.eq(ddmtd_counter + 1)
|
||||
|
Loading…
Reference in New Issue
Block a user