--==============================================================================
-- © Copyright CERN for the benefit of the HPTD interest group 2018. All rights not
-- expressly granted are reserved.
--
-- This file is part of tx_phase_aligner.
--
-- tx_phase_aligner is free VHDL code: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- tx_phase_aligner is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with tx_phase_aligner. If not, see .
--==============================================================================
--! @file tx_phase_aligner.vhd
--==============================================================================
--! Standard library
library ieee;
--! Standard packages
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--! Specific packages
-------------------------------------------------------------------------------
-- --
-- CERN, EP-ESE-BE, HPTD
-- --
-------------------------------------------------------------------------------
--
-- unit name: Tx Phase Aligner for usage when elastic buffer is enabled (tx_phase_aligner)
--
--! @brief Tx Phase Aligner for usage when elastic buffer is enabled
--! - Implements tx phase alignment procedure
--! - It is recommended to keep this block in a reset state ('reset_i' = 1) until the transceiver reset procedure is completed
--! - It is also recommended to keep the transmitter user logic in a reset state while the alignment procedure is not finished ('tx_aligned_o' = 0)
--! Different flavours are possible:
--! 1) At each reset, re-align transmitter with fine PI step:
--! - When is it recommended?
--! a) applications not requiring a perfect phase determinism (~5-10 ps variation) with resets
--! b) applications using this block only as a CDC strategy with minimal latency variation
--! - How to use design?
--! - Config ports:
--! Tie tx_pi_phase_calib_i to all '0'
--! Tie tx_ui_align_calib_i to '0'
--!
--! 2) At each reset, re-align the transmitter PI to a calibrated value
--! - When is it recommended?
--! a) applications requiring a perfect phase determinism (~1 ps variation) with resets
--! b) applications where the board FPGA is not subject to large temperature variations
--! - What does it cost?
--! a) Requires a initial calibration (automatically done by block) during first reset
--! b) Monitor the tx_fifo_fill_pd_o and perform re-calibration whenever it is all zeros or all ones
--!
--! - How to use design?
--! - Config ports:
--!
--! a) during first reset:
--! Tie tx_pi_phase_calib_i to all X (dont care)
--! Tie tx_ui_align_calib_i to '0'
--!
--! b) during other resets:
--! Tie tx_pi_phase_calib_i to the value of 'tx_pi_phase_o' after the first reset
--! Tie tx_ui_align_calib_i to '1'
--!
--! @author Eduardo Brandao de Souza Mendes - eduardo.brandao.de.souza.mendes@cern.ch
--! @date 03\05\2018
--! @version 1.0
--! @details
--!
--! Dependencies:\n
--!
--!
--! References:\n
--! \n
--!
--!
--! Modified by:\n
--! Author: Eduardo Brandao de Souza Mendes
-------------------------------------------------------------------------------
--! \n\nLast changes:\n
--! 03\05\2018 - EBSM - Created\n
--! 13\09\2018 - EBSM - Remove unused ports\n
--!
-------------------------------------------------------------------------------
--! @todo - \n
--! \n
--
-------------------------------------------------------------------------------
--==============================================================================
--! Entity declaration for tx_phase_aligner
--==============================================================================
entity tx_phase_aligner is
generic(
-- User choice of DRP control or port control
-- Recommended nowadays to use in DRP control as a strange behaviour was observed using the port in PI code stepping mode
g_DRP_NPORT_CTRL : boolean := true; --! Uses DRP control of port control for the transmitter PI
g_DRP_ADDR_TXPI_PPM_CFG : std_logic_vector(8 downto 0) := ("010011010") --! Check the transceiver user guide of your device for this address
);
port (
--==============================================================================
--! User control/monitor ports
--==============================================================================
-- Clock / reset
clk_sys_i : in std_logic; --! system clock input
reset_i : in std_logic; --! active high sync. reset (recommended to keep reset_i=1 while transceiver reset initialization is being performed)
-- Top level interface
tx_aligned_o : out std_logic; --! Use it as a reset for the user transmitter logic
-- Config (for different flavours)
tx_pi_phase_calib_i : in std_logic_vector(6 downto 0); --! previous calibrated tx pi phase (tx_pi_phase_o after first reset calibration)
tx_ui_align_calib_i : in std_logic; --! align with previous calibrated tx pi phase
tx_fifo_fill_pd_max_i : in std_logic_vector(31 downto 0); --! phase detector accumulated max output, sets precision of phase detector
--! this is supposedly a static signal, this block shall be reset whenever this signal changes
--! the time for each phase detection after a clear is given by tx_fifo_fill_pd_max_i * PERIOD_clk_txusr_i
tx_fine_realign_i : in std_logic; --! A rising edge will cause the Tx to perform a fine realignment to the half-response
-- It is only valid to re-shift clock once aligned (tx_aligned_o = '1')
ps_strobe_i : in std_logic; --! pulse synchronous to clk_sys_i to activate a shift in the phase (only captured rising edge, so a signal larger than a pulse is also fine)
ps_inc_ndec_i : in std_logic; --! 1 increments phase by phase_step_i units, 0 decrements phase by phase_step_i units
ps_phase_step_i : in std_logic_vector(3 downto 0); --! number of units to shift the phase of the receiver clock (see Xilinx transceiver User Guide to convert units in time)
ps_done_o : out std_logic; --! pulse synchronous to clk_sys_i to indicate a phase shift was performed
-- Tx PI phase value
tx_pi_phase_o : out std_logic_vector(6 downto 0); --! phase shift accumulated
-- Tx fifo fill level phase detector
tx_fifo_fill_pd_o : out std_logic_vector(31 downto 0); --! phase detector output, when aligned this value should be close to (0x2_0000)
--==============================================================================
--! MGT ports
--==============================================================================
clk_txusr_i : in std_logic; --! txusr2clk
-- Tx fifo fill level - see Xilinx transceiver User Guide for more information
tx_fifo_fill_level_i : in std_logic; --! connect to txbufstatus[0]
-- Transmitter PI ports - see Xilinx transceiver User Guide for more information
-- obs1: all txpi ports shall be connected to the transceiver even when using this block in DRP-mode
txpippmen_o : out std_logic; --! enable tx phase interpolator controller
txpippmovrden_o : out std_logic; --! enable DRP control of tx phase interpolator
txpippmsel_o : out std_logic; --! set to 1 when using tx pi ppm controler
txpippmpd_o : out std_logic; --! power down transmitter phase interpolator
txpippmstepsize_o : out std_logic_vector(4 downto 0); --! sets step size and direction of phase shift with port control PI code stepping mode
-- DRP interface - see Xilinx transceiver User Guide for more information
-- obs2: connect clk_sys_i to drpclk
-- obs3: if using this block in port-mode, DRP output can be left floating and input connected to '0'
drpaddr_o : out std_logic_vector(8 downto 0); --! For devices with a 10-bit DRP address interface, connect MSB to '0'
drpen_o : out std_logic; --! DRP enable transaction
drpdi_o : out std_logic_vector(15 downto 0); --! DRP data write
drprdy_i : in std_logic; --! DRP finished transaction
drpdo_i : in std_logic_vector(15 downto 0); --! DRP data read; not used nowadays, write only interface
drpwe_o : out std_logic --! DRP write enable
);
end tx_phase_aligner;
--==============================================================================
-- architecture declaration
--==============================================================================
architecture rtl of tx_phase_aligner is
--! Function declaration
--! Constant declaration
constant c_SPEED_PD_FACTOR : integer range 0 to 19 := 7;
constant c_PI_COARSE_STEP : integer range 0 to 15 := 8;
constant c_PI_FINE_STEP : integer range 0 to 15 := 1;
--! Signal declaration
-- tx_pi_ctrl <-> tx_phase_aligner_fsm
signal tx_aligner_tx_pi_strobe : std_logic;
signal tx_aligner_tx_pi_inc_ndec : std_logic;
signal tx_aligner_tx_pi_phase_step : std_logic_vector(3 downto 0);
signal tx_aligner_tx_pi_done : std_logic;
signal tx_pi_strobe : std_logic;
signal tx_pi_inc_ndec : std_logic;
signal tx_pi_phase_step : std_logic_vector(3 downto 0);
signal tx_pi_done : std_logic;
signal tx_pi_phase : std_logic_vector(6 downto 0);
-- tx_fifo_fill_level_acc <-> tx_phase_aligner_fsm
signal tx_fifo_fill_pd_clear : std_logic;
signal tx_fifo_fill_pd_done : std_logic;
signal tx_fifo_fill_pd : std_logic_vector(31 downto 0);
signal tx_fifo_fill_pd_max : std_logic_vector(31 downto 0);
signal reset_fifo_fill_level_acc : std_logic;
signal tx_aligned : std_logic;
--! Component declaration
component tx_phase_aligner_fsm is
generic(
g_SPEED_PD_FACTOR : integer range 0 to 19 := 10; --! coarse alignment procedure takes g_TX_FIFO_FILL_PD_MAX/(2**g_SPEED_PD_FACTOR)
g_PI_COARSE_STEP : integer range 0 to 15 := 8; --! coarse PI steps
g_PI_FINE_STEP : integer range 0 to 15 := 1 --! fine PI steps
);
port (
-- Clock / reset
clk_sys_i : in std_logic; --! system clock input
reset_i : in std_logic; --! active high sync. reset
-- Top level interface
tx_aligned_o : out std_logic; --! Use it as a reset for the user transmitter logic
-- Config (for different flavours)
tx_pi_phase_calib_i : in std_logic_vector(6 downto 0); --! previous calibrated tx pi phase
tx_ui_align_calib_i : in std_logic; --! align with previous calibrated tx pi phase
tx_fifo_fill_pd_max_i : in std_logic_vector(31 downto 0); --! phase detector accumulated max output, sets precision of phase detector
--! this is supposedly a static signal, this block shall be reset whenever this signal changes
--! the time for each phase detection after a clear is given by tx_fifo_fill_pd_max_i * PERIOD_clk_txusr_i
tx_fine_realign_i : in std_logic; --! A rising edge will cause the Tx to perform a fine realignment to the half-response
-- Tx pi controller interface - see user interface tx_pi_ctrl.vhd for more information
tx_pi_strobe_o : out std_logic; --! see user interface tx_pi_ctrl.vhd for more information
tx_pi_inc_ndec_o : out std_logic; --! see user interface tx_pi_ctrl.vhd for more information
tx_pi_phase_step_o : out std_logic_vector(3 downto 0); --! see user interface tx_pi_ctrl.vhd for more information
tx_pi_done_i : in std_logic; --! see user interface tx_pi_ctrl.vhd for more information
tx_pi_phase_i : in std_logic_vector(6 downto 0); --! see user interface tx_pi_ctrl.vhd for more information
-- Tx fifo fill level phase detector interface - see user interface fifo_fill_level_acc.vhd for more information
tx_fifo_fill_pd_clear_o : out std_logic; --! see user interface fifo_fill_level_acc.vhd for more information
tx_fifo_fill_pd_done_i : in std_logic; --! see user interface fifo_fill_level_acc.vhd for more information
tx_fifo_fill_pd_i : in std_logic_vector(31 downto 0); --! see user interface fifo_fill_level_acc.vhd for more information
tx_fifo_fill_pd_max_o : out std_logic_vector(31 downto 0) --! see user interface fifo_fill_level_acc.vhd for more information
);
end component tx_phase_aligner_fsm;
component tx_pi_ctrl is
generic(
-- User choice of DRP control or port control
-- Recommended nowadays to use in DRP control as a strange behaviour was observed using the port in PI code stepping mode
g_DRP_NPORT_CTRL : boolean := true; --! Uses DRP control of port control for the transmitter PI
g_DRP_ADDR_TXPI_PPM_CFG : std_logic_vector(8 downto 0) := ("010011010") --! Check the transceiver user guide of your device for this address
);
port (
-- User Interface
clk_sys_i : in std_logic; --! system clock input
reset_i : in std_logic; --! active high sync. reset
strobe_i : in std_logic; --! pulse synchronous to clk_sys_i to activate a shift in the transmitter phase (only captured rising edge, so a signal larger than a pulse is also fine)
inc_ndec_i : in std_logic; --! 1 increments tx phase by phase_step_i units, 0 decrements tx phase by phase_step_i units
phase_step_i : in std_logic_vector(3 downto 0); --! number of units to shift the phase of the transmitter (see Xilinx transceiver User Guide to convert units in time)
done_o : out std_logic; --! pulse synchronous to clk_sys_i to indicate a transmitter phase shift was performed
phase_o : out std_logic_vector(6 downto 0); --! phase shift accumulated
-- MGT interface
-- Transmitter PI ports - see Xilinx transceiver User Guide for more information
-- obs1: all txpi ports shall be connected to the transceiver even when using this block in DRP-mode
clk_txusr_i : in std_logic; --! txusr2clk
txpippmen_o : out std_logic; --! enable tx phase interpolator controller
txpippmovrden_o : out std_logic; --! enable DRP control of tx phase interpolator
txpippmsel_o : out std_logic; --! set to 1 when using tx pi ppm controler
txpippmpd_o : out std_logic; --! power down transmitter phase interpolator
txpippmstepsize_o : out std_logic_vector(4 downto 0); --! sets step size and direction of phase shift with port control PI code stepping mode
-- DRP interface - see Xilinx transceiver User Guide for more information
-- obs2: connect clk_sys_i to drpclk
-- obs3: if using this block in port-mode, DRP output can be left floating and input connected to '0'
drpaddr_o : out std_logic_vector(8 downto 0); --! For devices with a 10-bit DRP address interface, connect MSB to '0'
drpen_o : out std_logic; --! DRP enable transaction
drpdi_o : out std_logic_vector(15 downto 0); --! DRP data write
drprdy_i : in std_logic; --! DRP finished transaction
drpdo_i : in std_logic_vector(15 downto 0); --! DRP data read; not used nowadays, write only interface
drpwe_o : out std_logic --! DRP write enable
);
end component tx_pi_ctrl;
component fifo_fill_level_acc is
port (
-- User Interface
clk_sys_i : in std_logic; --! system clock input
reset_i : in std_logic; --! actived on rising edge sync. reset
done_o : out std_logic; --! latched to '1' to indicate accumulated value was reached, cleared only with clear/reset
phase_detector_o : out std_logic_vector(31 downto 0); --! phase detector accumulated output (increments for each pulse in which txfifofilllevel is 1)
phase_detector_max_i : in std_logic_vector(31 downto 0); --! phase detector accumulated max output, sets precision of phase detector
--! this is supposedly a static signal, this block shall be reset whenever this signal changes
--! the time for each phase detection after a clear is given by phase_detector_max_i * PERIOD_clk_txusr_i
-- MGT interface
-- Tx fifo fill level - see Xilinx transceiver User Guide for more information
clk_txusr_i : in std_logic; --! txusr2clk
tx_fifo_fill_level_i : in std_logic --! connect to txbufstatus[0]
);
end component fifo_fill_level_acc;
begin
cmp_tx_phase_aligner_fsm : tx_phase_aligner_fsm
generic map(
g_SPEED_PD_FACTOR => c_SPEED_PD_FACTOR ,
g_PI_COARSE_STEP => c_PI_COARSE_STEP ,
g_PI_FINE_STEP => c_PI_FINE_STEP
)
port map(
-- Clock / reset
clk_sys_i => clk_sys_i,
reset_i => reset_i ,
-- Top level interface
tx_aligned_o => tx_aligned ,
-- Config (for different flavours)
tx_pi_phase_calib_i => tx_pi_phase_calib_i,
tx_ui_align_calib_i => tx_ui_align_calib_i,
tx_fifo_fill_pd_max_i => tx_fifo_fill_pd_max_i,
tx_fine_realign_i => tx_fine_realign_i,
-- Tx pi controller interface - see user interface tx_pi_ctrl.vhd for more information
tx_pi_strobe_o => tx_aligner_tx_pi_strobe,
tx_pi_inc_ndec_o => tx_aligner_tx_pi_inc_ndec,
tx_pi_phase_step_o => tx_aligner_tx_pi_phase_step,
tx_pi_done_i => tx_aligner_tx_pi_done,
tx_pi_phase_i => tx_pi_phase,
-- Tx fifo fill level phase detector interface - see user interface fifo_fill_level_acc.vhd for more information
tx_fifo_fill_pd_clear_o => tx_fifo_fill_pd_clear,
tx_fifo_fill_pd_done_i => tx_fifo_fill_pd_done,
tx_fifo_fill_pd_i => tx_fifo_fill_pd,
tx_fifo_fill_pd_max_o => tx_fifo_fill_pd_max
);
cmp_tx_pi_ctrl : tx_pi_ctrl
generic map(
-- User choice of DRP control or port control
-- Recommended nowadays to use in DRP control as a strange behaviour was observed using the port in PI code stepping mode
g_DRP_NPORT_CTRL => g_DRP_NPORT_CTRL,
g_DRP_ADDR_TXPI_PPM_CFG => g_DRP_ADDR_TXPI_PPM_CFG
)
port map(
-- User Interface
clk_sys_i => clk_sys_i,
reset_i => reset_i ,
strobe_i => tx_pi_strobe,
inc_ndec_i => tx_pi_inc_ndec,
phase_step_i => tx_pi_phase_step,
done_o => tx_pi_done,
phase_o => tx_pi_phase,
-- MGT interface
-- Transmitter PI ports - see Xilinx transceiver User Guide for more information
-- obs1: all txpi ports shall be connected to the transceiver even when using this block in DRP-mode
clk_txusr_i => clk_txusr_i,
txpippmen_o => txpippmen_o,
txpippmovrden_o => txpippmovrden_o,
txpippmsel_o => txpippmsel_o,
txpippmpd_o => txpippmpd_o,
txpippmstepsize_o => txpippmstepsize_o,
-- DRP interface - see Xilinx transceiver User Guide for more information
-- obs2: connect clk_sys_i to drpclk
-- obs3: if using this block in port-mode, DRP output can be left floating and input connected to '0'
drpaddr_o => drpaddr_o,
drpen_o => drpen_o,
drpdi_o => drpdi_o,
drprdy_i => drprdy_i,
drpdo_i => drpdo_i,
drpwe_o => drpwe_o
);
tx_pi_phase_o <= tx_pi_phase;
tx_aligned_o <= tx_aligned;
tx_pi_strobe <= ps_strobe_i when tx_aligned = '1' else tx_aligner_tx_pi_strobe;
tx_pi_inc_ndec <= ps_inc_ndec_i when tx_aligned = '1' else tx_aligner_tx_pi_inc_ndec;
tx_pi_phase_step <= ps_phase_step_i when tx_aligned = '1' else tx_aligner_tx_pi_phase_step;
ps_done_o <= tx_pi_done when tx_aligned = '1' else '0';
tx_aligner_tx_pi_done <= tx_pi_done when tx_aligned = '0' else '0';
cmp_fifo_fill_level_acc : fifo_fill_level_acc
port map(
-- User Interface
clk_sys_i => clk_sys_i,
reset_i => reset_fifo_fill_level_acc,
done_o => tx_fifo_fill_pd_done,
phase_detector_o => tx_fifo_fill_pd,
phase_detector_max_i => tx_fifo_fill_pd_max,
-- MGT interface
-- Tx fifo fill level - see Xilinx transceiver User Guide for more information
clk_txusr_i => clk_txusr_i,
tx_fifo_fill_level_i => tx_fifo_fill_level_i
);
reset_fifo_fill_level_acc <= reset_i or tx_fifo_fill_pd_clear;
tx_fifo_fill_pd_o <= tx_fifo_fill_pd;
end architecture rtl;
--==============================================================================
-- architecture end
--==============================================================================