--============================================================================== -- © 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 fifo_fill_level_acc.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: Transmitter FIFO filling level phase detector (fifo_fill_level_acc) -- --! @brief Transmitter FIFO filling level phase detector based on the address difference of read and write pointers --! This block accumulates the FIFO filling level flag in order to obtain a high precision phase detector --! --! @author Eduardo Brandao de Souza Mendes - eduardo.brandao.de.souza.mendes@cern.ch --! @date 02\05\2018 --! @version 1.0 --! @details --! --! Dependencies:\n --! --! --! References:\n --! \n --! --! --! Modified by:\n --! Author: Eduardo Brandao de Souza Mendes ------------------------------------------------------------------------------- --! \n\nLast changes:\n --! 02\05\2018 - EBSM - Created\n --! ------------------------------------------------------------------------------- --! @todo - \n --! \n -- ------------------------------------------------------------------------------- --============================================================================== --! Entity declaration for fifo_fill_level_acc --============================================================================== entity 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 fifo_fill_level_acc; --============================================================================== -- architecture declaration --============================================================================== architecture rtl of fifo_fill_level_acc is --! Attribute declaration attribute async_reg : string; --! Constant declaration --! Signal declaration -- clear synchronizer to txusr clk using closed loop technique with synchronizer -- reset synchronizer using simple 2-FF -- clk_sys signal reset_r : std_logic; signal reset_toggle : std_logic := '0'; -- clk_txusr signal reset_toggle_txusr_meta : std_logic; signal reset_toggle_txusr_r : std_logic; signal reset_toggle_txusr_r2 : std_logic; attribute async_reg of reset_toggle_txusr_meta, reset_toggle_txusr_r, reset_toggle_txusr_r2 : signal is "true"; signal reset_txusr : std_logic; -- phase detector signal phase_detector_acc : unsigned(phase_detector_o'range); signal hits_acc : unsigned(phase_detector_max_i'range); signal done : std_logic; -- sync for done signal done_sys_meta : std_logic; signal done_sys_r : std_logic; signal done_sys_r2 : std_logic; attribute async_reg of done_sys_meta, done_sys_r, done_sys_r2 : signal is "true"; begin --============================================================================ -- Process p_reset_toggle --! Creates a toggle for the reset when rising edge is detected --! read: reset_i\n --! write: \n --! r/w: reset_toggle\n --============================================================================ p_reset_toggle : process(clk_sys_i) begin if(rising_edge(clk_sys_i)) then reset_r <= reset_i; if(reset_r = '0' and reset_i = '1') then reset_toggle <= not reset_toggle; end if; end if; end process p_reset_toggle; --============================================================================ -- Process p_reset_toggle_txusrsync --! Creates a toggle for the reset when rising edge is detected --! read: reset_toggle\n --! write: reset_txusr\n --! r/w: reset_toggle_txusr_meta, reset_toggle_txusr_r, reset_toggle_txusr_r2\n --============================================================================ p_reset_toggle_txusrsync : process(clk_txusr_i) begin if(rising_edge(clk_txusr_i)) then reset_toggle_txusr_meta <= reset_toggle; reset_toggle_txusr_r <= reset_toggle_txusr_meta; reset_toggle_txusr_r2 <= reset_toggle_txusr_r; reset_txusr <= reset_toggle_txusr_r2 xor reset_toggle_txusr_r; end if; end process p_reset_toggle_txusrsync; --============================================================================ -- Process p_phase_detector --! Creates reset toggle register with rising edge of reset --! read: reset_txusr\n --! write: done\n --! r/w: hits_acc, phase_detector_acc\n --============================================================================ p_phase_detector : process(clk_txusr_i) begin if(rising_edge(clk_txusr_i)) then if (reset_txusr = '1') then phase_detector_acc <= to_unsigned(0, phase_detector_acc'length); hits_acc <= to_unsigned(0, hits_acc'length); done <= '0'; else if(hits_acc < unsigned(phase_detector_max_i)) then hits_acc <= hits_acc + to_unsigned(1, hits_acc'length); if(tx_fifo_fill_level_i = '1') then phase_detector_acc <= phase_detector_acc + to_unsigned(1, phase_detector_acc'length); end if; done <= '0'; else done <= '1'; end if; end if; end if; end process p_phase_detector; --============================================================================ -- Process p_sys_sync --! System clock output synchronizer --! read: done\n --! write: done_sys_r2\n --! r/w: done_sys_meta, done_sys_r\n --============================================================================ p_sys_sync : process(clk_sys_i) begin if(rising_edge(clk_sys_i)) then done_sys_meta <= done; done_sys_r <= done_sys_meta; done_sys_r2 <= done_sys_r; end if; end process p_sys_sync; --============================================================================ -- Process p_done_out --! Output of done bit --! read: done_sys_r2, done_sys_r\n --! write: done_o\n --! r/w: -\n --============================================================================ p_done_out : process(clk_sys_i) begin if(rising_edge(clk_sys_i)) then if(reset_i = '1') then done_o <= '0'; else if(done_sys_r2 = '0' and done_sys_r = '1') then done_o <= '1'; end if; end if; end if; end process p_done_out; --============================================================================ -- Process p_pd_out --! Output of phase detector --! read: done_sys_r2, done_sys_r, phase_detector_acc\n --! write: phase_detector_o\n --! r/w: -\n --============================================================================ p_pd_out : process(clk_sys_i) begin if(rising_edge(clk_sys_i)) then if(done_sys_r2 = '0' and done_sys_r = '1') then phase_detector_o <= std_logic_vector(phase_detector_acc); end if; end if; end process p_pd_out; end architecture rtl; --============================================================================== -- architecture end --==============================================================================