Timestamp capture
PulsePins includes a dedicated timestamp-capture block for recording the clock-cycle position of selected events.
The main hardware block is ip/ts_core/ts_core.sv, and the main software interface is c++/timestamp.hh.
For a maintainer-oriented RTL map, see ip/ts_core/README.md.
For maintainers, the important split is:
ip/ts_core/ts_core.svowns the free-running counter and edge-capture logicc++/timestamp.hhowns source routing, FIFO draining, and reconstruction of 64-bit event records
Hardware model
ts_core maintains a free-running counter and captures its value when monitored asynchronous inputs change.
The hardware exposes two capture paths:
PPSpathsigApath
Each path produces timestamp values over its own Avalon-ST output FIFO.
Both capture paths trigger on rising edges only.
Internally the block:
- synchronizes each asynchronous input through a short flip-flop chain
- detects a rising edge
- copies the current free-running counter value into a capture register
- holds Avalon-ST
validhigh until the downstream FIFO accepts the captured timestamp - latches and counts overflow if another event arrives while the previous event on that path is still pending
This makes the block simple and deterministic, but it also means that timestamps are quantized to the ts_core clock.
Each capture path has one pending-event slot in front of its FIFO. Backpressure for one event is handled without data loss. If another edge arrives before that pending event is accepted, the later edge is dropped, the per-path overflow latch is set, and the per-path overflow counter increments.
For synchronizer and capture latency notes, see RTL latency and timing.
Source selection
The timestamp software interface exposes selectable signal sources for sigA and for the PPS reference path.
Supported sigA source selectors include:
- streamer trigger activated
- streamer trigger input 0
- external trigger input 0
- auxiliary input 0
- generated pulse sources from
1 msup to1 s
The PPS input can be switched between:
- external PPS input
- crystal-derived PPS source
The selector values exposed in c++/timestamp.hh are:
0- streamer trigger activated1- streamer trigger input 02- external trigger input 03- auxiliary input 04- 1 s pulse5- 100 ms pulse6- 10 ms pulse7- 1 ms pulse
C++ interface
The timestamp class in c++/timestamp.hh wraps two FIFOs, the ts_core status/control register block, and a configuration PIO block.
Important operations:
sel_pps_in()/sel_pps_xtal()- choose the PPS sourceselA()- choose thesigAsourceget_cfg()- return a readable summary of the current routingfilled()/filledA()- report whether FIFO data is availablestatus()- read pending and overflow status fromts_coreoverflow()/overflowA()- report per-path overflow latchesoverflow_count()/overflowA_count()- read per-path overflow countersclear_overflow()- clear timestamp overflow latches and countersclear_fifo()/clear_fifoA()- drain old samplesclear_capture_state()- drain both FIFOs and clear overflow stateread()/readA()- read one 64-bit timestamp from each pathread_with_timeout()/readA_with_timeout()- wait for a sample with timeout handling
Each timestamp is assembled from two 32-bit FIFO words into a 64-bit counter value.
The timeout-based read functions poll until two FIFO words are available, then reconstruct the full 64-bit timestamp. This is why the timeout is applied to a complete event record rather than to a single 32-bit transfer. By default they also fail if the relevant timestamp overflow latch is set; callers that are intentionally stress-testing fast sources can opt out and keep draining received samples.
The constructor clears both FIFOs on startup, which helps avoid stale samples after reset or reconfiguration. User-facing timestamp sessions select the requested PPS and sigA routes before clearing capture state again, so mux-switch artifacts are drained before the first sample is reported.
The main user-facing command implementations live in c++/pptool_measurement.cc (ppts and ppgpsdo).
Timing semantics
The returned timestamps are counter values, not elapsed times in seconds. To convert them into time units, use the clock frequency of the ts_core timebase.
Differences between successive timestamps are often more useful than the absolute counter values:
- PPS-to-PPS differences show the effective period of the selected PPS source
sigA-to-sigAdifferences show the period of the selected event source- comparisons between the two paths are useful for phase or drift analysis
Tool integration
ppts is the direct command-line tool for live timestamp observation.
ppgpsdo reuses the same timestamp hardware to compare PPS against another timing reference when disciplining an oscillator.
ppgpsdo effectively consumes the two timestamp streams as paired event series and computes phase-error updates from their differences.
Typical use cases
Use the timestamp block for:
- observing PPS alignment and jitter
- measuring the relative timing of internal and external trigger sources
- debugging trigger routing
- building higher-level closed-loop timing tools such as
ppgpsdo
Because the capture logic is edge-based and has only one pending slot per path ahead of the FIFO, this subsystem is best suited to sparse event streams such as PPS pulses, trigger events, and derived low-rate timing markers rather than dense arbitrary waveforms.