f59d6ebb43
Persisting navigation data changed its lifetime from one power cycle to weeks, and every piece of arithmetic that had only ever run over the shorter lifetime turned out to be wrong. Each fix below reproduces in a host test that fails against the previous behaviour. Almanac (gps_almanac.c, gps_lnav_parser.c) WNa was lifted against gps_ephems.toe.week, a field nothing ever writes, so any WNa above 128 underflowed to ~4.29e9. The propagation then reduced tk with a while-loop, turning one visibility refresh into 4.29e9 iterations - hours on the target, inside a 10 s periodic call. WNa is the week modulo 256, so this armed at GPS week 2433 and then for 127 weeks in every 256. Now lifted against tow.week in signed arithmetic, refused if impossible, and the propagation is closed form. The IS-GPS-200 20.3.3.5.2.3 half-week wrap was also applied to tk unconditionally. It is a week-crossover correction, not a general reduction: a GPS week is 14.0384 orbital periods, so aliasing one week moves a satellite 5161 km, enough to report one 5.1 degrees below the horizon as 5.7 above. The crossover guess now lives in gps_almanac_assumed_week(), used only before page 25 arrives, and an almanac too old to propagate yields no prediction rather than a wrong one. Ephemeris age (gps_ephemeris_validity.c, gps_lnav_parser.c) The curve-fit check compared two second-of-week values and never read a week at all, so a record exactly N weeks old read as current. Harmless while ephemeris lived in RAM; directly reachable once persisted across a power-off. gps_resolve_toe_week() now reconstructs Toe's week at commit time from the subframe 1 week number and the handover word; an unresolvable week yields no age, which reads as a rejection. A restored record could also outrank the live broadcast, because the Toe ordering inverts past half a week. Flash records are now marked restored and are candidates, never incumbents. Flash wear (gps_nav_context_store.c, gps_interrupt_handlers.c) The CRC wear policy never engaged: the payload carried the live WLS position and a receiver timestamp nothing on the restore path read, so every 60 s save was an erase - about 139 days to wear-out. The seed is now held and refreshed only on 5 km of movement, at most hourly: one erase per day instead of 1440. Measurement model (NavEquations.c) The elevation weighting was floored at 10 degrees, capping its term at 17.3 m where the model's own answer is 34.4 m at 5 degrees and 86 m at 2, so a low satellite was trusted several times more than the model allowed. Floor lowered to 3 degrees, which is where 1/sin must still be bounded because a zero weight fails the whole epoch. Measured on a six-satellite geometry, 30 m of uncorrected delay now moves the fix 4.18 m through a 4-degree satellite against 48.50 m through a 72-degree one. Both atmospheric corrections switched off below the horizon, so a satellite crossing it lost 78.8 m of tropospheric delay in one step. Elevation is now clamped at the horizon for the models, and the extrapolation is paid for in variance. Also: gps_pps_select_reference() returned early on the preferred PRN, leaving later non-finite capture times unscreened. Checked and found correct, with regressions added: the epoch assembly under satellite connect/disconnect and reassignment, coalesced captures, the 32-bit RF sample counter wrap (pseudoranges agree to 3.3 um across it), the refusal to publish a solvable subset of an incoherent epoch, and the Klobuchar model against IS-GPS-200 20.3.3.5.2.5. Tests: 22 host suites, 5 RTL testbenches, sanitizer clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
923 lines
39 KiB
Systemverilog
923 lines
39 KiB
Systemverilog
import definitions::*;
|
|
module tracking_wrapper #(
|
|
parameter HIGH_ADDRESS = 32'h20000,
|
|
parameter LOW_ADDRESS = 32'h10000,
|
|
parameter DATA_BUS_WIDTH = 32,
|
|
parameter ADDR_BUS_WIDTH = 12
|
|
)
|
|
|
|
(
|
|
// ########## APB BUS ####################
|
|
// input
|
|
input logic PCLK,
|
|
input logic PRESETN,
|
|
input logic[(ADDR_BUS_WIDTH - 1) : 0] PADDR,
|
|
input logic PSEL,
|
|
input logic PENABLE,
|
|
input logic PWRITE,
|
|
input logic[(DATA_BUS_WIDTH - 1) : 0] PWDATA,
|
|
|
|
// output
|
|
output logic PREADY, // ready handshake signal from slave
|
|
output logic[(DATA_BUS_WIDTH - 1) : 0] PRDATA, // read data from slave module
|
|
output logic PSLVERR, // read data from slave module
|
|
// ########## APB BUS ####################
|
|
|
|
input trck_resetn,
|
|
input afe_resetn,
|
|
input logic trck_clk,
|
|
input logic afe_clk,
|
|
input logic[3 : 0] afe_data,
|
|
input logic sample_align,
|
|
input logic[31 : 0] sample_counter,
|
|
|
|
// INTERRUPT LINES / PPS epoch timestamp request
|
|
output logic gps_frame_ready,
|
|
output logic pps_capture
|
|
);
|
|
|
|
|
|
import gps_top_pkg::*;
|
|
import trck_pkg::*;
|
|
|
|
localparam int unsigned MEAS_CARRIER_WL =
|
|
ACQUIRED_FREQ_IL + TRCK_CARR_NCO_FREQ_FL;
|
|
localparam int unsigned MEAS_SUM_WL =
|
|
TRCK_CORR_WL + $clog2(MS_PER_BIT);
|
|
localparam int unsigned MEAS_WBP_WL =
|
|
(2 * TRCK_CORR_WL) + 1 + $clog2(MS_PER_BIT);
|
|
localparam int unsigned MEAS_COUNT_WL = $clog2(MS_PER_BIT + 1);
|
|
|
|
// apb state machine
|
|
apb_state_e apb_bus_ps, apb_bus_ns;
|
|
// tracking lock state machine
|
|
//trck_state_e trck_state_p, trck_state_n;
|
|
|
|
// internal net declarations.
|
|
logic intr_clear; // generic interrupt flag clear signal.
|
|
logic start_trck;
|
|
logic stop_trck;
|
|
logic timeout_stop;
|
|
logic to_start_trck_pin;
|
|
logic to_stop_trck_pin;
|
|
|
|
logic to_start_trck_pin_ff;
|
|
logic to_stop_trck_pin_ff;
|
|
|
|
// nav solve timer I/O
|
|
logic nav_solve_timer_reached;
|
|
logic nav_solve_timer_load_abs_sample_signal;
|
|
logic nav_solve_phase_seed_consumed;
|
|
logic nav_solve_provisional;
|
|
|
|
|
|
//
|
|
logic [1 : 0] bit_vld_cc_p, bit_vld_cc_n, load_sigs_cc_p, load_sigs_cc_n;
|
|
|
|
// signals to be syned.
|
|
logic lock, lock_syned, busy, busy_syned;
|
|
logic bit_valid, load_sigs, bit_valid_syned; // -> loads sigs, load internal registers & signals.
|
|
logic nav_bit, nav_bit_syned; // navigation bits.
|
|
logic [31 : 0] abs_sample, abs_sample_syned;
|
|
logic [REM_CODE_PH_I_WL-1 : 0] rem_code_ph, rem_code_ph_syned;
|
|
logic measurement_valid, measurement_valid_syned;
|
|
logic measurement_bit, measurement_bit_syned;
|
|
logic [31:0] measurement_abs_sample, measurement_abs_sample_syned;
|
|
logic [REM_CODE_PH_I_WL-1:0] measurement_rem_code_ph;
|
|
logic [REM_CODE_PH_I_WL-1:0] measurement_rem_code_ph_syned;
|
|
logic signed [MEAS_CARRIER_WL-1:0] measurement_carrier_freq_q7;
|
|
logic [MEAS_CARRIER_WL-1:0] measurement_carrier_freq_q7_syned;
|
|
logic signed [MEAS_SUM_WL-1:0] measurement_cn0_sum_i;
|
|
logic signed [MEAS_SUM_WL-1:0] measurement_cn0_sum_q;
|
|
logic [MEAS_SUM_WL-1:0] measurement_cn0_sum_i_syned;
|
|
logic [MEAS_SUM_WL-1:0] measurement_cn0_sum_q_syned;
|
|
logic [MEAS_WBP_WL-1:0] measurement_cn0_wbp;
|
|
logic [MEAS_WBP_WL-1:0] measurement_cn0_wbp_syned;
|
|
logic [MEAS_COUNT_WL-1:0] measurement_cn0_sample_count;
|
|
logic [MEAS_COUNT_WL-1:0] measurement_cn0_sample_count_syned;
|
|
logic [15:0] measurement_sequence, measurement_sequence_syned;
|
|
logic preamble_ok;
|
|
|
|
// ( internal flags )
|
|
logic intr_pending_p, intr_pending_n; // generic interrupt flag.
|
|
logic trck_nav_bit_rcv_flag_p, trck_nav_bit_rcv_flag_n;
|
|
logic trck_timeout_flag_p, trck_timeout_flag_n;
|
|
logic trck_nav_solve_flag_p, trck_nav_solve_flag_n;
|
|
logic trck_measurement_flag_p, trck_measurement_flag_n;
|
|
|
|
logic [31 : 0] timeout_counter_p, timeout_counter_n; // tracking auto timeout value
|
|
|
|
|
|
logic [309 : 0] shift_reg_p, shift_reg_n;
|
|
|
|
// registers. (not be syned in this case since software write delay will be enough)
|
|
logic [13 : 0] code_phase_reg_p, code_phase_reg_n;
|
|
logic [4 : 0] prn_no_reg_p, prn_no_reg_n;
|
|
logic [21 : 0] doppler_reg_p, doppler_reg_n;
|
|
logic [31 : 0] abs_sample_reg_p, abs_sample_reg_n;
|
|
logic [REM_CODE_PH_I_WL-1 : 0] rem_code_ph_reg_p, rem_code_ph_reg_n;
|
|
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_seed_reg_p, nav_solve_phase_seed_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.
|
|
logic measurement_valid_r;
|
|
logic measurement_capture_pending;
|
|
logic [1:0] measurement_settle_count;
|
|
logic measurement_capture;
|
|
logic measurement_interrupt_pulse;
|
|
logic measurement_data_valid_reg;
|
|
logic measurement_bit_reg;
|
|
logic measurement_lock_reg;
|
|
logic [31:0] measurement_abs_sample_reg;
|
|
logic [REM_CODE_PH_I_WL-1:0] measurement_rem_code_ph_reg;
|
|
logic signed [MEAS_CARRIER_WL-1:0] measurement_carrier_freq_q7_reg;
|
|
logic signed [MEAS_SUM_WL-1:0] measurement_cn0_sum_i_reg;
|
|
logic signed [MEAS_SUM_WL-1:0] measurement_cn0_sum_q_reg;
|
|
logic [MEAS_WBP_WL-1:0] measurement_cn0_wbp_reg;
|
|
logic [MEAS_COUNT_WL-1:0] measurement_cn0_sample_count_reg;
|
|
logic [15:0] measurement_sequence_reg;
|
|
|
|
|
|
logic[2 : 0] start_trck_ctl_p, start_trck_ctl_n;
|
|
logic[2 : 0] stop_trck_ctl_p, stop_trck_ctl_n;
|
|
|
|
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.
|
|
assign pps_capture = nav_solve_timer_reached;
|
|
|
|
// comb. logic register cdc
|
|
always_ff @(posedge PCLK) begin : start_stop_cdc_ff
|
|
to_start_trck_pin_ff <= to_start_trck_pin;
|
|
to_stop_trck_pin_ff <= to_stop_trck_pin;
|
|
end : start_stop_cdc_ff
|
|
|
|
|
|
// syn. modules
|
|
double_ff_syn#(1, 2) i_bit_vld_syn(
|
|
.clk(PCLK),
|
|
.aresetn(PRESETN),
|
|
.Din(bit_valid),
|
|
.Dout(bit_valid_syned)
|
|
);
|
|
|
|
double_ff_syn#(1, 2) i_lock_syn( // multi bit acqusition status and acqusition end
|
|
.clk(PCLK),
|
|
.aresetn(PRESETN),
|
|
.Din(lock),
|
|
.Dout(lock_syned)
|
|
);
|
|
|
|
double_ff_syn#(1, 2) i_nav_bit_syn(
|
|
.clk(PCLK),
|
|
.aresetn(PRESETN),
|
|
.Din(nav_bit),
|
|
.Dout(nav_bit_syned)
|
|
);
|
|
|
|
double_ff_syn#(1, 2) i_busy_syn(
|
|
.clk(PCLK),
|
|
.aresetn(PRESETN),
|
|
.Din(busy),
|
|
.Dout(busy_syned)
|
|
);
|
|
|
|
double_ff_syn#(32, 2) i_abs_sample_syn(
|
|
.clk(PCLK),
|
|
.aresetn(PRESETN),
|
|
.Din(abs_sample),
|
|
.Dout(abs_sample_syned)
|
|
);
|
|
double_ff_syn#(REM_CODE_PH_I_WL, 2) i_rem_code_ph_syn(
|
|
.clk(PCLK),
|
|
.aresetn(PRESETN),
|
|
.Din(rem_code_ph),
|
|
.Dout(rem_code_ph_syned)
|
|
);
|
|
|
|
double_ff_syn#(1, 2) i_measurement_valid_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_valid), .Dout(measurement_valid_syned)
|
|
);
|
|
double_ff_syn#(1, 2) i_measurement_bit_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_bit), .Dout(measurement_bit_syned)
|
|
);
|
|
double_ff_syn#(32, 2) i_measurement_abs_sample_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_abs_sample), .Dout(measurement_abs_sample_syned)
|
|
);
|
|
double_ff_syn#(REM_CODE_PH_I_WL, 2) i_measurement_rem_code_ph_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_rem_code_ph), .Dout(measurement_rem_code_ph_syned)
|
|
);
|
|
double_ff_syn#(MEAS_CARRIER_WL, 2) i_measurement_carrier_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_carrier_freq_q7),
|
|
.Dout(measurement_carrier_freq_q7_syned)
|
|
);
|
|
double_ff_syn#(MEAS_SUM_WL, 2) i_measurement_sum_i_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_cn0_sum_i), .Dout(measurement_cn0_sum_i_syned)
|
|
);
|
|
double_ff_syn#(MEAS_SUM_WL, 2) i_measurement_sum_q_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_cn0_sum_q), .Dout(measurement_cn0_sum_q_syned)
|
|
);
|
|
double_ff_syn#(MEAS_WBP_WL, 2) i_measurement_wbp_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_cn0_wbp), .Dout(measurement_cn0_wbp_syned)
|
|
);
|
|
double_ff_syn#(MEAS_COUNT_WL, 2) i_measurement_count_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_cn0_sample_count),
|
|
.Dout(measurement_cn0_sample_count_syned)
|
|
);
|
|
double_ff_syn#(16, 2) i_measurement_sequence_syn(
|
|
.clk(PCLK), .aresetn(PRESETN),
|
|
.Din(measurement_sequence), .Dout(measurement_sequence_syned)
|
|
);
|
|
|
|
trck_top i_trck_top(
|
|
// common signals
|
|
.trk_rstn(trck_resetn),
|
|
.afe_rstn(afe_resetn),
|
|
.trk_clk(trck_clk),
|
|
.afe_clk(afe_clk),
|
|
.sample_align_i(sample_align), // from afe
|
|
.sample_counter_i(sample_counter), // from afe
|
|
.rf_data_i(afe_data), // from afe
|
|
|
|
// intputs from regs. destination module should implement cdc.
|
|
.start_i(to_start_trck_pin_ff),
|
|
.stop_i(to_stop_trck_pin_ff),
|
|
.prn_i(prn_no_reg_p),
|
|
.carr_freq_i(doppler_reg_p),
|
|
.code_phase_i(code_phase_reg_p),
|
|
|
|
// output to regs. (all values are valid on bit_vld except lock ?)
|
|
.bit_o(nav_bit),
|
|
.bit_vld_o(bit_valid),
|
|
.abs_sample_o(abs_sample), // 20 ms bit valid aligned
|
|
.rem_code_ph_o(rem_code_ph),
|
|
.measurement_vld_o(measurement_valid),
|
|
.measurement_bit_o(measurement_bit),
|
|
.measurement_abs_sample_o(measurement_abs_sample),
|
|
.measurement_rem_code_ph_o(measurement_rem_code_ph),
|
|
.measurement_carrier_freq_q7_o(measurement_carrier_freq_q7),
|
|
.measurement_cn0_sum_i_o(measurement_cn0_sum_i),
|
|
.measurement_cn0_sum_q_o(measurement_cn0_sum_q),
|
|
.measurement_cn0_wbp_o(measurement_cn0_wbp),
|
|
.measurement_cn0_sample_count_o(measurement_cn0_sample_count),
|
|
.measurement_sequence_o(measurement_sequence),
|
|
.lock_o(lock),
|
|
.busy_o(busy),
|
|
|
|
//unconnected ( for debug purposes )
|
|
.fifo_of_o()
|
|
|
|
);
|
|
|
|
/*
|
|
* The source payload is stable for 20 ms. Its valid marker and every data
|
|
* bit pass through the same three-stage synchronizer; two extra PCLK cycles
|
|
* after the synchronized rising edge provide a conservative bus-settle
|
|
* margin before the software-visible registers and interrupt are updated.
|
|
*/
|
|
always_ff @(posedge PCLK or negedge PRESETN) begin : measurement_capture_seq
|
|
if(!PRESETN) begin
|
|
measurement_valid_r <= 1'b0;
|
|
measurement_capture_pending <= 1'b0;
|
|
measurement_settle_count <= '0;
|
|
measurement_capture <= 1'b0;
|
|
measurement_interrupt_pulse <= 1'b0;
|
|
measurement_data_valid_reg <= 1'b0;
|
|
measurement_bit_reg <= 1'b0;
|
|
measurement_lock_reg <= 1'b0;
|
|
measurement_abs_sample_reg <= '0;
|
|
measurement_rem_code_ph_reg <= '0;
|
|
measurement_carrier_freq_q7_reg <= '0;
|
|
measurement_cn0_sum_i_reg <= '0;
|
|
measurement_cn0_sum_q_reg <= '0;
|
|
measurement_cn0_wbp_reg <= '0;
|
|
measurement_cn0_sample_count_reg <= '0;
|
|
measurement_sequence_reg <= '0;
|
|
end else begin
|
|
measurement_valid_r <= measurement_valid_syned;
|
|
measurement_capture <= 1'b0;
|
|
measurement_interrupt_pulse <= measurement_capture;
|
|
|
|
if(measurement_valid_syned && !measurement_valid_r) begin
|
|
measurement_capture_pending <= 1'b1;
|
|
measurement_settle_count <= 2;
|
|
end else if(measurement_capture_pending) begin
|
|
if(measurement_settle_count != 0) begin
|
|
measurement_settle_count <= measurement_settle_count - 1'b1;
|
|
end else begin
|
|
measurement_capture_pending <= 1'b0;
|
|
measurement_capture <= 1'b1;
|
|
measurement_data_valid_reg <= 1'b1;
|
|
measurement_bit_reg <= measurement_bit_syned;
|
|
measurement_lock_reg <= lock_syned;
|
|
measurement_abs_sample_reg <= measurement_abs_sample_syned;
|
|
measurement_rem_code_ph_reg <= measurement_rem_code_ph_syned;
|
|
measurement_carrier_freq_q7_reg <=
|
|
$signed(measurement_carrier_freq_q7_syned);
|
|
measurement_cn0_sum_i_reg <=
|
|
$signed(measurement_cn0_sum_i_syned);
|
|
measurement_cn0_sum_q_reg <=
|
|
$signed(measurement_cn0_sum_q_syned);
|
|
measurement_cn0_wbp_reg <= measurement_cn0_wbp_syned;
|
|
measurement_cn0_sample_count_reg <=
|
|
measurement_cn0_sample_count_syned;
|
|
measurement_sequence_reg <= measurement_sequence_syned;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
// internal signals & assignments
|
|
|
|
assign PREADY = (apb_bus_ps == APB_STATE_IDLE) ? 1'b0 : 1'b1;
|
|
assign bit_vld_cc_n = {bit_vld_cc_p[0], bit_valid_syned};
|
|
assign load_sigs_cc_n = {load_sigs_cc_p[0], load_sigs};
|
|
|
|
// APB NEXT STATE LOGIC && INTERNAL SIGNAL SEQ. LOGIC.
|
|
always_ff @(posedge PCLK or negedge PRESETN) begin : intr_sig_reg_seq
|
|
if(!PRESETN) begin
|
|
apb_bus_ps <= APB_STATE_IDLE;
|
|
//trck_state_p <= TRCK_STATE_IDLE;
|
|
shift_reg_p <= '0;
|
|
code_phase_reg_p <= '0;
|
|
prn_no_reg_p <= '0;
|
|
control_reg_p <= '0;
|
|
doppler_reg_p <= '0;
|
|
abs_sample_reg_p <= '0;
|
|
rem_code_ph_reg_p <= '0;
|
|
bit_vld_cc_p <= '0;
|
|
load_sigs_cc_p <= '0;
|
|
intr_pending_p <= '0;
|
|
timeout_reg_p <= trck_pkg::TRCK_TIMEOUT_RESET_VAL;
|
|
nav_solve_timer_reg_p <= 'ha;
|
|
nav_solve_phase_seed_reg_p <= '0;
|
|
timeout_counter_p <= '0;
|
|
start_trck_ctl_p <= '0;
|
|
stop_trck_ctl_p <= '0;
|
|
trck_timeout_flag_p <= '0;
|
|
trck_nav_solve_flag_p <= '0;
|
|
trck_nav_bit_rcv_flag_p <= '0;
|
|
trck_measurement_flag_p <= '0;
|
|
|
|
// control reg bit fields set by reset.
|
|
control_reg_p[TRCK_NAV_BITS_FLAG_ENABLE_POS] <= 1'b1;
|
|
control_reg_p[TRCK_NAV_SOLVE_FLAG_EN_POS] <= 1'b1;
|
|
control_reg_p[TRCK_STOP_ON_UNLOCK_FLAG_EN_POS] <= 1'b1;
|
|
control_reg_p[TRCK_MEASUREMENT_FLAG_EN_POS] <= 1'b1;
|
|
|
|
foreach(nav_bit_read_reg_p[i])
|
|
nav_bit_read_reg_p[i] <= '0;
|
|
end
|
|
else begin
|
|
apb_bus_ps <= apb_bus_ns;
|
|
//trck_state_p <= trck_state_n;
|
|
shift_reg_p <= shift_reg_n;
|
|
code_phase_reg_p <= code_phase_reg_n;
|
|
prn_no_reg_p <= prn_no_reg_n;
|
|
control_reg_p <= control_reg_n;
|
|
doppler_reg_p <= doppler_reg_n;
|
|
abs_sample_reg_p <= abs_sample_reg_n;
|
|
rem_code_ph_reg_p <= rem_code_ph_reg_n;
|
|
bit_vld_cc_p <= bit_vld_cc_n;
|
|
load_sigs_cc_p <= load_sigs_cc_n;
|
|
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_seed_reg_p <= nav_solve_phase_seed_reg_n;
|
|
timeout_counter_p <= timeout_counter_n;
|
|
start_trck_ctl_p <= start_trck_ctl_n;
|
|
stop_trck_ctl_p <= stop_trck_ctl_n;
|
|
trck_timeout_flag_p <= trck_timeout_flag_n;
|
|
trck_nav_bit_rcv_flag_p <= trck_nav_bit_rcv_flag_n;
|
|
trck_nav_solve_flag_p <= trck_nav_solve_flag_n;
|
|
trck_measurement_flag_p <= trck_measurement_flag_n;
|
|
foreach(nav_bit_read_reg_p[i])
|
|
nav_bit_read_reg_p[i] <= nav_bit_read_reg_n[i];
|
|
end
|
|
end : intr_sig_reg_seq
|
|
|
|
// tracking pulse counter
|
|
always_comb begin : start_stop_pulse_comb
|
|
start_trck_ctl_n = '0;
|
|
stop_trck_ctl_n = '0;
|
|
if(start_trck) begin
|
|
start_trck_ctl_n = (start_trck_ctl_p + 1);
|
|
end
|
|
if(start_trck_ctl_p != 0) begin
|
|
start_trck_ctl_n = (start_trck_ctl_p + 1);
|
|
end
|
|
if(stop_trck || timeout_stop) begin // signals that cause to stop trck
|
|
stop_trck_ctl_n = (stop_trck_ctl_p + 1);
|
|
end
|
|
if(stop_trck_ctl_p != 0) begin
|
|
stop_trck_ctl_n = (stop_trck_ctl_p + 1);
|
|
end
|
|
end : start_stop_pulse_comb
|
|
|
|
// tracking auto stop tracking.
|
|
always_comb begin : tracking_auto_stop_ctr_comb
|
|
timeout_counter_n = '0;
|
|
timeout_stop = '0;
|
|
if(control_reg_p[TRCK_STOP_ON_UNLOCK_EN_POS] && busy_syned && !lock_syned) begin
|
|
timeout_counter_n = (timeout_counter_p + 1);
|
|
if(timeout_counter_p == (timeout_reg_p - 1)) begin
|
|
timeout_counter_n = '0;
|
|
timeout_stop = '1;
|
|
end
|
|
end
|
|
|
|
end : tracking_auto_stop_ctr_comb
|
|
|
|
// next state comb. logic (might be obsolated.) TODO remove if unused.
|
|
always_comb begin :apb_bus_comb_logic
|
|
apb_bus_ns = apb_bus_ps;
|
|
//trck_state_n = trck_state_p;
|
|
case(apb_bus_ps)
|
|
APB_STATE_IDLE : if(PSEL) apb_bus_ns = APB_STATE_SEL;
|
|
APB_STATE_SEL : apb_bus_ns = APB_STATE_WR;
|
|
APB_STATE_WR : apb_bus_ns = APB_STATE_IDLE;
|
|
endcase
|
|
//case(trck_state_p)
|
|
// TRCK_STATE_IDLE: if(start_trck) trck_state_n = TRCK_STATE_UNLOCK; // only after reset
|
|
// TRCK_STATE_UNLOCK:
|
|
// begin
|
|
// if(stop_trck)
|
|
// trck_state_n = TRCK_STATE_IDLE;
|
|
// if(lock_syned)
|
|
// trck_state_n = TRCK_STATE_LOCK;
|
|
// end
|
|
// TRCK_STATE_LOCK:
|
|
// begin
|
|
// if(stop_trck)
|
|
// trck_state_n = TRCK_STATE_IDLE;
|
|
// if(!lock_syned)
|
|
// trck_state_n = TRCK_STATE_UNLOCK;
|
|
// end
|
|
//endcase
|
|
end : apb_bus_comb_logic
|
|
|
|
|
|
//always_comb begin : nav_bit_shift_comb_logic
|
|
// abs_sample_reg_n = abs_sample_reg_p;
|
|
// shift_reg_n = shift_reg_p;
|
|
// if(bit_vld_cc_p[0] & !bit_vld_cc_p[1]) begin
|
|
// abs_sample_reg_n = abs_sample;
|
|
// shift_reg_n = {shift_reg_p[308 : 0], nav_bit_syned};
|
|
// end
|
|
//end : nav_bit_shift_comb_logic
|
|
|
|
always_comb begin : nav_bit_shift_comb_logic
|
|
abs_sample_reg_n = abs_sample_reg_p;
|
|
rem_code_ph_reg_n = rem_code_ph_reg_p;
|
|
shift_reg_n = shift_reg_p;
|
|
if(bit_vld_cc_p[0] & !bit_vld_cc_p[1]) begin
|
|
shift_reg_n = {shift_reg_p[308 : 0], nav_bit_syned};
|
|
end
|
|
if((load_sigs) || (nav_solve_timer_reached)) begin
|
|
abs_sample_reg_n = abs_sample_syned;
|
|
rem_code_ph_reg_n = rem_code_ph_syned;
|
|
//abs_sample_reg_n = abs_sample;
|
|
end
|
|
end : nav_bit_shift_comb_logic
|
|
|
|
// preamble search comb. logic
|
|
always_comb begin : preamble_search_comb
|
|
preamble_ok = 1'b0;
|
|
if(lock_syned) begin
|
|
if(shift_reg_p[307-:8] == trck_pkg::PREAMBLE && (shift_reg_p[7 : 0] == ~(trck_pkg::PREAMBLE))) begin
|
|
preamble_ok = 1'b1;
|
|
end
|
|
else if(shift_reg_p[307-:8] == ~(trck_pkg::PREAMBLE) && (shift_reg_p[7 : 0] == trck_pkg::PREAMBLE))
|
|
preamble_ok = 1'b1;
|
|
else if(shift_reg_p[307-:8] == trck_pkg::PREAMBLE && (shift_reg_p[7 : 0] == trck_pkg::PREAMBLE))
|
|
preamble_ok = 1'b1;
|
|
else if(shift_reg_p[307-:8] == ~(trck_pkg::PREAMBLE) && (shift_reg_p[7 : 0] == ~(trck_pkg::PREAMBLE)))
|
|
preamble_ok = 1'b1;
|
|
end
|
|
end : preamble_search_comb
|
|
|
|
logic [301 : 0] shift_reg_resultant;
|
|
logic [16 : 0] how_z_count;
|
|
|
|
assign shift_reg_resultant[301-:2] = shift_reg_p[309-:2]; // always assign last 2 bit from previous subframe
|
|
/* Normalized HOW word is nav word 2 at [269:240]; bits [29:13] are
|
|
* the 17-bit Z-count used to align NAV solve timer phase globally. */
|
|
assign how_z_count = shift_reg_resultant[269-:17];
|
|
|
|
generate
|
|
genvar j;
|
|
for(j = 0 ; j < 10 ; j = j + 1) begin : inv_words
|
|
assign shift_reg_resultant[(299 - (j * 30))-: 24] = shift_reg_p[(308 - (j * 30))] ? ~shift_reg_p[(307 - (j * 30)) -:24] : shift_reg_p[(307 - (j * 30))-:24];
|
|
assign shift_reg_resultant[(275 - (j * 30))-: 6] = shift_reg_p[(283 - (j * 30))-:6];
|
|
end : inv_words
|
|
endgenerate
|
|
|
|
// parity CALCULATION
|
|
logic[9 : 0] D25;
|
|
logic[9 : 0] D26;
|
|
logic[9 : 0] D27;
|
|
logic[9 : 0] D28;
|
|
logic[9 : 0] D29;
|
|
logic[9 : 0] D30;
|
|
logic[9 : 0] pcw;
|
|
|
|
generate
|
|
genvar i;
|
|
for(i = 0 ; i < 10 ; i = i + 1) begin : parity_calc
|
|
assign D25[i] = shift_reg_resultant[301 - (30 * i)] ^ shift_reg_resultant[299 - (30 * i)] ^ shift_reg_resultant[298 -(30 * i)] ^ shift_reg_resultant[297 - (30 * i)] ^ shift_reg_resultant[295 -(30 * i)] ^ shift_reg_resultant[294 -(30 * i)] ^ shift_reg_resultant[290 -(30 * i)] ^ shift_reg_resultant[289 -(30 * i)] ^ shift_reg_resultant[288 -(30 * i)] ^ shift_reg_resultant[287 -(30 * i)] ^ shift_reg_resultant[286 -(30 * i)] ^ shift_reg_resultant[283 -(30 * i)] ^ shift_reg_resultant[282 -(30 * i)] ^ shift_reg_resultant[280 -(30 * i)] ^ shift_reg_resultant[277 -(30 * i)];
|
|
assign D26[i] = shift_reg_resultant[300 - (30 * i)] ^ shift_reg_resultant[298 - (30 * i)] ^ shift_reg_resultant[297 -(30 * i)] ^ shift_reg_resultant[296 - (30 * i)] ^ shift_reg_resultant[294 -(30 * i)] ^ shift_reg_resultant[293 -(30 * i)] ^ shift_reg_resultant[289 -(30 * i)] ^ shift_reg_resultant[288 -(30 * i)] ^ shift_reg_resultant[287 -(30 * i)] ^ shift_reg_resultant[286 -(30 * i)] ^ shift_reg_resultant[285 -(30 * i)] ^ shift_reg_resultant[282 -(30 * i)] ^ shift_reg_resultant[281 -(30 * i)] ^ shift_reg_resultant[279 -(30 * i)] ^ shift_reg_resultant[276 -(30 * i)];
|
|
assign D27[i] = shift_reg_resultant[301 - (30 * i)] ^ shift_reg_resultant[299 - (30 * i)] ^ shift_reg_resultant[297 -(30 * i)] ^ shift_reg_resultant[296 - (30 * i)] ^ shift_reg_resultant[295 -(30 * i)] ^ shift_reg_resultant[293 -(30 * i)] ^ shift_reg_resultant[292 -(30 * i)] ^ shift_reg_resultant[288 -(30 * i)] ^ shift_reg_resultant[287 -(30 * i)] ^ shift_reg_resultant[286 -(30 * i)] ^ shift_reg_resultant[285 -(30 * i)] ^ shift_reg_resultant[284 -(30 * i)] ^ shift_reg_resultant[281 -(30 * i)] ^ shift_reg_resultant[280 -(30 * i)] ^ shift_reg_resultant[278 -(30 * i)];
|
|
assign D28[i] = shift_reg_resultant[300 - (30 * i)] ^ shift_reg_resultant[298 - (30 * i)] ^ shift_reg_resultant[296 -(30 * i)] ^ shift_reg_resultant[295 - (30 * i)] ^ shift_reg_resultant[294 -(30 * i)] ^ shift_reg_resultant[292 -(30 * i)] ^ shift_reg_resultant[291 -(30 * i)] ^ shift_reg_resultant[287 -(30 * i)] ^ shift_reg_resultant[286 -(30 * i)] ^ shift_reg_resultant[285 -(30 * i)] ^ shift_reg_resultant[284 -(30 * i)] ^ shift_reg_resultant[283 -(30 * i)] ^ shift_reg_resultant[280 -(30 * i)] ^ shift_reg_resultant[279 -(30 * i)] ^ shift_reg_resultant[277 -(30 * i)];
|
|
assign D29[i] = shift_reg_resultant[300 - (30 * i)] ^ shift_reg_resultant[299 - (30 * i)] ^ shift_reg_resultant[297 -(30 * i)] ^ shift_reg_resultant[295 - (30 * i)] ^ shift_reg_resultant[294 -(30 * i)] ^ shift_reg_resultant[293 -(30 * i)] ^ shift_reg_resultant[291 -(30 * i)] ^ shift_reg_resultant[290 -(30 * i)] ^ shift_reg_resultant[286 -(30 * i)] ^ shift_reg_resultant[285 -(30 * i)] ^ shift_reg_resultant[284 -(30 * i)] ^ shift_reg_resultant[283 -(30 * i)] ^ shift_reg_resultant[282 -(30 * i)] ^ shift_reg_resultant[279 -(30 * i)] ^ shift_reg_resultant[278 -(30 * i)] ^ shift_reg_resultant[276 - (30 * i)];
|
|
assign D30[i] = shift_reg_resultant[301 - (30 * i)] ^ shift_reg_resultant[297 - (30 * i)] ^ shift_reg_resultant[295 -(30 * i)] ^ shift_reg_resultant[294 - (30 * i)] ^ shift_reg_resultant[292 -(30 * i)] ^ shift_reg_resultant[291 -(30 * i)] ^ shift_reg_resultant[290 -(30 * i)] ^ shift_reg_resultant[289 -(30 * i)] ^ shift_reg_resultant[287 -(30 * i)] ^ shift_reg_resultant[285 -(30 * i)] ^ shift_reg_resultant[281 -(30 * i)] ^ shift_reg_resultant[278 -(30 * i)] ^ shift_reg_resultant[277 -(30 * i)] ^ shift_reg_resultant[276 -(30 * i)];
|
|
assign pcw[i] = ({D25[i], D26[i], D27[i], D28[i], D29[i], D30[i]} == shift_reg_resultant[(275 - (i * 30)):(270 - (i * 30))]) ? 1 : 0;
|
|
end : parity_calc
|
|
endgenerate
|
|
|
|
assign load_sigs = ((bit_vld_cc_p[0] && !bit_vld_cc_p[1]) && (&pcw) && (preamble_ok)) ? '1 : '0;
|
|
|
|
|
|
// TODO: intr generation logic will be revised. handle all interrupts individually.
|
|
//assign gps_frame_ready = ((control_reg_p[TRCK_INTRPT_ENABLE_POS] && (!load_sigs_cc_p[1] & load_sigs_cc_p[0])) || (control_reg_p[TRCK_INTRPT_ENABLE_POS] && control_reg_p[TRCK_STOP_ON_UNLOCK_POS] && (timeout_counter_p == (timeout_reg_p - 1)))) ? '1 : '0; // 1 clock cycle delay after internal register update.
|
|
|
|
// Please notice that all if condition signals are 1 cc pulse based on SoC clock. (PCLK)
|
|
always_comb begin : intr_gen_comb_logic
|
|
gps_frame_ready = '0;
|
|
if(control_reg_p[TRCK_INTRPT_ENABLE_POS]) begin // if generic interrupt is enabled.
|
|
// intr due to nav bits ready.
|
|
if((control_reg_p[TRCK_NAV_BITS_INTR_ENABLE_POS]) && (!load_sigs_cc_p[1] & load_sigs_cc_p[0])) begin
|
|
gps_frame_ready = '1;
|
|
end
|
|
// intr due to nav stop on unlock.
|
|
if((control_reg_p[TRCK_STOP_ON_UNLOCK_INTR_EN_POS]) && (timeout_counter_p == (timeout_reg_p - 1))) begin
|
|
gps_frame_ready = '1;
|
|
end
|
|
// intr due to nav solve counter value reach.
|
|
if((control_reg_p[TRCK_NAV_SOLVE_INTR_EN_POS]) & (nav_solve_timer_reached)) begin
|
|
gps_frame_ready = '1;
|
|
end
|
|
// intr due to a coherent 20 ms Doppler/CN0 measurement.
|
|
if(control_reg_p[TRCK_MEASUREMENT_INTR_EN_POS] && measurement_interrupt_pulse) begin
|
|
gps_frame_ready = '1;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
always_comb begin : nav_bit_load_and_intr_flag_comb
|
|
// internal interrupt flags.
|
|
intr_pending_n = intr_pending_p;
|
|
trck_timeout_flag_n = trck_timeout_flag_p; // (all internal clear signals are tied to generic int_clear signal)
|
|
trck_nav_bit_rcv_flag_n = trck_nav_bit_rcv_flag_p;
|
|
trck_nav_solve_flag_n = trck_nav_solve_flag_p;
|
|
trck_measurement_flag_n = trck_measurement_flag_p;
|
|
foreach(nav_bit_read_reg_n[i])
|
|
nav_bit_read_reg_n[i] = nav_bit_read_reg_p[i];
|
|
|
|
// load navigation bit registers.
|
|
if(load_sigs) begin
|
|
foreach(nav_bit_read_reg_n[i])
|
|
nav_bit_read_reg_n[i] = shift_reg_resultant[(((i + 1) * 30) - 1)-:30];
|
|
|
|
if(control_reg_p[TRCK_NAV_BITS_FLAG_ENABLE_POS]) trck_nav_bit_rcv_flag_n = '1;
|
|
if(control_reg_p[TRCK_INTRPT_ENABLE_POS] && control_reg_p[TRCK_NAV_BITS_INTR_ENABLE_POS]) intr_pending_n = '1;
|
|
end
|
|
|
|
// tracking stop generic interrupt pending flag set.
|
|
if(timeout_counter_p == (timeout_reg_p - 1)) begin
|
|
|
|
if(control_reg_p[TRCK_STOP_ON_UNLOCK_FLAG_EN_POS]) trck_timeout_flag_n = '1;
|
|
if(control_reg_p[TRCK_INTRPT_ENABLE_POS] && control_reg_p[TRCK_STOP_ON_UNLOCK_INTR_EN_POS]) intr_pending_n = '1;
|
|
end
|
|
|
|
if(nav_solve_timer_reached) begin
|
|
if(control_reg_p[TRCK_NAV_SOLVE_FLAG_EN_POS]) trck_nav_solve_flag_n = '1;
|
|
if(control_reg_p[TRCK_INTRPT_ENABLE_POS] && control_reg_p[TRCK_NAV_SOLVE_INTR_EN_POS]) intr_pending_n = '1;
|
|
end
|
|
|
|
if(measurement_capture) begin
|
|
if(control_reg_p[TRCK_MEASUREMENT_FLAG_EN_POS])
|
|
trck_measurement_flag_n = '1;
|
|
if(control_reg_p[TRCK_INTRPT_ENABLE_POS] &&
|
|
control_reg_p[TRCK_MEASUREMENT_INTR_EN_POS])
|
|
intr_pending_n = '1;
|
|
end
|
|
|
|
// generic clear all interrupt pending flag and other flags.
|
|
if(intr_clear) begin // all internal flag clear
|
|
intr_pending_n = '0;
|
|
trck_timeout_flag_n = '0;
|
|
trck_nav_bit_rcv_flag_n = '0;
|
|
trck_nav_solve_flag_n = '0;
|
|
trck_measurement_flag_n = '0;
|
|
end
|
|
end : nav_bit_load_and_intr_flag_comb
|
|
|
|
|
|
// navitation solution period timer
|
|
nav_solve_timer i_nav_solve_timer(
|
|
.clk(PCLK), // clock.
|
|
.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.
|
|
.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.
|
|
.trck_busy(busy_syned), // stop counting when tracking is unlocked or do not start to count anyways.
|
|
.phase_seed_arm(control_reg_p[TRCK_NAV_SOLVE_SEED_ARM_POS]), // firmware warm-start phase estimate is pending.
|
|
.phase_seed_value(nav_solve_phase_seed_reg_p), // navigation-bit phase, already reduced modulo counter_max_val.
|
|
// output from module.
|
|
.phase_seed_consumed(nav_solve_phase_seed_consumed), // timer answered the seed; clears the arm bit.
|
|
.nav_solve_provisional(nav_solve_provisional), // epochs are running on an unconfirmed seed.
|
|
.nav_solve_timer_reached(nav_solve_timer_reached), // timer internal count is equal to predefined count value. (status flag) asserted 1 clock cycle. INTERRUPT SIGNAL TO CPU FROM TIMER TODO: will be integrated to main interrupt generation mechanishm.
|
|
.load_abs_sample(nav_solve_timer_load_abs_sample_signal) // when counter reaches to predefined value, trigger 1 clock cycle wide abs. sample load signal.
|
|
);
|
|
|
|
// reg r & w com. logic
|
|
always_comb begin : apb_register_write_read_comb
|
|
PRDATA = '0;
|
|
PSLVERR = '0;
|
|
|
|
start_trck = '0;
|
|
stop_trck = '0;
|
|
intr_clear = '0;
|
|
//clear_timeout_stop_sig = '0;
|
|
//trck_reset = '0;
|
|
code_phase_reg_n = code_phase_reg_p;
|
|
doppler_reg_n = doppler_reg_p;
|
|
prn_no_reg_n = prn_no_reg_p;
|
|
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_seed_reg_n = nav_solve_phase_seed_reg_p;
|
|
|
|
if(apb_bus_ps == APB_STATE_SEL) begin
|
|
if(PWRITE) begin // write to register
|
|
case(PADDR)
|
|
(LOW_ADDRESS + CONTROL_REG_OFFSET):
|
|
begin
|
|
if(PWDATA[TRCK_START_POS]) start_trck = '1;
|
|
if(PWDATA[TRCK_STOP_POS]) stop_trck = '1;
|
|
//if(PWDATA[TRCK_RESET_POS]) trck_reset = '1;
|
|
if(PWDATA[TRCK_INTRPT_ENABLE_POS]) control_reg_n[TRCK_INTRPT_ENABLE_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_INTRPT_ENABLE_POS]) control_reg_n[TRCK_INTRPT_ENABLE_POS] = 1'b0;
|
|
if(PWDATA[TRCK_INTRPT_CLEAR_POS]) intr_clear = '1;
|
|
if(PWDATA[TRCK_STOP_ON_UNLOCK_EN_POS]) control_reg_n[TRCK_STOP_ON_UNLOCK_EN_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_STOP_ON_UNLOCK_EN_POS]) control_reg_n[TRCK_STOP_ON_UNLOCK_EN_POS] = 1'b0;
|
|
if(PWDATA[TRCK_STOP_ON_UNLOCK_INTR_EN_POS]) control_reg_n[TRCK_STOP_ON_UNLOCK_INTR_EN_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_STOP_ON_UNLOCK_INTR_EN_POS]) control_reg_n[TRCK_STOP_ON_UNLOCK_INTR_EN_POS] = 1'b0;
|
|
if(PWDATA[TRCK_NAV_SOLVE_ENABLE_POS]) control_reg_n[TRCK_NAV_SOLVE_ENABLE_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_NAV_SOLVE_ENABLE_POS]) control_reg_n[TRCK_NAV_SOLVE_ENABLE_POS] = 1'b0;
|
|
if(PWDATA[TRCK_NAV_SOLVE_INTR_EN_POS]) control_reg_n[TRCK_NAV_SOLVE_INTR_EN_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_NAV_SOLVE_INTR_EN_POS]) control_reg_n[TRCK_NAV_SOLVE_INTR_EN_POS] = 1'b0;
|
|
if(PWDATA[TRCK_NAV_BITS_INTR_ENABLE_POS]) control_reg_n[TRCK_NAV_BITS_INTR_ENABLE_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_NAV_BITS_INTR_ENABLE_POS]) control_reg_n[TRCK_NAV_BITS_INTR_ENABLE_POS] = 1'b0;
|
|
|
|
if(PWDATA[TRCK_NAV_BITS_FLAG_ENABLE_POS]) control_reg_n[TRCK_NAV_BITS_FLAG_ENABLE_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_NAV_BITS_FLAG_ENABLE_POS]) control_reg_n[TRCK_NAV_BITS_FLAG_ENABLE_POS] = 1'b0;
|
|
|
|
if(PWDATA[TRCK_STOP_ON_UNLOCK_FLAG_EN_POS]) control_reg_n[TRCK_STOP_ON_UNLOCK_FLAG_EN_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_STOP_ON_UNLOCK_FLAG_EN_POS]) control_reg_n[TRCK_STOP_ON_UNLOCK_FLAG_EN_POS] = 1'b0;
|
|
|
|
if(PWDATA[TRCK_NAV_SOLVE_FLAG_EN_POS]) control_reg_n[TRCK_NAV_SOLVE_FLAG_EN_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_NAV_SOLVE_FLAG_EN_POS]) control_reg_n[TRCK_NAV_SOLVE_FLAG_EN_POS] = 1'b0;
|
|
if(PWDATA[TRCK_MEASUREMENT_INTR_EN_POS]) control_reg_n[TRCK_MEASUREMENT_INTR_EN_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_MEASUREMENT_INTR_EN_POS]) control_reg_n[TRCK_MEASUREMENT_INTR_EN_POS] = 1'b0;
|
|
if(PWDATA[TRCK_MEASUREMENT_FLAG_EN_POS]) control_reg_n[TRCK_MEASUREMENT_FLAG_EN_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_MEASUREMENT_FLAG_EN_POS]) control_reg_n[TRCK_MEASUREMENT_FLAG_EN_POS] = 1'b0;
|
|
if(PWDATA[TRCK_NAV_SOLVE_SEED_ARM_POS]) control_reg_n[TRCK_NAV_SOLVE_SEED_ARM_POS] = 1'b1;
|
|
if(!PWDATA[TRCK_NAV_SOLVE_SEED_ARM_POS]) control_reg_n[TRCK_NAV_SOLVE_SEED_ARM_POS] = 1'b0;
|
|
end
|
|
(LOW_ADDRESS + PRN_NUMBER_REG_OFFSET):
|
|
begin
|
|
prn_no_reg_n = PWDATA;
|
|
end
|
|
|
|
(LOW_ADDRESS + CODE_PHASE_REG_OFFSET):
|
|
begin
|
|
code_phase_reg_n = PWDATA;
|
|
end
|
|
|
|
(LOW_ADDRESS + DOPPLER_REG_OFFSET):
|
|
begin
|
|
doppler_reg_n = PWDATA;
|
|
end
|
|
|
|
(LOW_ADDRESS + TRCK_TIMEOUT_REG_OFFSET):
|
|
begin
|
|
timeout_reg_n = PWDATA;
|
|
end
|
|
(LOW_ADDRESS + NAV_SOLVE_TIMER_REG_OFFSET):
|
|
begin
|
|
nav_solve_timer_reg_n = PWDATA;
|
|
end
|
|
(LOW_ADDRESS + NAV_SOLVE_PHASE_SEED_REG_OFFSET):
|
|
begin
|
|
nav_solve_phase_seed_reg_n = PWDATA;
|
|
end
|
|
|
|
|
|
default:
|
|
begin
|
|
PSLVERR = '1;
|
|
end
|
|
endcase
|
|
end
|
|
else if(!PWRITE) begin
|
|
case(PADDR)
|
|
(LOW_ADDRESS + CONTROL_REG_OFFSET):
|
|
begin
|
|
PRDATA = 32'(
|
|
(control_reg_p[TRCK_INTRPT_ENABLE_POS] << trck_pkg::TRCK_INTRPT_ENABLE_POS) |
|
|
(control_reg_p[TRCK_NAV_BITS_INTR_ENABLE_POS] << trck_pkg::TRCK_NAV_BITS_INTR_ENABLE_POS) |
|
|
(control_reg_p[TRCK_STOP_ON_UNLOCK_EN_POS] << trck_pkg::TRCK_STOP_ON_UNLOCK_EN_POS) |
|
|
(control_reg_p[TRCK_STOP_ON_UNLOCK_INTR_EN_POS] << trck_pkg::TRCK_STOP_ON_UNLOCK_INTR_EN_POS) |
|
|
(control_reg_p[TRCK_NAV_SOLVE_ENABLE_POS] << trck_pkg::TRCK_NAV_SOLVE_ENABLE_POS) |
|
|
(control_reg_p[TRCK_NAV_SOLVE_INTR_EN_POS] << trck_pkg::TRCK_NAV_SOLVE_INTR_EN_POS) |
|
|
(control_reg_p[TRCK_NAV_BITS_FLAG_ENABLE_POS] << trck_pkg::TRCK_NAV_BITS_FLAG_ENABLE_POS) |
|
|
(control_reg_p[TRCK_STOP_ON_UNLOCK_FLAG_EN_POS] << trck_pkg::TRCK_STOP_ON_UNLOCK_FLAG_EN_POS) |
|
|
(control_reg_p[TRCK_NAV_SOLVE_FLAG_EN_POS] << trck_pkg::TRCK_NAV_SOLVE_FLAG_EN_POS) |
|
|
(control_reg_p[TRCK_MEASUREMENT_INTR_EN_POS] << trck_pkg::TRCK_MEASUREMENT_INTR_EN_POS) |
|
|
(control_reg_p[TRCK_MEASUREMENT_FLAG_EN_POS] << trck_pkg::TRCK_MEASUREMENT_FLAG_EN_POS) |
|
|
(control_reg_p[TRCK_NAV_SOLVE_SEED_ARM_POS] << trck_pkg::TRCK_NAV_SOLVE_SEED_ARM_POS)
|
|
);
|
|
end
|
|
(LOW_ADDRESS + STATUS_REG_OFFSET):
|
|
begin
|
|
PRDATA = 32'(
|
|
(busy_syned << TRCK_BUSY_POS) |
|
|
(lock_syned << TRCK_LOCKED_POS) |
|
|
(0 << TRCK_FIFO_OV_POS) | // fifo overflow is not considered for now.
|
|
(intr_pending_p << TRCK_INTR_PEND_POS) |
|
|
(trck_timeout_flag_p << TRCK_UNLOCK_FLAG_POS) |
|
|
(trck_nav_bit_rcv_flag_p << TRCK_NAV_BITS_RCV_FLAG_POS) |
|
|
(trck_nav_solve_flag_p << TRCK_NAV_SOLVE_FLAG_POS) |
|
|
(trck_measurement_flag_p << TRCK_MEASUREMENT_FLAG_POS) |
|
|
(nav_solve_provisional << TRCK_NAV_SOLVE_PROVISIONAL_POS)
|
|
);
|
|
|
|
end
|
|
(LOW_ADDRESS + PRN_NUMBER_REG_OFFSET):
|
|
begin
|
|
PRDATA = prn_no_reg_p;
|
|
end
|
|
(LOW_ADDRESS + CODE_PHASE_REG_OFFSET):
|
|
begin
|
|
PRDATA = code_phase_reg_p;
|
|
end
|
|
|
|
(LOW_ADDRESS + ABS_SAMPLE_REG_OFFSET):
|
|
begin
|
|
PRDATA = abs_sample_reg_p;
|
|
end
|
|
|
|
(LOW_ADDRESS + DOPPLER_REG_OFFSET):
|
|
begin
|
|
PRDATA = doppler_reg_p;
|
|
end
|
|
|
|
(LOW_ADDRESS + NAV_DATA_0_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[0]};
|
|
end
|
|
|
|
(LOW_ADDRESS + NAV_DATA_1_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[1]};
|
|
end
|
|
|
|
(LOW_ADDRESS + NAV_DATA_2_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[2]};
|
|
end
|
|
|
|
(LOW_ADDRESS + NAV_DATA_3_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[3]};
|
|
end
|
|
|
|
(LOW_ADDRESS + NAV_DATA_4_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[4]};
|
|
end
|
|
|
|
(LOW_ADDRESS + NAV_DATA_5_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[5]};
|
|
end
|
|
(LOW_ADDRESS + NAV_DATA_6_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[6]};
|
|
end
|
|
(LOW_ADDRESS + NAV_DATA_7_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[7]};
|
|
end
|
|
(LOW_ADDRESS + NAV_DATA_8_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[8]};
|
|
end
|
|
(LOW_ADDRESS + NAV_DATA_9_REG_OFFSET):
|
|
begin
|
|
PRDATA = {2'b00, nav_bit_read_reg_p[9]};
|
|
end
|
|
(LOW_ADDRESS + TRCK_TIMEOUT_REG_OFFSET):
|
|
begin
|
|
PRDATA = timeout_reg_p;
|
|
end
|
|
(LOW_ADDRESS + NAV_SOLVE_TIMER_REG_OFFSET):
|
|
begin
|
|
PRDATA = nav_solve_timer_reg_p;
|
|
end
|
|
(LOW_ADDRESS + NAV_SOLVE_PHASE_SEED_REG_OFFSET):
|
|
begin
|
|
PRDATA = nav_solve_phase_seed_reg_p;
|
|
end
|
|
(LOW_ADDRESS + REM_CODE_PH_REG_OFFSET):
|
|
begin
|
|
//PRDATA = rem_code_ph_reg_p;
|
|
PRDATA = {{(32-REM_CODE_PH_I_WL){1'b0}}, rem_code_ph_reg_p};
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_META_REG_OFFSET):
|
|
begin
|
|
PRDATA = {
|
|
8'h01,
|
|
11'b0,
|
|
measurement_cn0_sample_count_reg,
|
|
5'b0,
|
|
measurement_lock_reg,
|
|
measurement_bit_reg,
|
|
measurement_data_valid_reg
|
|
};
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_SEQUENCE_REG_OFFSET):
|
|
begin
|
|
PRDATA = {16'b0, measurement_sequence_reg};
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_CARRIER_REG_OFFSET):
|
|
begin
|
|
PRDATA = {{(32-MEAS_CARRIER_WL){
|
|
measurement_carrier_freq_q7_reg[MEAS_CARRIER_WL-1]}},
|
|
measurement_carrier_freq_q7_reg};
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_ABS_SAMPLE_REG_OFFSET):
|
|
begin
|
|
PRDATA = measurement_abs_sample_reg;
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_REM_CODE_REG_OFFSET):
|
|
begin
|
|
PRDATA = {{(32-REM_CODE_PH_I_WL){1'b0}},
|
|
measurement_rem_code_ph_reg};
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_SUM_I_REG_OFFSET):
|
|
begin
|
|
PRDATA = {{(32-MEAS_SUM_WL){
|
|
measurement_cn0_sum_i_reg[MEAS_SUM_WL-1]}},
|
|
measurement_cn0_sum_i_reg};
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_SUM_Q_REG_OFFSET):
|
|
begin
|
|
PRDATA = {{(32-MEAS_SUM_WL){
|
|
measurement_cn0_sum_q_reg[MEAS_SUM_WL-1]}},
|
|
measurement_cn0_sum_q_reg};
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_WBP_LO_REG_OFFSET):
|
|
begin
|
|
PRDATA = measurement_cn0_wbp_reg[31:0];
|
|
end
|
|
(LOW_ADDRESS + MEASUREMENT_WBP_HI_REG_OFFSET):
|
|
begin
|
|
PRDATA = {{(64-MEAS_WBP_WL){1'b0}},
|
|
measurement_cn0_wbp_reg[MEAS_WBP_WL-1:32]};
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
/* The timer answers an armed seed in one cycle and in every state, so
|
|
* clearing the arm bit here cannot race an APB write: firmware can only
|
|
* observe the bit set on the cycle after its own write, and consumption
|
|
* requires the bit to already be registered. Applying the clear after
|
|
* the decode keeps it authoritative. */
|
|
if(nav_solve_phase_seed_consumed) begin
|
|
control_reg_n[TRCK_NAV_SOLVE_SEED_ARM_POS] = 1'b0;
|
|
end
|
|
end : apb_register_write_read_comb
|
|
endmodule
|