feat(gps): expose Doppler and signal quality measurements
This commit is contained in:
+247
-16
@@ -40,6 +40,14 @@ module tracking_wrapper #(
|
||||
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
|
||||
@@ -70,6 +78,22 @@ module tracking_wrapper #(
|
||||
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 )
|
||||
@@ -77,6 +101,7 @@ module tracking_wrapper #(
|
||||
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
|
||||
|
||||
@@ -94,6 +119,24 @@ module tracking_wrapper #(
|
||||
logic [31 : 0] nav_solve_timer_reg_p, nav_solve_timer_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;
|
||||
@@ -152,11 +195,55 @@ module tracking_wrapper #(
|
||||
.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(PRESETN),
|
||||
.afe_rstn(PRESETN),
|
||||
.trk_rstn(trck_resetn),
|
||||
.afe_rstn(afe_resetn),
|
||||
.trk_clk(trck_clk),
|
||||
.afe_clk(afe_clk),
|
||||
.sample_align_i(sample_align), // from afe
|
||||
@@ -173,15 +260,83 @@ module tracking_wrapper #(
|
||||
// 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),
|
||||
.lock_o(lock),
|
||||
.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
|
||||
|
||||
|
||||
|
||||
@@ -214,11 +369,13 @@ module tracking_wrapper #(
|
||||
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;
|
||||
@@ -244,6 +401,7 @@ module tracking_wrapper #(
|
||||
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
|
||||
@@ -409,6 +567,10 @@ module tracking_wrapper #(
|
||||
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
|
||||
|
||||
@@ -419,6 +581,7 @@ module tracking_wrapper #(
|
||||
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];
|
||||
|
||||
@@ -443,12 +606,21 @@ module tracking_wrapper #(
|
||||
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
|
||||
|
||||
@@ -515,6 +687,10 @@ module tracking_wrapper #(
|
||||
|
||||
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;
|
||||
end
|
||||
(LOW_ADDRESS + PRN_NUMBER_REG_OFFSET):
|
||||
begin
|
||||
@@ -560,20 +736,23 @@ module tracking_wrapper #(
|
||||
(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_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)
|
||||
);
|
||||
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)
|
||||
);
|
||||
(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)
|
||||
);
|
||||
|
||||
end
|
||||
(LOW_ADDRESS + PRN_NUMBER_REG_OFFSET):
|
||||
@@ -653,6 +832,58 @@ module tracking_wrapper #(
|
||||
//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
|
||||
|
||||
+15
-3
@@ -21,7 +21,16 @@ package trck_pkg;
|
||||
NAV_DATA_9_REG_OFFSET = 60,
|
||||
TRCK_TIMEOUT_REG_OFFSET = 64,
|
||||
NAV_SOLVE_TIMER_REG_OFFSET = 68,
|
||||
REM_CODE_PH_REG_OFFSET = 76
|
||||
REM_CODE_PH_REG_OFFSET = 76,
|
||||
MEASUREMENT_META_REG_OFFSET = 80,
|
||||
MEASUREMENT_SEQUENCE_REG_OFFSET = 84,
|
||||
MEASUREMENT_CARRIER_REG_OFFSET = 88,
|
||||
MEASUREMENT_ABS_SAMPLE_REG_OFFSET = 92,
|
||||
MEASUREMENT_REM_CODE_REG_OFFSET = 96,
|
||||
MEASUREMENT_SUM_I_REG_OFFSET = 100,
|
||||
MEASUREMENT_SUM_Q_REG_OFFSET = 104,
|
||||
MEASUREMENT_WBP_LO_REG_OFFSET = 108,
|
||||
MEASUREMENT_WBP_HI_REG_OFFSET = 112
|
||||
}trck_wrapper_reg_offets_e;
|
||||
|
||||
|
||||
@@ -39,7 +48,9 @@ package trck_pkg;
|
||||
TRCK_STOP_ON_UNLOCK_FLAG_EN_POS = 9, // enable pos.
|
||||
TRCK_NAV_SOLVE_ENABLE_POS = 10, // clear pos
|
||||
TRCK_NAV_SOLVE_INTR_EN_POS = 11, // clear pos
|
||||
TRCK_NAV_SOLVE_FLAG_EN_POS = 12 // clear pos
|
||||
TRCK_NAV_SOLVE_FLAG_EN_POS = 12, // clear pos
|
||||
TRCK_MEASUREMENT_INTR_EN_POS = 13,
|
||||
TRCK_MEASUREMENT_FLAG_EN_POS = 14
|
||||
}trck_control_reg_pos_e;
|
||||
|
||||
typedef enum
|
||||
@@ -50,7 +61,8 @@ package trck_pkg;
|
||||
TRCK_INTR_PEND_POS = 3,
|
||||
TRCK_NAV_BITS_RCV_FLAG_POS = 4,
|
||||
TRCK_UNLOCK_FLAG_POS = 5,
|
||||
TRCK_NAV_SOLVE_FLAG_POS = 6
|
||||
TRCK_NAV_SOLVE_FLAG_POS = 6,
|
||||
TRCK_MEASUREMENT_FLAG_POS = 7
|
||||
}trck_status_reg_pos_e;
|
||||
|
||||
localparam logic [7 : 0] PREAMBLE = 8'b10001011;
|
||||
|
||||
+11
@@ -105,6 +105,17 @@ generate
|
||||
.bit_o (trck_o[ch].bit_o),
|
||||
.bit_vld_o (trck_o[ch].bit_vld),
|
||||
.abs_sample_o (trck_o[ch].abs_sample),
|
||||
.rem_code_ph_o (),
|
||||
.measurement_vld_o (),
|
||||
.measurement_bit_o (),
|
||||
.measurement_abs_sample_o(),
|
||||
.measurement_rem_code_ph_o(),
|
||||
.measurement_carrier_freq_q7_o(),
|
||||
.measurement_cn0_sum_i_o(),
|
||||
.measurement_cn0_sum_q_o(),
|
||||
.measurement_cn0_wbp_o(),
|
||||
.measurement_cn0_sample_count_o(),
|
||||
.measurement_sequence_o(),
|
||||
.fifo_of_o (), //reserved
|
||||
.lock_o (trck_o[ch].lock),
|
||||
.busy_o (trck_o[ch].busy)
|
||||
|
||||
Vendored
+1
@@ -35,6 +35,7 @@ trck_src/cordic_atan_one_stage.sv
|
||||
trck_src/cos2x.sv
|
||||
trck_src/divider.sv
|
||||
trck_src/lock_detector.sv
|
||||
trck_src/tracking_measurement.sv
|
||||
trck_src/trck_cntrl.sv
|
||||
trck_src/trck_top.sv
|
||||
trck_src/xil_fifo.sv
|
||||
|
||||
@@ -34,6 +34,8 @@ module lock_detector #(
|
||||
input logic corr_vld_i,
|
||||
input logic signed [IN_WL-1 : 0] i_p_i,
|
||||
input logic signed [IN_WL-1 : 0] q_p_i,
|
||||
output logic prompt_energy_vld_o,
|
||||
output logic [(2 * IN_WL):0] prompt_energy_o,
|
||||
output logic lock_o
|
||||
);
|
||||
localparam DIV_OUT_IL = DIV_OUT_WL - DIV_OUT_FL;
|
||||
@@ -64,6 +66,8 @@ logic lock_decision_bad;
|
||||
assign i_prompt_abs = i_p_i[IN_WL-1] ? (~i_p_i + {{(IN_WL-1){1'b0}}, 1'b1}) : i_p_i;
|
||||
assign q_prompt_abs = q_p_i[IN_WL-1] ? (~q_p_i + {{(IN_WL-1){1'b0}}, 1'b1}) : q_p_i;
|
||||
assign prompt_energy_sum = {1'b0, i_prompt_energy_r} + {1'b0, q_prompt_energy_r};
|
||||
assign prompt_energy_vld_o = prompt_energy_vld;
|
||||
assign prompt_energy_o = prompt_energy_sum;
|
||||
|
||||
cos2x #(
|
||||
.IN_WL (IN_WL),
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
QUESTA_VLOG ?= vlog
|
||||
QUESTA_VSIM ?= vsim
|
||||
QUESTA_RUN_DIR ?= /tmp/gps_tracking_measurement_questa
|
||||
|
||||
RTL_DIR := $(abspath ../..)
|
||||
|
||||
.PHONY: test clean
|
||||
|
||||
test:
|
||||
rm -rf $(QUESTA_RUN_DIR)
|
||||
mkdir -p $(QUESTA_RUN_DIR)
|
||||
cd $(QUESTA_RUN_DIR) && vlib work
|
||||
cd $(RTL_DIR) && $(QUESTA_VLOG) -sv -work $(QUESTA_RUN_DIR)/work \
|
||||
-f filelist.f \
|
||||
$(CURDIR)/lock_detector_energy_tb.sv \
|
||||
$(CURDIR)/tracking_measurement_tb.sv \
|
||||
$(CURDIR)/tracking_wrapper_measurement_tb.sv
|
||||
cd $(QUESTA_RUN_DIR) && $(QUESTA_VSIM) -c tracking_measurement_tb \
|
||||
-do 'run -all; quit -f'
|
||||
cd $(QUESTA_RUN_DIR) && $(QUESTA_VSIM) -c lock_detector_energy_tb \
|
||||
-do 'run -all; quit -f'
|
||||
cd $(QUESTA_RUN_DIR) && $(QUESTA_VSIM) -c tracking_wrapper_measurement_tb \
|
||||
-do 'run -all; quit -f'
|
||||
|
||||
clean:
|
||||
rm -rf $(QUESTA_RUN_DIR)
|
||||
@@ -0,0 +1,54 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
import definitions::*;
|
||||
|
||||
module lock_detector_energy_tb;
|
||||
logic clk = 1'b0;
|
||||
logic rstn = 1'b0;
|
||||
logic corr_valid = 1'b0;
|
||||
logic signed [TRCK_CORR_WL-1:0] i_prompt = '0;
|
||||
logic signed [TRCK_CORR_WL-1:0] q_prompt = '0;
|
||||
logic energy_valid;
|
||||
logic [(2*TRCK_CORR_WL):0] energy;
|
||||
logic lock;
|
||||
|
||||
always #4 clk = ~clk;
|
||||
|
||||
lock_detector #(
|
||||
.IN_WL(TRCK_CORR_WL),
|
||||
.IN_FL(TRCK_CORR_FL),
|
||||
.DIV_OUT_WL(LOCK_DET_DIV_O_WL),
|
||||
.DIV_OUT_FL(LOCK_DET_DIV_O_FL),
|
||||
.DIV_ITER(14)
|
||||
) dut (
|
||||
.rstn,
|
||||
.clk,
|
||||
.corr_vld_i(corr_valid),
|
||||
.i_p_i(i_prompt),
|
||||
.q_p_i(q_prompt),
|
||||
.prompt_energy_vld_o(energy_valid),
|
||||
.prompt_energy_o(energy),
|
||||
.lock_o(lock)
|
||||
);
|
||||
|
||||
initial begin
|
||||
repeat(4) @(posedge clk);
|
||||
rstn = 1'b1;
|
||||
repeat(2) @(posedge clk);
|
||||
|
||||
i_prompt = -22'sd1234;
|
||||
q_prompt = 22'sd567;
|
||||
corr_valid = 1'b1;
|
||||
@(posedge clk);
|
||||
corr_valid = 1'b0;
|
||||
|
||||
wait(energy_valid);
|
||||
#1;
|
||||
if(energy !== ((1234 * 1234) + (567 * 567)))
|
||||
$fatal(1, "prompt energy mismatch: got=%0d expected=%0d",
|
||||
energy, ((1234 * 1234) + (567 * 567)));
|
||||
|
||||
$display("lock_detector_energy_tb PASS");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,185 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
import definitions::*;
|
||||
|
||||
module tracking_measurement_tb;
|
||||
localparam int SUM_WL = TRCK_CORR_WL + $clog2(MS_PER_BIT);
|
||||
localparam int WBP_WL = (2 * TRCK_CORR_WL) + 1 + $clog2(MS_PER_BIT);
|
||||
localparam int COUNT_WL = $clog2(MS_PER_BIT + 1);
|
||||
localparam int CARRIER_WL = ACQUIRED_FREQ_IL + TRCK_CARR_NCO_FREQ_FL;
|
||||
|
||||
logic clk = 1'b0;
|
||||
logic rstn = 1'b0;
|
||||
logic bit_valid = 1'b0;
|
||||
logic nav_bit = 1'b0;
|
||||
logic [ABS_SAMPLE_CNTR_WL-1:0] absolute_sample = '0;
|
||||
logic [REM_CODE_PH_I_WL-1:0] rem_code_phase = '0;
|
||||
logic signed [CARRIER_WL-1:0] carrier_freq_q7 = '0;
|
||||
logic corr_valid = 1'b0;
|
||||
logic signed [TRCK_CORR_WL-1:0] i_prompt = '0;
|
||||
logic signed [TRCK_CORR_WL-1:0] q_prompt = '0;
|
||||
logic prompt_energy_valid = 1'b0;
|
||||
logic [(2*TRCK_CORR_WL):0] prompt_energy = '0;
|
||||
|
||||
logic measurement_valid;
|
||||
logic measurement_bit;
|
||||
logic [ABS_SAMPLE_CNTR_WL-1:0] measurement_abs_sample;
|
||||
logic [REM_CODE_PH_I_WL-1:0] measurement_rem_code_phase;
|
||||
logic signed [CARRIER_WL-1:0] measurement_carrier_freq_q7;
|
||||
logic signed [SUM_WL-1:0] cn0_sum_i;
|
||||
logic signed [SUM_WL-1:0] cn0_sum_q;
|
||||
logic [WBP_WL-1:0] cn0_wbp;
|
||||
logic [COUNT_WL-1:0] cn0_sample_count;
|
||||
logic [15:0] sequence_value;
|
||||
|
||||
integer expected_sum_i;
|
||||
integer expected_sum_q;
|
||||
longint unsigned expected_wbp;
|
||||
|
||||
always #4 clk = ~clk;
|
||||
|
||||
tracking_measurement dut (
|
||||
.clk,
|
||||
.rstn,
|
||||
.bit_valid_i(bit_valid),
|
||||
.nav_bit_i(nav_bit),
|
||||
.absolute_sample_i(absolute_sample),
|
||||
.rem_code_phase_i(rem_code_phase),
|
||||
.carrier_freq_q7_i(carrier_freq_q7),
|
||||
.corr_valid_i(corr_valid),
|
||||
.i_prompt_i(i_prompt),
|
||||
.q_prompt_i(q_prompt),
|
||||
.prompt_energy_valid_i(prompt_energy_valid),
|
||||
.prompt_energy_i(prompt_energy),
|
||||
.measurement_valid_o(measurement_valid),
|
||||
.nav_bit_o(measurement_bit),
|
||||
.absolute_sample_o(measurement_abs_sample),
|
||||
.rem_code_phase_o(measurement_rem_code_phase),
|
||||
.carrier_freq_q7_o(measurement_carrier_freq_q7),
|
||||
.cn0_sum_i_o(cn0_sum_i),
|
||||
.cn0_sum_q_o(cn0_sum_q),
|
||||
.cn0_wbp_o(cn0_wbp),
|
||||
.cn0_sample_count_o(cn0_sample_count),
|
||||
.sequence_o(sequence_value)
|
||||
);
|
||||
|
||||
task automatic clock_cycles(input int unsigned count);
|
||||
repeat(count) @(posedge clk);
|
||||
endtask
|
||||
|
||||
task automatic pulse_bit_epoch(input logic value);
|
||||
nav_bit = value;
|
||||
bit_valid = 1'b1;
|
||||
clock_cycles(12);
|
||||
bit_valid = 1'b0;
|
||||
clock_cycles(3);
|
||||
endtask
|
||||
|
||||
task automatic add_prompt(input integer i_value, input integer q_value);
|
||||
longint unsigned energy;
|
||||
energy = (i_value * i_value) + (q_value * q_value);
|
||||
i_prompt = i_value;
|
||||
q_prompt = q_value;
|
||||
corr_valid = 1'b1;
|
||||
@(posedge clk);
|
||||
corr_valid = 1'b0;
|
||||
@(posedge clk);
|
||||
prompt_energy = energy;
|
||||
prompt_energy_valid = 1'b1;
|
||||
@(posedge clk);
|
||||
prompt_energy_valid = 1'b0;
|
||||
@(posedge clk);
|
||||
expected_sum_i += i_value;
|
||||
expected_sum_q += q_value;
|
||||
expected_wbp += energy;
|
||||
endtask
|
||||
|
||||
task automatic check_measurement(
|
||||
input logic expected_bit,
|
||||
input logic [31:0] expected_abs,
|
||||
input logic [REM_CODE_PH_I_WL-1:0] expected_rem,
|
||||
input logic signed [CARRIER_WL-1:0] expected_carrier,
|
||||
input logic [15:0] expected_sequence);
|
||||
if(!measurement_valid)
|
||||
$fatal(1, "measurement valid did not remain high");
|
||||
if(measurement_bit !== expected_bit)
|
||||
$fatal(1, "NAV bit mismatch");
|
||||
if(measurement_abs_sample !== expected_abs)
|
||||
$fatal(1, "absolute sample mismatch");
|
||||
if(measurement_rem_code_phase !== expected_rem)
|
||||
$fatal(1, "remaining code phase mismatch");
|
||||
if(measurement_carrier_freq_q7 !== expected_carrier)
|
||||
$fatal(1, "carrier Q7 mismatch: got=%0d expected=%0d",
|
||||
measurement_carrier_freq_q7, expected_carrier);
|
||||
if($signed(cn0_sum_i) !== expected_sum_i)
|
||||
$fatal(1, "sum I mismatch: got=%0d expected=%0d",
|
||||
$signed(cn0_sum_i), expected_sum_i);
|
||||
if($signed(cn0_sum_q) !== expected_sum_q)
|
||||
$fatal(1, "sum Q mismatch: got=%0d expected=%0d",
|
||||
$signed(cn0_sum_q), expected_sum_q);
|
||||
if(cn0_wbp !== expected_wbp)
|
||||
$fatal(1, "WBP mismatch: got=%0d expected=%0d", cn0_wbp, expected_wbp);
|
||||
if(cn0_sample_count !== MS_PER_BIT)
|
||||
$fatal(1, "sample count mismatch: got=%0d", cn0_sample_count);
|
||||
if(sequence_value !== expected_sequence)
|
||||
$fatal(1, "sequence mismatch: got=%0d expected=%0d",
|
||||
sequence_value, expected_sequence);
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
clock_cycles(4);
|
||||
rstn = 1'b1;
|
||||
clock_cycles(2);
|
||||
|
||||
/* First edge only establishes the 20 ms integration phase. */
|
||||
pulse_bit_epoch(1'b0);
|
||||
|
||||
expected_sum_i = 0;
|
||||
expected_sum_q = 0;
|
||||
expected_wbp = 0;
|
||||
for(integer i = 0; i < MS_PER_BIT; i++) begin
|
||||
add_prompt(100 + i, -20 + i);
|
||||
end
|
||||
|
||||
nav_bit = 1'b1;
|
||||
absolute_sample = 32'h1234_5678;
|
||||
rem_code_phase = REM_CODE_PH_I_WL'(321);
|
||||
carrier_freq_q7 = CARRIER_WL'((CENTER_FREQ + 1250) * 128);
|
||||
bit_valid = 1'b1;
|
||||
clock_cycles(10);
|
||||
check_measurement(
|
||||
1'b1, 32'h1234_5678, REM_CODE_PH_I_WL'(321),
|
||||
CARRIER_WL'((CENTER_FREQ + 1250) * 128), 16'd1);
|
||||
|
||||
/* Payload inputs may move; the registered measurement must not. */
|
||||
carrier_freq_q7 = CARRIER_WL'((CENTER_FREQ - 3000) * 128);
|
||||
absolute_sample = 32'hffff_0000;
|
||||
clock_cycles(5);
|
||||
check_measurement(
|
||||
1'b1, 32'h1234_5678, REM_CODE_PH_I_WL'(321),
|
||||
CARRIER_WL'((CENTER_FREQ + 1250) * 128), 16'd1);
|
||||
bit_valid = 1'b0;
|
||||
clock_cycles(3);
|
||||
if(measurement_valid)
|
||||
$fatal(1, "measurement valid failed to deassert");
|
||||
|
||||
expected_sum_i = 0;
|
||||
expected_sum_q = 0;
|
||||
expected_wbp = 0;
|
||||
for(integer j = 0; j < MS_PER_BIT; j++) begin
|
||||
add_prompt(-50, 25);
|
||||
end
|
||||
nav_bit = 1'b0;
|
||||
absolute_sample = 32'h2345_6789;
|
||||
rem_code_phase = REM_CODE_PH_I_WL'(777);
|
||||
carrier_freq_q7 = CARRIER_WL'((CENTER_FREQ - 3000) * 128);
|
||||
bit_valid = 1'b1;
|
||||
clock_cycles(10);
|
||||
check_measurement(
|
||||
1'b0, 32'h2345_6789, REM_CODE_PH_I_WL'(777),
|
||||
CARRIER_WL'((CENTER_FREQ - 3000) * 128), 16'd2);
|
||||
|
||||
$display("tracking_measurement_tb PASS");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,172 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
import definitions::*;
|
||||
import trck_pkg::*;
|
||||
|
||||
module tracking_wrapper_measurement_tb;
|
||||
localparam int CARRIER_WL = ACQUIRED_FREQ_IL + TRCK_CARR_NCO_FREQ_FL;
|
||||
localparam int SUM_WL = TRCK_CORR_WL + $clog2(MS_PER_BIT);
|
||||
localparam int WBP_WL = (2 * TRCK_CORR_WL) + 1 + $clog2(MS_PER_BIT);
|
||||
localparam logic [29:0] EXPECTED_CARRIER =
|
||||
CARRIER_WL'((CENTER_FREQ + 2500) * 128);
|
||||
localparam logic [WBP_WL-1:0] EXPECTED_WBP =
|
||||
WBP_WL'(50'h2_1234_89ab_cdef);
|
||||
|
||||
logic PCLK = 1'b0;
|
||||
logic PRESETN = 1'b0;
|
||||
logic [11:0] PADDR = '0;
|
||||
logic PSEL = 1'b0;
|
||||
logic PENABLE = 1'b0;
|
||||
logic PWRITE = 1'b0;
|
||||
logic [31:0] PWDATA = '0;
|
||||
logic PREADY;
|
||||
logic [31:0] PRDATA;
|
||||
logic PSLVERR;
|
||||
logic trck_resetn = 1'b0;
|
||||
logic afe_resetn = 1'b0;
|
||||
logic trck_clk = 1'b0;
|
||||
logic afe_clk = 1'b0;
|
||||
logic [3:0] afe_data = '0;
|
||||
logic sample_align = 1'b0;
|
||||
logic [31:0] sample_counter = '0;
|
||||
logic gps_frame_ready;
|
||||
logic pps_capture;
|
||||
integer interrupt_count = 0;
|
||||
|
||||
always #5 PCLK = ~PCLK;
|
||||
always #4 trck_clk = ~trck_clk;
|
||||
always #8 afe_clk = ~afe_clk;
|
||||
always @(posedge PCLK)
|
||||
if(gps_frame_ready) interrupt_count++;
|
||||
|
||||
tracking_wrapper #(
|
||||
.LOW_ADDRESS(0),
|
||||
.HIGH_ADDRESS(4095),
|
||||
.ADDR_BUS_WIDTH(12)
|
||||
) dut (
|
||||
.PCLK, .PRESETN, .PADDR, .PSEL, .PENABLE, .PWRITE, .PWDATA,
|
||||
.PREADY, .PRDATA, .PSLVERR,
|
||||
.trck_resetn, .afe_resetn, .trck_clk, .afe_clk, .afe_data,
|
||||
.sample_align, .sample_counter, .gps_frame_ready, .pps_capture
|
||||
);
|
||||
|
||||
task automatic pclk_cycles(input int unsigned count);
|
||||
repeat(count) @(posedge PCLK);
|
||||
endtask
|
||||
|
||||
task automatic apb_write(input logic [11:0] address,
|
||||
input logic [31:0] data);
|
||||
@(negedge PCLK);
|
||||
PADDR = address;
|
||||
PWDATA = data;
|
||||
PWRITE = 1'b1;
|
||||
PSEL = 1'b1;
|
||||
PENABLE = 1'b0;
|
||||
@(posedge PCLK);
|
||||
#1;
|
||||
@(negedge PCLK);
|
||||
PENABLE = 1'b1;
|
||||
@(posedge PCLK);
|
||||
#1;
|
||||
@(negedge PCLK);
|
||||
PSEL = 1'b0;
|
||||
PENABLE = 1'b0;
|
||||
PWRITE = 1'b0;
|
||||
pclk_cycles(2);
|
||||
endtask
|
||||
|
||||
task automatic apb_read(input logic [11:0] address,
|
||||
output logic [31:0] data);
|
||||
@(negedge PCLK);
|
||||
PADDR = address;
|
||||
PWRITE = 1'b0;
|
||||
PSEL = 1'b1;
|
||||
PENABLE = 1'b0;
|
||||
@(posedge PCLK);
|
||||
#1;
|
||||
data = PRDATA;
|
||||
@(negedge PCLK);
|
||||
PSEL = 1'b0;
|
||||
pclk_cycles(2);
|
||||
endtask
|
||||
|
||||
task automatic expect_read(input logic [11:0] address,
|
||||
input logic [31:0] expected);
|
||||
logic [31:0] value;
|
||||
apb_read(address, value);
|
||||
if(value !== expected)
|
||||
$fatal(1, "APB read 0x%03x mismatch: got=0x%08x expected=0x%08x",
|
||||
address, value, expected);
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
force dut.measurement_valid = 1'b0;
|
||||
force dut.measurement_bit = 1'b1;
|
||||
force dut.measurement_abs_sample = 32'h89ab_cdef;
|
||||
force dut.measurement_rem_code_ph = REM_CODE_PH_I_WL'(555);
|
||||
force dut.measurement_carrier_freq_q7 = EXPECTED_CARRIER;
|
||||
force dut.measurement_cn0_sum_i = SUM_WL'(-12345);
|
||||
force dut.measurement_cn0_sum_q = SUM_WL'(6789);
|
||||
force dut.measurement_cn0_wbp = EXPECTED_WBP;
|
||||
force dut.measurement_cn0_sample_count = $clog2(MS_PER_BIT+1)'(20);
|
||||
force dut.measurement_sequence = 16'h55aa;
|
||||
force dut.lock = 1'b1;
|
||||
force dut.busy = 1'b1;
|
||||
force dut.bit_valid = 1'b0;
|
||||
|
||||
pclk_cycles(5);
|
||||
PRESETN = 1'b1;
|
||||
trck_resetn = 1'b1;
|
||||
afe_resetn = 1'b1;
|
||||
pclk_cycles(5);
|
||||
|
||||
apb_write(CONTROL_REG_OFFSET[11:0],
|
||||
(1 << TRCK_INTRPT_ENABLE_POS) |
|
||||
(1 << TRCK_MEASUREMENT_INTR_EN_POS) |
|
||||
(1 << TRCK_MEASUREMENT_FLAG_EN_POS));
|
||||
|
||||
@(negedge trck_clk);
|
||||
force dut.measurement_valid = 1'b1;
|
||||
pclk_cycles(12);
|
||||
if(interrupt_count !== 1)
|
||||
$fatal(1, "expected one measurement interrupt, got %0d", interrupt_count);
|
||||
|
||||
expect_read(MEASUREMENT_META_REG_OFFSET[11:0],
|
||||
{8'h01, 11'b0, 5'd20, 5'b0, 1'b1, 1'b1, 1'b1});
|
||||
expect_read(MEASUREMENT_SEQUENCE_REG_OFFSET[11:0], 32'h0000_55aa);
|
||||
expect_read(MEASUREMENT_CARRIER_REG_OFFSET[11:0],
|
||||
{{2{EXPECTED_CARRIER[29]}}, EXPECTED_CARRIER});
|
||||
expect_read(MEASUREMENT_ABS_SAMPLE_REG_OFFSET[11:0], 32'h89ab_cdef);
|
||||
expect_read(MEASUREMENT_REM_CODE_REG_OFFSET[11:0], 32'd555);
|
||||
expect_read(MEASUREMENT_SUM_I_REG_OFFSET[11:0], -32'sd12345);
|
||||
expect_read(MEASUREMENT_SUM_Q_REG_OFFSET[11:0], 32'd6789);
|
||||
expect_read(MEASUREMENT_WBP_LO_REG_OFFSET[11:0], EXPECTED_WBP[31:0]);
|
||||
expect_read(MEASUREMENT_WBP_HI_REG_OFFSET[11:0],
|
||||
{{(64-WBP_WL){1'b0}}, EXPECTED_WBP[WBP_WL-1:32]});
|
||||
|
||||
/* Source payload movement cannot tear the APB-domain snapshot. */
|
||||
force dut.measurement_carrier_freq_q7 =
|
||||
CARRIER_WL'((CENTER_FREQ - 4000) * 128);
|
||||
force dut.measurement_cn0_sum_i = SUM_WL'(22222);
|
||||
pclk_cycles(4);
|
||||
expect_read(MEASUREMENT_CARRIER_REG_OFFSET[11:0],
|
||||
{{2{EXPECTED_CARRIER[29]}}, EXPECTED_CARRIER});
|
||||
expect_read(MEASUREMENT_SUM_I_REG_OFFSET[11:0], -32'sd12345);
|
||||
|
||||
expect_read(STATUS_REG_OFFSET[11:0],
|
||||
(1 << TRCK_BUSY_POS) |
|
||||
(1 << TRCK_LOCKED_POS) |
|
||||
(1 << TRCK_INTR_PEND_POS) |
|
||||
(1 << TRCK_MEASUREMENT_FLAG_POS));
|
||||
apb_write(CONTROL_REG_OFFSET[11:0],
|
||||
(1 << TRCK_INTRPT_ENABLE_POS) |
|
||||
(1 << TRCK_INTRPT_CLEAR_POS) |
|
||||
(1 << TRCK_MEASUREMENT_INTR_EN_POS) |
|
||||
(1 << TRCK_MEASUREMENT_FLAG_EN_POS));
|
||||
expect_read(STATUS_REG_OFFSET[11:0],
|
||||
(1 << TRCK_BUSY_POS) | (1 << TRCK_LOCKED_POS));
|
||||
|
||||
$display("tracking_wrapper_measurement_tb PASS");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,142 @@
|
||||
import definitions::*;
|
||||
|
||||
/*
|
||||
* Builds one coherent tracking measurement for every decoded 20 ms NAV bit.
|
||||
*
|
||||
* The payload is registered in the tracking clock domain and remains unchanged
|
||||
* until the next measurement. measurement_valid_o remains asserted for the
|
||||
* rest of bit_valid_i so the APB clock can synchronize it without a CDC FIFO.
|
||||
*/
|
||||
module tracking_measurement #(
|
||||
parameter int unsigned CORR_WL = TRCK_CORR_WL,
|
||||
parameter int unsigned ENERGY_WL = (2 * TRCK_CORR_WL) + 1,
|
||||
parameter int unsigned SUM_WL = TRCK_CORR_WL + $clog2(MS_PER_BIT),
|
||||
parameter int unsigned WBP_WL = ENERGY_WL + $clog2(MS_PER_BIT),
|
||||
parameter int unsigned COUNT_WL = $clog2(MS_PER_BIT + 1),
|
||||
parameter int unsigned CARRIER_WL =
|
||||
ACQUIRED_FREQ_IL + TRCK_CARR_NCO_FREQ_FL,
|
||||
parameter int unsigned SNAPSHOT_DELAY_CYCLES = 4
|
||||
) (
|
||||
input logic clk,
|
||||
input logic rstn,
|
||||
input logic bit_valid_i,
|
||||
input logic nav_bit_i,
|
||||
input logic [ABS_SAMPLE_CNTR_WL-1:0] absolute_sample_i,
|
||||
input logic [REM_CODE_PH_I_WL-1:0] rem_code_phase_i,
|
||||
input logic signed [CARRIER_WL-1:0] carrier_freq_q7_i,
|
||||
input logic corr_valid_i,
|
||||
input logic signed [CORR_WL-1:0] i_prompt_i,
|
||||
input logic signed [CORR_WL-1:0] q_prompt_i,
|
||||
input logic prompt_energy_valid_i,
|
||||
input logic [ENERGY_WL-1:0] prompt_energy_i,
|
||||
|
||||
output logic measurement_valid_o,
|
||||
output logic nav_bit_o,
|
||||
output logic [ABS_SAMPLE_CNTR_WL-1:0] absolute_sample_o,
|
||||
output logic [REM_CODE_PH_I_WL-1:0] rem_code_phase_o,
|
||||
output logic signed [CARRIER_WL-1:0] carrier_freq_q7_o,
|
||||
output logic signed [SUM_WL-1:0] cn0_sum_i_o,
|
||||
output logic signed [SUM_WL-1:0] cn0_sum_q_o,
|
||||
output logic [WBP_WL-1:0] cn0_wbp_o,
|
||||
output logic [COUNT_WL-1:0] cn0_sample_count_o,
|
||||
output logic [15:0] sequence_o
|
||||
);
|
||||
|
||||
localparam int unsigned DELAY_WL =
|
||||
(SNAPSHOT_DELAY_CYCLES < 2) ? 1 : $clog2(SNAPSHOT_DELAY_CYCLES + 1);
|
||||
|
||||
logic bit_valid_r;
|
||||
logic measurement_armed;
|
||||
logic snapshot_pending;
|
||||
logic [DELAY_WL-1:0] snapshot_delay;
|
||||
logic signed [SUM_WL-1:0] sum_i;
|
||||
logic signed [SUM_WL-1:0] sum_q;
|
||||
logic [WBP_WL-1:0] wbp;
|
||||
logic [COUNT_WL-1:0] sample_count;
|
||||
|
||||
wire bit_epoch = bit_valid_i && !bit_valid_r;
|
||||
|
||||
always_ff @(posedge clk or negedge rstn) begin
|
||||
if(!rstn) begin
|
||||
bit_valid_r <= 1'b0;
|
||||
measurement_armed <= 1'b0;
|
||||
snapshot_pending <= 1'b0;
|
||||
snapshot_delay <= '0;
|
||||
sum_i <= '0;
|
||||
sum_q <= '0;
|
||||
wbp <= '0;
|
||||
sample_count <= '0;
|
||||
measurement_valid_o <= 1'b0;
|
||||
nav_bit_o <= 1'b0;
|
||||
absolute_sample_o <= '0;
|
||||
rem_code_phase_o <= '0;
|
||||
carrier_freq_q7_o <= '0;
|
||||
cn0_sum_i_o <= '0;
|
||||
cn0_sum_q_o <= '0;
|
||||
cn0_wbp_o <= '0;
|
||||
cn0_sample_count_o <= '0;
|
||||
sequence_o <= '0;
|
||||
end else begin
|
||||
bit_valid_r <= bit_valid_i;
|
||||
|
||||
if(!bit_valid_i) begin
|
||||
measurement_valid_o <= 1'b0;
|
||||
end
|
||||
|
||||
if(measurement_armed && corr_valid_i) begin
|
||||
sum_i <= sum_i + $signed(i_prompt_i);
|
||||
sum_q <= sum_q + $signed(q_prompt_i);
|
||||
sample_count <= sample_count + 1'b1;
|
||||
end
|
||||
if(measurement_armed && prompt_energy_valid_i) begin
|
||||
wbp <= wbp + prompt_energy_i;
|
||||
end
|
||||
|
||||
/*
|
||||
* The first synchronized NAV-bit edge defines the integration phase.
|
||||
* Samples gathered before that edge are intentionally discarded.
|
||||
*/
|
||||
if(bit_epoch) begin
|
||||
if(!measurement_armed) begin
|
||||
measurement_armed <= 1'b1;
|
||||
sum_i <= '0;
|
||||
sum_q <= '0;
|
||||
wbp <= '0;
|
||||
sample_count <= '0;
|
||||
end else begin
|
||||
snapshot_pending <= 1'b1;
|
||||
snapshot_delay <= DELAY_WL'(SNAPSHOT_DELAY_CYCLES);
|
||||
end
|
||||
end
|
||||
|
||||
/*
|
||||
* Prompt energy is pipelined in lock_detector. There is almost one
|
||||
* millisecond before the next correlator result, so waiting a few
|
||||
* tracking clocks includes the last energy term without mixing epochs.
|
||||
*/
|
||||
if(snapshot_pending) begin
|
||||
if(snapshot_delay != 0) begin
|
||||
snapshot_delay <= snapshot_delay - 1'b1;
|
||||
end else begin
|
||||
snapshot_pending <= 1'b0;
|
||||
measurement_valid_o <= 1'b1;
|
||||
nav_bit_o <= nav_bit_i;
|
||||
absolute_sample_o <= absolute_sample_i;
|
||||
rem_code_phase_o <= rem_code_phase_i;
|
||||
carrier_freq_q7_o <= carrier_freq_q7_i;
|
||||
cn0_sum_i_o <= sum_i;
|
||||
cn0_sum_q_o <= sum_q;
|
||||
cn0_wbp_o <= wbp;
|
||||
cn0_sample_count_o <= sample_count;
|
||||
sequence_o <= sequence_o + 1'b1;
|
||||
|
||||
sum_i <= '0;
|
||||
sum_q <= '0;
|
||||
wbp <= '0;
|
||||
sample_count <= '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
+52
-1
@@ -34,6 +34,27 @@ module trck_top
|
||||
output logic bit_vld_o,
|
||||
output logic [ABS_SAMPLE_CNTR_WL-1 : 0] abs_sample_o,
|
||||
output logic [REM_CODE_PH_I_WL-1 : 0] rem_code_ph_o,
|
||||
|
||||
// Coherent 20 ms tracking measurement (held until the next NAV bit)
|
||||
output logic measurement_vld_o,
|
||||
output logic measurement_bit_o,
|
||||
output logic [ABS_SAMPLE_CNTR_WL-1 : 0] measurement_abs_sample_o,
|
||||
output logic [REM_CODE_PH_I_WL-1 : 0] measurement_rem_code_ph_o,
|
||||
output logic signed [
|
||||
ACQUIRED_FREQ_IL+TRCK_CARR_NCO_FREQ_FL-1 : 0
|
||||
] measurement_carrier_freq_q7_o,
|
||||
output logic signed [
|
||||
TRCK_CORR_WL+$clog2(MS_PER_BIT)-1 : 0
|
||||
] measurement_cn0_sum_i_o,
|
||||
output logic signed [
|
||||
TRCK_CORR_WL+$clog2(MS_PER_BIT)-1 : 0
|
||||
] measurement_cn0_sum_q_o,
|
||||
output logic [
|
||||
(2*TRCK_CORR_WL)+1+$clog2(MS_PER_BIT)-1 : 0
|
||||
] measurement_cn0_wbp_o,
|
||||
output logic [$clog2(MS_PER_BIT+1)-1 : 0]
|
||||
measurement_cn0_sample_count_o,
|
||||
output logic [15:0] measurement_sequence_o,
|
||||
|
||||
// Status signals
|
||||
output logic fifo_of_o,
|
||||
@@ -77,6 +98,8 @@ logic ca_l, ca_p, ca_e;
|
||||
|
||||
logic corr_vld;
|
||||
logic signed [TRCK_CORR_WL-TRCK_CORR_FL-1 : -TRCK_CORR_FL] i_e, i_p, i_l, q_e, q_p, q_l;
|
||||
logic prompt_energy_vld;
|
||||
logic [(2*TRCK_CORR_WL):0] prompt_energy;
|
||||
|
||||
logic signed [RF_DATA_WIDTH-1 : 0] rf_data;
|
||||
|
||||
@@ -223,7 +246,8 @@ Disc_PLL_i (
|
||||
.y_i (q_p),
|
||||
|
||||
.vld_o (pll_error_vld),
|
||||
.angle_o (pll_error)
|
||||
.angle_o (pll_error),
|
||||
.vec_len_o()
|
||||
);
|
||||
|
||||
code_loop_discriminator #(
|
||||
@@ -259,6 +283,8 @@ lock_detector_i (
|
||||
.corr_vld_i (corr_vld),
|
||||
.i_p_i (i_p),
|
||||
.q_p_i (q_p),
|
||||
.prompt_energy_vld_o(prompt_energy_vld),
|
||||
.prompt_energy_o(prompt_energy),
|
||||
.lock_o (lock_o)
|
||||
);
|
||||
|
||||
@@ -276,6 +302,31 @@ bit_gen bit_gen_i (
|
||||
.rem_code_ph_o (rem_code_ph_o)
|
||||
);
|
||||
|
||||
tracking_measurement tracking_measurement_i (
|
||||
.clk (trk_clk),
|
||||
.rstn (rstn),
|
||||
.bit_valid_i (bit_vld_o),
|
||||
.nav_bit_i (bit_o),
|
||||
.absolute_sample_i (abs_sample_o),
|
||||
.rem_code_phase_i (rem_code_ph_o),
|
||||
.carrier_freq_q7_i (carr_freq_sum_p),
|
||||
.corr_valid_i (corr_vld),
|
||||
.i_prompt_i (i_p),
|
||||
.q_prompt_i (q_p),
|
||||
.prompt_energy_valid_i (prompt_energy_vld),
|
||||
.prompt_energy_i (prompt_energy),
|
||||
.measurement_valid_o (measurement_vld_o),
|
||||
.nav_bit_o (measurement_bit_o),
|
||||
.absolute_sample_o (measurement_abs_sample_o),
|
||||
.rem_code_phase_o (measurement_rem_code_ph_o),
|
||||
.carrier_freq_q7_o (measurement_carrier_freq_q7_o),
|
||||
.cn0_sum_i_o (measurement_cn0_sum_i_o),
|
||||
.cn0_sum_q_o (measurement_cn0_sum_q_o),
|
||||
.cn0_wbp_o (measurement_cn0_wbp_o),
|
||||
.cn0_sample_count_o (measurement_cn0_sample_count_o),
|
||||
.sequence_o (measurement_sequence_o)
|
||||
);
|
||||
|
||||
//freq valid
|
||||
always_ff @(posedge trk_clk or negedge rstn) begin
|
||||
if (!rstn) begin
|
||||
|
||||
Reference in New Issue
Block a user