Skip to content

Commit

Permalink
More extensive overhaul of the PTP period output module to improve re…
Browse files Browse the repository at this point in the history
…source consumption and parallelize computation

Signed-off-by: Alex Forencich <alex@alexforencich.com>
  • Loading branch information
alexforencich committed Jan 17, 2024
1 parent f313faf commit b4d09cb
Showing 1 changed file with 94 additions and 93 deletions.
187 changes: 94 additions & 93 deletions rtl/ptp_perout.v
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Copyright (c) 2019 Alex Forencich
Copyright (c) 2019-2024 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
Expand Down Expand Up @@ -77,15 +77,12 @@ module ptp_perout #
output wire output_pulse
);

localparam [2:0]
localparam [1:0]
STATE_IDLE = 3'd0,
STATE_UPDATE_RISE_1 = 3'd1,
STATE_UPDATE_RISE_2 = 3'd2,
STATE_UPDATE_FALL_1 = 3'd3,
STATE_UPDATE_FALL_2 = 3'd4,
STATE_WAIT_EDGE = 3'd5;
STATE_UPDATE_RISE = 3'd1,
STATE_UPDATE_FALL = 3'd2;

reg [2:0] state_reg = STATE_IDLE, state_next;
reg [1:0] state_reg = STATE_IDLE, state_next;

reg [47:0] time_s_reg = 0;
reg [30:0] time_ns_reg = 0;
Expand All @@ -95,9 +92,9 @@ reg [47:0] next_rise_s_reg = 0, next_rise_s_next;
reg [30:0] next_rise_ns_reg = 0, next_rise_ns_next;
reg [15:0] next_rise_fns_reg = 0, next_rise_fns_next;

reg [47:0] next_fall_s_reg = 0, next_fall_s_next;
reg [30:0] next_fall_ns_reg = 0, next_fall_ns_next;
reg [15:0] next_fall_fns_reg = 0, next_fall_fns_next;
reg [47:0] next_edge_s_reg = 0, next_edge_s_next;
reg [30:0] next_edge_ns_reg = 0, next_edge_ns_next;
reg [15:0] next_edge_fns_reg = 0, next_edge_fns_next;

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

reg restart_reg = 1'b1;
reg locked_reg = 1'b0, locked_next;
reg error_reg = 1'b0, error_next;
reg ffwd_reg = 1'b0, ffwd_next;
Expand All @@ -133,9 +131,9 @@ always @* begin
next_rise_ns_next = next_rise_ns_reg;
next_rise_fns_next = next_rise_fns_reg;

next_fall_s_next = next_fall_s_reg;
next_fall_ns_next = next_fall_ns_reg;
next_fall_fns_next = next_fall_fns_reg;
next_edge_s_next = next_edge_s_reg;
next_edge_ns_next = next_edge_ns_reg;
next_edge_fns_next = next_edge_fns_reg;

ts_96_ns_inc_next = ts_96_ns_inc_reg;
ts_96_fns_inc_next = ts_96_fns_inc_reg;
Expand All @@ -149,97 +147,97 @@ always @* begin
level_next = level_reg;
output_next = output_reg;

if (input_start_valid || input_period_valid || input_ts_step) begin
locked_next = 1'b0;
level_next = 1'b0;
output_next = 1'b0;
error_next = input_ts_step;
state_next = STATE_IDLE;
end else begin
case (state_reg)
STATE_IDLE: begin
// set next rise to start time
next_rise_s_next = start_s_reg;
next_rise_ns_next = start_ns_reg;
if (FNS_ENABLE) begin
next_rise_fns_next = start_fns_reg;
end
locked_next = 1'b0;
ffwd_next = 1'b1;
output_next = 1'b0;
level_next = 1'b0;
state_next = STATE_WAIT_EDGE;
end
STATE_UPDATE_RISE_1: begin
// set next rise time to next rise time plus period
case (state_reg)
STATE_IDLE: begin
if (ffwd_reg || level_reg) begin
// fast forward or falling edge, set up for next rising edge
// set next rise time to previous rise time plus period
{ts_96_ns_inc_next, ts_96_fns_inc_next} = {next_rise_ns_reg, next_rise_fns_reg} + {period_ns_reg, period_fns_reg};
{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};
state_next = STATE_UPDATE_RISE_2;
end
STATE_UPDATE_RISE_2: begin
if (!ts_96_ns_ovf_reg[30]) begin
// if the overflow lookahead did not borrow, one second has elapsed
next_rise_s_next = next_rise_s_reg + period_s_reg + 1;
next_rise_ns_next = ts_96_ns_ovf_reg;
next_rise_fns_next = ts_96_fns_ovf_reg;
end else begin
// no increment seconds field
next_rise_s_next = next_rise_s_reg + period_s_reg;
next_rise_ns_next = ts_96_ns_inc_reg;
next_rise_fns_next = ts_96_fns_inc_reg;
end
state_next = STATE_WAIT_EDGE;
end
STATE_UPDATE_FALL_1: begin
// set next fall time to next rise time plus width
end else begin
// rising edge; set up for next falling edge
// set next fall time to previous rise time plus width
{ts_96_ns_inc_next, ts_96_fns_inc_next} = {next_rise_ns_reg, next_rise_fns_reg} + {width_ns_reg, width_fns_reg};
{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};
state_next = STATE_UPDATE_FALL_2;
end
STATE_UPDATE_FALL_2: begin
if (!ts_96_ns_ovf_reg[30]) begin
// if the overflow lookahead did not borrow, one second has elapsed
next_fall_s_next = next_rise_s_reg + width_s_reg + 1;
next_fall_ns_next = ts_96_ns_ovf_reg;
next_fall_fns_next = ts_96_fns_ovf_reg;
end else begin
// no increment seconds field
next_fall_s_next = next_rise_s_reg + width_s_reg;
next_fall_ns_next = ts_96_ns_inc_reg;
next_fall_fns_next = ts_96_fns_inc_reg;
end
state_next = STATE_WAIT_EDGE;
end
STATE_WAIT_EDGE: begin
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
// rising edge
if (ffwd_reg) begin
output_next = 1'b0;
level_next = 1'b0;
state_next = STATE_UPDATE_RISE_1;
end else begin
locked_next = 1'b1;
error_next = 1'b0;
output_next = enable;
level_next = 1'b1;
state_next = STATE_UPDATE_FALL_1;
end
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
// falling edge

// wait for edge
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
if (ffwd_reg || level_reg) begin
// fast forward or falling edge, set up for next rising edge
output_next = 1'b0;
level_next = 1'b0;
state_next = STATE_UPDATE_RISE_1;
state_next = STATE_UPDATE_RISE;
end else begin
ffwd_next = 1'b0;
state_next = STATE_WAIT_EDGE;
// rising edge; set up for next falling edge
locked_next = 1'b1;
error_next = 1'b0;
output_next = enable;
level_next = 1'b1;
state_next = STATE_UPDATE_FALL;
end
end else begin
ffwd_next = 1'b0;
state_next = STATE_IDLE;
end
endcase
end
STATE_UPDATE_RISE: begin
if (!ts_96_ns_ovf_reg[30]) begin
// if the overflow lookahead did not borrow, one second has elapsed
next_edge_s_next = next_rise_s_reg + period_s_reg + 1;
next_edge_ns_next = ts_96_ns_ovf_reg;
next_edge_fns_next = ts_96_fns_ovf_reg;
end else begin
// no increment seconds field
next_edge_s_next = next_rise_s_reg + period_s_reg;
next_edge_ns_next = ts_96_ns_inc_reg;
next_edge_fns_next = ts_96_fns_inc_reg;
end
next_rise_s_next = next_edge_s_next;
next_rise_ns_next = next_edge_ns_next;
next_rise_fns_next = next_edge_fns_next;
state_next = STATE_IDLE;
end
STATE_UPDATE_FALL: begin
if (!ts_96_ns_ovf_reg[30]) begin
// if the overflow lookahead did not borrow, one second has elapsed
next_edge_s_next = next_rise_s_reg + width_s_reg + 1;
next_edge_ns_next = ts_96_ns_ovf_reg;
next_edge_fns_next = ts_96_fns_ovf_reg;
end else begin
// no increment seconds field
next_edge_s_next = next_rise_s_reg + width_s_reg;
next_edge_ns_next = ts_96_ns_inc_reg;
next_edge_fns_next = ts_96_fns_inc_reg;
end
state_next = STATE_IDLE;
end
endcase

if (restart_reg || input_ts_step) begin
// set next rise and next edge to start time
next_rise_s_next = start_s_reg;
next_rise_ns_next = start_ns_reg;
if (FNS_ENABLE) begin
next_rise_fns_next = start_fns_reg;
end
next_edge_s_next = start_s_reg;
next_edge_ns_next = start_ns_reg;
if (FNS_ENABLE) begin
next_edge_fns_next = start_fns_reg;
end
locked_next = 1'b0;
ffwd_next = 1'b1;
output_next = 1'b0;
level_next = 1'b0;
error_next = input_ts_step;
state_next = STATE_IDLE;
end
end

always @(posedge clk) begin
state_reg <= state_next;
restart_reg <= 1'b0;

time_s_reg <= input_ts_96[95:48];
time_ns_reg <= input_ts_96[45:16];
Expand All @@ -253,6 +251,7 @@ always @(posedge clk) begin
if (FNS_ENABLE) begin
start_fns_reg <= input_start[15:0];
end
restart_reg <= 1'b1;
end

if (input_period_valid) begin
Expand All @@ -261,6 +260,7 @@ always @(posedge clk) begin
if (FNS_ENABLE) begin
period_fns_reg <= input_period[15:0];
end
restart_reg <= 1'b1;
end

if (input_width_valid) begin
Expand All @@ -277,10 +277,10 @@ always @(posedge clk) begin
next_rise_fns_reg <= next_rise_fns_next;
end

next_fall_s_reg <= next_fall_s_next;
next_fall_ns_reg <= next_fall_ns_next;
next_edge_s_reg <= next_edge_s_next;
next_edge_ns_reg <= next_edge_ns_next;
if (FNS_ENABLE) begin
next_fall_fns_reg <= next_fall_fns_next;
next_edge_fns_reg <= next_edge_fns_next;
end

ts_96_ns_inc_reg <= ts_96_ns_inc_next;
Expand Down Expand Up @@ -314,6 +314,7 @@ always @(posedge clk) begin
width_ns_reg <= OUT_WIDTH_NS;
width_fns_reg <= OUT_WIDTH_FNS;

restart_reg <= 1'b1;
locked_reg <= 1'b0;
error_reg <= 1'b0;
output_reg <= 1'b0;
Expand Down

0 comments on commit b4d09cb

Please sign in to comment.