wrpll: new frequency meter

As per Mattermost discussion with Tom.
This commit is contained in:
Sebastien Bourdeauducq 2019-12-30 19:47:57 +08:00
parent 9e15ff7e6a
commit f57f235dca
2 changed files with 56 additions and 30 deletions

View File

@ -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() {

View File

@ -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)