From 060e55b915e2a11778c4927c3a70ff25653686c7 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 18 Sep 2023 16:39:30 -0700 Subject: [PATCH 01/12] Wait for correct PTP CDC instance to lock Signed-off-by: Alex Forencich --- tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py | 4 ++-- tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py index 5a3343087..0fe7ccaed 100644 --- a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py +++ b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py @@ -108,8 +108,8 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): await tb.reset() tb.log.info("Wait for PTP CDC lock") - while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer: - await RisingEdge(dut.tx_clk) + while not dut.rx_ptp.rx_ptp_cdc.locked.value.integer: + await RisingEdge(dut.rx_clk) test_frames = [payload_data(x) for x in payload_lengths()] tx_frames = [] diff --git a/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py b/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py index d6883df76..a4cd1b617 100644 --- a/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py +++ b/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py @@ -125,8 +125,8 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): await RisingEdge(dut.rx_clk) tb.log.info("Wait for PTP CDC lock") - while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer: - await RisingEdge(dut.tx_clk) + while not dut.rx_ptp.rx_ptp_cdc.locked.value.integer: + await RisingEdge(dut.rx_clk) # clear out sink buffer tb.axis_sink.clear() From 98b4fbb56d26d2ea2104a44340d933d48293772a Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 18 Sep 2023 16:58:02 -0700 Subject: [PATCH 02/12] Remove USE_SAMPLE_CLOCK parameter in PTP CDC module Signed-off-by: Alex Forencich --- rtl/eth_mac_10g_fifo.v | 7 +- rtl/eth_mac_phy_10g_fifo.v | 7 +- rtl/ptp_clock_cdc.v | 106 ++++++------------ tb/eth_mac_10g_fifo/Makefile | 1 - tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py | 9 +- tb/eth_mac_phy_10g_fifo/Makefile | 1 - .../test_eth_mac_phy_10g_fifo.py | 9 +- tb/ptp_clock_cdc/Makefile | 1 - tb/ptp_clock_cdc/test_ptp_clock_cdc.py | 4 +- 9 files changed, 46 insertions(+), 99 deletions(-) diff --git a/rtl/eth_mac_10g_fifo.v b/rtl/eth_mac_10g_fifo.v index 7bba80a28..4a393320c 100644 --- a/rtl/eth_mac_10g_fifo.v +++ b/rtl/eth_mac_10g_fifo.v @@ -55,7 +55,6 @@ module eth_mac_10g_fifo # parameter RX_DROP_WHEN_FULL = RX_DROP_OVERSIZE_FRAME, parameter PTP_PERIOD_NS = 4'h6, parameter PTP_PERIOD_FNS = 16'h6666, - parameter PTP_USE_SAMPLE_CLOCK = 0, parameter TX_PTP_TS_ENABLE = 0, parameter RX_PTP_TS_ENABLE = TX_PTP_TS_ENABLE, parameter TX_PTP_TS_CTRL_IN_TUSER = 0, @@ -229,8 +228,7 @@ if (TX_PTP_TS_ENABLE) begin : tx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), .NS_WIDTH(6), - .FNS_WIDTH(16), - .USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK) + .FNS_WIDTH(16) ) tx_ptp_cdc ( .input_clk(logic_clk), @@ -306,8 +304,7 @@ if (RX_PTP_TS_ENABLE) begin : rx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), .NS_WIDTH(6), - .FNS_WIDTH(16), - .USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK) + .FNS_WIDTH(16) ) rx_ptp_cdc ( .input_clk(logic_clk), diff --git a/rtl/eth_mac_phy_10g_fifo.v b/rtl/eth_mac_phy_10g_fifo.v index 25c1a7ac4..9d219d30b 100644 --- a/rtl/eth_mac_phy_10g_fifo.v +++ b/rtl/eth_mac_phy_10g_fifo.v @@ -63,7 +63,6 @@ module eth_mac_phy_10g_fifo # parameter RX_DROP_WHEN_FULL = RX_DROP_OVERSIZE_FRAME, parameter PTP_PERIOD_NS = 4'h6, parameter PTP_PERIOD_FNS = 16'h6666, - parameter PTP_USE_SAMPLE_CLOCK = 0, parameter TX_PTP_TS_ENABLE = 0, parameter RX_PTP_TS_ENABLE = TX_PTP_TS_ENABLE, parameter TX_PTP_TS_CTRL_IN_TUSER = 0, @@ -258,8 +257,7 @@ if (TX_PTP_TS_ENABLE) begin : tx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), .NS_WIDTH(6), - .FNS_WIDTH(16), - .USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK) + .FNS_WIDTH(16) ) tx_ptp_cdc ( .input_clk(logic_clk), @@ -335,8 +333,7 @@ if (RX_PTP_TS_ENABLE) begin : rx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), .NS_WIDTH(6), - .FNS_WIDTH(16), - .USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK) + .FNS_WIDTH(16) ) rx_ptp_cdc ( .input_clk(logic_clk), diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index 5dd32167a..19db941f8 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -36,7 +36,6 @@ module ptp_clock_cdc # parameter TS_WIDTH = 96, parameter NS_WIDTH = 4, parameter FNS_WIDTH = 16, - parameter USE_SAMPLE_CLOCK = 1, parameter LOG_RATE = 3, parameter PIPELINE_OUTPUT = 0 ) @@ -304,37 +303,35 @@ reg edge_2_reg = 1'b0; reg [3:0] active_reg = 0; always @(posedge sample_clk) begin - if (USE_SAMPLE_CLOCK) begin - // phase and frequency detector - if (dest_sync_sample_sync2_reg && !dest_sync_sample_sync3_reg) begin - if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin - edge_1_reg <= 1'b0; - edge_2_reg <= 1'b0; - end else begin - edge_1_reg <= !edge_2_reg; - edge_2_reg <= 1'b0; - end - end else if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin - edge_1_reg <= 1'b0; - edge_2_reg <= !edge_1_reg; - end - - // accumulator - sample_acc_reg <= $signed(sample_acc_reg) + $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg}); - - sample_cnt_reg <= sample_cnt_reg + 1; - + // phase and frequency detector + if (dest_sync_sample_sync2_reg && !dest_sync_sample_sync3_reg) begin if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin - active_reg[0] <= 1'b1; + edge_1_reg <= 1'b0; + edge_2_reg <= 1'b0; + end else begin + edge_1_reg <= !edge_2_reg; + edge_2_reg <= 1'b0; end + end else if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin + edge_1_reg <= 1'b0; + edge_2_reg <= !edge_1_reg; + end - if (sample_cnt_reg == 0) begin - active_reg <= {active_reg, src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg}; - sample_acc_reg <= $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg}); - sample_acc_out_reg <= sample_acc_reg; - if (active_reg != 0) begin - sample_update_reg <= !sample_update_reg; - end + // accumulator + sample_acc_reg <= $signed(sample_acc_reg) + $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg}); + + sample_cnt_reg <= sample_cnt_reg + 1; + + if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin + active_reg[0] <= 1'b1; + end + + if (sample_cnt_reg == 0) begin + active_reg <= {active_reg, src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg}; + sample_acc_reg <= $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg}); + sample_acc_out_reg <= sample_acc_reg; + if (active_reg != 0) begin + sample_update_reg <= !sample_update_reg; end end end @@ -348,50 +345,6 @@ end reg [SAMPLE_ACC_WIDTH-1:0] sample_acc_sync_reg = 0; reg sample_acc_sync_valid_reg = 0; -always @(posedge output_clk) begin - if (USE_SAMPLE_CLOCK) begin - // latch in synchronized counts from phase detector - sample_acc_sync_valid_reg <= 1'b0; - if (sample_update_sync2_reg ^ sample_update_sync3_reg) begin - sample_acc_sync_reg <= sample_acc_out_reg; - sample_acc_sync_valid_reg <= 1'b1; - end - end else begin - // phase and frequency detector - if (dest_sync_sync2_reg && !dest_sync_sync3_reg) begin - if (src_sync_sync2_reg && !src_sync_sync3_reg) begin - edge_1_reg <= 1'b0; - edge_2_reg <= 1'b0; - end else begin - edge_1_reg <= !edge_2_reg; - edge_2_reg <= 1'b0; - end - end else if (src_sync_sync2_reg && !src_sync_sync3_reg) begin - edge_1_reg <= 1'b0; - edge_2_reg <= !edge_1_reg; - end - - // accumulator - sample_acc_reg <= $signed(sample_acc_reg) + $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg}); - - sample_cnt_reg <= sample_cnt_reg + 1; - - if (src_sync_sync2_reg && !src_sync_sync3_reg) begin - active_reg[0] <= 1'b1; - end - - sample_acc_sync_valid_reg <= 1'b0; - if (sample_cnt_reg == 0) begin - active_reg <= {active_reg, src_sync_sync2_reg && !src_sync_sync3_reg}; - sample_acc_reg <= $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg}); - sample_acc_sync_reg <= sample_acc_reg; - if (active_reg != 0) begin - sample_acc_sync_valid_reg <= 1'b1; - end - end - end -end - reg [PHASE_ACC_WIDTH-1:0] dest_err_int_reg = 0, dest_err_int_next = 0; reg [1:0] dest_ovf; @@ -464,6 +417,13 @@ always @(posedge output_clk) begin dest_phase_inc_reg <= dest_phase_inc_next; dest_update_reg <= dest_update_next; + sample_acc_sync_valid_reg <= 1'b0; + if (sample_update_sync2_reg ^ sample_update_sync3_reg) begin + // latch in synchronized counts from phase detector + sample_acc_sync_reg <= sample_acc_out_reg; + sample_acc_sync_valid_reg <= 1'b1; + end + if (dest_update_reg) begin // capture local TS if (PIPELINE_OUTPUT > 0) begin diff --git a/tb/eth_mac_10g_fifo/Makefile b/tb/eth_mac_10g_fifo/Makefile index ae8109a08..2a85805e9 100644 --- a/tb/eth_mac_10g_fifo/Makefile +++ b/tb/eth_mac_10g_fifo/Makefile @@ -64,7 +64,6 @@ export PARAM_RX_DROP_BAD_FRAME := $(PARAM_RX_DROP_OVERSIZE_FRAME) export PARAM_RX_DROP_WHEN_FULL := $(PARAM_RX_DROP_OVERSIZE_FRAME) export PARAM_PTP_PERIOD_NS := 6 export PARAM_PTP_PERIOD_FNS := 26214 -export PARAM_PTP_USE_SAMPLE_CLOCK := 0 export PARAM_TX_PTP_TS_ENABLE := 1 export PARAM_RX_PTP_TS_ENABLE := $(PARAM_TX_PTP_TS_ENABLE) export PARAM_TX_PTP_TS_CTRL_IN_TUSER := $(PARAM_TX_PTP_TS_ENABLE) diff --git a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py index 0fe7ccaed..fe98b8de3 100644 --- a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py +++ b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py @@ -62,6 +62,7 @@ class TB: cocotb.start_soon(Clock(dut.logic_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.ptp_sample_clk, 9.9, units="ns").start()) self.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst) self.xgmii_sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst) @@ -72,7 +73,6 @@ class TB: self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts_96, clock=dut.logic_clk) self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst) - dut.ptp_sample_clk.setimmediatevalue(0) dut.ptp_ts_step.setimmediatevalue(0) dut.cfg_ifg.setimmediatevalue(0) @@ -138,7 +138,7 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.tdata == test_data assert frame_error == 0 - assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period*2 assert tb.axis_sink.empty() @@ -184,7 +184,7 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2 assert tb.xgmii_sink.empty() @@ -240,7 +240,7 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2 start_lane.append(rx_frame.start_lane) @@ -365,7 +365,6 @@ def test_eth_mac_10g_fifo(request, data_width, enable_dic): parameters['RX_DROP_WHEN_FULL'] = parameters['RX_DROP_OVERSIZE_FRAME'] parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3 parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333 - parameters['PTP_USE_SAMPLE_CLOCK'] = 0 parameters['TX_PTP_TS_ENABLE'] = 1 parameters['RX_PTP_TS_ENABLE'] = parameters['TX_PTP_TS_ENABLE'] parameters['TX_PTP_TS_CTRL_IN_TUSER'] = parameters['TX_PTP_TS_ENABLE'] diff --git a/tb/eth_mac_phy_10g_fifo/Makefile b/tb/eth_mac_phy_10g_fifo/Makefile index c44570970..9d94621aa 100644 --- a/tb/eth_mac_phy_10g_fifo/Makefile +++ b/tb/eth_mac_phy_10g_fifo/Makefile @@ -69,7 +69,6 @@ export PARAM_RX_DROP_BAD_FRAME := $(PARAM_RX_DROP_OVERSIZE_FRAME) export PARAM_RX_DROP_WHEN_FULL := $(PARAM_RX_DROP_OVERSIZE_FRAME) export PARAM_PTP_PERIOD_NS := 6 export PARAM_PTP_PERIOD_FNS := 26214 -export PARAM_PTP_USE_SAMPLE_CLOCK := 0 export PARAM_TX_PTP_TS_ENABLE := 1 export PARAM_RX_PTP_TS_ENABLE := $(PARAM_TX_PTP_TS_ENABLE) export PARAM_TX_PTP_TS_CTRL_IN_TUSER := $(PARAM_TX_PTP_TS_ENABLE) diff --git a/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py b/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py index a4cd1b617..6382e822a 100644 --- a/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py +++ b/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py @@ -73,6 +73,7 @@ class TB: cocotb.start_soon(Clock(dut.logic_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.ptp_sample_clk, 9.9, units="ns").start()) self.serdes_source = BaseRSerdesSource(dut.serdes_rx_data, dut.serdes_rx_hdr, dut.rx_clk, slip=dut.serdes_rx_bitslip) self.serdes_sink = BaseRSerdesSink(dut.serdes_tx_data, dut.serdes_tx_hdr, dut.tx_clk) @@ -83,7 +84,6 @@ class TB: self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts_96, clock=dut.logic_clk) self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst) - dut.ptp_sample_clk.setimmediatevalue(0) dut.ptp_ts_step.setimmediatevalue(0) dut.cfg_ifg.setimmediatevalue(0) @@ -158,7 +158,7 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.tdata == test_data assert frame_error == 0 - assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*4) < tb.clk_period + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*4) < tb.clk_period*2 assert tb.axis_sink.empty() @@ -204,7 +204,7 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*5) < tb.clk_period + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*5) < tb.clk_period*2 assert tb.serdes_sink.empty() @@ -260,7 +260,7 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*5) < tb.clk_period + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*5) < tb.clk_period*2 start_lane.append(rx_frame.start_lane) @@ -431,7 +431,6 @@ def test_eth_mac_phy_10g_fifo(request, data_width, enable_dic): parameters['RX_DROP_WHEN_FULL'] = parameters['RX_DROP_OVERSIZE_FRAME'] parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3 parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333 - parameters['PTP_USE_SAMPLE_CLOCK'] = 0 parameters['TX_PTP_TS_ENABLE'] = 1 parameters['RX_PTP_TS_ENABLE'] = parameters['TX_PTP_TS_ENABLE'] parameters['TX_PTP_TS_CTRL_IN_TUSER'] = parameters['TX_PTP_TS_ENABLE'] diff --git a/tb/ptp_clock_cdc/Makefile b/tb/ptp_clock_cdc/Makefile index 2272408ed..2bf883844 100644 --- a/tb/ptp_clock_cdc/Makefile +++ b/tb/ptp_clock_cdc/Makefile @@ -35,7 +35,6 @@ VERILOG_SOURCES += ../../rtl/$(DUT).v export PARAM_TS_WIDTH := 96 export PARAM_NS_WIDTH := 4 export PARAM_FNS_WIDTH := 16 -export PARAM_USE_SAMPLE_CLOCK := 1 export PARAM_LOG_RATE := 3 export PARAM_PIPELINE_OUTPUT := 0 diff --git a/tb/ptp_clock_cdc/test_ptp_clock_cdc.py b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py index 66cfd37a6..f3839ba33 100644 --- a/tb/ptp_clock_cdc/test_ptp_clock_cdc.py +++ b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py @@ -229,9 +229,8 @@ lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) -@pytest.mark.parametrize("sample_clock", [1, 0]) @pytest.mark.parametrize("ts_width", [96, 64]) -def test_ptp_clock_cdc(request, ts_width, sample_clock): +def test_ptp_clock_cdc(request, ts_width): dut = "ptp_clock_cdc" module = os.path.splitext(os.path.basename(__file__))[0] toplevel = dut @@ -245,7 +244,6 @@ def test_ptp_clock_cdc(request, ts_width, sample_clock): parameters['TS_WIDTH'] = ts_width parameters['NS_WIDTH'] = 4 parameters['FNS_WIDTH'] = 16 - parameters['USE_SAMPLE_CLOCK'] = sample_clock parameters['LOG_RATE'] = 3 parameters['PIPELINE_OUTPUT'] = 0 From aad30d09a1e35441d5b395fb416c0144f7d24c8e Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Thu, 21 Sep 2023 16:30:29 -0700 Subject: [PATCH 03/12] Make FNS_WIDTH an internal parameter in PTP CDC module Signed-off-by: Alex Forencich --- rtl/eth_mac_10g_fifo.v | 6 ++---- rtl/eth_mac_phy_10g_fifo.v | 6 ++---- rtl/ptp_clock_cdc.v | 3 ++- tb/ptp_clock_cdc/Makefile | 1 - tb/ptp_clock_cdc/test_ptp_clock_cdc.py | 1 - 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/rtl/eth_mac_10g_fifo.v b/rtl/eth_mac_10g_fifo.v index 4a393320c..32272cebb 100644 --- a/rtl/eth_mac_10g_fifo.v +++ b/rtl/eth_mac_10g_fifo.v @@ -227,8 +227,7 @@ if (TX_PTP_TS_ENABLE) begin : tx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), - .NS_WIDTH(6), - .FNS_WIDTH(16) + .NS_WIDTH(6) ) tx_ptp_cdc ( .input_clk(logic_clk), @@ -303,8 +302,7 @@ if (RX_PTP_TS_ENABLE) begin : rx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), - .NS_WIDTH(6), - .FNS_WIDTH(16) + .NS_WIDTH(6) ) rx_ptp_cdc ( .input_clk(logic_clk), diff --git a/rtl/eth_mac_phy_10g_fifo.v b/rtl/eth_mac_phy_10g_fifo.v index 9d219d30b..be84e7ac4 100644 --- a/rtl/eth_mac_phy_10g_fifo.v +++ b/rtl/eth_mac_phy_10g_fifo.v @@ -256,8 +256,7 @@ if (TX_PTP_TS_ENABLE) begin : tx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), - .NS_WIDTH(6), - .FNS_WIDTH(16) + .NS_WIDTH(6) ) tx_ptp_cdc ( .input_clk(logic_clk), @@ -332,8 +331,7 @@ if (RX_PTP_TS_ENABLE) begin : rx_ptp ptp_clock_cdc #( .TS_WIDTH(PTP_TS_WIDTH), - .NS_WIDTH(6), - .FNS_WIDTH(16) + .NS_WIDTH(6) ) rx_ptp_cdc ( .input_clk(logic_clk), diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index 19db941f8..780711156 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -35,7 +35,6 @@ module ptp_clock_cdc # ( parameter TS_WIDTH = 96, parameter NS_WIDTH = 4, - parameter FNS_WIDTH = 16, parameter LOG_RATE = 3, parameter PIPELINE_OUTPUT = 0 ) @@ -77,6 +76,8 @@ initial begin end end +parameter FNS_WIDTH = 16; + parameter TS_NS_WIDTH = TS_WIDTH == 96 ? 30 : 48; parameter PHASE_CNT_WIDTH = LOG_RATE; diff --git a/tb/ptp_clock_cdc/Makefile b/tb/ptp_clock_cdc/Makefile index 2bf883844..9fdff623b 100644 --- a/tb/ptp_clock_cdc/Makefile +++ b/tb/ptp_clock_cdc/Makefile @@ -34,7 +34,6 @@ VERILOG_SOURCES += ../../rtl/$(DUT).v # module parameters export PARAM_TS_WIDTH := 96 export PARAM_NS_WIDTH := 4 -export PARAM_FNS_WIDTH := 16 export PARAM_LOG_RATE := 3 export PARAM_PIPELINE_OUTPUT := 0 diff --git a/tb/ptp_clock_cdc/test_ptp_clock_cdc.py b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py index f3839ba33..8782fdbbd 100644 --- a/tb/ptp_clock_cdc/test_ptp_clock_cdc.py +++ b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py @@ -243,7 +243,6 @@ def test_ptp_clock_cdc(request, ts_width): parameters['TS_WIDTH'] = ts_width parameters['NS_WIDTH'] = 4 - parameters['FNS_WIDTH'] = 16 parameters['LOG_RATE'] = 3 parameters['PIPELINE_OUTPUT'] = 0 From 4b1f48ab5bd3dc6201e5987a4a10f3d3f1ada5eb Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Thu, 21 Sep 2023 16:34:05 -0700 Subject: [PATCH 04/12] Parameter clean-up in PTP CDC module Signed-off-by: Alex Forencich --- rtl/ptp_clock_cdc.v | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index 780711156..062a241e7 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -76,18 +76,21 @@ initial begin end end -parameter FNS_WIDTH = 16; +localparam FNS_WIDTH = 16; -parameter TS_NS_WIDTH = TS_WIDTH == 96 ? 30 : 48; +localparam TS_NS_WIDTH = TS_WIDTH == 96 ? 30 : 48; +localparam TS_FNS_WIDTH = FNS_WIDTH > 16 ? 16 : FNS_WIDTH; -parameter PHASE_CNT_WIDTH = LOG_RATE; -parameter PHASE_ACC_WIDTH = PHASE_CNT_WIDTH+16; +localparam PHASE_CNT_WIDTH = LOG_RATE; +localparam PHASE_ACC_WIDTH = PHASE_CNT_WIDTH+16; -parameter LOG_SAMPLE_SYNC_RATE = LOG_RATE; -parameter SAMPLE_ACC_WIDTH = LOG_SAMPLE_SYNC_RATE+2; +localparam LOG_SAMPLE_SYNC_RATE = LOG_RATE; +localparam SAMPLE_ACC_WIDTH = LOG_SAMPLE_SYNC_RATE+2; -parameter DEST_SYNC_LOCK_WIDTH = 7; -parameter PTP_LOCK_WIDTH = 8; +localparam DEST_SYNC_LOCK_WIDTH = 7; +localparam PTP_LOCK_WIDTH = 8; + +localparam TIME_ERR_INT_WIDTH = NS_WIDTH+FNS_WIDTH+16; localparam [30:0] NS_PER_S = 31'd1_000_000_000; @@ -100,16 +103,16 @@ reg [FNS_WIDTH-1:0] period_fns_ovf_reg = 0, period_fns_ovf_next; reg [47:0] src_ts_s_capt_reg = 0; reg [TS_NS_WIDTH-1:0] src_ts_ns_capt_reg = 0; -reg [FNS_WIDTH-1:0] src_ts_fns_capt_reg = 0; +reg [TS_FNS_WIDTH-1:0] src_ts_fns_capt_reg = 0; reg src_ts_step_capt_reg = 0; reg [47:0] dest_ts_s_capt_reg = 0; reg [TS_NS_WIDTH-1:0] dest_ts_ns_capt_reg = 0; -reg [FNS_WIDTH-1:0] dest_ts_fns_capt_reg = 0; +reg [TS_FNS_WIDTH-1:0] dest_ts_fns_capt_reg = 0; reg [47:0] ts_s_sync_reg = 0; reg [TS_NS_WIDTH-1:0] ts_ns_sync_reg = 0; -reg [FNS_WIDTH-1:0] ts_fns_sync_reg = 0; +reg [TS_FNS_WIDTH-1:0] ts_fns_sync_reg = 0; reg ts_step_sync_reg = 0; reg [47:0] ts_s_reg = 0, ts_s_next; @@ -126,7 +129,7 @@ reg pps_reg = 1'b0; reg [47:0] ts_s_pipe_reg[0:PIPELINE_OUTPUT-1]; reg [TS_NS_WIDTH-1:0] ts_ns_pipe_reg[0:PIPELINE_OUTPUT-1]; -reg [FNS_WIDTH-1:0] ts_fns_pipe_reg[0:PIPELINE_OUTPUT-1]; +reg [TS_FNS_WIDTH-1:0] ts_fns_pipe_reg[0:PIPELINE_OUTPUT-1]; reg ts_step_pipe_reg[0:PIPELINE_OUTPUT-1]; reg pps_pipe_reg[0:PIPELINE_OUTPUT-1]; @@ -264,7 +267,7 @@ always @(posedge input_clk) begin end else begin src_ts_ns_capt_reg <= input_ts[63:16]; end - src_ts_fns_capt_reg <= FNS_WIDTH > 16 ? input_ts[15:0] << (FNS_WIDTH-16) : input_ts[15:0] >> (16-FNS_WIDTH); + src_ts_fns_capt_reg <= input_ts[15:0] >> (16-TS_FNS_WIDTH); src_ts_step_capt_reg <= input_ts_step || input_ts_step_reg; input_ts_step_reg <= 1'b0; src_sync_reg <= !src_sync_reg; @@ -434,7 +437,7 @@ always @(posedge output_clk) begin end else begin dest_ts_s_capt_reg <= ts_s_reg; dest_ts_ns_capt_reg <= ts_ns_reg; - dest_ts_fns_capt_reg <= ts_fns_reg; + dest_ts_fns_capt_reg <= {ts_fns_reg, 16'd0} >> FNS_WIDTH; end dest_sync_reg <= !dest_sync_reg; @@ -477,8 +480,6 @@ always @(posedge output_clk) begin end end -parameter TIME_ERR_INT_WIDTH = NS_WIDTH+FNS_WIDTH+16; - reg sec_mismatch_reg = 1'b0, sec_mismatch_next; reg diff_valid_reg = 1'b0, diff_valid_next; reg diff_corr_valid_reg = 1'b0, diff_corr_valid_next; @@ -486,10 +487,10 @@ reg diff_corr_valid_reg = 1'b0, diff_corr_valid_next; reg ts_s_msb_diff_reg = 1'b0, ts_s_msb_diff_next; reg [7:0] ts_s_diff_reg = 0, ts_s_diff_next; reg [TS_NS_WIDTH+1-1:0] ts_ns_diff_reg = 0, ts_ns_diff_next; -reg [FNS_WIDTH-1:0] ts_fns_diff_reg = 0, ts_fns_diff_next; +reg [TS_FNS_WIDTH-1:0] ts_fns_diff_reg = 0, ts_fns_diff_next; reg [16:0] ts_ns_diff_corr_reg = 0, ts_ns_diff_corr_next; -reg [FNS_WIDTH-1:0] ts_fns_diff_corr_reg = 0, ts_fns_diff_corr_next; +reg [TS_FNS_WIDTH-1:0] ts_fns_diff_corr_reg = 0, ts_fns_diff_corr_next; reg [TIME_ERR_INT_WIDTH-1:0] time_err_int_reg = 0, time_err_int_next; From cf441f004dd5ada2ca51e85d292830bf3c444793 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 22 Sep 2023 01:07:12 -0700 Subject: [PATCH 05/12] Rename source sync signals in PTP CDC module for consistency Signed-off-by: Alex Forencich --- rtl/ptp_clock_cdc.v | 42 ++++++++++++++++++------------------ syn/vivado/ptp_clock_cdc.tcl | 18 ++++++++-------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index 062a241e7..ea73773e9 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -110,10 +110,10 @@ reg [47:0] dest_ts_s_capt_reg = 0; reg [TS_NS_WIDTH-1:0] dest_ts_ns_capt_reg = 0; reg [TS_FNS_WIDTH-1:0] dest_ts_fns_capt_reg = 0; -reg [47:0] ts_s_sync_reg = 0; -reg [TS_NS_WIDTH-1:0] ts_ns_sync_reg = 0; -reg [TS_FNS_WIDTH-1:0] ts_fns_sync_reg = 0; -reg ts_step_sync_reg = 0; +reg [47:0] src_ts_s_sync_reg = 0; +reg [TS_NS_WIDTH-1:0] src_ts_ns_sync_reg = 0; +reg [TS_FNS_WIDTH-1:0] src_ts_fns_sync_reg = 0; +reg src_ts_step_sync_reg = 0; reg [47:0] ts_s_reg = 0, ts_s_next; reg [TS_NS_WIDTH-1:0] ts_ns_reg = 0, ts_ns_next; @@ -449,11 +449,11 @@ always @(posedge output_clk) begin if (src_sync_sync2_reg ^ src_sync_sync3_reg) begin // store captured source TS if (TS_WIDTH == 96) begin - ts_s_sync_reg <= src_ts_s_capt_reg; + src_ts_s_sync_reg <= src_ts_s_capt_reg; end - ts_ns_sync_reg <= src_ts_ns_capt_reg; - ts_fns_sync_reg <= src_ts_fns_capt_reg; - ts_step_sync_reg <= src_ts_step_capt_reg; + src_ts_ns_sync_reg <= src_ts_ns_capt_reg; + src_ts_fns_sync_reg <= src_ts_fns_capt_reg; + src_ts_step_sync_reg <= src_ts_step_capt_reg; ts_sync_valid_reg <= ts_capt_valid_reg; ts_capt_valid_reg <= 1'b0; @@ -561,16 +561,16 @@ always @* begin if (ts_sync_valid_reg) begin // Read new value if (TS_WIDTH == 96) begin - if (ts_step_sync_reg || sec_mismatch_reg) begin + if (src_ts_step_sync_reg || sec_mismatch_reg) begin // input stepped sec_mismatch_next = 1'b0; - ts_s_next = ts_s_sync_reg; - ts_ns_next = ts_ns_sync_reg; - ts_ns_inc_next = ts_ns_sync_reg; + ts_s_next = src_ts_s_sync_reg; + ts_ns_next = src_ts_ns_sync_reg; + ts_ns_inc_next = src_ts_ns_sync_reg; ts_ns_ovf_next[30] = 1'b1; - ts_fns_next = ts_fns_sync_reg; - ts_fns_inc_next = ts_fns_sync_reg; + ts_fns_next = src_ts_fns_sync_reg; + ts_fns_inc_next = src_ts_fns_sync_reg; ts_step_next = 1; end else begin // input did not step @@ -578,16 +578,16 @@ always @* begin diff_valid_next = 1'b1; end // compute difference - ts_s_msb_diff_next = ts_s_sync_reg[47:8] != dest_ts_s_capt_reg[47:8]; - ts_s_diff_next = ts_s_sync_reg[7:0] - dest_ts_s_capt_reg[7:0]; - {ts_ns_diff_next, ts_fns_diff_next} = {ts_ns_sync_reg, ts_fns_sync_reg} - {dest_ts_ns_capt_reg, dest_ts_fns_capt_reg}; + ts_s_msb_diff_next = src_ts_s_sync_reg[47:8] != dest_ts_s_capt_reg[47:8]; + ts_s_diff_next = src_ts_s_sync_reg[7:0] - dest_ts_s_capt_reg[7:0]; + {ts_ns_diff_next, ts_fns_diff_next} = {src_ts_ns_sync_reg, src_ts_fns_sync_reg} - {dest_ts_ns_capt_reg, dest_ts_fns_capt_reg}; end else if (TS_WIDTH == 64) begin - if (ts_step_sync_reg || sec_mismatch_reg) begin + if (src_ts_step_sync_reg || sec_mismatch_reg) begin // input stepped sec_mismatch_next = 1'b0; - ts_ns_next = ts_ns_sync_reg; - ts_fns_next = ts_fns_sync_reg; + ts_ns_next = src_ts_ns_sync_reg; + ts_fns_next = src_ts_fns_sync_reg; ts_step_next = 1; end else begin // input did not step @@ -595,7 +595,7 @@ always @* begin diff_valid_next = 1'b1; end // compute difference - {ts_ns_diff_next, ts_fns_diff_next} = {ts_ns_sync_reg, ts_fns_sync_reg} - {dest_ts_ns_capt_reg, dest_ts_fns_capt_reg}; + {ts_ns_diff_next, ts_fns_diff_next} = {src_ts_ns_sync_reg, src_ts_fns_sync_reg} - {dest_ts_ns_capt_reg, dest_ts_fns_capt_reg}; end end diff --git a/syn/vivado/ptp_clock_cdc.tcl b/syn/vivado/ptp_clock_cdc.tcl index a51364781..9974c7b26 100644 --- a/syn/vivado/ptp_clock_cdc.tcl +++ b/syn/vivado/ptp_clock_cdc.tcl @@ -31,22 +31,22 @@ foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_clock_cdc || REF_NA set output_clk_period [if {[llength $output_clk]} {get_property -min PERIOD $output_clk} {expr 1.0}] # timestamp synchronization - set_property ASYNC_REG TRUE [get_cells -hier -regexp ".*/ts_(s|ns|fns|step)_sync_reg_reg(\\\[\\d+\\\])?" -filter "PARENT == $inst"] + set_property ASYNC_REG TRUE [get_cells -hier -regexp ".*/src_ts_(s|ns|fns|step)_sync_reg_reg(\\\[\\d+\\\])?" -filter "PARENT == $inst"] if {[llength [get_cells "$inst/src_ts_s_capt_reg_reg[*]"]]} { - set_max_delay -from [get_cells "$inst/src_ts_s_capt_reg_reg[*]"] -to [get_cells "$inst/ts_s_sync_reg_reg[*]"] -datapath_only $output_clk_period - set_bus_skew -from [get_cells "$inst/src_ts_s_capt_reg_reg[*]"] -to [get_cells "$inst/ts_s_sync_reg_reg[*]"] $input_clk_period + set_max_delay -from [get_cells "$inst/src_ts_s_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_s_sync_reg_reg[*]"] -datapath_only $output_clk_period + set_bus_skew -from [get_cells "$inst/src_ts_s_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_s_sync_reg_reg[*]"] $input_clk_period } - set_max_delay -from [get_cells "$inst/src_ts_ns_capt_reg_reg[*]"] -to [get_cells "$inst/ts_ns_sync_reg_reg[*]"] -datapath_only $output_clk_period - set_bus_skew -from [get_cells "$inst/src_ts_ns_capt_reg_reg[*]"] -to [get_cells "$inst/ts_ns_sync_reg_reg[*]"] $input_clk_period + set_max_delay -from [get_cells "$inst/src_ts_ns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_ns_sync_reg_reg[*]"] -datapath_only $output_clk_period + set_bus_skew -from [get_cells "$inst/src_ts_ns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_ns_sync_reg_reg[*]"] $input_clk_period - set_max_delay -from [get_cells "$inst/src_ts_fns_capt_reg_reg[*]"] -to [get_cells "$inst/ts_fns_sync_reg_reg[*]"] -datapath_only $output_clk_period - set_bus_skew -from [get_cells "$inst/src_ts_fns_capt_reg_reg[*]"] -to [get_cells "$inst/ts_fns_sync_reg_reg[*]"] $input_clk_period + set_max_delay -from [get_cells "$inst/src_ts_fns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_fns_sync_reg_reg[*]"] -datapath_only $output_clk_period + set_bus_skew -from [get_cells "$inst/src_ts_fns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_fns_sync_reg_reg[*]"] $input_clk_period if {[llength [get_cells "$inst/src_ts_step_capt_reg_reg"]]} { - set_max_delay -from [get_cells "$inst/src_ts_step_capt_reg_reg"] -to [get_cells "$inst/ts_step_sync_reg_reg"] -datapath_only $output_clk_period - set_bus_skew -from [get_cells "$inst/src_ts_step_capt_reg_reg"] -to [get_cells "$inst/ts_step_sync_reg_reg"] $input_clk_period + set_max_delay -from [get_cells "$inst/src_ts_step_capt_reg_reg"] -to [get_cells "$inst/src_ts_step_sync_reg_reg"] -datapath_only $output_clk_period + set_bus_skew -from [get_cells "$inst/src_ts_step_capt_reg_reg"] -to [get_cells "$inst/src_ts_step_sync_reg_reg"] $input_clk_period } # sample clock From 4a32c86f0791a3b4a7af457cb78c708adf3599bc Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 22 Sep 2023 01:07:43 -0700 Subject: [PATCH 06/12] Match integrator width to period register width in PTP CDC module Signed-off-by: Alex Forencich --- rtl/ptp_clock_cdc.v | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index ea73773e9..fb14cf6bc 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -90,7 +90,7 @@ localparam SAMPLE_ACC_WIDTH = LOG_SAMPLE_SYNC_RATE+2; localparam DEST_SYNC_LOCK_WIDTH = 7; localparam PTP_LOCK_WIDTH = 8; -localparam TIME_ERR_INT_WIDTH = NS_WIDTH+FNS_WIDTH+16; +localparam TIME_ERR_INT_WIDTH = NS_WIDTH+FNS_WIDTH; localparam [30:0] NS_PER_S = 31'd1_000_000_000; @@ -639,9 +639,9 @@ always @* begin // time integral of error if (ptp_locked_reg) begin - {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + $signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}); + {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**16); end else begin - {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) * 2**3); + {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**13); end // saturate @@ -655,9 +655,9 @@ always @* begin // compute output if (ptp_locked_reg) begin - {ptp_ovf, period_ns_next, period_fns_next} = ($signed({1'b0, time_err_int_reg}) / 2**16) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**10); + {ptp_ovf, period_ns_next, period_fns_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**10); end else begin - {ptp_ovf, period_ns_next, period_fns_next} = ($signed({1'b0, time_err_int_reg}) / 2**16) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**7); + {ptp_ovf, period_ns_next, period_fns_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**7); end // saturate From b0a4d75fd997cd794371e722a52988a9920b33b9 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 22 Sep 2023 01:08:01 -0700 Subject: [PATCH 07/12] Remove extraneous code Signed-off-by: Alex Forencich --- rtl/ptp_clock_cdc.v | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index fb14cf6bc..4b9e820c9 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -139,15 +139,12 @@ reg [PHASE_ACC_WIDTH-1:0] dest_phase_inc_reg = {PHASE_ACC_WIDTH{1'b0}}, dest_pha reg src_sync_reg = 1'b0; reg src_update_reg = 1'b0; -reg dest_sync_reg = 1'b0, dest_sync_next = 1'b0; +reg dest_sync_reg = 1'b0; reg dest_update_reg = 1'b0, dest_update_next = 1'b0; reg src_sync_sync1_reg = 1'b0; reg src_sync_sync2_reg = 1'b0; reg src_sync_sync3_reg = 1'b0; -reg dest_sync_sync1_reg = 1'b0; -reg dest_sync_sync2_reg = 1'b0; -reg dest_sync_sync3_reg = 1'b0; reg src_sync_sample_sync1_reg = 1'b0; reg src_sync_sample_sync2_reg = 1'b0; @@ -156,7 +153,7 @@ reg dest_sync_sample_sync1_reg = 1'b0; reg dest_sync_sample_sync2_reg = 1'b0; reg dest_sync_sample_sync3_reg = 1'b0; -reg [SAMPLE_ACC_WIDTH-1:0] sample_acc_reg = 0, sample_acc_next = 0; +reg [SAMPLE_ACC_WIDTH-1:0] sample_acc_reg = 0; reg [SAMPLE_ACC_WIDTH-1:0] sample_acc_out_reg = 0; reg [LOG_SAMPLE_SYNC_RATE-1:0] sample_cnt_reg = 0; reg sample_update_reg = 1'b0; @@ -287,9 +284,6 @@ always @(posedge output_clk) begin src_sync_sync1_reg <= src_sync_reg; src_sync_sync2_reg <= src_sync_sync1_reg; src_sync_sync3_reg <= src_sync_sync2_reg; - dest_sync_sync1_reg <= dest_sync_reg; - dest_sync_sync2_reg <= dest_sync_sync1_reg; - dest_sync_sync3_reg <= dest_sync_sync2_reg; end always @(posedge sample_clk) begin @@ -515,9 +509,6 @@ always @* begin ts_step_next = 0; - diff_valid_next = 1'b0; - diff_corr_valid_next = 1'b0; - sec_mismatch_next = sec_mismatch_reg; diff_valid_next = 1'b0; diff_corr_valid_next = 1'b0; From 5a37442706c25bce55d3f0893349f4c0428d95ec Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 22 Sep 2023 22:52:59 -0700 Subject: [PATCH 08/12] Merge FNS registers into NS registers in PTP CDC module Signed-off-by: Alex Forencich --- rtl/ptp_clock_cdc.v | 154 ++++++++++++----------------------- syn/vivado/ptp_clock_cdc.tcl | 5 +- 2 files changed, 54 insertions(+), 105 deletions(-) diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index 4b9e820c9..2f9042cbb 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -94,42 +94,32 @@ localparam TIME_ERR_INT_WIDTH = NS_WIDTH+FNS_WIDTH; localparam [30:0] NS_PER_S = 31'd1_000_000_000; -reg [NS_WIDTH-1:0] period_ns_reg = 0, period_ns_next; -reg [FNS_WIDTH-1:0] period_fns_reg = 0, period_fns_next; -reg [NS_WIDTH-1:0] period_ns_delay_reg = 0, period_ns_delay_next; -reg [FNS_WIDTH-1:0] period_fns_delay_reg = 0, period_fns_delay_next; -reg [30:0] period_ns_ovf_reg = 0, period_ns_ovf_next; -reg [FNS_WIDTH-1:0] period_fns_ovf_reg = 0, period_fns_ovf_next; +reg [NS_WIDTH+FNS_WIDTH-1:0] period_ns_reg = 0, period_ns_next; +reg [NS_WIDTH+FNS_WIDTH-1:0] period_ns_delay_reg = 0, period_ns_delay_next; +reg [31+FNS_WIDTH-1:0] period_ns_ovf_reg = 0, period_ns_ovf_next; reg [47:0] src_ts_s_capt_reg = 0; -reg [TS_NS_WIDTH-1:0] src_ts_ns_capt_reg = 0; -reg [TS_FNS_WIDTH-1:0] src_ts_fns_capt_reg = 0; +reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] src_ts_ns_capt_reg = 0; reg src_ts_step_capt_reg = 0; reg [47:0] dest_ts_s_capt_reg = 0; -reg [TS_NS_WIDTH-1:0] dest_ts_ns_capt_reg = 0; -reg [TS_FNS_WIDTH-1:0] dest_ts_fns_capt_reg = 0; +reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] dest_ts_ns_capt_reg = 0; reg [47:0] src_ts_s_sync_reg = 0; -reg [TS_NS_WIDTH-1:0] src_ts_ns_sync_reg = 0; -reg [TS_FNS_WIDTH-1:0] src_ts_fns_sync_reg = 0; +reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] src_ts_ns_sync_reg = 0; reg src_ts_step_sync_reg = 0; reg [47:0] ts_s_reg = 0, ts_s_next; -reg [TS_NS_WIDTH-1:0] ts_ns_reg = 0, ts_ns_next; -reg [FNS_WIDTH-1:0] ts_fns_reg = 0, ts_fns_next; -reg [TS_NS_WIDTH-1:0] ts_ns_inc_reg = 0, ts_ns_inc_next; -reg [FNS_WIDTH-1:0] ts_fns_inc_reg = 0, ts_fns_inc_next; -reg [TS_NS_WIDTH+1-1:0] ts_ns_ovf_reg = {TS_NS_WIDTH+1{1'b1}}, ts_ns_ovf_next; -reg [FNS_WIDTH-1:0] ts_fns_ovf_reg = {FNS_WIDTH{1'b1}}, ts_fns_ovf_next; +reg [TS_NS_WIDTH+FNS_WIDTH-1:0] ts_ns_reg = 0, ts_ns_next; +reg [TS_NS_WIDTH+FNS_WIDTH-1:0] ts_ns_inc_reg = 0, ts_ns_inc_next; +reg [TS_NS_WIDTH+FNS_WIDTH+1-1:0] ts_ns_ovf_reg = {TS_NS_WIDTH+FNS_WIDTH+1{1'b1}}, ts_ns_ovf_next; reg ts_step_reg = 1'b0, ts_step_next; reg pps_reg = 1'b0; reg [47:0] ts_s_pipe_reg[0:PIPELINE_OUTPUT-1]; -reg [TS_NS_WIDTH-1:0] ts_ns_pipe_reg[0:PIPELINE_OUTPUT-1]; -reg [TS_FNS_WIDTH-1:0] ts_fns_pipe_reg[0:PIPELINE_OUTPUT-1]; +reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] ts_ns_pipe_reg[0:PIPELINE_OUTPUT-1]; reg ts_step_pipe_reg[0:PIPELINE_OUTPUT-1]; reg pps_pipe_reg[0:PIPELINE_OUTPUT-1]; @@ -191,11 +181,9 @@ if (PIPELINE_OUTPUT > 0) begin if (TS_WIDTH == 96) begin output_ts_reg[0][95:48] <= ts_s_reg; output_ts_reg[0][47:46] <= 2'b00; - output_ts_reg[0][45:16] <= ts_ns_reg; - output_ts_reg[0][15:0] <= {ts_fns_reg, 16'd0} >> FNS_WIDTH; + output_ts_reg[0][45:0] <= {ts_ns_reg, 16'd0} >> FNS_WIDTH; end else if (TS_WIDTH == 64) begin - output_ts_reg[0][63:16] <= ts_ns_reg; - output_ts_reg[0][15:0] <= {ts_fns_reg, 16'd0} >> FNS_WIDTH; + output_ts_reg[0] <= {ts_ns_reg, 16'd0} >> FNS_WIDTH; end output_ts_step_reg[0] <= ts_step_reg; @@ -221,11 +209,9 @@ end else begin if (TS_WIDTH == 96) begin assign output_ts[95:48] = ts_s_reg; assign output_ts[47:46] = 2'b00; - assign output_ts[45:16] = ts_ns_reg; - assign output_ts[15:0] = {ts_fns_reg, 16'd0} >> FNS_WIDTH; + assign output_ts[45:0] = {ts_ns_reg, 16'd0} >> FNS_WIDTH; end else if (TS_WIDTH == 64) begin - assign output_ts[63:16] = ts_ns_reg; - assign output_ts[15:0] = {ts_fns_reg, 16'd0} >> FNS_WIDTH; + assign output_ts = {ts_ns_reg, 16'd0} >> FNS_WIDTH; end assign output_ts_step = ts_step_reg; @@ -242,7 +228,6 @@ initial begin for (i = 0; i < PIPELINE_OUTPUT; i = i + 1) begin ts_s_pipe_reg[i] = 0; ts_ns_pipe_reg[i] = 0; - ts_fns_pipe_reg[i] = 0; ts_step_pipe_reg[i] = 1'b0; pps_pipe_reg[i] = 1'b0; end @@ -260,11 +245,10 @@ always @(posedge input_clk) begin // capture source TS if (TS_WIDTH == 96) begin src_ts_s_capt_reg <= input_ts[95:48]; - src_ts_ns_capt_reg <= input_ts[45:16]; + src_ts_ns_capt_reg <= input_ts[45:0] >> (16-TS_FNS_WIDTH); end else begin - src_ts_ns_capt_reg <= input_ts[63:16]; + src_ts_ns_capt_reg <= input_ts >> (16-TS_FNS_WIDTH); end - src_ts_fns_capt_reg <= input_ts[15:0] >> (16-TS_FNS_WIDTH); src_ts_step_capt_reg <= input_ts_step || input_ts_step_reg; input_ts_step_reg <= 1'b0; src_sync_reg <= !src_sync_reg; @@ -427,11 +411,9 @@ always @(posedge output_clk) begin if (PIPELINE_OUTPUT > 0) begin dest_ts_s_capt_reg <= ts_s_pipe_reg[PIPELINE_OUTPUT-1]; dest_ts_ns_capt_reg <= ts_ns_pipe_reg[PIPELINE_OUTPUT-1]; - dest_ts_fns_capt_reg <= ts_fns_pipe_reg[PIPELINE_OUTPUT-1]; end else begin dest_ts_s_capt_reg <= ts_s_reg; - dest_ts_ns_capt_reg <= ts_ns_reg; - dest_ts_fns_capt_reg <= {ts_fns_reg, 16'd0} >> FNS_WIDTH; + dest_ts_ns_capt_reg <= ts_ns_reg >> FNS_WIDTH-TS_FNS_WIDTH; end dest_sync_reg <= !dest_sync_reg; @@ -446,7 +428,6 @@ always @(posedge output_clk) begin src_ts_s_sync_reg <= src_ts_s_capt_reg; end src_ts_ns_sync_reg <= src_ts_ns_capt_reg; - src_ts_fns_sync_reg <= src_ts_fns_capt_reg; src_ts_step_sync_reg <= src_ts_step_capt_reg; ts_sync_valid_reg <= ts_capt_valid_reg; @@ -480,11 +461,9 @@ reg diff_corr_valid_reg = 1'b0, diff_corr_valid_next; reg ts_s_msb_diff_reg = 1'b0, ts_s_msb_diff_next; reg [7:0] ts_s_diff_reg = 0, ts_s_diff_next; -reg [TS_NS_WIDTH+1-1:0] ts_ns_diff_reg = 0, ts_ns_diff_next; -reg [TS_FNS_WIDTH-1:0] ts_fns_diff_reg = 0, ts_fns_diff_next; +reg [TS_NS_WIDTH+TS_FNS_WIDTH+1-1:0] ts_ns_diff_reg = 0, ts_ns_diff_next; -reg [16:0] ts_ns_diff_corr_reg = 0, ts_ns_diff_corr_next; -reg [TS_FNS_WIDTH-1:0] ts_fns_diff_corr_reg = 0, ts_fns_diff_corr_next; +reg [17+TS_FNS_WIDTH-1:0] ts_ns_diff_corr_reg = 0, ts_ns_diff_corr_next; reg [TIME_ERR_INT_WIDTH-1:0] time_err_int_reg = 0, time_err_int_next; @@ -497,15 +476,11 @@ assign locked = ptp_locked_reg && dest_sync_locked_reg; always @* begin period_ns_next = period_ns_reg; - period_fns_next = period_fns_reg; ts_s_next = ts_s_reg; ts_ns_next = ts_ns_reg; - ts_fns_next = ts_fns_reg; ts_ns_inc_next = ts_ns_inc_reg; - ts_fns_inc_next = ts_fns_inc_reg; ts_ns_ovf_next = ts_ns_ovf_reg; - ts_fns_ovf_next = ts_fns_ovf_reg; ts_step_next = 0; @@ -516,10 +491,8 @@ always @* begin ts_s_msb_diff_next = ts_s_msb_diff_reg; ts_s_diff_next = ts_s_diff_reg; ts_ns_diff_next = ts_ns_diff_reg; - ts_fns_diff_next = ts_fns_diff_reg; ts_ns_diff_corr_next = ts_ns_diff_corr_reg; - ts_fns_diff_corr_next = ts_fns_diff_corr_reg; time_err_int_next = time_err_int_reg; @@ -527,26 +500,26 @@ always @* begin ptp_locked_next = ptp_locked_reg; // PTP clock - {period_ns_delay_next, period_fns_delay_next} = {period_ns_reg, period_fns_reg}; - {period_ns_ovf_next, period_fns_ovf_next} = {NS_PER_S, {FNS_WIDTH{1'b0}}} - {period_ns_reg, period_fns_reg}; + period_ns_delay_next = period_ns_reg; + period_ns_ovf_next = {NS_PER_S, {FNS_WIDTH{1'b0}}} - period_ns_reg; if (TS_WIDTH == 96) begin // 96 bit timestamp - {ts_ns_inc_next, ts_fns_inc_next} = {ts_ns_inc_reg, ts_fns_inc_reg} + {period_ns_delay_reg, period_fns_delay_reg}; - {ts_ns_ovf_next, ts_fns_ovf_next} = {ts_ns_inc_reg, ts_fns_inc_reg} - {period_ns_ovf_reg, period_fns_ovf_reg}; - {ts_ns_next, ts_fns_next} = {ts_ns_inc_reg, ts_fns_inc_reg}; + ts_ns_inc_next = ts_ns_inc_reg + period_ns_delay_reg; + ts_ns_ovf_next = ts_ns_inc_reg - period_ns_ovf_reg; + ts_ns_next = ts_ns_inc_reg; - if (!ts_ns_ovf_reg[30]) begin + if (!ts_ns_ovf_reg[30+FNS_WIDTH]) begin // if the overflow lookahead did not borrow, one second has elapsed // increment seconds field, pre-compute normal increment, force overflow lookahead borrow bit set - {ts_ns_inc_next, ts_fns_inc_next} = {ts_ns_ovf_reg, ts_fns_ovf_reg} + {period_ns_delay_reg, period_fns_delay_reg}; - ts_ns_ovf_next[30] = 1'b1; - {ts_ns_next, ts_fns_next} = {ts_ns_ovf_reg, ts_fns_ovf_reg}; + ts_ns_inc_next = ts_ns_ovf_reg + period_ns_delay_reg; + ts_ns_ovf_next[30+FNS_WIDTH] = 1'b1; + ts_ns_next = ts_ns_ovf_reg; ts_s_next = ts_s_reg + 1; end end else if (TS_WIDTH == 64) begin // 64 bit timestamp - {ts_ns_next, ts_fns_next} = {ts_ns_reg, ts_fns_reg} + {period_ns_reg, period_fns_reg}; + ts_ns_next = ts_ns_reg + period_ns_reg; end if (ts_sync_valid_reg) begin @@ -559,9 +532,7 @@ always @* begin ts_s_next = src_ts_s_sync_reg; ts_ns_next = src_ts_ns_sync_reg; ts_ns_inc_next = src_ts_ns_sync_reg; - ts_ns_ovf_next[30] = 1'b1; - ts_fns_next = src_ts_fns_sync_reg; - ts_fns_inc_next = src_ts_fns_sync_reg; + ts_ns_ovf_next[30+FNS_WIDTH] = 1'b1; ts_step_next = 1; end else begin // input did not step @@ -571,14 +542,13 @@ always @* begin // compute difference ts_s_msb_diff_next = src_ts_s_sync_reg[47:8] != dest_ts_s_capt_reg[47:8]; ts_s_diff_next = src_ts_s_sync_reg[7:0] - dest_ts_s_capt_reg[7:0]; - {ts_ns_diff_next, ts_fns_diff_next} = {src_ts_ns_sync_reg, src_ts_fns_sync_reg} - {dest_ts_ns_capt_reg, dest_ts_fns_capt_reg}; + ts_ns_diff_next = src_ts_ns_sync_reg - dest_ts_ns_capt_reg; end else if (TS_WIDTH == 64) begin if (src_ts_step_sync_reg || sec_mismatch_reg) begin // input stepped sec_mismatch_next = 1'b0; ts_ns_next = src_ts_ns_sync_reg; - ts_fns_next = src_ts_fns_sync_reg; ts_step_next = 1; end else begin // input did not step @@ -586,37 +556,35 @@ always @* begin diff_valid_next = 1'b1; end // compute difference - {ts_ns_diff_next, ts_fns_diff_next} = {src_ts_ns_sync_reg, src_ts_fns_sync_reg} - {dest_ts_ns_capt_reg, dest_ts_fns_capt_reg}; + ts_ns_diff_next = src_ts_ns_sync_reg - dest_ts_ns_capt_reg; end end if (diff_valid_reg) begin // seconds field correction if (TS_WIDTH == 96) begin - if ($signed(ts_s_diff_reg) == 0 && ts_s_msb_diff_reg == 0 && ($signed(ts_ns_diff_reg[30:16]) == 0 || $signed(ts_ns_diff_reg[30:16]) == -1)) begin + if ($signed(ts_s_diff_reg) == 0 && ts_s_msb_diff_reg == 0 && ($signed(ts_ns_diff_reg[16+FNS_WIDTH +: 14]) == 0 || $signed(ts_ns_diff_reg[16+FNS_WIDTH +: 14]) == -1)) begin // difference is small and no seconds difference; slew - ts_ns_diff_corr_next = ts_ns_diff_reg[16:0]; - ts_fns_diff_corr_next = ts_fns_diff_reg; + ts_ns_diff_corr_next = ts_ns_diff_reg[16+FNS_WIDTH:0]; diff_corr_valid_next = 1'b1; - end else if ($signed(ts_s_diff_reg) == 1 && ts_ns_diff_reg[30:16] == ~NS_PER_S[30:16]) begin + end else if ($signed(ts_s_diff_reg) == 1 && ts_ns_diff_reg[16+FNS_WIDTH +: 14] == ~NS_PER_S[30:16]) begin // difference is small with 1 second difference; adjust and slew - ts_ns_diff_corr_next = ts_ns_diff_reg[16:0] + NS_PER_S[16:0]; - ts_fns_diff_corr_next = ts_fns_diff_reg; + ts_ns_diff_corr_next[FNS_WIDTH +: NS_WIDTH] = ts_ns_diff_reg[FNS_WIDTH +: 17] + NS_PER_S[0 +: 17]; + ts_ns_diff_corr_next[0 +: FNS_WIDTH] = ts_ns_diff_reg[0 +: FNS_WIDTH]; diff_corr_valid_next = 1'b1; - end else if ($signed(ts_s_diff_reg) == -1 && ts_ns_diff_reg[30:16] == NS_PER_S[30:16]) begin + end else if ($signed(ts_s_diff_reg) == -1 && ts_ns_diff_reg[16+FNS_WIDTH +: 14] == NS_PER_S[30:16]) begin // difference is small with 1 second difference; adjust and slew - ts_ns_diff_corr_next = ts_ns_diff_reg[16:0] - NS_PER_S[16:0]; - ts_fns_diff_corr_next = ts_fns_diff_reg; + ts_ns_diff_corr_next[FNS_WIDTH +: NS_WIDTH] = ts_ns_diff_reg[FNS_WIDTH +: 17] - NS_PER_S[0 +: 17]; + ts_ns_diff_corr_next[0 +: FNS_WIDTH] = ts_ns_diff_reg[0 +: FNS_WIDTH]; diff_corr_valid_next = 1'b1; end else begin // difference is too large; step the clock sec_mismatch_next = 1'b1; end end else if (TS_WIDTH == 64) begin - if ($signed(ts_ns_diff_reg[47:16]) == 0 || $signed(ts_ns_diff_reg[47:16]) == -1) begin + if ($signed(ts_ns_diff_reg[16+FNS_WIDTH +: 32]) == 0 || $signed(ts_ns_diff_reg[16+FNS_WIDTH +: 32]) == -1) begin // difference is small enough to slew - ts_ns_diff_corr_next = ts_ns_diff_reg[16:0]; - ts_fns_diff_corr_next = ts_fns_diff_reg; + ts_ns_diff_corr_next = ts_ns_diff_reg[16+FNS_WIDTH:0]; diff_corr_valid_next = 1'b1; end else begin // difference is too large; step the clock @@ -630,9 +598,9 @@ always @* begin // time integral of error if (ptp_locked_reg) begin - {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**16); + {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**16); end else begin - {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**13); + {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**13); end // saturate @@ -646,29 +614,29 @@ always @* begin // compute output if (ptp_locked_reg) begin - {ptp_ovf, period_ns_next, period_fns_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**10); + {ptp_ovf, period_ns_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**10); end else begin - {ptp_ovf, period_ns_next, period_fns_next} = $signed({1'b0, time_err_int_reg}) + ($signed({ts_ns_diff_corr_reg, ts_fns_diff_corr_reg}) / 2**7); + {ptp_ovf, period_ns_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**7); end // saturate if (ptp_ovf[1]) begin // sign bit set indicating underflow across zero; saturate to zero - {period_ns_next, period_fns_next} = {NS_WIDTH+FNS_WIDTH{1'b0}}; + period_ns_next = {NS_WIDTH+FNS_WIDTH{1'b0}}; end else if (ptp_ovf[0]) begin // sign bit clear but carry bit set indicating overflow; saturate to all 1 - {period_ns_next, period_fns_next} = {NS_WIDTH+FNS_WIDTH{1'b1}}; + period_ns_next = {NS_WIDTH+FNS_WIDTH{1'b1}}; end // adjust period if integrator is saturated if (time_err_int_reg == 0) begin - {period_ns_next, period_fns_next} = {NS_WIDTH+FNS_WIDTH{1'b0}}; + period_ns_next = {NS_WIDTH+FNS_WIDTH{1'b0}}; end else if (~time_err_int_reg == 0) begin - {period_ns_next, period_fns_next} = {NS_WIDTH+FNS_WIDTH{1'b1}}; + period_ns_next = {NS_WIDTH+FNS_WIDTH{1'b1}}; end // locked status - if ($signed(ts_ns_diff_corr_reg[17-1:4]) == 0 || $signed(ts_ns_diff_corr_reg[17-1:4]) == -1) begin + if ($signed(ts_ns_diff_corr_reg[17+FNS_WIDTH-1:4+FNS_WIDTH]) == 0 || $signed(ts_ns_diff_corr_reg[17+FNS_WIDTH-1:4+FNS_WIDTH]) == -1) begin if (ptp_lock_count_reg == {PTP_LOCK_WIDTH{1'b1}}) begin ptp_locked_next = 1'b1; end else begin @@ -683,19 +651,13 @@ end always @(posedge output_clk) begin period_ns_reg <= period_ns_next; - period_fns_reg <= period_fns_next; period_ns_delay_reg <= period_ns_delay_next; - period_fns_delay_reg <= period_fns_delay_next; period_ns_ovf_reg <= period_ns_ovf_next; - period_fns_ovf_reg <= period_fns_ovf_next; ts_s_reg <= ts_s_next; ts_ns_reg <= ts_ns_next; - ts_fns_reg <= ts_fns_next; ts_ns_inc_reg <= ts_ns_inc_next; - ts_fns_inc_reg <= ts_fns_inc_next; ts_ns_ovf_reg <= ts_ns_ovf_next; - ts_fns_ovf_reg <= ts_fns_ovf_next; ts_step_reg <= ts_step_next; @@ -706,10 +668,8 @@ always @(posedge output_clk) begin ts_s_msb_diff_reg <= ts_s_msb_diff_next; ts_s_diff_reg <= ts_s_diff_next; ts_ns_diff_reg <= ts_ns_diff_next; - ts_fns_diff_reg <= ts_fns_diff_next; ts_ns_diff_corr_reg <= ts_ns_diff_corr_next; - ts_fns_diff_corr_reg <= ts_fns_diff_corr_next; time_err_int_reg <= time_err_int_next; @@ -718,7 +678,7 @@ always @(posedge output_clk) begin // PPS output if (TS_WIDTH == 96) begin - pps_reg <= !ts_ns_ovf_reg[30]; + pps_reg <= !ts_ns_ovf_reg[30+FNS_WIDTH]; end else if (TS_WIDTH == 64) begin pps_reg <= 1'b0; // not currently implemented for 64 bit timestamp format end @@ -726,15 +686,13 @@ always @(posedge output_clk) begin // pipeline if (PIPELINE_OUTPUT > 0) begin ts_s_pipe_reg[0] <= ts_s_reg; - ts_ns_pipe_reg[0] <= ts_ns_reg; - ts_fns_pipe_reg[0] <= ts_fns_reg; + ts_ns_pipe_reg[0] <= ts_ns_reg >> FNS_WIDTH-TS_FNS_WIDTH; ts_step_pipe_reg[0] <= ts_step_reg; pps_pipe_reg[0] <= pps_reg; for (i = 0; i < PIPELINE_OUTPUT-1; i = i + 1) begin ts_s_pipe_reg[i+1] <= ts_s_pipe_reg[i]; ts_ns_pipe_reg[i+1] <= ts_ns_pipe_reg[i]; - ts_fns_pipe_reg[i+1] <= ts_fns_pipe_reg[i]; ts_step_pipe_reg[i+1] <= ts_step_pipe_reg[i]; pps_pipe_reg[i+1] <= pps_pipe_reg[i]; end @@ -742,16 +700,11 @@ always @(posedge output_clk) begin if (output_rst) begin period_ns_reg <= 0; - period_fns_reg <= 0; period_ns_delay_reg <= 0; - period_fns_delay_reg <= 0; period_ns_ovf_reg <= 0; - period_fns_ovf_reg <= 0; ts_s_reg <= 0; ts_ns_reg <= 0; - ts_fns_reg <= 0; ts_ns_inc_reg <= 0; - ts_fns_inc_reg <= 0; ts_ns_ovf_reg[30] <= 1'b1; ts_step_reg <= 0; pps_reg <= 0; @@ -768,7 +721,6 @@ always @(posedge output_clk) begin for (i = 0; i < PIPELINE_OUTPUT; i = i + 1) begin ts_s_pipe_reg[i] <= 0; ts_ns_pipe_reg[i] <= 0; - ts_fns_pipe_reg[i] <= 0; ts_step_pipe_reg[i] <= 1'b0; pps_pipe_reg[i] <= 1'b0; end diff --git a/syn/vivado/ptp_clock_cdc.tcl b/syn/vivado/ptp_clock_cdc.tcl index 9974c7b26..1edef96d6 100644 --- a/syn/vivado/ptp_clock_cdc.tcl +++ b/syn/vivado/ptp_clock_cdc.tcl @@ -31,7 +31,7 @@ foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_clock_cdc || REF_NA set output_clk_period [if {[llength $output_clk]} {get_property -min PERIOD $output_clk} {expr 1.0}] # timestamp synchronization - set_property ASYNC_REG TRUE [get_cells -hier -regexp ".*/src_ts_(s|ns|fns|step)_sync_reg_reg(\\\[\\d+\\\])?" -filter "PARENT == $inst"] + set_property ASYNC_REG TRUE [get_cells -hier -regexp ".*/src_ts_(s|ns|step)_sync_reg_reg(\\\[\\d+\\\])?" -filter "PARENT == $inst"] if {[llength [get_cells "$inst/src_ts_s_capt_reg_reg[*]"]]} { set_max_delay -from [get_cells "$inst/src_ts_s_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_s_sync_reg_reg[*]"] -datapath_only $output_clk_period @@ -41,9 +41,6 @@ foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_clock_cdc || REF_NA set_max_delay -from [get_cells "$inst/src_ts_ns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_ns_sync_reg_reg[*]"] -datapath_only $output_clk_period set_bus_skew -from [get_cells "$inst/src_ts_ns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_ns_sync_reg_reg[*]"] $input_clk_period - set_max_delay -from [get_cells "$inst/src_ts_fns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_fns_sync_reg_reg[*]"] -datapath_only $output_clk_period - set_bus_skew -from [get_cells "$inst/src_ts_fns_capt_reg_reg[*]"] -to [get_cells "$inst/src_ts_fns_sync_reg_reg[*]"] $input_clk_period - if {[llength [get_cells "$inst/src_ts_step_capt_reg_reg"]]} { set_max_delay -from [get_cells "$inst/src_ts_step_capt_reg_reg"] -to [get_cells "$inst/src_ts_step_sync_reg_reg"] -datapath_only $output_clk_period set_bus_skew -from [get_cells "$inst/src_ts_step_capt_reg_reg"] -to [get_cells "$inst/src_ts_step_sync_reg_reg"] $input_clk_period From f9ae6da8bd4ea2f83ef1bfc820edfe448f2b3f71 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 23 Sep 2023 14:33:14 -0700 Subject: [PATCH 09/12] Improve PTP CDC module testbench Signed-off-by: Alex Forencich --- rtl/ptp_clock_cdc.v | 2 +- tb/ptp_clock_cdc/Makefile | 2 +- tb/ptp_clock_cdc/test_ptp_clock_cdc.py | 309 ++++++++++++++++++++----- 3 files changed, 255 insertions(+), 58 deletions(-) diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index 2f9042cbb..13f8276fd 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -25,7 +25,7 @@ THE SOFTWARE. // Language: Verilog 2001 `resetall -`timescale 1ns / 1ps +`timescale 1ns / 1fs `default_nettype none /* diff --git a/tb/ptp_clock_cdc/Makefile b/tb/ptp_clock_cdc/Makefile index 9fdff623b..9ea3ca651 100644 --- a/tb/ptp_clock_cdc/Makefile +++ b/tb/ptp_clock_cdc/Makefile @@ -24,7 +24,7 @@ SIM ?= icarus WAVES ?= 0 COCOTB_HDL_TIMEUNIT = 1ns -COCOTB_HDL_TIMEPRECISION = 1ps +COCOTB_HDL_TIMEPRECISION = 1fs DUT = ptp_clock_cdc TOPLEVEL = $(DUT) diff --git a/tb/ptp_clock_cdc/test_ptp_clock_cdc.py b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py index 8782fdbbd..52ff65455 100644 --- a/tb/ptp_clock_cdc/test_ptp_clock_cdc.py +++ b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py @@ -1,7 +1,7 @@ #!/usr/bin/env python """ -Copyright (c) 2020 Alex Forencich +Copyright (c) 2020-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 @@ -25,6 +25,7 @@ THE SOFTWARE. import logging import os +from statistics import mean, stdev import pytest import cocotb_test.simulator @@ -32,7 +33,7 @@ import cocotb_test.simulator import cocotb from cocotb.clock import Clock from cocotb.triggers import RisingEdge, Timer -from cocotb.utils import get_sim_steps +from cocotb.utils import get_sim_steps, get_sim_time from cocotbext.eth import PtpClock @@ -44,9 +45,7 @@ class TB: self.log = logging.getLogger("cocotb.tb") self.log.setLevel(logging.DEBUG) - cocotb.start_soon(Clock(dut.input_clk, 6.4, units="ns").start()) - - cocotb.start_soon(Clock(dut.sample_clk, 10, units="ns").start()) + cocotb.start_soon(Clock(dut.sample_clk, 9.9, units="ns").start()) if len(dut.input_ts) == 64: self.ptp_clock = PtpClock( @@ -65,8 +64,13 @@ class TB: period_ns=6.4 ) - self._clock_cr = None - self.set_output_clock_period(6.4) + self.input_clock_period = 6.4 + dut.input_clk.setimmediatevalue(0) + cocotb.start_soon(self._run_input_clock()) + + self.output_clock_period = 6.4 + dut.output_clk.setimmediatevalue(0) + cocotb.start_soon(self._run_output_clock()) async def reset(self): self.dut.input_rst.setimmediatevalue(0) @@ -82,17 +86,33 @@ class TB: for k in range(10): await RisingEdge(self.dut.input_clk) - def set_output_clock_period(self, period): - if self._clock_cr is not None: - self._clock_cr.kill() + def set_input_clock_period(self, period): + self.input_clock_period = period - self._clock_cr = cocotb.start_soon(self._run_clock(period)) - - async def _run_clock(self, period): - half_period = get_sim_steps(period / 2.0, 'ns') - t = Timer(half_period) + async def _run_input_clock(self): + period = None + steps_per_ns = get_sim_steps(1.0, 'ns') while True: + if period != self.input_clock_period: + period = self.input_clock_period + t = Timer(int(steps_per_ns * period / 2.0)) + await t + self.dut.input_clk.value = 1 + await t + self.dut.input_clk.value = 0 + + def set_output_clock_period(self, period): + self.output_clock_period = period + + async def _run_output_clock(self): + period = None + steps_per_ns = get_sim_steps(1.0, 'ns') + + while True: + if period != self.output_clock_period: + period = self.output_clock_period + t = Timer(int(steps_per_ns * period / 2.0)) await t self.dut.output_clk.value = 1 await t @@ -112,14 +132,45 @@ class TB: else: return (ts >> 48) + ((ts & 0xffffffffffff)/2**16*1e-9) - async def measure_ts_diff(self, N=1000): - total = 0 + async def measure_ts_diff(self, N=100): + input_ts_lst = [] + output_ts_lst = [] + + async def collect_timestamps(clk, get_ts, lst): + while True: + await RisingEdge(clk) + lst.append((get_sim_time('sec'), get_ts())) + + input_cr = cocotb.start_soon(collect_timestamps(self.dut.input_clk, self.get_input_ts_ns, input_ts_lst)) + output_cr = cocotb.start_soon(collect_timestamps(self.dut.output_clk, self.get_output_ts_ns, output_ts_lst)) + for k in range(N): - input_ts_ns = self.get_input_ts_ns() - output_ts_ns = self.get_output_ts_ns() - total += input_ts_ns-output_ts_ns - await Timer(100, 'ps') - return total/N + await RisingEdge(self.dut.output_clk) + + input_cr.kill() + output_cr.kill() + + diffs = [] + + its1 = input_ts_lst.pop(0) + its2 = input_ts_lst.pop(0) + + for ots in output_ts_lst: + while its2[0] < ots[0] and input_ts_lst: + its1 = its2 + its2 = input_ts_lst.pop(0) + + if its2[0] < ots[0]: + break + + dt = its2[0] - its1[0] + dts = its2[1] - its1[1] + + its = its1[1]+dts/dt*(ots[0]-its1[0]) + + diffs.append(ots[1] - its) + + return diffs @cocotb.test() @@ -132,90 +183,236 @@ async def run_test(dut): await RisingEdge(dut.input_clk) tb.log.info("Same clock speed") + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.4) + await RisingEdge(dut.input_clk) - for i in range(40000): + for i in range(100000): await RisingEdge(dut.input_clk) assert tb.dut.locked.value.integer - diff = await tb.measure_ts_diff()*1e9 - - tb.log.info(f"Difference: {diff} ns") - - assert abs(diff) < 10 + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 await RisingEdge(dut.input_clk) - tb.log.info("Slightly faster") + tb.log.info("10 ppm slower") - tb.set_output_clock_period(6.2) + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.4*(1+.00001)) await RisingEdge(dut.input_clk) - for i in range(40000): + for i in range(100000): await RisingEdge(dut.input_clk) assert tb.dut.locked.value.integer - diff = await tb.measure_ts_diff()*1e9 - - tb.log.info(f"Difference: {diff} ns") - - assert abs(diff) < 10 + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 await RisingEdge(dut.input_clk) - tb.log.info("Slightly slower") + tb.log.info("10 ppm faster") - tb.set_output_clock_period(6.6) + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.4*(1-.00001)) await RisingEdge(dut.input_clk) - for i in range(40000): + for i in range(100000): await RisingEdge(dut.input_clk) assert tb.dut.locked.value.integer - diff = await tb.measure_ts_diff()*1e9 - - tb.log.info(f"Difference: {diff} ns") - - assert abs(diff) < 10 + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 await RisingEdge(dut.input_clk) - tb.log.info("Significantly faster") + tb.log.info("200 ppm slower") + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.4*(1+.0002)) + + await RisingEdge(dut.input_clk) + + for i in range(100000): + await RisingEdge(dut.input_clk) + + assert tb.dut.locked.value.integer + + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 + + await RisingEdge(dut.input_clk) + tb.log.info("200 ppm faster") + + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.4*(1-.0002)) + + await RisingEdge(dut.input_clk) + + for i in range(100000): + await RisingEdge(dut.input_clk) + + assert tb.dut.locked.value.integer + + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 + + await RisingEdge(dut.input_clk) + tb.log.info("Coherent tracking (+/- 10 ppm)") + + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.4) + + await RisingEdge(dut.input_clk) + + period = 6.400 + step = 0.000002 + period_min = 6.4*(1-.00001) + period_max = 6.4*(1+.00001) + + for i in range(500): + period += step + + if period <= period_min: + step = abs(step) + if period >= period_max: + step = -abs(step) + + tb.set_output_clock_period(period) + + for i in range(200): + await RisingEdge(dut.input_clk) + + assert tb.dut.locked.value.integer + + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 + + await RisingEdge(dut.input_clk) + tb.log.info("Coherent tracking (+/- 200 ppm)") + + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.4) + + await RisingEdge(dut.input_clk) + + period = 6.400 + step = 0.000002 + period_min = 6.4*(1-.0002) + period_max = 6.4*(1+.0002) + + for i in range(5000): + period += step + + if period <= period_min: + step = abs(step) + if period >= period_max: + step = -abs(step) + + tb.set_output_clock_period(period) + + for i in range(20): + await RisingEdge(dut.input_clk) + + assert tb.dut.locked.value.integer + + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 + + await RisingEdge(dut.input_clk) + tb.log.info("Slightly faster (6.3 ns)") + + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.3) + + await RisingEdge(dut.input_clk) + + for i in range(100000): + await RisingEdge(dut.input_clk) + + assert tb.dut.locked.value.integer + + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 + + await RisingEdge(dut.input_clk) + tb.log.info("Slightly slower (6.5 ns)") + + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(6.5) + + await RisingEdge(dut.input_clk) + + for i in range(100000): + await RisingEdge(dut.input_clk) + + assert tb.dut.locked.value.integer + + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 + + await RisingEdge(dut.input_clk) + tb.log.info("Significantly faster (250 MHz)") + + tb.set_input_clock_period(6.4) tb.set_output_clock_period(4.0) await RisingEdge(dut.input_clk) - for i in range(40000): + for i in range(100000): await RisingEdge(dut.input_clk) assert tb.dut.locked.value.integer - diff = await tb.measure_ts_diff()*1e9 - - tb.log.info(f"Difference: {diff} ns") - - assert abs(diff) < 10 + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 await RisingEdge(dut.input_clk) - tb.log.info("Significantly slower") + tb.log.info("Significantly slower (100 MHz)") + tb.set_input_clock_period(6.4) tb.set_output_clock_period(10.0) await RisingEdge(dut.input_clk) - for i in range(30000): + for i in range(100000): await RisingEdge(dut.input_clk) assert tb.dut.locked.value.integer - diff = await tb.measure_ts_diff()*1e9 + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 - tb.log.info(f"Difference: {diff} ns") + await RisingEdge(dut.input_clk) + tb.log.info("Significantly faster (390.625 MHz)") - assert abs(diff) < 10 + tb.set_input_clock_period(6.4) + tb.set_output_clock_period(2.56) + + await RisingEdge(dut.input_clk) + + for i in range(100000): + await RisingEdge(dut.input_clk) + + assert tb.dut.locked.value.integer + + diffs = await tb.measure_ts_diff() + tb.log.info(f"Difference: {mean(diffs)*1e9} ns (stdev: {stdev(diffs)*1e9})") + assert abs(mean(diffs)*1e9) < 5 await RisingEdge(dut.input_clk) await RisingEdge(dut.input_clk) From a9e3d3cae8b4ac69057f9499f897c6710cfe20e7 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 23 Sep 2023 14:52:48 -0700 Subject: [PATCH 10/12] Wait longer to ensure PTP CDC module has fully stabilized in MAC testbenches Signed-off-by: Alex Forencich --- tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py | 6 ++++++ tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py index fe98b8de3..3ba0a2655 100644 --- a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py +++ b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py @@ -110,6 +110,8 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): tb.log.info("Wait for PTP CDC lock") while not dut.rx_ptp.rx_ptp_cdc.locked.value.integer: await RisingEdge(dut.rx_clk) + for k in range(1000): + await RisingEdge(dut.rx_clk) test_frames = [payload_data(x) for x in payload_lengths()] tx_frames = [] @@ -159,6 +161,8 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): tb.log.info("Wait for PTP CDC lock") while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer: await RisingEdge(dut.tx_clk) + for k in range(1000): + await RisingEdge(dut.tx_clk) test_frames = [payload_data(x) for x in payload_lengths()] @@ -209,6 +213,8 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): tb.log.info("Wait for PTP CDC lock") while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer: await RisingEdge(dut.tx_clk) + for k in range(1000): + await RisingEdge(dut.tx_clk) for length in range(60, 92): diff --git a/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py b/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py index 6382e822a..43a6269b7 100644 --- a/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py +++ b/tb/eth_mac_phy_10g_fifo/test_eth_mac_phy_10g_fifo.py @@ -127,6 +127,8 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): tb.log.info("Wait for PTP CDC lock") while not dut.rx_ptp.rx_ptp_cdc.locked.value.integer: await RisingEdge(dut.rx_clk) + for k in range(1000): + await RisingEdge(dut.rx_clk) # clear out sink buffer tb.axis_sink.clear() @@ -179,6 +181,8 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): tb.log.info("Wait for PTP CDC lock") while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer: await RisingEdge(dut.tx_clk) + for k in range(1000): + await RisingEdge(dut.tx_clk) test_frames = [payload_data(x) for x in payload_lengths()] @@ -229,6 +233,8 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): tb.log.info("Wait for PTP CDC lock") while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer: await RisingEdge(dut.tx_clk) + for k in range(1000): + await RisingEdge(dut.tx_clk) for length in range(60, 92): From 90e6dfc63862d06f600b005c5f0471ec9ee5a080 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 23 Sep 2023 14:58:44 -0700 Subject: [PATCH 11/12] Use phase detector in PTP CDC module for coarse period tuning, use 9 LSBs of timestamp for fine sync to avoid rollover corrections, reduce FNS comparison width to 4 bits Signed-off-by: Alex Forencich --- rtl/ptp_clock_cdc.v | 278 +++++++++++++++++++++++------------ syn/vivado/ptp_clock_cdc.tcl | 21 ++- 2 files changed, 207 insertions(+), 92 deletions(-) diff --git a/rtl/ptp_clock_cdc.v b/rtl/ptp_clock_cdc.v index 13f8276fd..388ea7b2e 100644 --- a/rtl/ptp_clock_cdc.v +++ b/rtl/ptp_clock_cdc.v @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Alex Forencich +Copyright (c) 2019-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 @@ -81,13 +81,19 @@ localparam FNS_WIDTH = 16; localparam TS_NS_WIDTH = TS_WIDTH == 96 ? 30 : 48; localparam TS_FNS_WIDTH = FNS_WIDTH > 16 ? 16 : FNS_WIDTH; +localparam CMP_FNS_WIDTH = 4; + localparam PHASE_CNT_WIDTH = LOG_RATE; localparam PHASE_ACC_WIDTH = PHASE_CNT_WIDTH+16; localparam LOG_SAMPLE_SYNC_RATE = LOG_RATE; localparam SAMPLE_ACC_WIDTH = LOG_SAMPLE_SYNC_RATE+2; +localparam LOG_PHASE_ERR_RATE = 4; +localparam PHASE_ERR_ACC_WIDTH = LOG_PHASE_ERR_RATE+2; + localparam DEST_SYNC_LOCK_WIDTH = 7; +localparam FREQ_LOCK_WIDTH = 8; localparam PTP_LOCK_WIDTH = 8; localparam TIME_ERR_INT_WIDTH = NS_WIDTH+FNS_WIDTH; @@ -99,14 +105,14 @@ reg [NS_WIDTH+FNS_WIDTH-1:0] period_ns_delay_reg = 0, period_ns_delay_next; reg [31+FNS_WIDTH-1:0] period_ns_ovf_reg = 0, period_ns_ovf_next; reg [47:0] src_ts_s_capt_reg = 0; -reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] src_ts_ns_capt_reg = 0; +reg [TS_NS_WIDTH+CMP_FNS_WIDTH-1:0] src_ts_ns_capt_reg = 0; reg src_ts_step_capt_reg = 0; reg [47:0] dest_ts_s_capt_reg = 0; -reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] dest_ts_ns_capt_reg = 0; +reg [TS_NS_WIDTH+CMP_FNS_WIDTH-1:0] dest_ts_ns_capt_reg = 0; reg [47:0] src_ts_s_sync_reg = 0; -reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] src_ts_ns_sync_reg = 0; +reg [TS_NS_WIDTH+CMP_FNS_WIDTH-1:0] src_ts_ns_sync_reg = 0; reg src_ts_step_sync_reg = 0; reg [47:0] ts_s_reg = 0, ts_s_next; @@ -119,7 +125,7 @@ reg ts_step_reg = 1'b0, ts_step_next; reg pps_reg = 1'b0; reg [47:0] ts_s_pipe_reg[0:PIPELINE_OUTPUT-1]; -reg [TS_NS_WIDTH+TS_FNS_WIDTH-1:0] ts_ns_pipe_reg[0:PIPELINE_OUTPUT-1]; +reg [TS_NS_WIDTH+CMP_FNS_WIDTH-1:0] ts_ns_pipe_reg[0:PIPELINE_OUTPUT-1]; reg ts_step_pipe_reg[0:PIPELINE_OUTPUT-1]; reg pps_pipe_reg[0:PIPELINE_OUTPUT-1]; @@ -129,12 +135,20 @@ reg [PHASE_ACC_WIDTH-1:0] dest_phase_inc_reg = {PHASE_ACC_WIDTH{1'b0}}, dest_pha reg src_sync_reg = 1'b0; reg src_update_reg = 1'b0; +reg src_phase_sync_reg = 1'b0; reg dest_sync_reg = 1'b0; reg dest_update_reg = 1'b0, dest_update_next = 1'b0; +reg dest_phase_sync_reg = 1'b0; reg src_sync_sync1_reg = 1'b0; reg src_sync_sync2_reg = 1'b0; reg src_sync_sync3_reg = 1'b0; +reg src_phase_sync_sync1_reg = 1'b0; +reg src_phase_sync_sync2_reg = 1'b0; +reg src_phase_sync_sync3_reg = 1'b0; +reg dest_phase_sync_sync1_reg = 1'b0; +reg dest_phase_sync_sync2_reg = 1'b0; +reg dest_phase_sync_sync3_reg = 1'b0; reg src_sync_sample_sync1_reg = 1'b0; reg src_sync_sample_sync2_reg = 1'b0; @@ -239,15 +253,17 @@ reg input_ts_step_reg = 1'b0; always @(posedge input_clk) begin input_ts_step_reg <= input_ts_step || input_ts_step_reg; + src_phase_sync_reg <= input_ts[16+8]; + {src_update_reg, src_phase_reg} <= src_phase_reg+1; if (src_update_reg) begin // capture source TS if (TS_WIDTH == 96) begin src_ts_s_capt_reg <= input_ts[95:48]; - src_ts_ns_capt_reg <= input_ts[45:0] >> (16-TS_FNS_WIDTH); + src_ts_ns_capt_reg <= input_ts[45:0] >> (16-CMP_FNS_WIDTH); end else begin - src_ts_ns_capt_reg <= input_ts >> (16-TS_FNS_WIDTH); + src_ts_ns_capt_reg <= input_ts >> (16-CMP_FNS_WIDTH); end src_ts_step_capt_reg <= input_ts_step || input_ts_step_reg; input_ts_step_reg <= 1'b0; @@ -268,6 +284,12 @@ always @(posedge output_clk) begin src_sync_sync1_reg <= src_sync_reg; src_sync_sync2_reg <= src_sync_sync1_reg; src_sync_sync3_reg <= src_sync_sync2_reg; + src_phase_sync_sync1_reg <= src_phase_sync_reg; + src_phase_sync_sync2_reg <= src_phase_sync_sync1_reg; + src_phase_sync_sync3_reg <= src_phase_sync_sync2_reg; + dest_phase_sync_sync1_reg <= dest_phase_sync_reg; + dest_phase_sync_sync2_reg <= dest_phase_sync_sync1_reg; + dest_phase_sync_sync3_reg <= dest_phase_sync_sync2_reg; end always @(posedge sample_clk) begin @@ -391,6 +413,16 @@ always @* begin end end +reg [PHASE_ERR_ACC_WIDTH-1:0] phase_err_acc_reg = 0; +reg [PHASE_ERR_ACC_WIDTH-1:0] phase_err_out_reg = 0; +reg [LOG_PHASE_ERR_RATE-1:0] phase_err_cnt_reg = 0; +reg phase_err_out_valid_reg = 0; + +reg phase_edge_1_reg = 1'b0; +reg phase_edge_2_reg = 1'b0; + +reg [5:0] phase_active_reg = 0; + reg ts_sync_valid_reg = 1'b0; reg ts_capt_valid_reg = 1'b0; @@ -406,6 +438,45 @@ always @(posedge output_clk) begin sample_acc_sync_valid_reg <= 1'b1; end + if (PIPELINE_OUTPUT > 0) begin + dest_phase_sync_reg <= ts_ns_pipe_reg[PIPELINE_OUTPUT-1][8+FNS_WIDTH]; + end else begin + dest_phase_sync_reg <= ts_ns_reg[8+FNS_WIDTH]; + end + + // phase and frequency detector + if (dest_phase_sync_sync2_reg && !dest_phase_sync_sync3_reg) begin + if (src_phase_sync_sync2_reg && !src_phase_sync_sync3_reg) begin + phase_edge_1_reg <= 1'b0; + phase_edge_2_reg <= 1'b0; + end else begin + phase_edge_1_reg <= !phase_edge_2_reg; + phase_edge_2_reg <= 1'b0; + end + end else if (src_phase_sync_sync2_reg && !src_phase_sync_sync3_reg) begin + phase_edge_1_reg <= 1'b0; + phase_edge_2_reg <= !phase_edge_1_reg; + end + + // accumulator + phase_err_acc_reg <= $signed(phase_err_acc_reg) + $signed({1'b0, phase_edge_2_reg}) - $signed({1'b0, phase_edge_1_reg}); + + phase_err_cnt_reg <= phase_err_cnt_reg + 1; + + if (src_phase_sync_sync2_reg && !src_phase_sync_sync3_reg) begin + phase_active_reg[0] <= 1'b1; + end + + phase_err_out_valid_reg <= 1'b0; + if (phase_err_cnt_reg == 0) begin + phase_active_reg <= {phase_active_reg, src_phase_sync_sync2_reg && !src_phase_sync_sync3_reg}; + phase_err_acc_reg <= $signed({1'b0, phase_edge_2_reg}) - $signed({1'b0, phase_edge_1_reg}); + phase_err_out_reg <= phase_err_acc_reg; + if (phase_active_reg != 0) begin + phase_err_out_valid_reg <= 1'b1; + end + end + if (dest_update_reg) begin // capture local TS if (PIPELINE_OUTPUT > 0) begin @@ -413,7 +484,7 @@ always @(posedge output_clk) begin dest_ts_ns_capt_reg <= ts_ns_pipe_reg[PIPELINE_OUTPUT-1]; end else begin dest_ts_s_capt_reg <= ts_s_reg; - dest_ts_ns_capt_reg <= ts_ns_reg >> FNS_WIDTH-TS_FNS_WIDTH; + dest_ts_ns_capt_reg <= ts_ns_reg >> FNS_WIDTH-CMP_FNS_WIDTH; end dest_sync_reg <= !dest_sync_reg; @@ -455,24 +526,25 @@ always @(posedge output_clk) begin end end -reg sec_mismatch_reg = 1'b0, sec_mismatch_next; -reg diff_valid_reg = 1'b0, diff_valid_next; -reg diff_corr_valid_reg = 1'b0, diff_corr_valid_next; +reg ts_diff_reg = 1'b0, ts_diff_next; +reg ts_diff_valid_reg = 1'b0, ts_diff_valid_next; +reg [3:0] mismatch_cnt_reg = 0, mismatch_cnt_next; +reg load_ts_reg = 1'b0, load_ts_next; -reg ts_s_msb_diff_reg = 1'b0, ts_s_msb_diff_next; -reg [7:0] ts_s_diff_reg = 0, ts_s_diff_next; -reg [TS_NS_WIDTH+TS_FNS_WIDTH+1-1:0] ts_ns_diff_reg = 0, ts_ns_diff_next; - -reg [17+TS_FNS_WIDTH-1:0] ts_ns_diff_corr_reg = 0, ts_ns_diff_corr_next; +reg [9+CMP_FNS_WIDTH-1:0] ts_ns_diff_reg = 0, ts_ns_diff_next; reg [TIME_ERR_INT_WIDTH-1:0] time_err_int_reg = 0, time_err_int_next; reg [1:0] ptp_ovf; +reg [FREQ_LOCK_WIDTH-1:0] freq_lock_count_reg = 0, freq_lock_count_next; +reg freq_locked_reg = 1'b0, freq_locked_next; reg [PTP_LOCK_WIDTH-1:0] ptp_lock_count_reg = 0, ptp_lock_count_next; reg ptp_locked_reg = 1'b0, ptp_locked_next; -assign locked = ptp_locked_reg && dest_sync_locked_reg; +reg gain_sel_reg = 0, gain_sel_next; + +assign locked = ptp_locked_reg && freq_locked_reg && dest_sync_locked_reg; always @* begin period_ns_next = period_ns_reg; @@ -484,21 +556,22 @@ always @* begin ts_step_next = 0; - sec_mismatch_next = sec_mismatch_reg; - diff_valid_next = 1'b0; - diff_corr_valid_next = 1'b0; + ts_diff_next = 1'b0; + ts_diff_valid_next = 1'b0; + mismatch_cnt_next = mismatch_cnt_reg; + load_ts_next = load_ts_reg; - ts_s_msb_diff_next = ts_s_msb_diff_reg; - ts_s_diff_next = ts_s_diff_reg; ts_ns_diff_next = ts_ns_diff_reg; - ts_ns_diff_corr_next = ts_ns_diff_corr_reg; - time_err_int_next = time_err_int_reg; + freq_lock_count_next = freq_lock_count_reg; + freq_locked_next = freq_locked_reg; ptp_lock_count_next = ptp_lock_count_reg; ptp_locked_next = ptp_locked_reg; + gain_sel_next = gain_sel_reg; + // PTP clock period_ns_delay_next = period_ns_reg; period_ns_ovf_next = {NS_PER_S, {FNS_WIDTH{1'b0}}} - period_ns_reg; @@ -525,84 +598,100 @@ always @* begin if (ts_sync_valid_reg) begin // Read new value if (TS_WIDTH == 96) begin - if (src_ts_step_sync_reg || sec_mismatch_reg) begin + if (src_ts_step_sync_reg || load_ts_reg) begin // input stepped - sec_mismatch_next = 1'b0; + load_ts_next = 1'b0; ts_s_next = src_ts_s_sync_reg; - ts_ns_next = src_ts_ns_sync_reg; - ts_ns_inc_next = src_ts_ns_sync_reg; + ts_ns_next[TS_NS_WIDTH+FNS_WIDTH-1:9+FNS_WIDTH] = src_ts_ns_sync_reg[TS_NS_WIDTH+CMP_FNS_WIDTH-1:9+CMP_FNS_WIDTH]; + ts_ns_inc_next[TS_NS_WIDTH+FNS_WIDTH-1:9+FNS_WIDTH] = src_ts_ns_sync_reg[TS_NS_WIDTH+CMP_FNS_WIDTH-1:9+CMP_FNS_WIDTH]; ts_ns_ovf_next[30+FNS_WIDTH] = 1'b1; ts_step_next = 1; end else begin // input did not step - sec_mismatch_next = 1'b0; - diff_valid_next = 1'b1; + load_ts_next = 1'b0; + ts_diff_valid_next = freq_locked_reg; end // compute difference - ts_s_msb_diff_next = src_ts_s_sync_reg[47:8] != dest_ts_s_capt_reg[47:8]; - ts_s_diff_next = src_ts_s_sync_reg[7:0] - dest_ts_s_capt_reg[7:0]; ts_ns_diff_next = src_ts_ns_sync_reg - dest_ts_ns_capt_reg; + ts_diff_next = src_ts_s_sync_reg != dest_ts_s_capt_reg || src_ts_ns_sync_reg[TS_NS_WIDTH+CMP_FNS_WIDTH-1:9+CMP_FNS_WIDTH] != dest_ts_ns_capt_reg[TS_NS_WIDTH+CMP_FNS_WIDTH-1:9+CMP_FNS_WIDTH]; end else if (TS_WIDTH == 64) begin - if (src_ts_step_sync_reg || sec_mismatch_reg) begin + if (src_ts_step_sync_reg || load_ts_reg) begin // input stepped - sec_mismatch_next = 1'b0; + load_ts_next = 1'b0; - ts_ns_next = src_ts_ns_sync_reg; + ts_ns_next[TS_NS_WIDTH+FNS_WIDTH-1:9+FNS_WIDTH] = src_ts_ns_sync_reg[TS_NS_WIDTH+CMP_FNS_WIDTH-1:9+CMP_FNS_WIDTH]; ts_step_next = 1; end else begin // input did not step - sec_mismatch_next = 1'b0; - diff_valid_next = 1'b1; + load_ts_next = 1'b0; + ts_diff_valid_next = freq_locked_reg; end // compute difference ts_ns_diff_next = src_ts_ns_sync_reg - dest_ts_ns_capt_reg; + ts_diff_next = src_ts_ns_sync_reg[TS_NS_WIDTH+CMP_FNS_WIDTH-1:9+CMP_FNS_WIDTH] != dest_ts_ns_capt_reg[TS_NS_WIDTH+CMP_FNS_WIDTH-1:9+CMP_FNS_WIDTH]; end end - if (diff_valid_reg) begin - // seconds field correction - if (TS_WIDTH == 96) begin - if ($signed(ts_s_diff_reg) == 0 && ts_s_msb_diff_reg == 0 && ($signed(ts_ns_diff_reg[16+FNS_WIDTH +: 14]) == 0 || $signed(ts_ns_diff_reg[16+FNS_WIDTH +: 14]) == -1)) begin - // difference is small and no seconds difference; slew - ts_ns_diff_corr_next = ts_ns_diff_reg[16+FNS_WIDTH:0]; - diff_corr_valid_next = 1'b1; - end else if ($signed(ts_s_diff_reg) == 1 && ts_ns_diff_reg[16+FNS_WIDTH +: 14] == ~NS_PER_S[30:16]) begin - // difference is small with 1 second difference; adjust and slew - ts_ns_diff_corr_next[FNS_WIDTH +: NS_WIDTH] = ts_ns_diff_reg[FNS_WIDTH +: 17] + NS_PER_S[0 +: 17]; - ts_ns_diff_corr_next[0 +: FNS_WIDTH] = ts_ns_diff_reg[0 +: FNS_WIDTH]; - diff_corr_valid_next = 1'b1; - end else if ($signed(ts_s_diff_reg) == -1 && ts_ns_diff_reg[16+FNS_WIDTH +: 14] == NS_PER_S[30:16]) begin - // difference is small with 1 second difference; adjust and slew - ts_ns_diff_corr_next[FNS_WIDTH +: NS_WIDTH] = ts_ns_diff_reg[FNS_WIDTH +: 17] - NS_PER_S[0 +: 17]; - ts_ns_diff_corr_next[0 +: FNS_WIDTH] = ts_ns_diff_reg[0 +: FNS_WIDTH]; - diff_corr_valid_next = 1'b1; + if (ts_diff_valid_reg) begin + if (ts_diff_reg) begin + if (&mismatch_cnt_reg) begin + load_ts_next = 1'b1; + mismatch_cnt_next = 0; end else begin - // difference is too large; step the clock - sec_mismatch_next = 1'b1; - end - end else if (TS_WIDTH == 64) begin - if ($signed(ts_ns_diff_reg[16+FNS_WIDTH +: 32]) == 0 || $signed(ts_ns_diff_reg[16+FNS_WIDTH +: 32]) == -1) begin - // difference is small enough to slew - ts_ns_diff_corr_next = ts_ns_diff_reg[16+FNS_WIDTH:0]; - diff_corr_valid_next = 1'b1; - end else begin - // difference is too large; step the clock - sec_mismatch_next = 1'b1; + mismatch_cnt_next = mismatch_cnt_reg + 1; end + end else begin + mismatch_cnt_next = 0; end end - if (diff_corr_valid_reg) begin + if (phase_err_out_valid_reg) begin + // coarse phase/frequency lock of PTP clock + if ($signed(phase_err_out_reg) > 4 || $signed(phase_err_out_reg) < -4) begin + if (freq_lock_count_reg) begin + freq_lock_count_next = freq_lock_count_reg - 1; + end else begin + freq_locked_next = 1'b0; + end + end else begin + if (&freq_lock_count_reg) begin + freq_locked_next = 1'b1; + end else begin + freq_lock_count_next = freq_lock_count_reg + 1; + end + end + + if (!freq_locked_reg) begin + ts_ns_diff_next = $signed(phase_err_out_reg) * 8 * 2**CMP_FNS_WIDTH; + ts_diff_valid_next = 1'b1; + end + end + + if (ts_diff_valid_reg) begin // PI control - // time integral of error - if (ptp_locked_reg) begin - {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**16); + // gain scheduling + if (!ts_ns_diff_reg[8+CMP_FNS_WIDTH]) begin + if (ts_ns_diff_reg[4+CMP_FNS_WIDTH +: 4]) begin + gain_sel_next = 1'b1; + end else begin + gain_sel_next = 1'b0; + end end else begin - {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**13); + if (~ts_ns_diff_reg[4+CMP_FNS_WIDTH +: 4]) begin + gain_sel_next = 1'b1; + end else begin + gain_sel_next = 1'b0; + end end + // time integral of error + case (gain_sel_reg) + 1'b0: {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_reg) / 2**4); + 1'b1: {ptp_ovf, time_err_int_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_reg) * 2**2); + endcase + // saturate if (ptp_ovf[1]) begin // sign bit set indicating underflow across zero; saturate to zero @@ -613,11 +702,10 @@ always @* begin end // compute output - if (ptp_locked_reg) begin - {ptp_ovf, period_ns_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**10); - end else begin - {ptp_ovf, period_ns_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_corr_reg) / 2**7); - end + case (gain_sel_reg) + 1'b0: {ptp_ovf, period_ns_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_reg) * 2**2); + 1'b1: {ptp_ovf, period_ns_next} = $signed({1'b0, time_err_int_reg}) + ($signed(ts_ns_diff_reg) * 2**6); + endcase // saturate if (ptp_ovf[1]) begin @@ -636,15 +724,21 @@ always @* begin end // locked status - if ($signed(ts_ns_diff_corr_reg[17+FNS_WIDTH-1:4+FNS_WIDTH]) == 0 || $signed(ts_ns_diff_corr_reg[17+FNS_WIDTH-1:4+FNS_WIDTH]) == -1) begin - if (ptp_lock_count_reg == {PTP_LOCK_WIDTH{1'b1}}) begin + if (!freq_locked_reg) begin + ptp_lock_count_next = 0; + ptp_locked_next = 1'b0; + end else if (gain_sel_reg == 1'b0) begin + if (&ptp_lock_count_reg) begin ptp_locked_next = 1'b1; end else begin ptp_lock_count_next = ptp_lock_count_reg + 1; end end else begin - ptp_lock_count_next = 0; - ptp_locked_next = 1'b0; + if (ptp_lock_count_reg) begin + ptp_lock_count_next = ptp_lock_count_reg - 1; + end else begin + ptp_locked_next = 1'b0; + end end end end @@ -661,21 +755,22 @@ always @(posedge output_clk) begin ts_step_reg <= ts_step_next; - sec_mismatch_reg <= sec_mismatch_next; - diff_valid_reg <= diff_valid_next; - diff_corr_valid_reg <= diff_corr_valid_next; + ts_diff_reg <= ts_diff_next; + ts_diff_valid_reg <= ts_diff_valid_next; + mismatch_cnt_reg <= mismatch_cnt_next; + load_ts_reg <= load_ts_next; - ts_s_msb_diff_reg <= ts_s_msb_diff_next; - ts_s_diff_reg <= ts_s_diff_next; ts_ns_diff_reg <= ts_ns_diff_next; - ts_ns_diff_corr_reg <= ts_ns_diff_corr_next; - time_err_int_reg <= time_err_int_next; + freq_lock_count_reg <= freq_lock_count_next; + freq_locked_reg <= freq_locked_next; ptp_lock_count_reg <= ptp_lock_count_next; ptp_locked_reg <= ptp_locked_next; + gain_sel_reg <= gain_sel_next; + // PPS output if (TS_WIDTH == 96) begin pps_reg <= !ts_ns_ovf_reg[30+FNS_WIDTH]; @@ -705,16 +800,19 @@ always @(posedge output_clk) begin ts_s_reg <= 0; ts_ns_reg <= 0; ts_ns_inc_reg <= 0; - ts_ns_ovf_reg[30] <= 1'b1; + ts_ns_ovf_reg[30+FNS_WIDTH] <= 1'b1; ts_step_reg <= 0; pps_reg <= 0; - sec_mismatch_reg <= 1'b0; - diff_valid_reg <= 1'b0; - diff_corr_valid_reg <= 1'b0; + ts_diff_reg <= 1'b0; + ts_diff_valid_reg <= 1'b0; + mismatch_cnt_reg <= 0; + load_ts_reg <= 0; time_err_int_reg <= 0; + freq_lock_count_reg <= 0; + freq_locked_reg <= 1'b0; ptp_lock_count_reg <= 0; ptp_locked_reg <= 1'b0; diff --git a/syn/vivado/ptp_clock_cdc.tcl b/syn/vivado/ptp_clock_cdc.tcl index 1edef96d6..8d1bcd998 100644 --- a/syn/vivado/ptp_clock_cdc.tcl +++ b/syn/vivado/ptp_clock_cdc.tcl @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 Alex Forencich +# Copyright (c) 2019-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 @@ -79,7 +79,7 @@ foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_clock_cdc || REF_NA set_bus_skew -from [get_cells "$inst/sample_acc_out_reg_reg[*]"] -to [get_cells $inst/sample_acc_sync_reg_reg[*]] $output_clk_period } - # no sample clock + # timestamp transfer sync set sync_ffs [get_cells -quiet -hier -regexp ".*/src_sync_sync\[12\]_reg_reg" -filter "PARENT == $inst"] if {[llength $sync_ffs]} { @@ -87,4 +87,21 @@ foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_clock_cdc || REF_NA set_max_delay -from [get_cells "$inst/src_sync_reg_reg"] -to [get_cells "$inst/src_sync_sync1_reg_reg"] -datapath_only $input_clk_period } + + # phase sync + set sync_ffs [get_cells -quiet -hier -regexp ".*/src_phase_sync_sync\[12\]_reg_reg" -filter "PARENT == $inst"] + + if {[llength $sync_ffs]} { + set_property ASYNC_REG TRUE $sync_ffs + + # hunt down source + set dest_pins [get_pins -of_objects [get_cells "$inst/src_phase_sync_sync1_reg_reg"] -filter {REF_PIN_NAME == "D"}] + set nets [get_nets -segments -of_objects $dest_pins] + set source_pins [get_pins -of_objects $nets -filter {IS_LEAF && DIRECTION == "OUT"}] + set source [get_cells -of_objects $source_pins] + + if {[llength $source]} { + set_max_delay -from $source -to [get_cells "$inst/src_phase_sync_sync1_reg_reg"] -datapath_only $input_clk_period + } + } } From 5ff1e17a294a5070a325f191f3c8274cdf49c57b Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sun, 24 Sep 2023 13:35:29 -0700 Subject: [PATCH 12/12] Add missing assign to frame_min_count_reg in axis_baser_tx_64 module Signed-off-by: Alex Forencich --- rtl/axis_baser_tx_64.v | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rtl/axis_baser_tx_64.v b/rtl/axis_baser_tx_64.v index 234b85dd2..2fc0b634e 100644 --- a/rtl/axis_baser_tx_64.v +++ b/rtl/axis_baser_tx_64.v @@ -662,6 +662,8 @@ always @(posedge clk) begin swap_lanes_reg <= swap_lanes_next; + frame_min_count_reg <= frame_min_count_next; + ifg_count_reg <= ifg_count_next; deficit_idle_count_reg <= deficit_idle_count_next;