Skip to content

Commit b4d09cb

Browse files
committed
More extensive overhaul of the PTP period output module to improve resource consumption and parallelize computation
Signed-off-by: Alex Forencich <alex@alexforencich.com>
1 parent f313faf commit b4d09cb

File tree

1 file changed

+94
-93
lines changed

1 file changed

+94
-93
lines changed

rtl/ptp_perout.v

Lines changed: 94 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
3-
Copyright (c) 2019 Alex Forencich
3+
Copyright (c) 2019-2024 Alex Forencich
44
55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal
@@ -77,15 +77,12 @@ module ptp_perout #
7777
output wire output_pulse
7878
);
7979

80-
localparam [2:0]
80+
localparam [1:0]
8181
STATE_IDLE = 3'd0,
82-
STATE_UPDATE_RISE_1 = 3'd1,
83-
STATE_UPDATE_RISE_2 = 3'd2,
84-
STATE_UPDATE_FALL_1 = 3'd3,
85-
STATE_UPDATE_FALL_2 = 3'd4,
86-
STATE_WAIT_EDGE = 3'd5;
82+
STATE_UPDATE_RISE = 3'd1,
83+
STATE_UPDATE_FALL = 3'd2;
8784

88-
reg [2:0] state_reg = STATE_IDLE, state_next;
85+
reg [1:0] state_reg = STATE_IDLE, state_next;
8986

9087
reg [47:0] time_s_reg = 0;
9188
reg [30:0] time_ns_reg = 0;
@@ -95,9 +92,9 @@ reg [47:0] next_rise_s_reg = 0, next_rise_s_next;
9592
reg [30:0] next_rise_ns_reg = 0, next_rise_ns_next;
9693
reg [15:0] next_rise_fns_reg = 0, next_rise_fns_next;
9794

98-
reg [47:0] next_fall_s_reg = 0, next_fall_s_next;
99-
reg [30:0] next_fall_ns_reg = 0, next_fall_ns_next;
100-
reg [15:0] next_fall_fns_reg = 0, next_fall_fns_next;
95+
reg [47:0] next_edge_s_reg = 0, next_edge_s_next;
96+
reg [30:0] next_edge_ns_reg = 0, next_edge_ns_next;
97+
reg [15:0] next_edge_fns_reg = 0, next_edge_fns_next;
10198

10299
reg [47:0] start_s_reg = OUT_START_S;
103100
reg [30:0] start_ns_reg = OUT_START_NS;
@@ -116,6 +113,7 @@ reg [15:0] ts_96_fns_inc_reg = 0, ts_96_fns_inc_next;
116113
reg [30:0] ts_96_ns_ovf_reg = 0, ts_96_ns_ovf_next;
117114
reg [15:0] ts_96_fns_ovf_reg = 0, ts_96_fns_ovf_next;
118115

116+
reg restart_reg = 1'b1;
119117
reg locked_reg = 1'b0, locked_next;
120118
reg error_reg = 1'b0, error_next;
121119
reg ffwd_reg = 1'b0, ffwd_next;
@@ -133,9 +131,9 @@ always @* begin
133131
next_rise_ns_next = next_rise_ns_reg;
134132
next_rise_fns_next = next_rise_fns_reg;
135133

136-
next_fall_s_next = next_fall_s_reg;
137-
next_fall_ns_next = next_fall_ns_reg;
138-
next_fall_fns_next = next_fall_fns_reg;
134+
next_edge_s_next = next_edge_s_reg;
135+
next_edge_ns_next = next_edge_ns_reg;
136+
next_edge_fns_next = next_edge_fns_reg;
139137

140138
ts_96_ns_inc_next = ts_96_ns_inc_reg;
141139
ts_96_fns_inc_next = ts_96_fns_inc_reg;
@@ -149,97 +147,97 @@ always @* begin
149147
level_next = level_reg;
150148
output_next = output_reg;
151149

152-
if (input_start_valid || input_period_valid || input_ts_step) begin
153-
locked_next = 1'b0;
154-
level_next = 1'b0;
155-
output_next = 1'b0;
156-
error_next = input_ts_step;
157-
state_next = STATE_IDLE;
158-
end else begin
159-
case (state_reg)
160-
STATE_IDLE: begin
161-
// set next rise to start time
162-
next_rise_s_next = start_s_reg;
163-
next_rise_ns_next = start_ns_reg;
164-
if (FNS_ENABLE) begin
165-
next_rise_fns_next = start_fns_reg;
166-
end
167-
locked_next = 1'b0;
168-
ffwd_next = 1'b1;
169-
output_next = 1'b0;
170-
level_next = 1'b0;
171-
state_next = STATE_WAIT_EDGE;
172-
end
173-
STATE_UPDATE_RISE_1: begin
174-
// set next rise time to next rise time plus period
150+
case (state_reg)
151+
STATE_IDLE: begin
152+
if (ffwd_reg || level_reg) begin
153+
// fast forward or falling edge, set up for next rising edge
154+
// set next rise time to previous rise time plus period
175155
{ts_96_ns_inc_next, ts_96_fns_inc_next} = {next_rise_ns_reg, next_rise_fns_reg} + {period_ns_reg, period_fns_reg};
176156
{ts_96_ns_ovf_next, ts_96_fns_ovf_next} = {next_rise_ns_reg, next_rise_fns_reg} + {period_ns_reg, period_fns_reg} - {31'd1_000_000_000, 16'd0};
177-
state_next = STATE_UPDATE_RISE_2;
178-
end
179-
STATE_UPDATE_RISE_2: begin
180-
if (!ts_96_ns_ovf_reg[30]) begin
181-
// if the overflow lookahead did not borrow, one second has elapsed
182-
next_rise_s_next = next_rise_s_reg + period_s_reg + 1;
183-
next_rise_ns_next = ts_96_ns_ovf_reg;
184-
next_rise_fns_next = ts_96_fns_ovf_reg;
185-
end else begin
186-
// no increment seconds field
187-
next_rise_s_next = next_rise_s_reg + period_s_reg;
188-
next_rise_ns_next = ts_96_ns_inc_reg;
189-
next_rise_fns_next = ts_96_fns_inc_reg;
190-
end
191-
state_next = STATE_WAIT_EDGE;
192-
end
193-
STATE_UPDATE_FALL_1: begin
194-
// set next fall time to next rise time plus width
157+
end else begin
158+
// rising edge; set up for next falling edge
159+
// set next fall time to previous rise time plus width
195160
{ts_96_ns_inc_next, ts_96_fns_inc_next} = {next_rise_ns_reg, next_rise_fns_reg} + {width_ns_reg, width_fns_reg};
196161
{ts_96_ns_ovf_next, ts_96_fns_ovf_next} = {next_rise_ns_reg, next_rise_fns_reg} + {width_ns_reg, width_fns_reg} - {31'd1_000_000_000, 16'd0};
197-
state_next = STATE_UPDATE_FALL_2;
198162
end
199-
STATE_UPDATE_FALL_2: begin
200-
if (!ts_96_ns_ovf_reg[30]) begin
201-
// if the overflow lookahead did not borrow, one second has elapsed
202-
next_fall_s_next = next_rise_s_reg + width_s_reg + 1;
203-
next_fall_ns_next = ts_96_ns_ovf_reg;
204-
next_fall_fns_next = ts_96_fns_ovf_reg;
205-
end else begin
206-
// no increment seconds field
207-
next_fall_s_next = next_rise_s_reg + width_s_reg;
208-
next_fall_ns_next = ts_96_ns_inc_reg;
209-
next_fall_fns_next = ts_96_fns_inc_reg;
210-
end
211-
state_next = STATE_WAIT_EDGE;
212-
end
213-
STATE_WAIT_EDGE: begin
214-
if ((!level_reg || ffwd_reg) && ((time_s_reg > next_rise_s_reg) || (time_s_reg == next_rise_s_reg && {time_ns_reg, time_fns_reg} > {next_rise_ns_reg, next_rise_fns_reg}))) begin
215-
// rising edge
216-
if (ffwd_reg) begin
217-
output_next = 1'b0;
218-
level_next = 1'b0;
219-
state_next = STATE_UPDATE_RISE_1;
220-
end else begin
221-
locked_next = 1'b1;
222-
error_next = 1'b0;
223-
output_next = enable;
224-
level_next = 1'b1;
225-
state_next = STATE_UPDATE_FALL_1;
226-
end
227-
end else if (level_reg && ((time_s_reg > next_fall_s_reg) || (time_s_reg == next_fall_s_reg && {time_ns_reg, time_fns_reg} > {next_fall_ns_reg, next_fall_fns_reg}))) begin
228-
// falling edge
163+
164+
// wait for edge
165+
if ((time_s_reg > next_edge_s_reg) || (time_s_reg == next_edge_s_reg && {time_ns_reg, time_fns_reg} > {next_edge_ns_reg, next_edge_fns_reg})) begin
166+
if (ffwd_reg || level_reg) begin
167+
// fast forward or falling edge, set up for next rising edge
229168
output_next = 1'b0;
230169
level_next = 1'b0;
231-
state_next = STATE_UPDATE_RISE_1;
170+
state_next = STATE_UPDATE_RISE;
232171
end else begin
233-
ffwd_next = 1'b0;
234-
state_next = STATE_WAIT_EDGE;
172+
// rising edge; set up for next falling edge
173+
locked_next = 1'b1;
174+
error_next = 1'b0;
175+
output_next = enable;
176+
level_next = 1'b1;
177+
state_next = STATE_UPDATE_FALL;
235178
end
179+
end else begin
180+
ffwd_next = 1'b0;
181+
state_next = STATE_IDLE;
236182
end
237-
endcase
183+
end
184+
STATE_UPDATE_RISE: begin
185+
if (!ts_96_ns_ovf_reg[30]) begin
186+
// if the overflow lookahead did not borrow, one second has elapsed
187+
next_edge_s_next = next_rise_s_reg + period_s_reg + 1;
188+
next_edge_ns_next = ts_96_ns_ovf_reg;
189+
next_edge_fns_next = ts_96_fns_ovf_reg;
190+
end else begin
191+
// no increment seconds field
192+
next_edge_s_next = next_rise_s_reg + period_s_reg;
193+
next_edge_ns_next = ts_96_ns_inc_reg;
194+
next_edge_fns_next = ts_96_fns_inc_reg;
195+
end
196+
next_rise_s_next = next_edge_s_next;
197+
next_rise_ns_next = next_edge_ns_next;
198+
next_rise_fns_next = next_edge_fns_next;
199+
state_next = STATE_IDLE;
200+
end
201+
STATE_UPDATE_FALL: begin
202+
if (!ts_96_ns_ovf_reg[30]) begin
203+
// if the overflow lookahead did not borrow, one second has elapsed
204+
next_edge_s_next = next_rise_s_reg + width_s_reg + 1;
205+
next_edge_ns_next = ts_96_ns_ovf_reg;
206+
next_edge_fns_next = ts_96_fns_ovf_reg;
207+
end else begin
208+
// no increment seconds field
209+
next_edge_s_next = next_rise_s_reg + width_s_reg;
210+
next_edge_ns_next = ts_96_ns_inc_reg;
211+
next_edge_fns_next = ts_96_fns_inc_reg;
212+
end
213+
state_next = STATE_IDLE;
214+
end
215+
endcase
216+
217+
if (restart_reg || input_ts_step) begin
218+
// set next rise and next edge to start time
219+
next_rise_s_next = start_s_reg;
220+
next_rise_ns_next = start_ns_reg;
221+
if (FNS_ENABLE) begin
222+
next_rise_fns_next = start_fns_reg;
223+
end
224+
next_edge_s_next = start_s_reg;
225+
next_edge_ns_next = start_ns_reg;
226+
if (FNS_ENABLE) begin
227+
next_edge_fns_next = start_fns_reg;
228+
end
229+
locked_next = 1'b0;
230+
ffwd_next = 1'b1;
231+
output_next = 1'b0;
232+
level_next = 1'b0;
233+
error_next = input_ts_step;
234+
state_next = STATE_IDLE;
238235
end
239236
end
240237

241238
always @(posedge clk) begin
242239
state_reg <= state_next;
240+
restart_reg <= 1'b0;
243241

244242
time_s_reg <= input_ts_96[95:48];
245243
time_ns_reg <= input_ts_96[45:16];
@@ -253,6 +251,7 @@ always @(posedge clk) begin
253251
if (FNS_ENABLE) begin
254252
start_fns_reg <= input_start[15:0];
255253
end
254+
restart_reg <= 1'b1;
256255
end
257256

258257
if (input_period_valid) begin
@@ -261,6 +260,7 @@ always @(posedge clk) begin
261260
if (FNS_ENABLE) begin
262261
period_fns_reg <= input_period[15:0];
263262
end
263+
restart_reg <= 1'b1;
264264
end
265265

266266
if (input_width_valid) begin
@@ -277,10 +277,10 @@ always @(posedge clk) begin
277277
next_rise_fns_reg <= next_rise_fns_next;
278278
end
279279

280-
next_fall_s_reg <= next_fall_s_next;
281-
next_fall_ns_reg <= next_fall_ns_next;
280+
next_edge_s_reg <= next_edge_s_next;
281+
next_edge_ns_reg <= next_edge_ns_next;
282282
if (FNS_ENABLE) begin
283-
next_fall_fns_reg <= next_fall_fns_next;
283+
next_edge_fns_reg <= next_edge_fns_next;
284284
end
285285

286286
ts_96_ns_inc_reg <= ts_96_ns_inc_next;
@@ -314,6 +314,7 @@ always @(posedge clk) begin
314314
width_ns_reg <= OUT_WIDTH_NS;
315315
width_fns_reg <= OUT_WIDTH_FNS;
316316

317+
restart_reg <= 1'b1;
317318
locked_reg <= 1'b0;
318319
error_reg <= 1'b0;
319320
output_reg <= 1'b0;

0 commit comments

Comments
 (0)