feat(gps): add timer-based assisted reacquisition

Remove the fixed pseudorange start offset, preserve per-PRN navigation assistance across RF loss and power cycles, and seed coherent navigation measurement phase on reacquisition. Add full LNAV almanac visibility scheduling, power-safe QSPI journaling, RF-domain reset isolation, and PPS Gray CDC hardening with Linux, sanitizer, RTL, and end-to-end coverage.
This commit is contained in:
onur
2026-08-04 02:52:35 +03:00
parent 347e1c671d
commit 30179df8e6
69 changed files with 6162 additions and 247 deletions
+23 -3
View File
@@ -67,6 +67,8 @@ module tracking_wrapper #(
// nav solve timer I/O
logic nav_solve_timer_reached;
logic nav_solve_timer_load_abs_sample_signal;
logic nav_solve_phase_seed_valid;
logic [31:0] nav_solve_phase_seed;
//
@@ -117,6 +119,7 @@ module tracking_wrapper #(
logic [31 : 0] control_reg_p, control_reg_n;
logic [31 : 0] timeout_reg_p, timeout_reg_n;
logic [31 : 0] nav_solve_timer_reg_p, nav_solve_timer_reg_n;
logic [31 : 0] nav_solve_phase_reg_p, nav_solve_phase_reg_n;
logic [30 : 0] nav_bit_read_reg_p[10], nav_bit_read_reg_n[10];
// Atomic APB-domain copy of the 20 ms measurement.
@@ -143,9 +146,9 @@ module tracking_wrapper #(
assign to_start_trck_pin = (start_trck_ctl_p != 0) ? 1 : 0;
assign to_stop_trck_pin = (stop_trck_ctl_p != 0) ? 1 : 0;
// ABS_SAMPLE and REM_CODE_PHASE are latched on this same PCLK pulse. PPS
// timestamps only navigation-solve epochs; subframe-ready is not a position
// epoch and therefore must not create a PPS anchor.
// This pulse and the measurement payload originate on the same 125 MHz
// tracking epoch. PPS latches it natively; the payload uses the bundled-data
// PCLK crossing below. Subframe-ready is not a position/PPS epoch.
assign pps_capture = nav_solve_timer_reached;
// comb. logic register cdc
@@ -363,6 +366,7 @@ module tracking_wrapper #(
intr_pending_p <= '0;
timeout_reg_p <= trck_pkg::TRCK_TIMEOUT_RESET_VAL;
nav_solve_timer_reg_p <= 'ha;
nav_solve_phase_reg_p <= '0;
timeout_counter_p <= '0;
start_trck_ctl_p <= '0;
stop_trck_ctl_p <= '0;
@@ -395,6 +399,7 @@ module tracking_wrapper #(
intr_pending_p <= intr_pending_n;
timeout_reg_p <= timeout_reg_n;
nav_solve_timer_reg_p <= nav_solve_timer_reg_n;
nav_solve_phase_reg_p <= nav_solve_phase_reg_n;
timeout_counter_p <= timeout_counter_n;
start_trck_ctl_p <= start_trck_ctl_n;
stop_trck_ctl_p <= stop_trck_ctl_n;
@@ -631,6 +636,8 @@ module tracking_wrapper #(
.resetn(PRESETN), // active low reset.
.enable(control_reg_p[TRCK_NAV_SOLVE_ENABLE_POS]), // timer enable bit.
.counter_max_val(nav_solve_timer_reg_p), // timer generates interrupt when internal timer reaches this value.
.phase_seed_valid(nav_solve_phase_seed_valid),
.phase_seed(nav_solve_phase_seed),
.bit_valid(bit_valid_syned), // timer counts bit valid signals.
.subframe_ready(load_sigs), // signal that asserts 1 clock cycle after a subframe bit reached ( in essence, 300 bit + 8 preamble bit !!!)
.subframe_count(how_z_count), // HOW Z-count of this globally identified subframe boundary.
@@ -656,6 +663,9 @@ module tracking_wrapper #(
control_reg_n = control_reg_p;
timeout_reg_n = timeout_reg_p;
nav_solve_timer_reg_n = nav_solve_timer_reg_p;
nav_solve_phase_reg_n = nav_solve_phase_reg_p;
nav_solve_phase_seed_valid = 1'b0;
nav_solve_phase_seed = nav_solve_phase_reg_p;
if(apb_bus_ps == APB_STATE_SEL) begin
if(PWRITE) begin // write to register
@@ -715,6 +725,12 @@ module tracking_wrapper #(
begin
nav_solve_timer_reg_n = PWDATA;
end
(LOW_ADDRESS + NAV_SOLVE_PHASE_REG_OFFSET):
begin
nav_solve_phase_reg_n = PWDATA;
nav_solve_phase_seed = PWDATA;
nav_solve_phase_seed_valid = 1'b1;
end
default:
@@ -827,6 +843,10 @@ module tracking_wrapper #(
begin
PRDATA = nav_solve_timer_reg_p;
end
(LOW_ADDRESS + NAV_SOLVE_PHASE_REG_OFFSET):
begin
PRDATA = nav_solve_phase_reg_p;
end
(LOW_ADDRESS + REM_CODE_PH_REG_OFFSET):
begin
//PRDATA = rem_code_ph_reg_p;
+1
View File
@@ -21,6 +21,7 @@ package trck_pkg;
NAV_DATA_9_REG_OFFSET = 60,
TRCK_TIMEOUT_REG_OFFSET = 64,
NAV_SOLVE_TIMER_REG_OFFSET = 68,
NAV_SOLVE_PHASE_REG_OFFSET = 72,
REM_CODE_PH_REG_OFFSET = 76,
MEASUREMENT_META_REG_OFFSET = 80,
MEASUREMENT_SEQUENCE_REG_OFFSET = 84,
+16 -1
View File
@@ -4,6 +4,8 @@ module nav_solve_timer(
input logic resetn,
input logic enable,
input logic [31 : 0] counter_max_val,
input logic phase_seed_valid,
input logic [31 : 0] phase_seed,
input logic bit_valid,
input logic subframe_ready,
input logic [16 : 0] subframe_count,
@@ -84,6 +86,18 @@ module nav_solve_timer(
phase_bit_n = 5'd25;
nav_solve_state_n = nav_solve_timer_pkg::ALIGN;
end
/* A cached, week-qualified HOW/sample anchor lets software identify the
* global navigation-bit phase from the first coherent 20 ms tracking
* measurement. This explicit seed starts COUNT without waiting as long
* as six seconds for another complete LNAV subframe. */
if(phase_seed_valid && enable && trck_busy &&
(counter_max_val != 0) && (phase_seed < counter_max_val)) begin
internal_counter_n = phase_seed;
phase_dividend_n = '0;
phase_remainder_n = '0;
phase_bit_n = '0;
nav_solve_state_n = nav_solve_timer_pkg::COUNT;
end
if(nav_solve_state_p == nav_solve_timer_pkg::ALIGN) begin
if(!enable || !trck_busy || (counter_max_val == 0)) begin
nav_solve_state_n = nav_solve_timer_pkg::IDLE;
@@ -114,7 +128,8 @@ module nav_solve_timer(
internal_counter_n = (internal_counter_p == (counter_max_val - 1)) ? 0 : (internal_counter_p + 1);
end
end
if(nav_solve_state_p == nav_solve_timer_pkg::IDLE) begin
if((nav_solve_state_p == nav_solve_timer_pkg::IDLE) &&
!phase_seed_valid) begin
internal_counter_n = '0;
end
@@ -5,6 +5,10 @@ module nav_solve_timer_tb;
logic resetn = 1'b0;
logic enable = 1'b1;
logic [31:0] counter_max_val;
logic phase_seed_valid_a = 1'b0;
logic phase_seed_valid_b = 1'b0;
logic [31:0] phase_seed_a = '0;
logic [31:0] phase_seed_b = '0;
logic bit_valid = 1'b0;
logic subframe_ready_a = 1'b0;
logic subframe_ready_b = 1'b0;
@@ -22,7 +26,9 @@ module nav_solve_timer_tb;
always #5 clk = ~clk;
nav_solve_timer timer_a (
.clk, .resetn, .enable, .counter_max_val, .bit_valid,
.clk, .resetn, .enable, .counter_max_val,
.phase_seed_valid(phase_seed_valid_a), .phase_seed(phase_seed_a),
.bit_valid,
.subframe_ready(subframe_ready_a),
.subframe_count(subframe_count_a),
.trck_busy, .nav_solve_timer_reached(reached_a),
@@ -30,7 +36,9 @@ module nav_solve_timer_tb;
);
nav_solve_timer timer_b (
.clk, .resetn, .enable, .counter_max_val, .bit_valid,
.clk, .resetn, .enable, .counter_max_val,
.phase_seed_valid(phase_seed_valid_b), .phase_seed(phase_seed_b),
.bit_valid,
.subframe_ready(subframe_ready_b),
.subframe_count(subframe_count_b),
.trck_busy, .nav_solve_timer_reached(reached_b),
@@ -96,11 +104,36 @@ module nav_solve_timer_tb;
repeat(period * 3) pulse_nav_bit();
endtask
task automatic run_cached_seed_scenario(input int unsigned period,
input int unsigned start_bit);
counter_max_val = period;
global_bit = start_bit;
b_active = 1'b1;
resetn = 1'b0;
clock_cycles(3);
resetn = 1'b1;
clock_cycles(2);
/* Software observed start_bit's already-consumed measurement and writes
* its global bit phase. No subframe_ready pulse is provided. */
phase_seed_a = start_bit % period;
phase_seed_b = start_bit % period;
phase_seed_valid_a = 1'b1;
phase_seed_valid_b = 1'b1;
@(posedge clk);
@(negedge clk);
phase_seed_valid_a = 1'b0;
phase_seed_valid_b = 1'b0;
repeat(period * 3) pulse_nav_bit();
endtask
initial begin
run_late_join_scenario(40);
run_late_join_scenario(37);
run_late_join_scenario(512);
run_late_join_scenario(1);
run_cached_seed_scenario(10, 30007);
run_cached_seed_scenario(37, 30111);
$display("nav_solve_timer_tb PASS");
$finish;
end
+36 -13
View File
@@ -17,6 +17,24 @@ commit aligns the separate disciplined accumulator. Later commits update a
signed fixed-point PI rate word; holdover freezes the last rate word. The raw
counter is never slewed or reset by a navigation solution.
At cold power-on the raw counter resets to zero and immediately increments on
every 125 MHz clock, even with no antenna signal. It is therefore a valid
elapsed-time/capture source, but it has no GPS week/TOW meaning by itself.
`STATUS.VALID`, lock, and the physical PPS pin remain suppressed until fresh
LNAV time/ephemeris supports WLS, a coarse mapping is committed, and the lock
qualification completes.
Position differential pseudorange uses the tracking-domain observation
`ABS_SAMPLE - REM_CODE_PHASE/1.023e6`, not per-channel PPS capture-counter
differences. The shared RF sample counter supplies the integer datum and the
code-NCO residue removes its 61 ns integer-sample quantum. The 125 MHz raw
counter remains the monotonic source for epoch assembly, GPS-time/PPS mailbox
anchoring, discipline, and holdover. Thus PPS capture quantization and its CDC
pipeline are not injected into XYZ WLS. RF sample-rate scale error still does
not behave as a common WLS bias, but its effect is limited to the
millisecond-scale inter-channel receive-time span rather than the duration of
a tunnel outage.
`GPS_FRACTION_Q32` is a Q0.32 fraction of one GPS second. `KP` and `KI` are
signed 48-bit Q2.46 discrete coefficients. Q2.46 is required because the
125 MHz clock makes the low-bandwidth integral coefficient smaller than one
@@ -59,11 +77,13 @@ generation remain in hardware.
In a conventional absolute-pseudorange model, receiver clock bias and
receiver clock drift are the level and slope of the same physical clock:
`b_r = c*delta_t_r` and `bdot_r = c*d(delta_t_r)/dt`. The position-WLS bias
in this project is different: subtracting the common capture time and adding
`STARTOFFSET` makes it a reference-satellite-relative datum, approximately
`c*STARTOFFSET - reference_range`, rather than a pure receiver oscillator
offset.
`b_r = c*delta_t_r` and `bdot_r = c*d(delta_t_r)/dt`. The position observations
in this project instead subtract satellite transmit-time differences from
wrap-safe corrected RF-sample differences. The fractional code residue removes
the integer RF-sample quantum. No startup or nominal flight-time constant is
added. The position-WLS bias is therefore approximately
`-reference_range` plus the reference satellite clock correction, rather than
a pure receiver oscillator offset.
The Doppler WLS still solves a fourth, common receiver clock/frequency-drift
state. The PPS pre-filter does not use that state directly as the derivative
@@ -83,12 +103,14 @@ The APB register offsets live in `pps_pkg.sv`. Multiword input fields are
shadow registers and must be followed by one `COMMIT` write. A new mailbox
must not be written while `STATUS.COMMIT_BUSY` is set.
The `capture_i` vector is synchronous to `PCLK`. Each pulse stores the
Gray-synchronized 125 MHz counter and increments that channel's capture
sequence. The two-stage crossing adds a small fixed timestamp pipeline offset;
the SoC-level connection must use the exact PCLK event that updates
`ABS_SAMPLE/REM_CODE_PHASE`. `CAPTURE_COUNTER` initially refers to the integer
RF-sample event. Before writing `EPOCH_COUNTER`, navigation software subtracts
The `capture_i` vector is synchronous to `pps_clk`, which is the same 125 MHz
clock used by every tracking channel. Each one-cycle pulse latches the native
raw counter and increments that channel's source-domain sequence, so it cannot
be missed or phase-quantized by the slower APB clock. The stable bundled
counter crosses to PCLK first and its visible sequence is delayed one extra
PCLK cycle; firmware's sequence/data/sequence read rejects any capture that
changes during an APB transaction. `CAPTURE_COUNTER` initially refers to the
integer RF-sample event. Before writing `EPOCH_COUNTER`, navigation software subtracts
```
round((REM_CODE_PHASE / 1.023e6) * (125e6 / RF_HZ))
@@ -96,8 +118,9 @@ round((REM_CODE_PHASE / 1.023e6) * (125e6 / RF_HZ))
counter ticks, so the counter and corrected WLS observation refer to the same
fractional code boundary. This removes an otherwise variable 0--61 ns term.
The remaining PCLK/Gray pipeline delay is fixed and must be measured once on
hardware.
The PPS timebase reset is independent of RF/MMCM readiness, so its raw counter,
disciplined accumulator and holdover rate survive a tunnel or antenna-clock
loss while acquisition/tracking DSP domains reset and restart.
## APB register map
+58 -21
View File
@@ -46,10 +46,18 @@ module pps_wrapper #(
logic commit_overrun_p, commit_overrun_n;
logic diag_req_toggle_p, diag_req_toggle_n;
logic [PPS_COUNTER_WIDTH-1:0] capture_counter_p [NUM_CAPTURE_CHANNELS];
logic [PPS_COUNTER_WIDTH-1:0] capture_counter_n [NUM_CAPTURE_CHANNELS];
logic [PPS_SEQUENCE_WIDTH-1:0] capture_sequence_p [NUM_CAPTURE_CHANNELS];
logic [PPS_SEQUENCE_WIDTH-1:0] capture_sequence_n [NUM_CAPTURE_CHANNELS];
logic [PPS_COUNTER_WIDTH-1:0] capture_counter_pps [NUM_CAPTURE_CHANNELS];
logic [PPS_SEQUENCE_WIDTH-1:0] capture_sequence_pps [NUM_CAPTURE_CHANNELS];
(* ASYNC_REG = "TRUE" *) logic [PPS_COUNTER_WIDTH-1:0]
capture_counter_sync1_p [NUM_CAPTURE_CHANNELS];
(* ASYNC_REG = "TRUE" *) logic [PPS_COUNTER_WIDTH-1:0]
capture_counter_sync2_p [NUM_CAPTURE_CHANNELS];
(* ASYNC_REG = "TRUE" *) logic [PPS_SEQUENCE_WIDTH-1:0]
capture_sequence_sync1_p [NUM_CAPTURE_CHANNELS];
(* ASYNC_REG = "TRUE" *) logic [PPS_SEQUENCE_WIDTH-1:0]
capture_sequence_sync2_p [NUM_CAPTURE_CHANNELS];
logic [PPS_SEQUENCE_WIDTH-1:0]
capture_sequence_visible_p [NUM_CAPTURE_CHANNELS];
logic [PPS_COUNTER_WIDTH-1:0] raw_snapshot_p, raw_snapshot_n;
logic [PPS_COUNTER_WIDTH-1:0] raw_counter_pps;
@@ -93,17 +101,41 @@ module pps_wrapper #(
logic apb_write_access;
logic apb_read_access;
logic [31:0] paddr_extended;
integer channel_pps;
integer channel_seq;
integer channel_comb;
assign raw_counter_pclk = pps_gray_to_binary(raw_gray_sync2_p);
assign raw_counter_gray_pps = raw_counter_pps ^ (raw_counter_pps >> 1);
assign commit_busy = commit_req_toggle_p ^ commit_ack_sync2_p;
assign diag_busy = diag_req_toggle_p ^ diag_ack_sync2_p;
assign apb_write_access = (apb_bus_ps == PPS_APB_STATE_ACCESS) && PWRITE;
assign apb_read_access = (apb_bus_ps == PPS_APB_STATE_ACCESS) && !PWRITE;
assign paddr_extended = {{(32-ADDR_BUS_WIDTH){1'b0}}, PADDR};
/* Capture events are native to this same 125 MHz tracking/PPS domain. Latch
* the counter here so an 8 ns event cannot be missed or quantized by PCLK.
* Counter/sequence remain stable for an entire navigation-solve period; the
* delayed visible sequence below is the bundled-data validity marker. */
always_ff @(posedge pps_clk or negedge pps_resetn) begin
if (!pps_resetn) begin
raw_counter_gray_pps <= '0;
for (channel_pps = 0; channel_pps < NUM_CAPTURE_CHANNELS;
channel_pps = channel_pps + 1) begin
capture_counter_pps[channel_pps] <= '0;
capture_sequence_pps[channel_pps] <= '0;
end
end else begin
raw_counter_gray_pps <= raw_counter_pps ^ (raw_counter_pps >> 1);
for (channel_pps = 0; channel_pps < NUM_CAPTURE_CHANNELS;
channel_pps = channel_pps + 1) begin
if (capture_i[channel_pps]) begin
capture_counter_pps[channel_pps] <= raw_counter_pps;
capture_sequence_pps[channel_pps] <=
capture_sequence_pps[channel_pps] + 1'b1;
end
end
end
end
always_ff @(posedge pps_clk or negedge pps_resetn) begin
if (!pps_resetn) begin
control_sync1_p <= '0;
@@ -180,8 +212,11 @@ module pps_wrapper #(
rate_word_sync1_p <= '0;
rate_word_sync2_p <= '0;
for (channel_seq = 0; channel_seq < NUM_CAPTURE_CHANNELS; channel_seq = channel_seq + 1) begin
capture_counter_p[channel_seq] <= '0;
capture_sequence_p[channel_seq] <= '0;
capture_counter_sync1_p[channel_seq] <= '0;
capture_counter_sync2_p[channel_seq] <= '0;
capture_sequence_sync1_p[channel_seq] <= '0;
capture_sequence_sync2_p[channel_seq] <= '0;
capture_sequence_visible_p[channel_seq] <= '0;
end
end else begin
apb_bus_ps <= apb_bus_ns;
@@ -233,8 +268,18 @@ module pps_wrapper #(
rate_word_sync1_p <= diag_rate_word_pps;
rate_word_sync2_p <= rate_word_sync1_p;
for (channel_seq = 0; channel_seq < NUM_CAPTURE_CHANNELS; channel_seq = channel_seq + 1) begin
capture_counter_p[channel_seq] <= capture_counter_n[channel_seq];
capture_sequence_p[channel_seq] <= capture_sequence_n[channel_seq];
capture_counter_sync1_p[channel_seq] <=
capture_counter_pps[channel_seq];
capture_counter_sync2_p[channel_seq] <=
capture_counter_sync1_p[channel_seq];
capture_sequence_sync1_p[channel_seq] <=
capture_sequence_pps[channel_seq];
capture_sequence_sync2_p[channel_seq] <=
capture_sequence_sync1_p[channel_seq];
/* Publish sequence one PCLK later than the payload. Firmware reads
* sequence/data/sequence and therefore never accepts a mixed capture. */
capture_sequence_visible_p[channel_seq] <=
capture_sequence_sync2_p[channel_seq];
end
end
end
@@ -266,14 +311,6 @@ module pps_wrapper #(
commit_overrun_n = commit_overrun_p;
diag_req_toggle_n = diag_req_toggle_p;
raw_snapshot_n = raw_snapshot_p;
for (channel_comb = 0; channel_comb < NUM_CAPTURE_CHANNELS; channel_comb = channel_comb + 1) begin
capture_counter_n[channel_comb] = capture_counter_p[channel_comb];
capture_sequence_n[channel_comb] = capture_sequence_p[channel_comb];
if (capture_i[channel_comb]) begin
capture_counter_n[channel_comb] = raw_counter_pclk;
capture_sequence_n[channel_comb] = capture_sequence_p[channel_comb] + 32'd1;
end
end
if (apb_read_access && (paddr_extended == (LOW_ADDRESS + PPS_RAW_COUNTER_LO_REG_OFFSET)))
raw_snapshot_n = raw_counter_pclk;
@@ -388,9 +425,9 @@ module pps_wrapper #(
PRDATA = '0;
PRDATA[CAPTURE_SEL_WIDTH-1:0] = capture_select_p;
end
(LOW_ADDRESS + PPS_CAPTURE_COUNTER_LO_OFFSET): PRDATA = capture_counter_p[capture_select_p][31:0];
(LOW_ADDRESS + PPS_CAPTURE_COUNTER_HI_OFFSET): PRDATA = capture_counter_p[capture_select_p][63:32];
(LOW_ADDRESS + PPS_CAPTURE_SEQUENCE_OFFSET): PRDATA = capture_sequence_p[capture_select_p];
(LOW_ADDRESS + PPS_CAPTURE_COUNTER_LO_OFFSET): PRDATA = capture_counter_sync2_p[capture_select_p][31:0];
(LOW_ADDRESS + PPS_CAPTURE_COUNTER_HI_OFFSET): PRDATA = capture_counter_sync2_p[capture_select_p][63:32];
(LOW_ADDRESS + PPS_CAPTURE_SEQUENCE_OFFSET): PRDATA = capture_sequence_visible_p[capture_select_p];
(LOW_ADDRESS + PPS_EPOCH_COUNTER_LO_OFFSET): PRDATA = epoch_counter_shadow_p[31:0];
(LOW_ADDRESS + PPS_EPOCH_COUNTER_HI_OFFSET): PRDATA = epoch_counter_shadow_p[63:32];
(LOW_ADDRESS + PPS_GPS_SECONDS_LO_OFFSET): PRDATA = gps_seconds_shadow_p[31:0];
+15 -9
View File
@@ -114,6 +114,15 @@ module pps_wrapper_tb;
end
endtask
task automatic pulse_native_capture(input int unsigned channel_index);
begin
/* Real tracking capture is exactly one shared 125 MHz PPS-clock pulse,
* potentially narrower than a PCLK period. */
@(negedge pps_clk); capture_i[channel_index] = 1'b1;
@(negedge pps_clk); capture_i[channel_index] = 1'b0;
end
endtask
task automatic wait_commit_idle;
logic [31:0] status;
int timeout;
@@ -238,9 +247,8 @@ module pps_wrapper_tb;
check_true((dut.i_pps_core.raw_counter - raw_snapshot_value) < 100,
"raw-counter low-read snapshot keeps the high word coherent");
@(negedge PCLK); capture_i[1] = 1'b1;
@(negedge PCLK); capture_i[1] = 1'b0;
repeat (3) @(posedge PCLK);
pulse_native_capture(1);
repeat (5) @(posedge PCLK);
read_capture(1, capture_counter, capture_sequence_id);
check_true(capture_sequence_id == 1, "channel capture sequence increments");
check_true(capture_counter != 0, "channel capture stores the free-running counter");
@@ -311,9 +319,8 @@ module pps_wrapper_tb;
// Build the next navigation reference from a new captured hardware epoch.
repeat (40) @(posedge pps_clk);
@(negedge PCLK); capture_i[2] = 1'b1;
@(negedge PCLK); capture_i[2] = 1'b0;
repeat (3) @(posedge PCLK);
pulse_native_capture(2);
repeat (5) @(posedge PCLK);
read_capture(2, second_capture, second_capture_sequence);
check_true(second_capture_sequence == 1, "independent capture bank per tracking channel");
phase_ticks = (second_capture - pps_edge_counter) + 2;
@@ -346,9 +353,8 @@ module pps_wrapper_tb;
"new diagnostic snapshot advances the observed time");
// Replaying sequence 7 must acknowledge the mailbox but not update PI.
@(negedge PCLK); capture_i[2] = 1'b1;
@(negedge PCLK); capture_i[2] = 1'b0;
repeat (3) @(posedge PCLK);
pulse_native_capture(2);
repeat (5) @(posedge PCLK);
read_capture(2, second_capture, second_capture_sequence);
check_true(second_capture_sequence == 2, "repeated channel capture advances its sequence");
pps_sw_commit(second_capture, 102, ticks_to_fraction_q32(phase_ticks), 7, 1'b0);
+4 -2
View File
@@ -105,8 +105,10 @@ gelir. Bu ortak state olmadan oscillator hatasi receiver hareketinin bir
parcasi sanilirdi.
Bu projedeki position WLS bias'i ise mutlak receiver clock bias'i degildir.
Ortak capture zamani cikarildigi ve `STARTOFFSET` eklendigi icin
referans-uyduya bagli goreli bir datum cozer. Bu nedenle Doppler WLS
Wrap-safe corrected RF-sample farkindan satellite transmit-time farki
cikarildigi icin, sabit startup offset'i olmadan referans-uyduya bagli goreli
bir datum cozer. Fractional code residue integer RF-sample quantization'ini
giderir. Bu nedenle Doppler WLS
`clock_drift_mps` state'i, position WLS `clock_bias_m` degerinin turevi olarak
dogrudan baglanmaz.