Skip to content

Commit 6f2d581

Browse files
committed
Add output pipeline to PTP clock CDC module
1 parent 945f22f commit 6f2d581

File tree

3 files changed

+126
-15
lines changed

3 files changed

+126
-15
lines changed

rtl/ptp_clock_cdc.v

Lines changed: 122 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ module ptp_clock_cdc #
3737
parameter NS_WIDTH = 4,
3838
parameter FNS_WIDTH = 16,
3939
parameter USE_SAMPLE_CLOCK = 1,
40-
parameter LOG_RATE = 3
40+
parameter LOG_RATE = 3,
41+
parameter PIPELINE_OUTPUT = 0
4142
)
4243
(
4344
input wire input_clk,
@@ -115,7 +116,13 @@ reg [FNS_WIDTH-1:0] ts_fns_ovf_reg = {FNS_WIDTH{1'b1}}, ts_fns_ovf_next;
115116

116117
reg ts_step_reg = 1'b0, ts_step_next;
117118

118-
reg pps_reg = 0;
119+
reg pps_reg = 1'b0;
120+
121+
reg [47:0] ts_s_pipe_reg[0:PIPELINE_OUTPUT-1];
122+
reg [TS_NS_WIDTH-1:0] ts_ns_pipe_reg[0:PIPELINE_OUTPUT-1];
123+
reg [FNS_WIDTH-1:0] ts_fns_pipe_reg[0:PIPELINE_OUTPUT-1];
124+
reg ts_step_pipe_reg[0:PIPELINE_OUTPUT-1];
125+
reg pps_pipe_reg[0:PIPELINE_OUTPUT-1];
119126

120127
reg [PHASE_CNT_WIDTH-1:0] src_phase_reg = {PHASE_CNT_WIDTH{1'b0}};
121128
reg [PHASE_ACC_WIDTH-1:0] dest_phase_reg = {PHASE_ACC_WIDTH{1'b0}}, dest_phase_next;
@@ -150,21 +157,90 @@ reg sample_update_sync3_reg = 1'b0;
150157

151158
generate
152159

153-
if (TS_WIDTH == 96) begin
154-
assign output_ts[95:48] = ts_s_reg;
155-
assign output_ts[47:46] = 2'b00;
156-
assign output_ts[45:16] = ts_ns_reg;
157-
assign output_ts[15:0] = FNS_WIDTH > 16 ? ts_fns_reg >> (FNS_WIDTH-16) : ts_fns_reg << (16-FNS_WIDTH);
158-
end else if (TS_WIDTH == 64) begin
159-
assign output_ts[63:16] = ts_ns_reg;
160-
assign output_ts[15:0] = FNS_WIDTH > 16 ? ts_fns_reg >> (FNS_WIDTH-16) : ts_fns_reg << (16-FNS_WIDTH);
160+
if (PIPELINE_OUTPUT > 0) begin
161+
162+
// pipeline
163+
(* shreg_extract = "no" *)
164+
reg [TS_WIDTH-1:0] output_ts_reg[0:PIPELINE_OUTPUT-1];
165+
(* shreg_extract = "no" *)
166+
reg output_ts_step_reg[0:PIPELINE_OUTPUT-1];
167+
(* shreg_extract = "no" *)
168+
reg output_pps_reg[0:PIPELINE_OUTPUT-1];
169+
170+
assign output_ts = output_ts_reg[PIPELINE_OUTPUT-1];
171+
assign output_ts_step = output_ts_step_reg[PIPELINE_OUTPUT-1];
172+
assign output_pps = output_pps_reg[PIPELINE_OUTPUT-1];
173+
174+
integer i;
175+
176+
initial begin
177+
for (i = 0; i < PIPELINE_OUTPUT; i = i + 1) begin
178+
output_ts_reg[i] = 0;
179+
output_ts_step_reg[i] = 1'b0;
180+
output_pps_reg[i] = 1'b0;
181+
end
182+
end
183+
184+
always @(posedge output_clk) begin
185+
if (TS_WIDTH == 96) begin
186+
output_ts_reg[0][95:48] <= ts_s_reg;
187+
output_ts_reg[0][47:46] <= 2'b00;
188+
output_ts_reg[0][45:16] <= ts_ns_reg;
189+
output_ts_reg[0][15:0] <= {ts_fns_reg, 16'd0} >> FNS_WIDTH;
190+
end else if (TS_WIDTH == 64) begin
191+
output_ts_reg[0][63:16] <= ts_ns_reg;
192+
output_ts_reg[0][15:0] <= {ts_fns_reg, 16'd0} >> FNS_WIDTH;
193+
end
194+
195+
output_ts_step_reg[0] <= ts_step_reg;
196+
output_pps_reg[0] <= pps_reg;
197+
198+
for (i = 0; i < PIPELINE_OUTPUT-1; i = i + 1) begin
199+
output_ts_reg[i+1] <= output_ts_reg[i];
200+
output_ts_step_reg[i+1] <= output_ts_step_reg[i];
201+
output_pps_reg[i+1] <= output_pps_reg[i];
202+
end
203+
204+
if (output_rst) begin
205+
for (i = 0; i < PIPELINE_OUTPUT; i = i + 1) begin
206+
output_ts_reg[i] = 0;
207+
output_ts_step_reg[i] = 1'b0;
208+
output_pps_reg[i] = 1'b0;
209+
end
210+
end
211+
end
212+
213+
end else begin
214+
215+
if (TS_WIDTH == 96) begin
216+
assign output_ts[95:48] = ts_s_reg;
217+
assign output_ts[47:46] = 2'b00;
218+
assign output_ts[45:16] = ts_ns_reg;
219+
assign output_ts[15:0] = {ts_fns_reg, 16'd0} >> FNS_WIDTH;
220+
end else if (TS_WIDTH == 64) begin
221+
assign output_ts[63:16] = ts_ns_reg;
222+
assign output_ts[15:0] = {ts_fns_reg, 16'd0} >> FNS_WIDTH;
223+
end
224+
225+
assign output_ts_step = ts_step_reg;
226+
227+
assign output_pps = pps_reg;
228+
161229
end
162230

163231
endgenerate
164232

165-
assign output_ts_step = ts_step_reg;
233+
integer i;
166234

167-
assign output_pps = pps_reg;
235+
initial begin
236+
for (i = 0; i < PIPELINE_OUTPUT; i = i + 1) begin
237+
ts_s_pipe_reg[i] = 0;
238+
ts_ns_pipe_reg[i] = 0;
239+
ts_fns_pipe_reg[i] = 0;
240+
ts_step_pipe_reg[i] = 1'b0;
241+
pps_pipe_reg[i] = 1'b0;
242+
end
243+
end
168244

169245
// source PTP clock capture and sync logic
170246
reg input_ts_step_reg = 1'b0;
@@ -381,9 +457,15 @@ always @(posedge output_clk) begin
381457

382458
if (dest_update_reg) begin
383459
// capture local TS
384-
dest_ts_s_capt_reg <= ts_s_reg;
385-
dest_ts_ns_capt_reg <= ts_ns_reg;
386-
dest_ts_fns_capt_reg <= ts_fns_reg;
460+
if (PIPELINE_OUTPUT > 0) begin
461+
dest_ts_s_capt_reg <= ts_s_pipe_reg[PIPELINE_OUTPUT-1];
462+
dest_ts_ns_capt_reg <= ts_ns_pipe_reg[PIPELINE_OUTPUT-1];
463+
dest_ts_fns_capt_reg <= ts_fns_pipe_reg[PIPELINE_OUTPUT-1];
464+
end else begin
465+
dest_ts_s_capt_reg <= ts_s_reg;
466+
dest_ts_ns_capt_reg <= ts_ns_reg;
467+
dest_ts_fns_capt_reg <= ts_fns_reg;
468+
end
387469

388470
dest_sync_reg <= !dest_sync_reg;
389471
ts_capt_valid_reg <= 1'b1;
@@ -668,6 +750,23 @@ always @(posedge output_clk) begin
668750
pps_reg <= 1'b0; // not currently implemented for 64 bit timestamp format
669751
end
670752

753+
// pipeline
754+
if (PIPELINE_OUTPUT > 0) begin
755+
ts_s_pipe_reg[0] <= ts_s_reg;
756+
ts_ns_pipe_reg[0] <= ts_ns_reg;
757+
ts_fns_pipe_reg[0] <= ts_fns_reg;
758+
ts_step_pipe_reg[0] <= ts_step_reg;
759+
pps_pipe_reg[0] <= pps_reg;
760+
761+
for (i = 0; i < PIPELINE_OUTPUT-1; i = i + 1) begin
762+
ts_s_pipe_reg[i+1] <= ts_s_pipe_reg[i];
763+
ts_ns_pipe_reg[i+1] <= ts_ns_pipe_reg[i];
764+
ts_fns_pipe_reg[i+1] <= ts_fns_pipe_reg[i];
765+
ts_step_pipe_reg[i+1] <= ts_step_pipe_reg[i];
766+
pps_pipe_reg[i+1] <= pps_pipe_reg[i];
767+
end
768+
end
769+
671770
if (output_rst) begin
672771
period_ns_reg <= 0;
673772
period_fns_reg <= 0;
@@ -689,6 +788,14 @@ always @(posedge output_clk) begin
689788

690789
ptp_lock_count_reg <= 0;
691790
ptp_locked_reg <= 1'b0;
791+
792+
for (i = 0; i < PIPELINE_OUTPUT; i = i + 1) begin
793+
ts_s_pipe_reg[i] = 0;
794+
ts_ns_pipe_reg[i] = 0;
795+
ts_fns_pipe_reg[i] = 0;
796+
ts_step_pipe_reg[i] = 1'b0;
797+
pps_pipe_reg[i] = 1'b0;
798+
end
692799
end
693800
end
694801

tb/ptp_clock_cdc/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export PARAM_NS_WIDTH ?= 4
3737
export PARAM_FNS_WIDTH ?= 16
3838
export PARAM_USE_SAMPLE_CLOCK ?= 1
3939
export PARAM_LOG_RATE ?= 3
40+
export PARAM_PIPELINE_OUTPUT ?= 0
4041

4142
ifeq ($(SIM), icarus)
4243
PLUSARGS += -fst
@@ -46,6 +47,7 @@ ifeq ($(SIM), icarus)
4647
COMPILE_ARGS += -P $(TOPLEVEL).FNS_WIDTH=$(PARAM_FNS_WIDTH)
4748
COMPILE_ARGS += -P $(TOPLEVEL).USE_SAMPLE_CLOCK=$(PARAM_USE_SAMPLE_CLOCK)
4849
COMPILE_ARGS += -P $(TOPLEVEL).LOG_RATE=$(PARAM_LOG_RATE)
50+
COMPILE_ARGS += -P $(TOPLEVEL).PIPELINE_OUTPUT=$(PARAM_PIPELINE_OUTPUT)
4951

5052
ifeq ($(WAVES), 1)
5153
VERILOG_SOURCES += iverilog_dump.v
@@ -59,6 +61,7 @@ else ifeq ($(SIM), verilator)
5961
COMPILE_ARGS += -GFNS_WIDTH=$(PARAM_FNS_WIDTH)
6062
COMPILE_ARGS += -GUSE_SAMPLE_CLOCK=$(PARAM_USE_SAMPLE_CLOCK)
6163
COMPILE_ARGS += -GLOG_RATE=$(PARAM_LOG_RATE)
64+
COMPILE_ARGS += -GPIPELINE_OUTPUT=$(PARAM_PIPELINE_OUTPUT)
6265

6366
ifeq ($(WAVES), 1)
6467
COMPILE_ARGS += --trace-fst

tb/ptp_clock_cdc/test_ptp_clock_cdc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ def test_ptp_clock_cdc(request, ts_width, sample_clock):
247247
parameters['FNS_WIDTH'] = 16
248248
parameters['USE_SAMPLE_CLOCK'] = sample_clock
249249
parameters['LOG_RATE'] = 3
250+
parameters['PIPELINE_OUTPUT'] = 0
250251

251252
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
252253

0 commit comments

Comments
 (0)