diff --git a/README.md b/README.md index 11593d3..95ac809 100644 --- a/README.md +++ b/README.md @@ -585,15 +585,15 @@ Methods: ### PTP clock -The `PtpClock` class implements a PTP hardware clock that produces IEEE 1588 format 96 and 64 bit PTP timestamps. +The `PtpClock` class implements a PTP hardware clock that produces IEEE 1588 format 96-bit time-of-day and 64-bit relative PTP timestamps. To use this module, import it and connect it to the DUT: from cocotbext.eth import PtpClock ptp_clock = PtpClock( - ts_96=dut.ts_96, - ts_64=dut.ts_64, + ts_tod=dut.ts_tod, + ts_rel=dut.ts_rel, ts_step=dut.ts_step, pps=dut.pps, clock=dut.clk, @@ -605,15 +605,15 @@ Once the clock is instantiated, it will generate a continuous stream of monotoni #### Signals -* `ts_96`: 96-bit timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns) -* `ts_64`: 64-bit timestamp (48 bit ns, 16 bit fractional ns) +* `ts_tod`: 96-bit time-of-day timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns) +* `ts_rel`: 64-bit relative timestamp (48 bit ns, 16 bit fractional ns) * `ts_step`: step output, pulsed when non-monotonic step occurs -* `pps`: pulse-per-second output, pulsed when ts_96 seconds field increments +* `pps`: pulse-per-second output, pulsed when ts_tod seconds field increments #### Constructor parameters: -* _ts_96_: 96-bit timestamp signal (optional) -* _ts_64_: 64-bit timestamp signal (optional) +* _ts_tod_: 96-bit time-of-day timestamp signal (optional) +* _ts_rel_: 64-bit relative timestamp signal (optional) * _ts_step_: timestamp step signal (optional) * _pps_: pulse-per-second signal (optional) * _clock_: clock @@ -623,11 +623,11 @@ Once the clock is instantiated, it will generate a continuous stream of monotoni #### Attributes: -* _ts_96_s_: current 96-bit timestamp seconds field -* _ts_96_ns_: current 96-bit timestamp ns field -* _ts_96_fns_: current 96-bit timestamp fractional ns field -* _ts_64_ns_: current 64-bit timestamp ns field -* _ts_64_fns_: current 64-bit timestamp fractional ns field +* _ts_tod_s_: current 96-bit ToD timestamp seconds field +* _ts_tod_ns_: current 96-bit ToD timestamp ns field +* _ts_tod_fns_: current 96-bit ToD timestamp fractional ns field +* _ts_rel_ns_: current 64-bit relative timestamp ns field +* _ts_rel_fns_: current 64-bit relative timestamp fractional ns field #### Methods @@ -635,30 +635,34 @@ Once the clock is instantiated, it will generate a continuous stream of monotoni * `set_drift(num, denom)`: set clock drift from separate fields * `set_period_ns(t)`: set 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_ns(t)`: set 96-bit timestamp from ns (float) -* `set_ts_96_s(t)`: set 96-bit timestamp from seconds (float) -* `get_ts_96()`: return current 96-bit timestamp as an integer -* `get_ts_96_ns()`: return current 96-bit timestamp in ns (float) -* `get_ts_96_s()`: return current 96-bit timestamp in seconds (float) -* `set_ts_64(ts_ns, ts_fns=None)`: set 64-bit timestamp from integer or from separate fields -* `set_ts_64_ns(t)`: set 64-bit timestamp from ns (float) -* `set_ts_64_s(t)`: set 64-bit timestamp from seconds (float) -* `get_ts_64()`: return current 64-bit timestamp as an integer -* `get_ts_64_ns()`: return current 64-bit timestamp in ns (float) -* `get_ts_64_s()`: return current 64-bit timestamp in seconds (float) +* `set_ts_tod(ts_s, ts_ns, ts_fns)`: set 96-bit ToD timestamp from separate fields +* `set_ts_tod_96(ts)`: set 96-bit ToD timestamp from integer +* `set_ts_tod_ns(t)`: set 96-bit ToD timestamp from ns (float) +* `set_ts_tod_s(t)`: set 96-bit ToD timestamp from seconds (float) +* `get_ts_tod()`: return current 96-bit ToD timestamp as separate fields +* `get_ts_tod_96()`: return current 96-bit ToD timestamp as an integer +* `get_ts_tod_ns()`: return current 96-bit ToD timestamp in ns (float) +* `get_ts_tod_s()`: return current 96-bit ToD timestamp in seconds (float) +* `set_ts_rel(ts_ns, ts_fns)`: set 64-bit relative timestamp from separate fields +* `set_ts_rel_64(ts)`: set 64-bit relative timestamp from integer +* `set_ts_rel_ns(t)`: set 64-bit relative timestamp from ns (float) +* `set_ts_rel_s(t)`: set 64-bit relative timestamp from seconds (float) +* `get_ts_rel()`: return current 64-bit relative timestamp as separate fields +* `get_ts_rel_64()`: return current 64-bit relative timestamp as an integer +* `get_ts_rel_ns()`: return current 64-bit relative timestamp in ns (float) +* `get_ts_rel_s()`: return current 64-bit relative timestamp in seconds (float) ### PTP clock (sim time) -The `PtpClockSimTime` class implements a PTP hardware clock that produces IEEE 1588 format 96 and 64 bit PTP timestamps, derived from the current simulation time. This module can be used in place of `PtpClock` so that captured PTP timestamps can be easily compared to captured simulation time. +The `PtpClockSimTime` class implements a PTP hardware clock that produces IEEE 1588 format 96-bit time-of-day and 64-bit relative PTP timestamps, derived from the current simulation time. This module can be used in place of `PtpClock` so that captured PTP timestamps can be easily compared to captured simulation time. To use this module, import it and connect it to the DUT: from cocotbext.eth import PtpClockSimTime ptp_clock = PtpClockSimTime( - ts_96=dut.ts_96, - ts_64=dut.ts_64, + ts_tod=dut.ts_tod, + ts_rel=dut.ts_rel, pps=dut.pps, clock=dut.clk ) @@ -667,30 +671,32 @@ Once the clock is instantiated, it will generate a continuous stream of monotoni #### Signals -* `ts_96`: 96-bit timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns) -* `ts_64`: 64-bit timestamp (48 bit ns, 16 bit fractional ns) -* `pps`: pulse-per-second output, pulsed when ts_96 seconds field increments +* `ts_tod`: 96-bit time-of-day timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns) +* `ts_rel`: 64-bit relative timestamp (48 bit ns, 16 bit fractional ns) +* `pps`: pulse-per-second output, pulsed when ts_tod seconds field increments #### Constructor parameters: -* _ts_96_: 96-bit timestamp signal (optional) -* _ts_64_: 64-bit timestamp signal (optional) +* _ts_tod_: 96-bit time-of-day timestamp signal (optional) +* _ts_rel_: 64-bit relative timestamp signal (optional) * _pps_: pulse-per-second signal (optional) * _clock_: clock #### Attributes: -* _ts_96_s_: current 96-bit timestamp seconds field -* _ts_96_ns_: current 96-bit timestamp ns field -* _ts_96_fns_: current 96-bit timestamp fractional ns field -* _ts_64_ns_: current 64-bit timestamp ns field -* _ts_64_fns_: current 64-bit timestamp fractional ns field +* _ts_tod_s_: current 96-bit ToD timestamp seconds field +* _ts_tod_ns_: current 96-bit ToD timestamp ns field +* _ts_tod_fns_: current 96-bit ToD timestamp fractional ns field +* _ts_rel_ns_: current 64-bit relative timestamp ns field +* _ts_rel_fns_: current 64-bit relative timestamp fractional ns field #### Methods -* `get_ts_96()`: return current 96-bit timestamp as an integer -* `get_ts_96_ns()`: return current 96-bit timestamp in ns (float) -* `get_ts_96_s()`: return current 96-bit timestamp in seconds (float) -* `get_ts_64()`: return current 64-bit timestamp as an integer -* `get_ts_64_ns()`: return current 64-bit timestamp in ns (float) -* `get_ts_64_s()`: return current 64-bit timestamp in seconds (float) +* `get_ts_tod()`: return current 96-bit ToD timestamp as separate fields +* `get_ts_tod_96()`: return current 96-bit ToD timestamp as an integer +* `get_ts_tod_ns()`: return current 96-bit ToD timestamp in ns (float) +* `get_ts_tod_s()`: return current 96-bit ToD timestamp in seconds (float) +* `get_ts_rel()`: return current 64-bit relative timestamp as separate fields +* `get_ts_rel_96()`: return current 64-bit relative timestamp as an integer +* `get_ts_rel_ns()`: return current 64-bit relative timestamp in ns (float) +* `get_ts_rel_s()`: return current 64-bit relative timestamp in seconds (float) diff --git a/cocotbext/eth/ptp.py b/cocotbext/eth/ptp.py index b4328c6..7934d58 100644 --- a/cocotbext/eth/ptp.py +++ b/cocotbext/eth/ptp.py @@ -38,8 +38,8 @@ class PtpClock(Reset): def __init__( self, - ts_96=None, - ts_64=None, + ts_tod=None, + ts_rel=None, ts_step=None, pps=None, clock=None, @@ -49,8 +49,8 @@ class PtpClock(Reset): *args, **kwargs): self.log = logging.getLogger(f"cocotb.eth.{type(self).__name__}") - self.ts_96 = ts_96 - self.ts_64 = ts_64 + self.ts_tod = ts_tod + self.ts_rel = ts_rel self.ts_step = ts_step self.pps = pps self.clock = clock @@ -70,19 +70,19 @@ class PtpClock(Reset): super().__init__(*args, **kwargs) - self.ts_96_s = 0 - self.ts_96_ns = 0 - self.ts_96_fns = 0 + self.ts_tod_s = 0 + self.ts_tod_ns = 0 + self.ts_tod_fns = 0 - self.ts_64_ns = 0 - self.ts_64_fns = 0 + self.ts_rel_ns = 0 + self.ts_rel_fns = 0 self.ts_updated = False - if self.ts_96 is not None: - self.ts_96.setimmediatevalue(0) - if self.ts_64 is not None: - self.ts_64.setimmediatevalue(0) + if self.ts_tod is not None: + self.ts_tod.setimmediatevalue(0) + if self.ts_rel is not None: + self.ts_rel.setimmediatevalue(0) if self.ts_step is not None: self.ts_step.setimmediatevalue(0) if self.pps is not None: @@ -115,65 +115,70 @@ class PtpClock(Reset): return p + self.drift_num / self.drift_rate / 2**16 return p - def set_ts_96(self, ts_s, ts_ns=None, ts_fns=None): - ts_s = int(ts_s) - if ts_fns is not None: - # got separate fields - self.ts_96_s = ts_s - self.ts_96_ns = int(ts_ns) - self.ts_96_fns = int(ts_fns) - else: - # got timestamp as integer - self.ts_96_s = ts_s >> 48 - self.ts_96_ns = (ts_s >> 16) & 0x3fffffff - self.ts_96_fns = ts_s & 0xffff + def set_ts_tod(self, ts_s, ts_ns, ts_fns): + self.ts_tod_s = int(ts_s) + self.ts_tod_ns = int(ts_ns) + self.ts_tod_fns = int(ts_fns) self.ts_updated = True - def set_ts_96_ns(self, t): - self.set_ts_96_s(t*1e-9) + def set_ts_tod_96(self, ts): + ts = int(ts) + self.set_ts_tod(ts >> 48, (ts >> 32) & 0x3fffffff, ts & 0xffff) - def set_ts_96_s(self, t): + def set_ts_tod_ns(self, t): + self.set_ts_tod_s(t*1e-9) + + def set_ts_tod_s(self, t): ts_ns, ts_s = math.modf(t) ts_ns *= 1e9 ts_fns, ts_ns = math.modf(ts_ns) ts_fns *= 2**16 - self.set_ts_96(ts_s, ts_ns, ts_fns) + self.set_ts_tod(ts_s, ts_ns, ts_fns) - def get_ts_96(self): - return (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns + def get_ts_tod(self): + return (self.ts_tod_s, self.ts_tod_ns, self.ts_tod_fns) - def get_ts_96_ns(self): - return self.ts_96_s*1e9+self.ts_96_ns+self.ts_96_fns/2**16 + def get_ts_tod_96(self): + ts_s, ts_ns, ts_fns = self.get_ts_tod() + return (ts_s << 48) | (ts_ns << 16) | ts_fns - def get_ts_96_s(self): - return self.get_ts_96_ns()*1e-9 + def get_ts_tod_ns(self): + ts_s, ts_ns, ts_fns = self.get_ts_tod() + return ts_s*1e9+ts_ns+ts_fns/2**16 - def set_ts_64(self, ts_ns, ts_fns=None): - ts_ns = int(ts_ns) - if ts_fns is not None: - # got separate fields - self.ts_64_ns = ts_ns - self.ts_64_fns = int(ts_fns) - else: - # got timestamp as integer - self.ts_64_ns = ts_ns >> 16 - self.ts_64_fns = ts_ns & 0xffff + def get_ts_tod_s(self): + return self.get_ts_tod_ns()*1e-9 + + def set_ts_rel(self, ts_ns, ts_fns): + self.ts_rel_ns = int(ts_ns) + self.ts_rel_fns = int(ts_fns) self.ts_updated = True - def set_ts_64_ns(self, t): - self.set_ts_64(t*2**16) + def set_ts_rel_64(self, ts): + ts = int(ts) + self.set_ts_rel(ts >> 16, (ts & 0xffff) << 16) - def set_ts_64_s(self, t): - self.set_ts_64_ns(t*1e9) + def set_ts_rel_ns(self, t): + ts_fns, ts_ns = math.modf(t) + ts_fns *= 2**16 + self.set_ts_rel(ts_ns, ts_fns) - def get_ts_64(self): - return (self.ts_64_ns << 16) | self.ts_64_fns + def set_ts_rel_s(self, t): + self.set_ts_rel_ns(t*1e9) - def get_ts_64_ns(self): - return self.get_ts_64()/2**16 + def get_ts_rel(self): + return (self.ts_rel_ns, self.ts_rel_fns) - def get_ts_64_s(self): - return self.get_ts_64()*1e-9 + def get_ts_rel_64(self): + ts_ns, ts_fns = self.get_ts_rel() + return (ts_ns << 16) | (ts_fns >> 16) + + def get_ts_rel_ns(self): + ts_ns, ts_fns = self.get_ts_rel() + return ts_ns + ts_fns/2**16 + + def get_ts_rel_s(self): + return self.get_ts_rel()*1e-9 def _handle_reset(self, state): if state: @@ -182,16 +187,16 @@ class PtpClock(Reset): self._run_cr.kill() self._run_cr = None - self.ts_96_s = 0 - self.ts_96_ns = 0 - self.ts_96_fns = 0 - self.ts_64_ns = 0 - self.ts_64_fns = 0 + self.ts_tod_s = 0 + self.ts_tod_ns = 0 + self.ts_tod_fns = 0 + self.ts_rel_ns = 0 + self.ts_rel_fns = 0 self.drift_cnt = 0 - if self.ts_96 is not None: - self.ts_96.value = 0 - if self.ts_64 is not None: - self.ts_64.value = 0 + if self.ts_tod is not None: + self.ts_tod.value = 0 + if self.ts_rel is not None: + self.ts_rel.value = 0 if self.ts_step is not None: self.ts_step.value = 0 if self.pps is not None: @@ -215,35 +220,35 @@ class PtpClock(Reset): self.pps.value = 0 # increment 96 bit timestamp - 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) + if self.ts_tod is not None or self.pps is not None: + t = ((self.ts_tod_ns << 16) + self.ts_tod_fns) + ((self.period_ns << 16) + self.period_fns) if self.drift_denom and self.drift_cnt == 0: t += self.drift_num if t > (1000000000 << 16): - self.ts_96_s += 1 + self.ts_tod_s += 1 t -= (1000000000 << 16) if self.pps is not None: self.pps.value = 1 - self.ts_96_fns = t & 0xffff - self.ts_96_ns = t >> 16 + self.ts_tod_fns = t & 0xffff + self.ts_tod_ns = t >> 16 - if self.ts_96 is not None: - self.ts_96.value = (self.ts_96_s << 48) | (self.ts_96_ns << 16) | (self.ts_96_fns) + if self.ts_tod is not None: + self.ts_tod.value = (self.ts_tod_s << 48) | (self.ts_tod_ns << 16) | (self.ts_tod_fns) # increment 64 bit timestamp - if self.ts_64 is not None: - t = ((self.ts_64_ns << 16) + self.ts_64_fns) + ((self.period_ns << 16) + self.period_fns) + if self.ts_rel is not None: + t = ((self.ts_rel_ns << 16) + self.ts_rel_fns) + ((self.period_ns << 16) + self.period_fns) if self.drift_denom and self.drift_cnt == 0: t += self.drift_num - self.ts_64_fns = t & 0xffff - self.ts_64_ns = t >> 16 + self.ts_rel_fns = t & 0xffff + self.ts_rel_ns = t >> 16 - self.ts_64.value = (self.ts_64_ns << 16) | self.ts_64_fns + self.ts_rel.value = (self.ts_rel_ns << 16) | self.ts_rel_fns if self.drift_denom: if self.drift_cnt > 0: @@ -254,10 +259,10 @@ class PtpClock(Reset): class PtpClockSimTime: - def __init__(self, ts_96=None, ts_64=None, pps=None, clock=None, *args, **kwargs): + def __init__(self, ts_tod=None, ts_rel=None, pps=None, clock=None, *args, **kwargs): self.log = logging.getLogger(f"cocotb.eth.{type(self).__name__}") - self.ts_96 = ts_96 - self.ts_64 = ts_64 + self.ts_tod = ts_tod + self.ts_rel = ts_rel self.pps = pps self.clock = clock @@ -268,41 +273,48 @@ class PtpClockSimTime: super().__init__(*args, **kwargs) - self.ts_96_s = 0 - self.ts_96_ns = 0 - self.ts_96_fns = 0 + self.ts_tod_s = 0 + self.ts_tod_ns = 0 + self.ts_tod_fns = 0 - self.ts_64_ns = 0 - self.ts_64_fns = 0 + self.ts_rel_ns = 0 + self.ts_rel_fns = 0 - self.last_ts_96_s = 0 + self.last_ts_tod_s = 0 - if self.ts_96 is not None: - self.ts_96.setimmediatevalue(0) - if self.ts_64 is not None: - self.ts_64.setimmediatevalue(0) + if self.ts_tod is not None: + self.ts_tod.setimmediatevalue(0) + if self.ts_rel is not None: + self.ts_rel.setimmediatevalue(0) if self.pps is not None: self.pps.value = 0 self._run_cr = cocotb.start_soon(self._run()) - def get_ts_96(self): - return (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns + def get_ts_tod(self): + return (self.ts_tod_s, self.ts_tod_ns, self.ts_tod_fns) - def get_ts_96_ns(self): - return self.ts_96_s*1e9+self.ts_96_ns+self.ts_96_fns/2**16 + def get_ts_tod_96(self): + ts_s, ts_ns, ts_fns = self.get_ts_tod() + return (ts_s << 48) | (ts_ns << 16) | ts_fns - def get_ts_96_s(self): - return self.get_ts_96_ns()*1e-9 + def get_ts_tod_ns(self): + ts_s, ts_ns, ts_fns = self.get_ts_tod() + return ts_s*1e9+ts_ns+ts_fns/2**16 - def get_ts_64(self): - return (self.ts_64_ns << 16) | self.ts_64_fns + def get_ts_rel(self): + return (self.ts_rel_ns, self.ts_rel_fns) - def get_ts_64_ns(self): - return self.get_ts_64()/2**16 + def get_ts_rel_64(self): + ts_ns, ts_fns = self.get_ts_rel() + return (ts_ns << 16) | (ts_fns >> 16) - def get_ts_64_s(self): - return self.get_ts_64()*1e-9 + def get_ts_rel_ns(self): + ts_ns, ts_fns = self.get_ts_rel() + return ts_ns + ts_fns/2**16 + + def get_ts_rel_s(self): + return self.get_ts_rel()*1e-9 async def _run(self): clock_edge_event = RisingEdge(self.clock) @@ -310,21 +322,21 @@ class PtpClockSimTime: while True: await clock_edge_event - self.ts_64_fns, self.ts_64_ns = math.modf(get_sim_time('ns')) + self.ts_rel_fns, self.ts_rel_ns = math.modf(get_sim_time('ns')) - self.ts_64_ns = int(self.ts_64_ns) - self.ts_64_fns = int(self.ts_64_fns*0x10000) + self.ts_rel_ns = int(self.ts_rel_ns) + self.ts_rel_fns = int(self.ts_rel_fns*0x10000) - self.ts_96_s, self.ts_96_ns = divmod(self.ts_64_ns, 1000000000) - self.ts_96_fns = self.ts_64_fns + self.ts_tod_s, self.ts_tod_ns = divmod(self.ts_rel_ns, 1000000000) + self.ts_tod_fns = self.ts_rel_fns - if self.ts_96 is not None: - self.ts_96.value = (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns + if self.ts_tod is not None: + self.ts_tod.value = (self.ts_tod_s << 48) | (self.ts_tod_ns << 16) | self.ts_tod_fns - if self.ts_64 is not None: - self.ts_64.value = (self.ts_64_ns << 16) | self.ts_64_fns + if self.ts_rel is not None: + self.ts_rel.value = (self.ts_rel_ns << 16) | self.ts_rel_fns if self.pps is not None: - self.pps.value = int(self.last_ts_96_s != self.ts_96_s) + self.pps.value = int(self.last_ts_tod_s != self.ts_tod_s) - self.last_ts_96_s = self.ts_96_s + self.last_ts_tod_s = self.ts_tod_s diff --git a/tests/eth_mac/test_eth_mac.py b/tests/eth_mac/test_eth_mac.py index 3c255e3..b4fe8ca 100644 --- a/tests/eth_mac/test_eth_mac.py +++ b/tests/eth_mac/test_eth_mac.py @@ -77,12 +77,12 @@ class TB: ) self.tx_ptp = PtpClockSimTime( - ts_96=dut.tx_ptp_time, + ts_tod=dut.tx_ptp_time, clock=dut.tx_clk ) self.rx_ptp = PtpClockSimTime( - ts_96=dut.rx_ptp_time, + ts_tod=dut.rx_ptp_time, clock=dut.rx_clk ) diff --git a/tests/ptp_clock/test_ptp_clock.py b/tests/ptp_clock/test_ptp_clock.py index 102f15c..dfb47be 100644 --- a/tests/ptp_clock/test_ptp_clock.py +++ b/tests/ptp_clock/test_ptp_clock.py @@ -46,8 +46,8 @@ class TB: cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start()) self.ptp_clock = PtpClock( - ts_96=dut.ts_96, - ts_64=dut.ts_64, + ts_tod=dut.ts_tod, + ts_rel=dut.ts_rel, ts_step=dut.ts_step, pps=dut.pps, clock=dut.clk, @@ -76,30 +76,31 @@ async def run_default_rate(dut): await RisingEdge(dut.clk) start_time = get_sim_time('sec') - start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 await ClockCycles(dut.clk, 10000) stop_time = get_sim_time('sec') - stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - stop_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 time_delta = stop_time-start_time - ts_96_delta = stop_ts_96-start_ts_96 - ts_64_delta = stop_ts_64-start_ts_64 + ts_tod_delta = stop_ts_tod-start_ts_tod + ts_rel_delta = stop_ts_rel-start_ts_rel - ts_96_diff = time_delta - ts_96_delta - ts_64_diff = time_delta - ts_64_delta + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("ToD ts delta : %g s", ts_tod_delta) + tb.log.info("rel ts delta : %g s", ts_rel_delta) - tb.log.info("sim time delta : %g s", time_delta) - tb.log.info("96 bit ts delta : %g s", ts_96_delta) - tb.log.info("64 bit ts delta : %g s", ts_64_delta) - tb.log.info("96 bit ts diff : %g s", ts_96_diff) - tb.log.info("64 bit ts diff : %g s", ts_64_diff) + ts_tod_diff = time_delta - ts_tod_delta + ts_rel_diff = time_delta - ts_rel_delta - assert abs(ts_96_diff) < 1e-12 - assert abs(ts_64_diff) < 1e-12 + tb.log.info("ToD ts diff : %g s", ts_tod_diff) + tb.log.info("rel ts diff : %g s", ts_rel_diff) + + assert abs(ts_tod_diff) < 1e-12 + assert abs(ts_rel_diff) < 1e-12 await RisingEdge(dut.clk) await RisingEdge(dut.clk) @@ -112,40 +113,41 @@ async def run_load_timestamps(dut): await tb.reset() - tb.ptp_clock.set_ts_96(12345678) - tb.ptp_clock.set_ts_64(12345678) + tb.ptp_clock.set_ts_tod_ns(12345678) + tb.ptp_clock.set_ts_rel_ns(12345678) await RisingEdge(dut.clk) - assert dut.ts_96.value.integer == 12345678+((tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns) - assert dut.ts_64.value.integer == 12345678+((tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns) + assert dut.ts_tod.value.integer == 12345678*2**16 + (tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns + assert dut.ts_rel.value.integer == 12345678*2**16 + (tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns assert dut.ts_step.value.integer == 1 start_time = get_sim_time('sec') - start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 await ClockCycles(dut.clk, 2000) stop_time = get_sim_time('sec') - stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - stop_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 time_delta = stop_time-start_time - ts_96_delta = stop_ts_96-start_ts_96 - ts_64_delta = stop_ts_64-start_ts_64 + ts_tod_delta = stop_ts_tod-start_ts_tod + ts_rel_delta = stop_ts_rel-start_ts_rel - ts_96_diff = time_delta - ts_96_delta - ts_64_diff = time_delta - ts_64_delta + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("ToD ts delta : %g s", ts_tod_delta) + tb.log.info("rel ts delta : %g s", ts_rel_delta) - tb.log.info("sim time delta : %g s", time_delta) - tb.log.info("96 bit ts delta : %g s", ts_96_delta) - tb.log.info("64 bit ts delta : %g s", ts_64_delta) - tb.log.info("96 bit ts diff : %g s", ts_96_diff) - tb.log.info("64 bit ts diff : %g s", ts_64_diff) + ts_tod_diff = time_delta - ts_tod_delta + ts_rel_diff = time_delta - ts_rel_delta - assert abs(ts_96_diff) < 1e-12 - assert abs(ts_64_diff) < 1e-12 + tb.log.info("ToD ts diff : %g s", ts_tod_diff) + tb.log.info("rel ts diff : %g s", ts_rel_diff) + + assert abs(ts_tod_diff) < 1e-12 + assert abs(ts_rel_diff) < 1e-12 await RisingEdge(dut.clk) await RisingEdge(dut.clk) @@ -158,15 +160,15 @@ async def run_seconds_increment(dut): await tb.reset() - tb.ptp_clock.set_ts_96(999990000*2**16) - tb.ptp_clock.set_ts_64(999990000*2**16) + tb.ptp_clock.set_ts_tod_ns(999990000) + tb.ptp_clock.set_ts_rel_ns(999990000) await RisingEdge(dut.clk) await RisingEdge(dut.clk) start_time = get_sim_time('sec') - start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 saw_pps = False @@ -175,30 +177,31 @@ async def run_seconds_increment(dut): if dut.pps.value.integer: saw_pps = True - assert dut.ts_96.value.integer >> 48 == 1 - assert dut.ts_96.value.integer & 0xffffffffffff < 10*2**16 + assert dut.ts_tod.value.integer >> 48 == 1 + assert dut.ts_tod.value.integer & 0xffffffffffff < 10*2**16 assert saw_pps stop_time = get_sim_time('sec') - stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - stop_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 time_delta = stop_time-start_time - ts_96_delta = stop_ts_96-start_ts_96 - ts_64_delta = stop_ts_64-start_ts_64 + ts_tod_delta = stop_ts_tod-start_ts_tod + ts_rel_delta = stop_ts_rel-start_ts_rel - ts_96_diff = time_delta - ts_96_delta - ts_64_diff = time_delta - ts_64_delta + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("ToD ts delta : %g s", ts_tod_delta) + tb.log.info("rel ts delta : %g s", ts_rel_delta) - tb.log.info("sim time delta : %g s", time_delta) - tb.log.info("96 bit ts delta : %g s", ts_96_delta) - tb.log.info("64 bit ts delta : %g s", ts_64_delta) - tb.log.info("96 bit ts diff : %g s", ts_96_diff) - tb.log.info("64 bit ts diff : %g s", ts_64_diff) + ts_tod_diff = time_delta - ts_tod_delta + ts_rel_diff = time_delta - ts_rel_delta - assert abs(ts_96_diff) < 1e-12 - assert abs(ts_64_diff) < 1e-12 + tb.log.info("ToD ts diff : %g s", ts_tod_diff) + tb.log.info("rel ts diff : %g s", ts_rel_diff) + + assert abs(ts_tod_diff) < 1e-12 + assert abs(ts_rel_diff) < 1e-12 await RisingEdge(dut.clk) await RisingEdge(dut.clk) @@ -216,30 +219,31 @@ async def run_frequency_adjustment(dut): await RisingEdge(dut.clk) start_time = get_sim_time('sec') - start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 await ClockCycles(dut.clk, 10000) stop_time = get_sim_time('sec') - stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - stop_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 time_delta = stop_time-start_time - ts_96_delta = stop_ts_96-start_ts_96 - ts_64_delta = stop_ts_64-start_ts_64 + ts_tod_delta = stop_ts_tod-start_ts_tod + ts_rel_delta = stop_ts_rel-start_ts_rel - ts_96_diff = time_delta - ts_96_delta * 6.4/(6+(0x6624+2/5)/2**16) - ts_64_diff = time_delta - ts_64_delta * 6.4/(6+(0x6624+2/5)/2**16) + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("ToD ts delta : %g s", ts_tod_delta) + tb.log.info("rel ts delta : %g s", ts_rel_delta) - tb.log.info("sim time delta : %g s", time_delta) - tb.log.info("96 bit ts delta : %g s", ts_96_delta) - tb.log.info("64 bit ts delta : %g s", ts_64_delta) - tb.log.info("96 bit ts diff : %g s", ts_96_diff) - tb.log.info("64 bit ts diff : %g s", ts_64_diff) + ts_tod_diff = time_delta - ts_tod_delta * 6.4/(6+(0x6624+2/5)/2**16) + ts_rel_diff = time_delta - ts_rel_delta * 6.4/(6+(0x6624+2/5)/2**16) - assert abs(ts_96_diff) < 1e-12 - assert abs(ts_64_diff) < 1e-12 + tb.log.info("ToD ts diff : %g s", ts_tod_diff) + tb.log.info("rel ts diff : %g s", ts_rel_diff) + + assert abs(ts_tod_diff) < 1e-12 + assert abs(ts_rel_diff) < 1e-12 await RisingEdge(dut.clk) await RisingEdge(dut.clk) @@ -257,30 +261,31 @@ async def run_drift_adjustment(dut): await RisingEdge(dut.clk) start_time = get_sim_time('sec') - start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 await ClockCycles(dut.clk, 10000) stop_time = get_sim_time('sec') - stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - stop_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 time_delta = stop_time-start_time - ts_96_delta = stop_ts_96-start_ts_96 - ts_64_delta = stop_ts_64-start_ts_64 + ts_tod_delta = stop_ts_tod-start_ts_tod + ts_rel_delta = stop_ts_rel-start_ts_rel - ts_96_diff = time_delta - ts_96_delta * 6.4/(6+(0x6666+20/5)/2**16) - ts_64_diff = time_delta - ts_64_delta * 6.4/(6+(0x6666+20/5)/2**16) + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("ToD ts delta : %g s", ts_tod_delta) + tb.log.info("rel ts delta : %g s", ts_rel_delta) - tb.log.info("sim time delta : %g s", time_delta) - tb.log.info("96 bit ts delta : %g s", ts_96_delta) - tb.log.info("64 bit ts delta : %g s", ts_64_delta) - tb.log.info("96 bit ts diff : %g s", ts_96_diff) - tb.log.info("64 bit ts diff : %g s", ts_64_diff) + ts_tod_diff = time_delta - ts_tod_delta * 6.4/(6+(0x6666+20/5)/2**16) + ts_rel_diff = time_delta - ts_rel_delta * 6.4/(6+(0x6666+20/5)/2**16) - assert abs(ts_96_diff) < 1e-12 - assert abs(ts_64_diff) < 1e-12 + tb.log.info("ToD ts diff : %g s", ts_tod_diff) + tb.log.info("rel ts diff : %g s", ts_rel_diff) + + assert abs(ts_tod_diff) < 1e-12 + assert abs(ts_rel_diff) < 1e-12 await RisingEdge(dut.clk) await RisingEdge(dut.clk) diff --git a/tests/ptp_clock/test_ptp_clock.v b/tests/ptp_clock/test_ptp_clock.v index 59e03f3..ed92ced 100644 --- a/tests/ptp_clock/test_ptp_clock.v +++ b/tests/ptp_clock/test_ptp_clock.v @@ -34,8 +34,8 @@ module test_ptp_clock input wire clk, input wire rst, - inout wire [95:0] ts_96, - inout wire [63:0] ts_64, + inout wire [95:0] ts_tod, + inout wire [63:0] ts_rel, inout wire ts_step, inout wire pps ); diff --git a/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.py b/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.py index b07cf54..20c12b8 100644 --- a/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.py +++ b/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.py @@ -46,8 +46,8 @@ class TB: cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start()) self.ptp_clock = PtpClockSimTime( - ts_96=dut.ts_96, - ts_64=dut.ts_64, + ts_tod=dut.ts_tod, + ts_rel=dut.ts_rel, pps=dut.pps, clock=dut.clk ) @@ -63,30 +63,31 @@ async def run_test(dut): await RisingEdge(dut.clk) start_time = get_sim_time('sec') - start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 await ClockCycles(dut.clk, 10000) stop_time = get_sim_time('sec') - stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) - stop_ts_64 = dut.ts_64.value.integer/2**16*1e-9 + stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9 time_delta = stop_time-start_time - ts_96_delta = stop_ts_96-start_ts_96 - ts_64_delta = stop_ts_64-start_ts_64 + ts_tod_delta = stop_ts_tod-start_ts_tod + ts_rel_delta = stop_ts_rel-start_ts_rel - ts_96_diff = time_delta - ts_96_delta - ts_64_diff = time_delta - ts_64_delta + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("ToD ts delta : %g s", ts_tod_delta) + tb.log.info("rel ts delta : %g s", ts_rel_delta) - tb.log.info("sim time delta : %g s", time_delta) - tb.log.info("96 bit ts delta : %g s", ts_96_delta) - tb.log.info("64 bit ts delta : %g s", ts_64_delta) - tb.log.info("96 bit ts diff : %g s", ts_96_diff) - tb.log.info("64 bit ts diff : %g s", ts_64_diff) + ts_tod_diff = time_delta - ts_tod_delta + ts_rel_diff = time_delta - ts_rel_delta - assert abs(ts_96_diff) < 1e-12 - assert abs(ts_64_diff) < 1e-12 + tb.log.info("ToD ts diff : %g s", ts_tod_diff) + tb.log.info("rel ts diff : %g s", ts_rel_diff) + + assert abs(ts_tod_diff) < 1e-12 + assert abs(ts_rel_diff) < 1e-12 await RisingEdge(dut.clk) await RisingEdge(dut.clk) diff --git a/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.v b/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.v index da55b44..a58e4ae 100644 --- a/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.v +++ b/tests/ptp_clock_sim_time/test_ptp_clock_sim_time.v @@ -33,8 +33,8 @@ module test_ptp_clock_sim_time ( input wire clk, - inout wire [95:0] ts_96, - inout wire [63:0] ts_64, + inout wire [95:0] ts_tod, + inout wire [63:0] ts_rel, inout wire pps );