mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
bd8e8e5b20
Signed-off-by: Alex Forencich <alex@alexforencich.com>
604 lines
19 KiB
Verilog
604 lines
19 KiB
Verilog
/*
|
|
|
|
Copyright (c) 2023 Alex Forencich
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
// Language: Verilog 2001
|
|
|
|
`resetall
|
|
`timescale 1ns / 1ps
|
|
`default_nettype none
|
|
|
|
/*
|
|
* PTP time distribution PHC
|
|
*/
|
|
module ptp_td_phc #
|
|
(
|
|
parameter PERIOD_NS_NUM = 32,
|
|
parameter PERIOD_NS_DENOM = 5
|
|
)
|
|
(
|
|
input wire clk,
|
|
input wire rst,
|
|
|
|
/*
|
|
* ToD timestamp control
|
|
*/
|
|
input wire [47:0] input_ts_tod_s,
|
|
input wire [29:0] input_ts_tod_ns,
|
|
input wire input_ts_tod_valid,
|
|
output wire input_ts_tod_ready,
|
|
input wire [29:0] input_ts_tod_offset_ns,
|
|
input wire input_ts_tod_offset_valid,
|
|
output wire input_ts_tod_offset_ready,
|
|
|
|
/*
|
|
* Relative timestamp control
|
|
*/
|
|
input wire [47:0] input_ts_rel_ns,
|
|
input wire input_ts_rel_valid,
|
|
output wire input_ts_rel_ready,
|
|
input wire [31:0] input_ts_rel_offset_ns,
|
|
input wire input_ts_rel_offset_valid,
|
|
output wire input_ts_rel_offset_ready,
|
|
|
|
/*
|
|
* Fractional ns control
|
|
*/
|
|
input wire [31:0] input_ts_offset_fns,
|
|
input wire input_ts_offset_valid,
|
|
output wire input_ts_offset_ready,
|
|
|
|
/*
|
|
* Period control
|
|
*/
|
|
input wire [7:0] input_period_ns,
|
|
input wire [31:0] input_period_fns,
|
|
input wire input_period_valid,
|
|
output wire input_period_ready,
|
|
input wire [15:0] input_drift_num,
|
|
input wire [15:0] input_drift_denom,
|
|
input wire input_drift_valid,
|
|
output wire input_drift_ready,
|
|
|
|
/*
|
|
* Time distribution serial data output
|
|
*/
|
|
output wire ptp_td_sdo,
|
|
|
|
/*
|
|
* PPS output
|
|
*/
|
|
output wire output_pps,
|
|
output wire output_pps_str
|
|
);
|
|
|
|
localparam INC_NS_W = 9+8;
|
|
|
|
localparam FNS_W = 32;
|
|
|
|
localparam PERIOD_NS = PERIOD_NS_NUM / PERIOD_NS_DENOM;
|
|
localparam PERIOD_NS_REM = PERIOD_NS_NUM - PERIOD_NS*PERIOD_NS_DENOM;
|
|
localparam PERIOD_FNS = (PERIOD_NS_REM * {32'd1, {FNS_W{1'b0}}}) / PERIOD_NS_DENOM;
|
|
localparam PERIOD_FNS_REM = (PERIOD_NS_REM * {32'd1, {FNS_W{1'b0}}}) - PERIOD_FNS*PERIOD_NS_DENOM;
|
|
|
|
localparam [30:0] NS_PER_S = 31'd1_000_000_000;
|
|
|
|
reg [7:0] period_ns_reg = PERIOD_NS;
|
|
reg [FNS_W-1:0] period_fns_reg = PERIOD_FNS;
|
|
|
|
reg [15:0] drift_num_reg = PERIOD_FNS_REM;
|
|
reg [15:0] drift_denom_reg = PERIOD_NS_DENOM;
|
|
reg [15:0] drift_cnt_reg = 0;
|
|
reg [15:0] drift_cnt_d1_reg = 0;
|
|
reg drift_apply_reg = 1'b0;
|
|
reg [23:0] drift_acc_reg = 0;
|
|
|
|
reg [INC_NS_W-1:0] ts_inc_ns_reg = 0;
|
|
reg [FNS_W-1:0] ts_fns_reg = 0;
|
|
|
|
reg [32:0] ts_rel_ns_inc_reg = 0;
|
|
reg [47:0] ts_rel_ns_reg = 0;
|
|
reg ts_rel_updated_reg = 1'b0;
|
|
|
|
reg [47:0] ts_tod_s_reg = 0;
|
|
reg [29:0] ts_tod_ns_reg = 0;
|
|
reg ts_tod_updated_reg = 1'b0;
|
|
|
|
reg [31:0] ts_tod_offset_ns_reg = 0;
|
|
|
|
reg [47:0] ts_tod_alt_s_reg = 0;
|
|
reg [31:0] ts_tod_alt_offset_ns_reg = 0;
|
|
|
|
reg [7:0] td_update_cnt_reg = 0;
|
|
reg td_update_reg = 1'b0;
|
|
reg [1:0] td_msg_i_reg = 0;
|
|
|
|
reg input_ts_tod_ready_reg = 1'b0;
|
|
reg input_ts_tod_offset_ready_reg = 1'b0;
|
|
reg input_ts_rel_ready_reg = 1'b0;
|
|
reg input_ts_rel_offset_ready_reg = 1'b0;
|
|
reg input_ts_offset_ready_reg = 1'b0;
|
|
|
|
reg [17*14-1:0] td_shift_reg = {17*14{1'b1}};
|
|
|
|
reg [15:0] pps_gen_fns_reg = 0;
|
|
reg [9:0] pps_gen_ns_inc_reg = 0;
|
|
reg [30:0] pps_gen_ns_reg = 31'h40000000;
|
|
|
|
reg [9:0] pps_delay_reg = 0;
|
|
reg pps_reg = 0;
|
|
reg pps_str_reg = 0;
|
|
|
|
reg [3:0] update_state_reg = 0;
|
|
|
|
reg [47:0] adder_a_reg = 0;
|
|
reg [47:0] adder_b_reg = 0;
|
|
reg adder_cin_reg = 0;
|
|
wire [47:0] adder_sum;
|
|
wire adder_cout;
|
|
|
|
assign {adder_cout, adder_sum} = adder_a_reg + adder_b_reg + adder_cin_reg;
|
|
|
|
assign input_ts_tod_ready = input_ts_tod_ready_reg;
|
|
assign input_ts_tod_offset_ready = input_ts_tod_offset_ready_reg;
|
|
assign input_ts_rel_ready = input_ts_rel_ready_reg;
|
|
assign input_ts_rel_offset_ready = input_ts_rel_offset_ready_reg;
|
|
assign input_ts_offset_ready = input_ts_offset_ready_reg;
|
|
|
|
assign input_period_ready = 1'b1;
|
|
assign input_drift_ready = 1'b1;
|
|
|
|
assign output_pps = pps_reg;
|
|
assign output_pps_str = pps_str_reg;
|
|
|
|
assign ptp_td_sdo = td_shift_reg[0];
|
|
|
|
always @(posedge clk) begin
|
|
drift_apply_reg <= 1'b0;
|
|
|
|
input_ts_tod_ready_reg <= 1'b0;
|
|
input_ts_tod_offset_ready_reg <= 1'b0;
|
|
input_ts_rel_ready_reg <= 1'b0;
|
|
input_ts_rel_offset_ready_reg <= 1'b0;
|
|
input_ts_offset_ready_reg <= 1'b0;
|
|
|
|
// update and message generation cadence
|
|
{td_update_reg, td_update_cnt_reg} <= td_update_cnt_reg + 1;
|
|
|
|
// latch drift setting
|
|
if (input_drift_valid) begin
|
|
drift_num_reg <= input_drift_num;
|
|
drift_denom_reg <= input_drift_denom;
|
|
end
|
|
|
|
// drift
|
|
if (drift_denom_reg) begin
|
|
if (drift_cnt_reg == 0) begin
|
|
drift_cnt_reg <= drift_denom_reg - 1;
|
|
drift_apply_reg <= 1'b1;
|
|
end else begin
|
|
drift_cnt_reg <= drift_cnt_reg - 1;
|
|
end
|
|
end else begin
|
|
drift_cnt_reg <= 0;
|
|
end
|
|
|
|
drift_cnt_d1_reg <= drift_cnt_reg;
|
|
|
|
// drift accumulation
|
|
if (drift_apply_reg) begin
|
|
drift_acc_reg <= drift_acc_reg + drift_num_reg;
|
|
end
|
|
|
|
// latch period setting
|
|
if (input_period_valid) begin
|
|
period_ns_reg <= input_period_ns;
|
|
period_fns_reg <= input_period_fns;
|
|
end
|
|
|
|
// PPS generation
|
|
if (td_update_reg) begin
|
|
{pps_gen_ns_inc_reg, pps_gen_fns_reg} <= {period_ns_reg, period_fns_reg[31:16]} + ts_fns_reg[31:16];
|
|
end else begin
|
|
{pps_gen_ns_inc_reg, pps_gen_fns_reg} <= {period_ns_reg, period_fns_reg[31:16]} + pps_gen_fns_reg;
|
|
end
|
|
pps_gen_ns_reg <= pps_gen_ns_reg + pps_gen_ns_inc_reg;
|
|
|
|
if (!pps_gen_ns_reg[30]) begin
|
|
// pps_delay_reg <= 14*17 + 32 + 1;
|
|
pps_delay_reg <= 14*17 + 32 + 248;
|
|
pps_gen_ns_reg[30] <= 1'b1;
|
|
end
|
|
|
|
pps_reg <= 1'b0;
|
|
|
|
if (ts_tod_ns_reg[29]) begin
|
|
pps_str_reg <= 1'b0;
|
|
end
|
|
|
|
if (pps_delay_reg) begin
|
|
pps_delay_reg <= pps_delay_reg - 1;
|
|
if (pps_delay_reg == 1) begin
|
|
pps_reg <= 1'b1;
|
|
pps_str_reg <= 1'b1;
|
|
end
|
|
end
|
|
|
|
// update state machine
|
|
case (update_state_reg)
|
|
0: begin
|
|
// idle
|
|
|
|
// set relative timestamp
|
|
if (input_ts_rel_valid) begin
|
|
ts_rel_ns_reg <= input_ts_rel_ns;
|
|
input_ts_rel_ready_reg <= 1'b1;
|
|
ts_rel_updated_reg <= 1'b1;
|
|
end
|
|
|
|
// set ToD timestamp
|
|
if (input_ts_tod_valid) begin
|
|
ts_tod_s_reg <= input_ts_tod_s;
|
|
ts_tod_ns_reg <= input_ts_tod_ns;
|
|
input_ts_tod_ready_reg <= 1'b1;
|
|
ts_tod_updated_reg <= 1'b1;
|
|
end
|
|
|
|
// compute period 1 - add drift and requested offset
|
|
if (drift_apply_reg) begin
|
|
adder_a_reg <= drift_acc_reg + drift_num_reg;
|
|
end else begin
|
|
adder_a_reg <= drift_acc_reg;
|
|
end
|
|
adder_b_reg <= input_ts_offset_valid ? $signed(input_ts_offset_fns) : 0;
|
|
adder_cin_reg <= 0;
|
|
|
|
if (td_update_reg) begin
|
|
drift_acc_reg <= 0;
|
|
input_ts_offset_ready_reg <= input_ts_offset_valid;
|
|
update_state_reg <= 1;
|
|
end else begin
|
|
update_state_reg <= 0;
|
|
end
|
|
end
|
|
1: begin
|
|
// compute period 2 - add drift and offset to period
|
|
adder_a_reg <= adder_sum;
|
|
adder_b_reg <= {period_ns_reg, period_fns_reg, 8'd0};
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 2;
|
|
end
|
|
2: begin
|
|
// compute next fns
|
|
adder_a_reg <= adder_sum;
|
|
adder_b_reg <= ts_fns_reg;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 3;
|
|
end
|
|
3: begin
|
|
// store fns; compute relative timestamp 1 - add previous value and offset
|
|
{ts_inc_ns_reg, ts_fns_reg} <= {adder_cout, adder_sum};
|
|
|
|
adder_a_reg <= ts_rel_ns_reg;
|
|
adder_b_reg <= 0;
|
|
adder_cin_reg <= 0;
|
|
|
|
// offset relative timestamp if requested
|
|
if (input_ts_rel_offset_valid) begin
|
|
adder_b_reg <= $signed(input_ts_rel_offset_ns);
|
|
input_ts_rel_offset_ready_reg <= 1'b1;
|
|
ts_rel_updated_reg <= 1'b1;
|
|
end
|
|
|
|
update_state_reg <= 4;
|
|
end
|
|
4: begin
|
|
// compute relative timestamp 2 - add increment
|
|
adder_a_reg <= adder_sum;
|
|
adder_b_reg <= ts_inc_ns_reg;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 5;
|
|
end
|
|
5: begin
|
|
// store relative timestamp; compute ToD timestamp 1 - add previous value and increment
|
|
ts_rel_ns_reg <= adder_sum;
|
|
|
|
adder_a_reg <= ts_tod_ns_reg;
|
|
adder_b_reg <= ts_inc_ns_reg;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 6;
|
|
end
|
|
6: begin
|
|
// compute ToD timestamp 2 - add offset
|
|
adder_a_reg <= adder_sum;
|
|
adder_b_reg <= 0;
|
|
adder_cin_reg <= 0;
|
|
|
|
// offset ToD timestamp if requested
|
|
if (input_ts_tod_offset_valid) begin
|
|
adder_b_reg <= $signed(input_ts_tod_offset_ns);
|
|
input_ts_tod_offset_ready_reg <= 1'b1;
|
|
ts_tod_updated_reg <= 1'b1;
|
|
end
|
|
|
|
update_state_reg <= 7;
|
|
end
|
|
7: begin
|
|
// compute ToD timestamp 2 - check for underflow/overflow
|
|
ts_tod_ns_reg <= adder_sum;
|
|
|
|
if (adder_b_reg[47] && !adder_cout) begin
|
|
// borrowed; add 1 billion
|
|
adder_a_reg <= adder_sum;
|
|
adder_b_reg <= NS_PER_S;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 8;
|
|
end else begin
|
|
// did not borrow; subtract 1 billion to check for overflow
|
|
adder_a_reg <= adder_sum;
|
|
adder_b_reg <= -NS_PER_S;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 9;
|
|
end
|
|
end
|
|
8: begin
|
|
// seconds decrement
|
|
ts_tod_ns_reg <= adder_sum;
|
|
pps_gen_ns_reg[30] <= 1'b1;
|
|
|
|
adder_a_reg <= ts_tod_s_reg;
|
|
adder_b_reg <= -1;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 10;
|
|
end
|
|
9: begin
|
|
// seconds increment
|
|
pps_gen_ns_reg <= adder_sum;
|
|
|
|
if (!adder_cout) begin
|
|
// borrowed; leave seconds alone
|
|
|
|
adder_a_reg <= ts_tod_s_reg;
|
|
adder_b_reg <= 0;
|
|
adder_cin_reg <= 0;
|
|
end else begin
|
|
// did not borrow; decrement seconds
|
|
ts_tod_ns_reg <= adder_sum;
|
|
|
|
adder_a_reg <= ts_tod_s_reg;
|
|
adder_b_reg <= 1;
|
|
adder_cin_reg <= 0;
|
|
end
|
|
|
|
update_state_reg <= 10;
|
|
end
|
|
10: begin
|
|
// store seconds; compute offset
|
|
ts_tod_s_reg <= adder_sum;
|
|
|
|
if (adder_sum == ts_tod_alt_s_reg) begin
|
|
// store previous offset as alternate
|
|
ts_tod_alt_s_reg <= ts_tod_s_reg;
|
|
ts_tod_alt_offset_ns_reg <= ts_tod_offset_ns_reg;
|
|
end
|
|
|
|
adder_a_reg <= ts_tod_ns_reg;
|
|
adder_b_reg <= ~ts_rel_ns_reg;
|
|
adder_cin_reg <= 1;
|
|
|
|
update_state_reg <= 11;
|
|
end
|
|
11: begin
|
|
// store offset
|
|
ts_tod_offset_ns_reg <= adder_sum;
|
|
|
|
adder_a_reg <= adder_sum;
|
|
adder_b_reg <= -NS_PER_S;
|
|
adder_cin_reg <= 0;
|
|
|
|
if (ts_tod_ns_reg[29]) begin
|
|
// latter half of second; compute offset for next second
|
|
adder_b_reg <= -NS_PER_S;
|
|
update_state_reg <= 12;
|
|
end else begin
|
|
// former half of second; compute offset for previous second
|
|
adder_b_reg <= NS_PER_S;
|
|
update_state_reg <= 14;
|
|
end
|
|
end
|
|
12: begin
|
|
// store alternate offset for next second
|
|
ts_tod_alt_offset_ns_reg <= adder_sum;
|
|
|
|
adder_a_reg <= ts_tod_s_reg;
|
|
adder_b_reg <= 1;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 13;
|
|
end
|
|
13: begin
|
|
// store alternate second for next second
|
|
ts_tod_alt_s_reg <= adder_sum;
|
|
|
|
update_state_reg <= 0;
|
|
end
|
|
14: begin
|
|
// store alternate offset for previous second
|
|
ts_tod_alt_offset_ns_reg <= adder_sum;
|
|
|
|
adder_a_reg <= ts_tod_s_reg;
|
|
adder_b_reg <= -1;
|
|
adder_cin_reg <= 0;
|
|
|
|
update_state_reg <= 15;
|
|
end
|
|
15: begin
|
|
// store alternate second for previous second
|
|
ts_tod_alt_s_reg <= adder_sum;
|
|
|
|
update_state_reg <= 0;
|
|
end
|
|
default: begin
|
|
// invalid state; return to idle
|
|
update_state_reg <= 0;
|
|
end
|
|
endcase
|
|
|
|
// time distribution message generation
|
|
td_shift_reg <= {1'b1, td_shift_reg} >> 1;
|
|
|
|
if (td_update_reg) begin
|
|
// word 0: control
|
|
td_shift_reg[17*0+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*0+1 +: 16] <= 0;
|
|
td_shift_reg[17*0+1+0 +: 4] <= td_msg_i_reg;
|
|
td_shift_reg[17*0+1+8 +: 1] <= ts_rel_updated_reg;
|
|
td_shift_reg[17*0+1+9 +: 1] <= ts_tod_s_reg[0];
|
|
ts_rel_updated_reg <= 1'b0;
|
|
|
|
case (td_msg_i_reg)
|
|
2'd0: begin
|
|
// msg 0 word 1: current ToD ns 15:0
|
|
td_shift_reg[17*1+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*1+1 +: 16] <= ts_tod_ns_reg[15:0];
|
|
// msg 0 word 2: current ToD ns 29:16
|
|
td_shift_reg[17*2+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*2+1+0 +: 15] <= ts_tod_ns_reg[29:16];
|
|
td_shift_reg[17*2+1+15 +: 1] <= ts_tod_updated_reg;
|
|
ts_tod_updated_reg <= 1'b0;
|
|
// msg 0 word 3: current ToD seconds 15:0
|
|
td_shift_reg[17*3+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*3+1 +: 16] <= ts_tod_s_reg[15:0];
|
|
// msg 0 word 4: current ToD seconds 31:16
|
|
td_shift_reg[17*4+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*4+1 +: 16] <= ts_tod_s_reg[31:16];
|
|
// msg 0 word 5: current ToD seconds 47:32
|
|
td_shift_reg[17*5+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*5+1 +: 16] <= ts_tod_s_reg[47:32];
|
|
|
|
td_msg_i_reg <= 2'd1;
|
|
end
|
|
2'd1: begin
|
|
// msg 1 word 1: current ToD ns offset 15:0
|
|
td_shift_reg[17*1+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*1+1 +: 16] <= ts_tod_offset_ns_reg[15:0];
|
|
// msg 1 word 2: current ToD ns offset 31:16
|
|
td_shift_reg[17*2+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*2+1 +: 16] <= ts_tod_offset_ns_reg[31:16];
|
|
// msg 1 word 3: drift num
|
|
td_shift_reg[17*3+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*3+1 +: 16] <= drift_num_reg;
|
|
// msg 1 word 4: drift denom
|
|
td_shift_reg[17*4+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*4+1 +: 16] <= drift_denom_reg;
|
|
// msg 1 word 5: drift state
|
|
td_shift_reg[17*5+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*5+1 +: 16] <= drift_cnt_d1_reg;
|
|
|
|
td_msg_i_reg <= 2'd2;
|
|
end
|
|
2'd2: begin
|
|
// msg 2 word 1: alternate ToD ns offset 15:0
|
|
td_shift_reg[17*1+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*1+1 +: 16] <= ts_tod_alt_offset_ns_reg[15:0];
|
|
// msg 2 word 2: alternate ToD ns offset 31:16
|
|
td_shift_reg[17*2+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*2+1 +: 16] <= ts_tod_alt_offset_ns_reg[31:16];
|
|
// msg 2 word 3: alternate ToD seconds 15:0
|
|
td_shift_reg[17*3+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*3+1 +: 16] <= ts_tod_alt_s_reg[15:0];
|
|
// msg 2 word 4: alternate ToD seconds 31:16
|
|
td_shift_reg[17*4+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*4+1 +: 16] <= ts_tod_alt_s_reg[31:16];
|
|
// msg 2 word 5: alternate ToD seconds 47:32
|
|
td_shift_reg[17*5+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*5+1 +: 16] <= ts_tod_alt_s_reg[47:32];
|
|
|
|
td_msg_i_reg <= 2'd0;
|
|
end
|
|
endcase
|
|
|
|
// word 6: current fns 15:0
|
|
td_shift_reg[17*6+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*6+1 +: 16] <= ts_fns_reg[15:0];
|
|
// word 7: current fns 31:16
|
|
td_shift_reg[17*7+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*7+1 +: 16] <= ts_fns_reg[31:16];
|
|
// word 8: current ns 15:0
|
|
td_shift_reg[17*8+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*8+1 +: 16] <= ts_rel_ns_reg[15:0];
|
|
// word 9: current ns 31:16
|
|
td_shift_reg[17*9+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*9+1 +: 16] <= ts_rel_ns_reg[31:16];
|
|
// word 10: current ns 47:32
|
|
td_shift_reg[17*10+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*10+1 +: 16] <= ts_rel_ns_reg[47:32];
|
|
// word 11: current phase increment fns 15:0
|
|
td_shift_reg[17*11+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*11+1 +: 16] <= period_fns_reg[15:0];
|
|
// word 12: current phase increment fns 31:16
|
|
td_shift_reg[17*12+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*12+1 +: 16] <= period_fns_reg[31:16];
|
|
// word 13: current phase increment ns 7:0 + crc
|
|
td_shift_reg[17*13+0 +: 1] <= 1'b0;
|
|
td_shift_reg[17*13+1 +: 16] <= period_ns_reg[7:0];
|
|
end
|
|
|
|
if (rst) begin
|
|
period_ns_reg <= PERIOD_NS;
|
|
period_fns_reg <= PERIOD_FNS;
|
|
drift_num_reg <= PERIOD_FNS_REM;
|
|
drift_denom_reg <= PERIOD_NS_DENOM;
|
|
drift_cnt_reg <= 0;
|
|
drift_acc_reg <= 0;
|
|
ts_fns_reg <= 0;
|
|
ts_rel_ns_reg <= 0;
|
|
ts_rel_updated_reg <= 0;
|
|
ts_tod_s_reg <= 0;
|
|
ts_tod_ns_reg <= 0;
|
|
ts_tod_updated_reg <= 0;
|
|
|
|
pps_gen_ns_reg[30] <= 1'b1;
|
|
pps_delay_reg <= 0;
|
|
pps_reg <= 0;
|
|
pps_str_reg <= 0;
|
|
|
|
td_update_cnt_reg <= 0;
|
|
td_update_reg <= 1'b0;
|
|
td_msg_i_reg <= 0;
|
|
|
|
td_shift_reg <= {17*14{1'b1}};
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
`resetall
|