Compare commits
6 Commits
aa4bb8bae8
...
14fa038118
Author | SHA1 | Date |
---|---|---|
morgan | 14fa038118 | |
morgan | b81323af30 | |
morgan | 291777f764 | |
morgan | a1d80fb93b | |
morgan | 7827c7b803 | |
morgan | e4d8d44c7c |
|
@ -26,7 +26,7 @@ class DDMTDSampler(Module):
|
|||
|
||||
|
||||
class DDMTDDeglitcherFirstEdge(Module):
|
||||
def __init__(self, input_signal, blind_period=300):
|
||||
def __init__(self, input_signal, blind_period=400):
|
||||
self.detect = Signal()
|
||||
rising = Signal()
|
||||
input_signal_r = Signal()
|
||||
|
|
|
@ -7,7 +7,7 @@ from ddmtd import DDMTDSampler, DDMTD
|
|||
from si549 import Si549
|
||||
|
||||
class FrequencyCounter(Module, AutoCSR):
|
||||
def __init__(self, domains, counter_width=24, freq_div=2):
|
||||
def __init__(self, domains, counter_width=24):
|
||||
self.update = CSR()
|
||||
self.busy = CSRStatus()
|
||||
|
||||
|
@ -21,8 +21,8 @@ class FrequencyCounter(Module, AutoCSR):
|
|||
self.submodules += fsm
|
||||
|
||||
fsm.act("IDLE",
|
||||
If(self.update.re,
|
||||
counter_reset.eq(1),
|
||||
If(self.update.re,
|
||||
NextValue(timer, 2**counter_width - 1),
|
||||
NextState("COUNTING")
|
||||
)
|
||||
|
@ -42,37 +42,29 @@ class FrequencyCounter(Module, AutoCSR):
|
|||
counter_csr = CSRStatus(counter_width, name=name)
|
||||
setattr(self, name, counter_csr)
|
||||
|
||||
counter = Signal(max=freq_div)
|
||||
result = Signal(counter_width)
|
||||
divider = Signal(2)
|
||||
divided = Signal()
|
||||
divided_sys = Signal()
|
||||
divided_sys_r = Signal()
|
||||
divided_tick = Signal()
|
||||
counter = Signal(counter_width)
|
||||
|
||||
# # #
|
||||
|
||||
reset_ps = PulseSynchronizer("sys", domain)
|
||||
stb_ps = PulseSynchronizer("sys", domain)
|
||||
self.submodules +=[
|
||||
reset_ps,
|
||||
stb_ps
|
||||
]
|
||||
self.sync +=[
|
||||
reset_ps.i.eq(counter_reset),
|
||||
stb_ps.i.eq(counter_stb)
|
||||
]
|
||||
|
||||
sync_domain = getattr(self.sync, domain)
|
||||
sync_domain +=[
|
||||
If(counter != 0,
|
||||
counter.eq(counter - 1)
|
||||
).Else(
|
||||
result.eq(result + 1),
|
||||
counter.eq(freq_div - 1)
|
||||
),
|
||||
If(reset_ps.o,
|
||||
counter.eq(0),
|
||||
result.eq(0)
|
||||
),
|
||||
If(stb_ps.o, counter_csr.status.eq(result))
|
||||
divider.eq(divider + 1),
|
||||
divided.eq(divider[-1])
|
||||
]
|
||||
self.specials += MultiReg(divided, divided_sys)
|
||||
self.sync += divided_sys_r.eq(divided_sys)
|
||||
self.comb += divided_tick.eq(divided_sys & ~divided_sys_r)
|
||||
|
||||
self.sync += [
|
||||
If(counter_stb, counter_csr.status.eq(counter)),
|
||||
If(divided_tick, counter.eq(counter + 1)),
|
||||
If(counter_reset, counter.eq(0))
|
||||
]
|
||||
|
||||
class SkewTester(Module, AutoCSR):
|
||||
def __init__(self, rx_synchronizer):
|
||||
|
|
|
@ -333,14 +333,18 @@ pub mod wrpll {
|
|||
const BEATING_PERIOD: i32 = 0x8000;
|
||||
const BEATING_HALFPERIOD: i32 = 0x4000;
|
||||
const COUNTER_WIDTH: u32 = 24;
|
||||
const FREQ_DIV: u32 = 2;
|
||||
const DIV_WIDTH: u32 = 2;
|
||||
|
||||
const KP: i32 = 6;
|
||||
const KI: i32 = 2;
|
||||
// 4 ppm capture range
|
||||
const ADPLL_LIM: i32 = (4.0 / 0.0001164) as i32;
|
||||
|
||||
static mut BASE_ADPLL: i32 = 0;
|
||||
static mut H_INTEGRATOR: i32 = 0;
|
||||
static mut M_INTEGRATOR: i32 = 0;
|
||||
static mut H_LAST_ADPLL: i32 = 0;
|
||||
static mut LAST_PERIOD_ERR: i32 = 0;
|
||||
static mut M_LAST_ADPLL: i32 = 0;
|
||||
static mut LAST_PHASE_ERR: i32 = 0;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ISR {
|
||||
|
@ -439,10 +443,9 @@ pub mod wrpll {
|
|||
}
|
||||
}
|
||||
|
||||
/// To get within capture range
|
||||
fn set_base_adpll() -> Result<(), &'static str> {
|
||||
let count2adpll =
|
||||
|error: i32| ((error as f64 * FREQ_DIV as f64 * 1e6) / (0.0001164 * (1 << COUNTER_WIDTH) as f64)) as i32;
|
||||
|error: i32| ((error as f64 * 1e6) / (0.0001164 * (1 << (COUNTER_WIDTH - DIV_WIDTH)) as f64)) as i32;
|
||||
|
||||
let (ref_count, main_count) = get_freq_counts();
|
||||
unsafe {
|
||||
|
@ -469,8 +472,10 @@ pub mod wrpll {
|
|||
|
||||
fn reset_plls(timer: &mut GlobalTimer) -> Result<(), &'static str> {
|
||||
unsafe {
|
||||
H_INTEGRATOR = 0;
|
||||
M_INTEGRATOR = 0;
|
||||
H_LAST_ADPLL = 0;
|
||||
LAST_PERIOD_ERR = 0;
|
||||
M_LAST_ADPLL = 0;
|
||||
LAST_PHASE_ERR = 0;
|
||||
}
|
||||
set_adpll(i2c::DCXO::Main, 0)?;
|
||||
set_adpll(i2c::DCXO::Helper, 0)?;
|
||||
|
@ -497,7 +502,6 @@ pub mod wrpll {
|
|||
if is_pending(ISR::RefTag) {
|
||||
tag_collector::collect_tags(ISR::RefTag);
|
||||
clear_pending(ISR::RefTag);
|
||||
|
||||
helper_pll().expect("failed to run helper DCXO PLL");
|
||||
}
|
||||
|
||||
|
@ -514,22 +518,25 @@ pub mod wrpll {
|
|||
|
||||
fn helper_pll() -> Result<(), &'static str> {
|
||||
let period_err = tag_collector::get_period_error();
|
||||
|
||||
let h_adpll = unsafe {
|
||||
H_INTEGRATOR += period_err * KI;
|
||||
(BASE_ADPLL + period_err * KP + H_INTEGRATOR).clamp(-ADPLL_MAX, ADPLL_MAX)
|
||||
unsafe {
|
||||
// Based on https://hackmd.io/IACbwcOTSt6Adj3_F9bKuw?view#Integral-wind-up-and-output-limiting
|
||||
let adpll = (H_LAST_ADPLL + (KP + KI) * period_err - KP * LAST_PERIOD_ERR).clamp(-ADPLL_LIM, ADPLL_LIM);
|
||||
set_adpll(i2c::DCXO::Helper, BASE_ADPLL + adpll)?;
|
||||
H_LAST_ADPLL = adpll;
|
||||
LAST_PERIOD_ERR = period_err;
|
||||
};
|
||||
set_adpll(i2c::DCXO::Helper, h_adpll)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main_pll() -> Result<(), &'static str> {
|
||||
let phase_err = tag_collector::get_phase_error();
|
||||
let m_adpll = unsafe {
|
||||
M_INTEGRATOR += phase_err * KI;
|
||||
(BASE_ADPLL + phase_err * KP + M_INTEGRATOR).clamp(-ADPLL_MAX, ADPLL_MAX)
|
||||
unsafe {
|
||||
// Based on https://hackmd.io/IACbwcOTSt6Adj3_F9bKuw?view#Integral-wind-up-and-output-limiting
|
||||
let adpll = (M_LAST_ADPLL + (KP + KI) * phase_err - KP * LAST_PHASE_ERR).clamp(-ADPLL_LIM, ADPLL_LIM);
|
||||
set_adpll(i2c::DCXO::Main, BASE_ADPLL + adpll)?;
|
||||
M_LAST_ADPLL = adpll;
|
||||
LAST_PHASE_ERR = phase_err;
|
||||
};
|
||||
set_adpll(i2c::DCXO::Main, m_adpll)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -646,6 +653,8 @@ pub mod wrpll {
|
|||
if rc {
|
||||
tag_collector::reset();
|
||||
reset_plls(timer).expect("failed to reset main and helper PLL");
|
||||
|
||||
// get within capture range
|
||||
set_base_adpll().expect("failed to set base adpll");
|
||||
|
||||
// clear gateware pending flag
|
||||
|
|
Loading…
Reference in New Issue