--============================================================================== -- © Copyright CERN for the benefit of the TTC-PON project. All rights not -- expressly granted are reserved. -- -- This file is part of ttc_pon. -- -- ttc_pon 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. -- -- ttc_pon 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 ttc_pon. If not, see . --============================================================================= --! @file drp_arbiter.vhd --============================================================================= --! Standard library library ieee; --! Standard packages use ieee.std_logic_1164.all; use ieee.numeric_std.all; --! Specific packages ------------------------------------------------------------------------------- -- -- -- CERN, EP-ESE-BE, TTC-PON -- -- ------------------------------------------------------------------------------- -- -- unit name: GTH/GTX DRP arbiter (drp_arbiter) -- --! @brief Dynamic Reconfiguration Port arbiter for GTX/GTH-Xilinx transceivers --! --! --! @author Eduardo Brandao de Souza Mendes - eduardo.brandao.de.souza.mendes@cern.ch --! @date 31\10\2018 --! @version 1.0 --! @details --! --! Dependencies:\n --! --! --! References:\n --! \n --! --! --! Modified by:\n --! Author: Eduardo Brandao de Souza Mendes ------------------------------------------------------------------------------- --! \n\nLast changes:\n --! 31\10\2018 - EBSM - Created\n --! ------------------------------------------------------------------------------- --! @todo - \n --! \n -- ------------------------------------------------------------------------------- --============================================================================ --! Entity declaration for drp_arbiter --============================================================================ entity drp_arbiter is generic( g_NUM_MASTER : integer := 2 ); port ( -- global input signals -- clk_i : in std_logic; reset_i : in std_logic; -------------------------- -- Interface to user -- master_drpwe_i : in std_logic_vector(g_NUM_MASTER-1 downto 0); master_drpen_i : in std_logic_vector(g_NUM_MASTER-1 downto 0); master_drpaddr_i : in std_logic_vector(10*g_NUM_MASTER-1 downto 0); master_drpdi_i : in std_logic_vector(16*g_NUM_MASTER-1 downto 0); master_drprdy_o : out std_logic_vector(g_NUM_MASTER-1 downto 0); master_drpdo_o : out std_logic_vector(16*g_NUM_MASTER-1 downto 0); ------------------------------- -- DRP connection to GTH/GTX -- mgt_drpwe_o : out std_logic; mgt_drpen_o : out std_logic; mgt_drpaddr_o : out std_logic_vector(9 downto 0); mgt_drpdi_o : out std_logic_vector(15 downto 0); mgt_drprdy_i : in std_logic; mgt_drpdo_i : in std_logic_vector(15 downto 0) ------------------------------- ); end entity drp_arbiter; --============================================================================ -- ! architecture declaration --============================================================================ architecture rtl of drp_arbiter is --! Signal declaration signal master_cntr : integer range 0 to g_NUM_MASTER-1; --! master select signal clear_req : std_logic_vector(g_NUM_MASTER-1 downto 0); --! clear request memory signal master_drprdy_r : std_logic_vector(g_NUM_MASTER-1 downto 0); --! delay response master to avoid dead time signal mgt_drpdo_r : std_logic_vector(mgt_drpdo_i'range); --! delay response master to avoid dead time signal mgt_drpdo_r2 : std_logic_vector(mgt_drpdo_i'range); --! delay response master to avoid dead time --! memorize DRP transaction requests signal drpwe_mem : std_logic_vector(g_NUM_MASTER-1 downto 0); signal drpen_mem : std_logic_vector(g_NUM_MASTER-1 downto 0); signal master_drpaddr_mem : std_logic_vector(10*g_NUM_MASTER-1 downto 0); signal master_drpdi_mem : std_logic_vector(16*g_NUM_MASTER-1 downto 0); type t_ARBITER_FSM is (IDLE, CHECK_REQUEST, GO_TRANS, WAIT_TRANS, CLEAR_REQUEST, NEXT_MASTER); signal arbiter_state : t_ARBITER_FSM; --! Component declaration --============================================================================ -- architecture begin --============================================================================ begin --============================================================================ --! DRP Latch Request --============================================================================ gen_request_loop : for i in 0 to g_NUM_MASTER-1 generate p_drp_request : process (clk_i) is begin -- process p_drp_write if clk_i'event and clk_i = '1' then -- rising clock edge if reset_i = '1' or clear_req(i) = '1' then drpwe_mem(i) <= '0'; drpen_mem(i) <= '0'; else if(master_drpen_i(i) = '1') then drpen_mem(i) <= '1'; drpwe_mem(i) <= master_drpwe_i(i); end if; end if; if(master_drpen_i(i) = '1') then master_drpaddr_mem(10*(i+1)-1 downto 10*i) <= master_drpaddr_i(10*(i+1)-1 downto 10*i); master_drpdi_mem(16*(i+1)-1 downto 16*i) <= master_drpdi_i(16*(i+1)-1 downto 16*i); end if; end if; end process p_drp_request; end generate gen_request_loop; --============================================================================ --! DRP acknowledgment --============================================================================ p_drp_ack : process (clk_i) is begin -- process p_drp_write if clk_i'event and clk_i = '1' then -- rising clock edge master_drprdy_o <= master_drprdy_r; mgt_drpdo_r2 <= mgt_drpdo_r; mgt_drpdo_r <= mgt_drpdo_i; if(arbiter_state = WAIT_TRANS) then master_drprdy_r <= (others => '0'); master_drprdy_r(master_cntr) <= mgt_drprdy_i; else master_drprdy_r <= (others => '0'); end if; end if; end process p_drp_ack; gen_drp_do : for i in 0 to g_NUM_MASTER-1 generate master_drpdo_o(16*(i+1)-1 downto 16*i) <= mgt_drpdo_r2; end generate; --============================================================================ --! DRP arbiter fsm --============================================================================ p_arbiter_fsm : process(clk_i) begin if(rising_edge(clk_i)) then if(reset_i = '1') then arbiter_state <= IDLE; else case arbiter_state is when IDLE => arbiter_state <= CHECK_REQUEST; when CHECK_REQUEST => if(drpen_mem(master_cntr) = '1') then arbiter_state <= GO_TRANS; else arbiter_state <= NEXT_MASTER; end if; when GO_TRANS => arbiter_state <= WAIT_TRANS; when WAIT_TRANS => if(mgt_drprdy_i = '1') then arbiter_state <= CLEAR_REQUEST; end if; when CLEAR_REQUEST => arbiter_state <= NEXT_MASTER; when NEXT_MASTER => arbiter_state <= CHECK_REQUEST; when others => arbiter_state <= IDLE; end case; end if; end if; end process p_arbiter_fsm; --============================================================================ --! DRP clear request --============================================================================ p_clear_request : process(clk_i) begin if(rising_edge(clk_i)) then if(reset_i = '1') then clear_req <= (others => '0'); else if(arbiter_state = CLEAR_REQUEST) then clear_req <= (others => '0'); clear_req(master_cntr) <= '1'; else clear_req <= (others => '0'); end if; end if; end if; end process p_clear_request; --============================================================================ --! DRP master counter --============================================================================ p_master_cntr : process(clk_i) begin if(rising_edge(clk_i)) then if(reset_i = '1') then master_cntr <= 0; else if(arbiter_state = NEXT_MASTER) then if(master_cntr = g_NUM_MASTER-1) then master_cntr <= 0; else master_cntr <= master_cntr + 1; end if; end if; end if; end if; end process p_master_cntr; --============================================================================ --! DRP generate transaction --============================================================================ p_gen_drp_transaction : process(clk_i) begin if(rising_edge(clk_i)) then if(reset_i = '1') then mgt_drpen_o <= '0'; mgt_drpwe_o <= '0'; mgt_drpaddr_o <= (others => '0'); mgt_drpdi_o <= (others => '0'); else if(arbiter_state = GO_TRANS) then mgt_drpen_o <= '1'; mgt_drpwe_o <= drpwe_mem(master_cntr); mgt_drpaddr_o <= master_drpaddr_mem(10*(master_cntr+1)-1 downto 10*master_cntr); mgt_drpdi_o <= master_drpdi_mem(16*(master_cntr+1)-1 downto 16*master_cntr); else mgt_drpen_o <= '0'; mgt_drpwe_o <= '0'; mgt_drpaddr_o <= (others => '0'); mgt_drpdi_o <= (others => '0'); end if; end if; end if; end process p_gen_drp_transaction; end architecture rtl; --============================================================================ -- architecture end --============================================================================