Use num/denom for PTP clock drift

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2023-11-07 00:41:02 -08:00
parent 6131079494
commit 357dd26aae
3 changed files with 19 additions and 26 deletions

View File

@@ -632,7 +632,7 @@ Once the clock is instantiated, it will generate a continuous stream of monotoni
#### Methods #### Methods
* `set_period(ns, fns)`: set clock period from separate fields * `set_period(ns, fns)`: set clock period from separate fields
* `set_drift(ns, fns, rate)`: set clock drift from separate fields * `set_drift(num, denom)`: set clock drift from separate fields
* `set_period_ns(t)`: set clock period in ns (float) * `set_period_ns(t)`: set clock period in ns (float)
* `get_period_ns()`: return current clock period in ns (float) * `get_period_ns()`: return current clock period in ns (float)
* `set_ts_96(ts_s, ts_ns=None, ts_fns=None)`: set 96-bit timestamp from integer or from separate fields * `set_ts_96(ts_s, ts_ns=None, ts_fns=None)`: set 96-bit timestamp from integer or from separate fields

View File

@@ -58,9 +58,9 @@ class PtpClock(Reset):
self.period_ns = 0 self.period_ns = 0
self.period_fns = 0 self.period_fns = 0
self.drift_ns = 0 self.drift_num = 0
self.drift_fns = 0 self.drift_denom = 0
self.drift_rate = 0 self.drift_cnt = 0
self.set_period_ns(period_ns) self.set_period_ns(period_ns)
self.log.info("PTP clock") self.log.info("PTP clock")
@@ -79,8 +79,6 @@ class PtpClock(Reset):
self.ts_updated = False self.ts_updated = False
self.drift_cnt = 0
if self.ts_96 is not None: if self.ts_96 is not None:
self.ts_96.setimmediatevalue(0) self.ts_96.setimmediatevalue(0)
if self.ts_64 is not None: if self.ts_64 is not None:
@@ -98,27 +96,23 @@ class PtpClock(Reset):
self.period_ns = int(ns) self.period_ns = int(ns)
self.period_fns = int(fns) & 0xffff self.period_fns = int(fns) & 0xffff
def set_drift(self, ns, fns, rate): def set_drift(self, num, denom):
self.drift_ns = int(ns) self.drift_num = int(num)
self.drift_fns = int(fns) & 0xffff self.drift_denom = int(denom)
self.drift_rate = int(rate)
def set_period_ns(self, t): def set_period_ns(self, t):
drift, period = math.modf(t*2**16) drift, period = math.modf(t*2**16)
period = int(period) period = int(period)
frac = Fraction(drift).limit_denominator(2**16) frac = Fraction(drift).limit_denominator(2**16)
drift = frac.numerator
rate = frac.denominator
self.period_ns = period >> 16 self.period_ns = period >> 16
self.period_fns = period & 0xffff self.period_fns = period & 0xffff
self.drift_ns = drift >> 16 self.drift_num = frac.numerator
self.drift_fns = drift & 0xffff self.drift_denom = frac.denominator
self.drift_rate = rate
def get_period_ns(self): def get_period_ns(self):
p = ((self.period_ns << 16) | self.period_fns) / 2**16 p = ((self.period_ns << 16) | self.period_fns) / 2**16
if self.drift_rate: if self.drift_denom:
return p + ((self.drift_ns << 16) | self.drift_fns) / self.drift_rate / 2**16 return p + self.drift_num / self.drift_rate / 2**16
return p return p
def set_ts_96(self, ts_s, ts_ns=None, ts_fns=None): def set_ts_96(self, ts_s, ts_ns=None, ts_fns=None):
@@ -224,8 +218,8 @@ class PtpClock(Reset):
if self.ts_96 is not None or self.pps is not None: if self.ts_96 is not None or self.pps is not None:
t = ((self.ts_96_ns << 16) + self.ts_96_fns) + ((self.period_ns << 16) + self.period_fns) t = ((self.ts_96_ns << 16) + self.ts_96_fns) + ((self.period_ns << 16) + self.period_fns)
if self.drift_rate and self.drift_cnt == 0: if self.drift_denom and self.drift_cnt == 0:
t += (self.drift_ns << 16) + self.drift_fns t += self.drift_num
if t > (1000000000 << 16): if t > (1000000000 << 16):
self.ts_96_s += 1 self.ts_96_s += 1
@@ -243,19 +237,19 @@ class PtpClock(Reset):
if self.ts_64 is not None: if self.ts_64 is not None:
t = ((self.ts_64_ns << 16) + self.ts_64_fns) + ((self.period_ns << 16) + self.period_fns) t = ((self.ts_64_ns << 16) + self.ts_64_fns) + ((self.period_ns << 16) + self.period_fns)
if self.drift_rate and self.drift_cnt == 0: if self.drift_denom and self.drift_cnt == 0:
t += ((self.drift_ns << 16) + self.drift_fns) t += self.drift_num
self.ts_64_fns = t & 0xffff self.ts_64_fns = t & 0xffff
self.ts_64_ns = t >> 16 self.ts_64_ns = t >> 16
self.ts_64.value = (self.ts_64_ns << 16) | self.ts_64_fns self.ts_64.value = (self.ts_64_ns << 16) | self.ts_64_fns
if self.drift_rate: if self.drift_denom:
if self.drift_cnt > 0: if self.drift_cnt > 0:
self.drift_cnt -= 1 self.drift_cnt -= 1
else: else:
self.drift_cnt = self.drift_rate-1 self.drift_cnt = self.drift_denom-1
class PtpClockSimTime: class PtpClockSimTime:

View File

@@ -252,9 +252,8 @@ async def run_drift_adjustment(dut):
await tb.reset() await tb.reset()
tb.ptp_clock.drift_ns = 0 tb.ptp_clock.drift_num = 20
tb.ptp_clock.drift_fns = 20 tb.ptp_clock.drift_denom = 5
tb.ptp_clock.drift_rate = 5
await RisingEdge(dut.clk) await RisingEdge(dut.clk)
start_time = get_sim_time('sec') start_time = get_sim_time('sec')