------------------------------------------------------- --! @file --! @author Julian Mendez (CERN - EP-ESE-BE) --! @version 6.0 --! @brief GBT-FPGA IP - Tx gearbox (Latency-optimized) ------------------------------------------------------- -- IEEE VHDL standard library: library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library UNISIM; use UNISIM.VComponents.all; Library xpm; use xpm.vcomponents.all; -- Custom libraries and packages: use work.vendor_specific_gbt_bank_package.all; use work.gbt_bank_package.all; --! @brief GBT_tx_gearbox_latopt - Tx gearbox (Latency-optimized) --! @details --! The GBT_tx_gearbox_latopt module ensure the frameclock to transceiver's wordclock --! clock domain crossing with fixed and low latency. entity gbt_tx_gearbox is generic (TX_OPTIMIZATION : integer range 0 to 1 := STANDARD); port ( --================-- -- Reset & Clocks -- --================-- -- Reset: --------- TX_RESET_I : in std_logic; -- Clocks: ---------- TX_WORDCLK_I : in std_logic; TX_FRAMECLK_I : in std_logic; TX_CLKEN_i : in std_logic; --=========-- -- Status -- --=========-- TX_PHALIGNED_O : out std_logic; TX_PHCOMPUTED_O : out std_logic; --==============-- -- Frame & Word -- --==============-- TX_FRAME_I : in std_logic_vector(119 downto 0); TX_WORD_O : out std_logic_vector(WORD_WIDTH-1 downto 0) ); end gbt_tx_gearbox; --! @brief GBT_tx_gearbox_latopt - Tx gearbox (Standard - Read/Write control) --! @details The GBT_tx_gearbox_latopt uses a single register to ensure the clock domain crossing --! The reset signal is used to synchronize the counter with the rising edge of the frameclock. It --! also implements a process to check the clock phase and the data integrety. architecture behavioral of gbt_tx_gearbox is COMPONENT RAM32x6D PORT( wclk : IN std_logic; rclk : IN std_logic; di : IN std_logic_vector(5 downto 0); we : IN std_logic; wa : IN std_logic_vector(4 downto 0); ra : IN std_logic_vector(4 downto 0); ceReg : IN std_logic; do : OUT std_logic_vector(5 downto 0) ); END COMPONENT; --================================ Signal Declarations ================================-- signal txFrame_from_frameInverter : std_logic_vector (119 downto 0); --=====================================================================================-- signal FIFO_do: std_logic_vector (119 downto 0); signal FIFO_wa: std_logic_vector (4 downto 0) := "00000"; signal FIFO_ra: std_logic_vector (4 downto 0) := "00000"; signal TOGGLE : std_logic := '0'; signal TOGGLE_sync : std_logic_vector (GBT_WORD_RATIO-1 downto 0) := (others => '0'); signal address : integer range 0 to 5 := 0; signal ready : std_logic := '0'; --=================================================================================================-- begin --========#### Architecture Body ####========-- --=================================================================================================-- --==================================== User Logic =====================================-- TX_PHCOMPUTED_O <= '1'; TX_PHALIGNED_O <= '1'; process(TX_RESET_I, TX_FRAMECLK_I) begin if TX_RESET_I = '1' then TOGGLE <= '0'; elsif rising_edge(TX_FRAMECLK_I) then if(TX_CLKEN_I = '1')then TOGGLE <= not TOGGLE; end if; end if; end process; xpm_cdc_single_inst: xpm_cdc_single generic map ( DEST_SYNC_FF => 4, -- integer; range: 2-10 INIT_SYNC_FF => 0, -- integer; 0=disable simulation init values, 1=enable simulation init values SIM_ASSERT_CHK => 0, -- integer; 0=disable simulation messages, 1=enable simulation messages SRC_INPUT_REG => 1 -- integer; 0=do not register input, 1=register input ) port map ( src_clk => TX_FRAMECLK_I, -- optional; required when SRC_INPUT_REG = 1 src_in => TOGGLE, dest_clk => TX_WORDCLK_I, dest_out => TOGGLE_sync(0) ); process(TX_WORDCLK_I) begin if(TX_WORDCLK_I'event and TX_WORDCLK_I = '1')then TOGGLE_sync(GBT_WORD_RATIO-1 downto 1) <= TOGGLE_sync(GBT_WORD_RATIO-2 downto 0); end if; end process; txGearboxStd_gen: if TX_OPTIMIZATION = STANDARD generate process(TX_RESET_I, TX_FRAMECLK_I) begin if TX_RESET_I = '1' then FIFO_wa <= (others => '0'); elsif rising_edge(TX_FRAMECLK_I) then if(TX_CLKEN_I = '1')then FIFO_wa(1) <= FIFO_wa(1) xor FIFO_wa(0); FIFO_wa(0) <= not FIFO_wa(0); end if; end if; end process; process(TX_RESET_I, TX_WORDCLK_I) begin if TX_RESET_I = '1' then FIFO_ra <= (others => '0'); elsif rising_edge(TX_WORDCLK_I) then if ready = '1' and address = GBT_WORD_RATIO-1 then FIFO_ra(1) <= FIFO_ra(1) xor FIFO_ra(0); FIFO_ra(0) <= not FIFO_ra(0); end if; end if; end process; g_FIFO : for i in 0 to 19 generate i_RAM32M : RAM32M port map ( DOA => FIFO_do(i*6+1 downto i*6), -- Read port A 2-bit output DOB => FIFO_do(i*6+3 downto i*6+2), -- Read port B 2-bit output DOC => FIFO_do(i*6+5 downto i*6+4), -- Read port C 2-bit output DOD => open, -- Read/Write port D 2-bit output ADDRA => FIFO_ra, -- Read port A 5-bit address input ADDRB => FIFO_ra, -- Read port B 5-bit address input ADDRC => FIFO_ra, -- Read port C 5-bit address input ADDRD => FIFO_wa, -- Read/Write port D 5-bit address input DIA => TX_FRAME_I(i*6+1 downto i*6), -- RAM 2-bit data write input addressed by ADDRD, -- read addressed by ADDRA DIB => TX_FRAME_I(i*6+3 downto i*6+2), -- RAM 2-bit data write input addressed by ADDRD, -- read addressed by ADDRB DIC => TX_FRAME_I(i*6+5 downto i*6+4), -- RAM 2-bit data write input addressed by ADDRD, -- read addressed by ADDRC DID => "00", -- RAM 2-bit data write input addressed by ADDRD, -- read addressed by ADDRD WCLK => TX_FRAMECLK_I, -- Write clock input WE => TX_CLKEN_i -- Write enable input ); end generate g_FIFO; process(TX_RESET_I, TX_WORDCLK_I) begin if TX_RESET_I = '1' then address <= GBT_WORD_RATIO-1; ready <= '0'; TX_WORD_O <= (others => '0'); txFrame_from_frameInverter <= (others => '0'); elsif rising_edge(TX_WORDCLK_I) then if TOGGLE_sync(1) /= TOGGLE_sync(0) then ready <= '1'; end if; if ready = '1' then if address = GBT_WORD_RATIO-1 then for i in 0 to 119 loop txFrame_from_frameInverter(i) <= FIFO_do(119-i); end loop; address <= 0; else address <= address + 1; end if; end if; TX_WORD_O <= txFrame_from_frameInverter(WORD_WIDTH*(address+1)-1 downto WORD_WIDTH*address); end if; end process; end generate txGearboxStd_gen; txGearboxLatOpt_gen: if TX_OPTIMIZATION = LATENCY_OPTIMIZED generate --==============-- -- Common logic -- --==============-- -- Comment: Note!! The reset of the gearbox is synchronous to TX_FRAMECLK in order to align the address 0 -- of the gearbox with the rising edge of TX_FRAMECLK after reset. process(TX_RESET_I, TX_WORDCLK_I) begin if TX_RESET_I = '1' then address <= 0; ready <= '0'; TX_WORD_O <= (others => '0'); txFrame_from_frameInverter <= (others => '0'); elsif rising_edge(TX_WORDCLK_I) then if TOGGLE_sync(GBT_WORD_RATIO-1) /= TOGGLE_sync(GBT_WORD_RATIO-2) then ready <= '1'; for i in 0 to 119 loop txFrame_from_frameInverter(i) <= TX_FRAME_I(119-i); end loop; address <= 0; elsif ready = '1' then address <= address + 1; end if; TX_WORD_O <= txFrame_from_frameInverter(WORD_WIDTH*(address+1)-1 downto WORD_WIDTH*address); end if; end process; end generate txGearboxLatOpt_gen; --=====================================================================================-- end behavioral; --=================================================================================================-- --#################################################################################################-- --=================================================================================================--