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 {
|
fn get_frequencies() -> (u32, u32, u32) {
|
||||||
unsafe { csr::wrpll::helper_frequency_start_write(1); }
|
unsafe {
|
||||||
clock::spin_us(10_000);
|
csr::wrpll::frequency_counter_update_en_write(1);
|
||||||
unsafe { csr::wrpll::helper_frequency_stop_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);
|
clock::spin_us(1);
|
||||||
unsafe { csr::wrpll::helper_frequency_counter_read() }
|
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 {
|
fn get_ddmtd_main_tag() -> u16 {
|
||||||
|
@ -309,7 +322,7 @@ pub fn init() {
|
||||||
unsafe { csr::wrpll::helper_reset_write(0); }
|
unsafe { csr::wrpll::helper_reset_write(0); }
|
||||||
clock::spin_us(1);
|
clock::spin_us(1);
|
||||||
|
|
||||||
info!("helper clock frequency: {}MHz", get_helper_frequency()/10000);
|
log_frequencies();
|
||||||
let mut tags = [0; 10];
|
let mut tags = [0; 10];
|
||||||
for i in 0..tags.len() {
|
for i in 0..tags.len() {
|
||||||
tags[i] = get_ddmtd_main_tag();
|
tags[i] = get_ddmtd_main_tag();
|
||||||
|
@ -319,6 +332,7 @@ pub fn init() {
|
||||||
|
|
||||||
pub fn select_recovered_clock(rc: bool) {
|
pub fn select_recovered_clock(rc: bool) {
|
||||||
info!("select_recovered_clock: {}", rc);
|
info!("select_recovered_clock: {}", rc);
|
||||||
|
log_frequencies();
|
||||||
if rc {
|
if rc {
|
||||||
let mut tags = [0; 10];
|
let mut tags = [0; 10];
|
||||||
for i in 0..tags.len() {
|
for i in 0..tags.len() {
|
||||||
|
|
|
@ -9,31 +9,42 @@ from artiq.gateware.drtio.wrpll import thls, filters
|
||||||
|
|
||||||
|
|
||||||
class FrequencyCounter(Module, AutoCSR):
|
class FrequencyCounter(Module, AutoCSR):
|
||||||
def __init__(self):
|
def __init__(self, timer_width=23, counter_width=23, domains=["helper", "rtio", "rtio_rx0"]):
|
||||||
self.counter = CSRStatus(32)
|
for domain in domains:
|
||||||
self.start = CSR()
|
name = "counter_" + domain
|
||||||
self.stop = CSR()
|
counter = CSRStatus(counter_width, name=name)
|
||||||
|
setattr(self, name, counter)
|
||||||
|
self.update_en = CSRStorage()
|
||||||
|
|
||||||
ps_start = PulseSynchronizer("sys", "helper")
|
timer = Signal(timer_width)
|
||||||
ps_stop = PulseSynchronizer("sys", "helper")
|
timer_tick = Signal()
|
||||||
self.submodules += ps_start, ps_stop
|
self.sync += Cat(timer, timer_tick).eq(timer + 1)
|
||||||
|
|
||||||
self.comb += [
|
for domain in domains:
|
||||||
ps_start.i.eq(self.start.re & self.start.r),
|
sync_domain = getattr(self.sync, domain)
|
||||||
ps_stop.i.eq(self.stop.re & self.stop.r)
|
divider = Signal(2)
|
||||||
]
|
sync_domain += divider.eq(divider + 1)
|
||||||
|
|
||||||
counter = Signal(32)
|
divided = Signal()
|
||||||
self.specials += MultiReg(counter, self.counter.status)
|
divided.attr.add("no_retiming")
|
||||||
|
sync_domain += divided.eq(divider[-1])
|
||||||
|
divided_sys = Signal()
|
||||||
|
self.specials += MultiReg(divided, divided_sys)
|
||||||
|
|
||||||
counting = Signal()
|
divided_sys_r = Signal()
|
||||||
self.sync.helper += [
|
divided_tick = Signal()
|
||||||
If(counting, counter.eq(counter + 1)),
|
self.sync += divided_sys_r.eq(divided_sys)
|
||||||
If(ps_start.o,
|
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),
|
counter.eq(0),
|
||||||
counting.eq(1)
|
).Else(
|
||||||
),
|
If(divided_tick, counter.eq(counter + 1))
|
||||||
If(ps_stop.o, counting.eq(0))
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +63,8 @@ class WRPLL(Module, AutoCSR):
|
||||||
self.submodules.helper_dcxo = Si549(helper_dxco_i2c)
|
self.submodules.helper_dcxo = Si549(helper_dxco_i2c)
|
||||||
self.submodules.main_dcxo = Si549(main_dcxo_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)
|
ddmtd_counter = Signal(N)
|
||||||
self.sync.helper += ddmtd_counter.eq(ddmtd_counter + 1)
|
self.sync.helper += ddmtd_counter.eq(ddmtd_counter + 1)
|
||||||
|
|
Loading…
Reference in New Issue