-- Pretrigger interface module to the CTP library ieee; use ieee.std_logic_1164.ALL; use ieee.numeric_std.ALL; library UNISIM; use UNISIM.Vcomponents.ALL; entity PIMFPGA is port ( BUSY_IN1 : in std_logic; -- bussy signal from the GTU --BUSY_IN2 : in std_logic; --BUSY_IN3 : in std_logic; --BUSY_IN4 : in std_logic; --CB_A_BUSY_backup : out std_logic; --CB_A_BUSY_primary : out std_logic; --CB_A_PIMLINK0_backup : in std_logic; CB_A_PIMLINK0_primary : in std_logic; --CB_A_PIMLINK1_backup : in std_logic; --CB_A_PIMLINK1_primary : in std_logic; --CB_A_PIMLINK2_backup : in std_logic; --CB_A_PIMLINK2_primary : in std_logic; --CB_C_BUSY_backup : out std_logic; --CB_C_BUSY_primary : out std_logic; --CB_C_PIMLINK0_backup : in std_logic; --CB_C_PIMLINK0_primary : in std_logic; --CB_C_PIMLINK1_backup : in std_logic; --CB_C_PIMLINK1_primary : in std_logic; --CB_C_PIMLINK2_backup : in std_logic; --CB_C_PIMLINK2_primary : in std_logic; CB_TOF_BUSY_backup : out std_logic; -- fiber output for busy to CBTOF CB_TOF_BUSY_primary : out std_logic; -- fiber output for busy to CBTOF CB_TOF_PIMLINK0_backup : in std_logic; CB_TOF_PIMLINK0_primary : in std_logic; -- clk: will be delayed for xor decoding CB_TOF_PIMLINK1_backup : in std_logic; CB_TOF_PIMLINK1_primary : in std_logic; CB_TOF_PIMLINK2_backup : in std_logic; CB_TOF_PIMLINK2_primary : in std_logic; LED1 : out std_logic; LED2 : out std_logic; BUSY_OUT1 : out std_logic; -- L0 pre-trigger output BUSY_OUT2 : out std_logic; -- L0 UPC trigger output BUSY_OUT3 : out std_logic; -- L1 output UPC data BUSY_OUT4 : out std_logic; -- L1 output UPC data BUSY_OUT5 : out std_logic; -- L1 output UPC data BUSY_OUT6 : out std_logic; -- L1 output UPC data BUSY_OUT7 : out std_logic; BUSY_OUT8 : out std_logic; dummy_clock : in std_logic ); end PIMFPGA; architecture BEHAVIORAL of PIMFPGA is COMPONENT clk_enable_logic PORT( clk40 : IN std_logic; clk160 : IN std_logic; reset : IN std_logic; en0deg : OUT std_logic; en90deg : OUT std_logic; en180deg : OUT std_logic; en270deg : OUT std_logic ); END COMPONENT; signal clk40, clk80, clk40_prebuf, clk80_prebuf, clk160, clk160_prebuf, clkpad, reset, clk160_debug : std_logic; signal clk80_con, clk40_con: std_logic; signal en0deg, en90deg, en180deg, en270deg : std_logic; signal PIM0_signal, PIM1_signal, PIM2_signal : std_logic; signal Busy_out1_signal, Busy_out2_signal, Busy_out3_signal : std_logic; signal Busy_out4_signal, Busy_out5_signal, Busy_out6_signal : std_logic; signal sig1, sig2, sig3, sig4, sig5, sig6, sig7, sig8 : std_logic; signal sig9, sig10, sig11, sig12, sig13, sig14, sig15 : std_logic; signal sig16, sig17, sig18 : std_logic; signal parallize : std_logic_vector(7 downto 0); signal sig19 : std_logic_vector(2 downto 0); signal CB_TOF_BUSY_signal : std_logic; signal reset_1, reset_2, reset_3, reset_4, reset_5, reset_6, reset_7, reset_DCM : std_logic; signal DCM1_locked, DCM2_reset : std_logic; begin PIM0_signal <= CB_TOF_PIMLINK0_primary or CB_TOF_PIMLINK0_backup; PIM1_signal <= CB_TOF_PIMLINK1_primary or CB_TOF_PIMLINK1_backup; PIM2_signal <= CB_TOF_PIMLINK2_primary or CB_TOF_PIMLINK2_backup; CB_TOF_BUSY_primary <= CB_TOF_BUSY_signal; CB_TOF_BUSY_backup <= CB_TOF_BUSY_signal; DCM_inst1 : DCM generic map ( CLKDV_DIVIDE => 2.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5 -- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0 CLKFX_DIVIDE => 1, -- Can be any interger from 1 to 32 CLKFX_MULTIPLY => 4, -- Can be any integer from 1 to 32 CLKIN_DIVIDE_BY_2 => FALSE, -- TRUE/FALSE to enable CLKIN divide by two feature CLKIN_PERIOD => 24.0, -- Specify period of input clock CLKOUT_PHASE_SHIFT => "FIXED", -- Specify phase shift of NONE, FIXED or VARIABLE CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE, 1X or 2X DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or -- an integer from 0 to 15 DFS_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for frequency synthesis DLL_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for DLL DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE FACTORY_JF => X"C080", -- FACTORY JF Values PHASE_SHIFT => 16 ,--15 only works if senders are cold -- Amount of fixed phase shift from -255 to 255 STARTUP_WAIT => TRUE) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE port map ( CLK0 => clk40_prebuf, -- 0 degree DCM CLK ouptput CLK180 => open, -- 180 degree DCM CLK output CLK270 => open, -- 270 degree DCM CLK output CLK2X => clk80_prebuf, -- 2X DCM CLK output CLK2X180 => open, -- 2X, 180 degree DCM CLK out CLK90 => open, -- 90 degree DCM CLK output CLKDV => open, -- Divided DCM CLK out (CLKDV_DIVIDE) CLKFX => open, -- DCM CLK synthesis out (M/D) CLKFX180 => open, -- 180 degree CLK synthesis out LOCKED => DCM1_locked, -- DCM LOCK status output PSDONE => open, -- Dynamic phase adjust done output STATUS => open, -- 8-bit DCM status bits output CLKFB => clk40, -- DCM clock feedback CLKIN => CB_TOF_PIMLINK0_primary, --PIM0_signal, -- Clock input (from IBUFG, BUFG or DCM) PSCLK => open, -- Dynamic phase adjust clock input PSEN => open, -- Dynamic phase adjust enable input PSINCDEC => open, -- Dynamic phase adjust increment/decrement RST => '0' -- DCM asynchronous reset input ); DCM_inst2 : DCM generic map ( CLKDV_DIVIDE => 2.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5 -- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0 CLKFX_DIVIDE => 1, -- Can be any interger from 1 to 32 CLKFX_MULTIPLY => 4, -- Can be any integer from 1 to 32 CLKIN_DIVIDE_BY_2 => FALSE, -- TRUE/FALSE to enable CLKIN divide by two feature CLKIN_PERIOD => 12.0, -- Specify period of input clock CLKOUT_PHASE_SHIFT => "NONE", -- Specify phase shift of NONE, FIXED or VARIABLE CLK_FEEDBACK => "2X", -- Specify clock feedback of NONE, 1X or 2X DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or -- an integer from 0 to 15 DFS_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for frequency synthesis DLL_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for DLL DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE FACTORY_JF => X"C080", -- FACTORY JF Values PHASE_SHIFT => 0, -- Amount of fixed phase shift from -255 to 255 STARTUP_WAIT => FALSE) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE port map ( CLK0 => open, -- 0 degree DCM CLK ouptput CLK180 => open, -- 180 degree DCM CLK output CLK270 => open, -- 270 degree DCM CLK output CLK2X => clk160_prebuf, -- 2X DCM CLK output CLK2X180 => open, -- 2X, 180 degree DCM CLK out CLK90 => open, -- 90 degree DCM CLK output CLKDV => open, -- Divided DCM CLK out (CLKDV_DIVIDE) CLKFX => open, -- DCM CLK synthesis out (M/D) CLKFX180 => open, -- 180 degree CLK synthesis out LOCKED => open, -- DCM LOCK status output PSDONE => open, -- Dynamic phase adjust done output STATUS => open, -- 8-bit DCM status bits output CLKFB => clk160, -- DCM clock feedback CLKIN => clk80, -- Clock input (from IBUFG, BUFG or DCM) PSCLK => open, -- Dynamic phase adjust clock input PSEN => open, -- Dynamic phase adjust enable input PSINCDEC => open, -- Dynamic phase adjust increment/decrement RST => DCM2_reset -- DCM asynchronous reset input ); DCM2_reset <= (not DCM1_locked) or reset; BUFG_inst_clk40 : BUFG port map ( O => clk40, -- Clock buffer output I => clk40_prebuf -- Clock buffer input ); BUFG_inst_clk80 : BUFG port map ( O => clk80, -- Clock buffer output I => clk80_prebuf -- Clock buffer input ); BUFG_inst_clk160 : BUFG port map ( O => clk160, -- Clock buffer output I => clk160_prebuf -- Clock buffer input ); -- CB_TOF_PIMLINK0 is 40MHz clock -- CB_TOF_PIMLINK1 and 2 each encode 3 data bit in 4 bit sent at 160MHz -- data bits 0,1,2 are mapped to encoded bits 0,1,3 -- encoded bit 2 is: 1 if all data bits are 0 or during reset -- 0 in all other cases -- "Reset" if all CB_TOF_PIMLINK0,1,2 all have 80MHz clock -- extract reset; reset if there is a one at rising and falling clk40 edge of PIM1 and PIM2 -- (use the 2nd and 4th bit to zero to have an AC signal) -- (PIM0 should be a bit delayed compared to PIM1 and PIM2) -- reset the reset chain with the DCM1_locked signal. Otherwise initial setup of the registers -- can be a reset and then you are trapped into the reset state; clkpad <= clk40; process(clkpad, CB_TOF_PIMLINK1_primary, DCM1_locked) begin if clkpad'event and clkpad = '1' then sig1 <= CB_TOF_PIMLINK1_primary; end if; end process; process(clkpad, CB_TOF_PIMLINK1_primary, DCM1_locked, sig1) begin if clkpad'event and clkpad = '0' then -- request a 1 at the rising edge -- otherwise a falling edge bit from the previous clk40 cycle can -- issue a wrong reset sig2 <= CB_TOF_PIMLINK1_primary and sig1; end if; end process; process(clkpad, CB_TOF_PIMLINK2_primary, DCM1_locked) begin if clkpad'event and clkpad = '1' then sig3 <= CB_TOF_PIMLINK2_primary; end if; end process; process(clkpad, CB_TOF_PIMLINK2_primary, DCM1_locked, sig3) begin if clkpad'event and clkpad = '0' then -- request a 1 at the rising edge -- otherwise a falling edge bit from the previous clk40 cycle can -- issue a wrong reset sig4 <= CB_TOF_PIMLINK2_primary and sig3; end if; end process; reset <= sig1 and sig2 and sig3 and sig4; -- parallize trigger process(clk160, reset, PIM1_signal) begin if reset = '1' then parallize(0) <= '0'; elsif clk160'event and clk160 = '1' then parallize(0) <= PIM1_signal; end if; end process; process(clk160, reset, parallize(0)) begin if reset = '1' then parallize(1) <= '0'; elsif clk160'event and clk160 = '1' then parallize(1) <= parallize(0); end if; end process; process(clk160, reset, parallize(1)) begin if reset = '1' then parallize(2) <= '0'; elsif clk160'event and clk160 = '1' then parallize(2) <= parallize(1); end if; end process; process(clk160, reset, parallize(2)) begin if reset = '1' then parallize(3) <= '0'; elsif clk160'event and clk160 = '1' then parallize(3) <= parallize(2); end if; end process; process(clk160, reset, PIM2_signal) begin if reset = '1' then parallize(4) <= '0'; elsif clk160'event and clk160 = '1' then parallize(4) <= PIM2_signal; end if; end process; process(clk160, reset, parallize(4)) begin if reset = '1' then parallize(5) <= '0'; elsif clk160'event and clk160 = '1' then parallize(5) <= parallize(4); end if; end process; process(clk160, reset, parallize(5)) begin if reset = '1' then parallize(6) <= '0'; elsif clk160'event and clk160 = '1' then parallize(6) <= parallize(5); end if; end process; process(clk160, reset, parallize(6)) begin if reset = '1' then parallize(7) <= '0'; elsif clk160'event and clk160 = '1' then parallize(7) <= parallize(6); end if; end process; --output register process(clk160, reset, en0deg, reset, parallize(3)) begin if reset = '1' then Busy_OUT1_signal <= '0'; elsif clk160'event and clk160 = '1' and en0deg = '1' then Busy_OUT1_signal <= parallize(3); end if; end process; process(clk160, reset, en0deg, reset, parallize(2)) begin if reset = '1' then Busy_OUT2_signal <= '0'; elsif clk160'event and clk160 = '1' and en0deg = '1' then Busy_OUT2_signal <= parallize(2); end if; end process; process(clk160, reset, en0deg, reset, parallize(0)) begin if reset = '1' then Busy_OUT3_signal <= '0'; elsif clk160'event and clk160 = '1' and en0deg = '1' then Busy_OUT3_signal <= parallize(0); end if; end process; process(clk160, reset, en0deg, reset, parallize(7)) begin if reset = '1' then Busy_OUT4_signal <= '0'; elsif clk160'event and clk160 = '1' and en0deg = '1' then Busy_OUT4_signal <= parallize(7); end if; end process; process(clk160, reset, en0deg, reset, parallize(6)) begin if reset = '1' then Busy_OUT5_signal <= '0'; elsif clk160'event and clk160 = '1' and en0deg = '1' then Busy_OUT5_signal <= parallize(6); end if; end process; process(clk160, reset, en0deg, reset, parallize(4)) begin if reset = '1' then Busy_OUT6_signal <= '0'; elsif clk160'event and clk160 = '1' and en0deg = '1' then Busy_OUT6_signal <= parallize(4); end if; end process; --clk enable logic Inst_clk_enable_logic: clk_enable_logic PORT MAP( clk40 => clk40, clk160 => clk160, en0deg => en0deg, en90deg => en90deg, en180deg => en180deg, en270deg => en270deg, reset => reset ); -- GTU busy encoding CB_TOF_BUSY_signal <= sig16 xor clk40; process(BUSY_IN1, reset, sig17) begin case (reset) is when '0' => sig16 <= BUSY_IN1; when '1' => sig16 <= sig17; when others => sig16 <= '0'; end case; end process; process(clk40, reset, sig18) begin if reset = '1' then sig17 <= '0'; elsif clk40'event and clk40='1' then sig17 <= sig18; end if; end process; process(sig19) begin case (sig19) is when "000" => sig18 <= '1'; when "001" => sig18 <= '1'; when "010" => sig18 <= '1'; when "011" => sig18 <= '1'; when "100" => sig18 <= '0'; when "101" => sig18 <= '1'; when "110" => sig18 <= '0'; when "111" => sig18 <= '0'; when others => sig18 <= '0'; end case; end process; LED1 <= not DCM2_reset; LED2 <= Busy_OUT1_signal or Busy_out2_signal or Busy_out3_signal or Busy_out4_signal or Busy_out5_signal or Busy_out6_signal; Busy_out1 <= Busy_out1_signal; Busy_out2 <= Busy_out2_signal; BUsy_OUT3 <= Busy_out3_signal; Busy_out4 <= BUSY_out4_signal; Busy_out5 <= Busy_out5_signal; Busy_out6 <= BUSY_out6_signal; Busy_out7 <= PIM1_signal; Busy_out8 <= PIM2_signal; end BEHAVIORAL;