-- PROJECT: D0 Run IIb Trigger L1 Calorimeter upgrade -- -- MODULE: Channel Link Receiver Test Card -- -- ELEMENT: ChalinkR_FPGA_test -- -- DESCRIPTION: Testbench for the Channel Link -- Receiver Tester. -- -- AUTHOR: D. Calvet calvet@hep.saclay.cea.fr -- -- DATE AND HISTORY: -- June 2003 : created -- April 2004: added generation of FRAME, BX_COUNT and PARITY -- April 2004: changed LFSR_RESET so that it is independant of bus RESET -- This is to ensure that LFSR are always loaded and enabled when restarting -- a simulation. -- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; library work; use work.utility_pkg.all; -------------------------------------------------------------------------------- entity ChalinkR_FPGA_test is constant H_WCLK_PERIOD : TIME := 20 ns; constant H_RX_CLK_PERIOD : TIME := 8 ns; constant H_REF_CLK_PERIOD : TIME := 5 ns; -- 100 MHz reference clock type natural_vector is array (natural range<>) of natural; constant LFSR_SEEDS : natural_vector(31 downto 0) := ( 0 => 16#0000#, 1 => 16#FFFE#, 2 => 16#012E#, 3 => 16#0C26#, 4 => 16#A128#, 5 => 16#16EA#, 6 => 16#2AB4#, 7 => 16#36BA#, 8 => 16#AA00#, 9 => 16#0332#, 10 => 16#1FFE#, 11 => 16#A002#, 12 => 16#1F0E#, 13 => 16#C002#, 14 => 16#7202#, 15 => 16#E412#, 16 => 16#7208#, 17 => 16#3208#, others => 0 ); end ChalinkR_FPGA_test; architecture behavior of ChalinkR_FPGA_test is -- -- 16-bit LFSR -- component lfsr port ( RESET : in std_logic; -- Asynchronous RESET CLK : in std_logic; -- Clock SE : in std_logic; -- Synchronous Shift Enable LOAD_L : in std_logic; -- Load Lower byte of Seed LOAD_H : in std_logic; -- Load Higher byte of Seed SEED : in std_logic_vector(15 downto 0); -- Seed Q : out std_logic_vector(15 downto 0) -- Output ); end component; component ChalinkR_FPGA port ( ----------------------------------------------------------------------- -- -- Miscellaneous signals -- RESET : in std_logic; -- Register RESET ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- LED indicators -- LED_USER : out std_logic; -- LED indicator ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Bus interface signals -- WE : in std_logic; -- Write Enable CS_B : in std_logic; -- Chip Select active low ADDR : in std_logic_vector(11 downto 0); -- Address bus DATA : inout std_logic_vector(7 downto 0); -- Data bus WCLK : in std_logic; -- Write Clock DTACK_B : out std_logic; -- Data acknowledge active low ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Clock signals -- CLK_BC_PLL : out std_logic; -- BC clock ouptut for board level PLL CLK_BC_OUT : out std_logic; -- BC clock ouptut for board level distribution CLK_BC_IN : in std_logic; -- BC clock input from board level distribution CLK_BC4X_IN : in std_logic; -- BCX4 clock input from board level distribution ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Channel Link Deserializer interface signals -- RX_CLK : in std_logic; -- Received clock RX_DATA : in std_logic_vector(35 downto 0); -- Received data ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- SCL interface cable signals -- ----------------------------------------------------------------------- SCLIF_CLK7_P : in std_logic; -- Bunch crossing clock input LVDS Positive SCLIF_CLK7_N : in std_logic; -- Bunch crossing clock input LVDS Negative SCLIF_BUSY_B_OUT_P : out std_logic; -- Busy signal (active low) upstream ADF -> SCL receiver LVDS Positive SCLIF_BUSY_B_OUT_N : out std_logic; -- Busy signal (active low) upstream ADF -> SCL receiver LVDS Negative SCLIF_CMDU_OUT_P : out std_logic; -- Command upstream ADF's -> SCL receiver LVDS Positive SCLIF_CMDU_OUT_N : out std_logic; -- Command upstream ADF's -> SCL receiver LVDS Negative SCLIF_CMDD_IN_P : in std_logic; -- Command downstream ADF's <- SCL receiver LVDS Positive SCLIF_CMDD_IN_N : in std_logic; -- Command downstream ADF's <- SCL receiver LVDS Negative SCLIF_ERR_B_OUT_P : out std_logic; -- Error signal (active low) upstream ADF -> SCL receiver LVDS Positive SCLIF_ERR_B_OUT_N : out std_logic; -- Error signal (active low) upstream ADF -> SCL receiver LVDS Negative SCLIF_STRIG_B_P : out std_logic; -- Self trigger ADF -> SCLIF LVDS Positive SCLIF_STRIG_B_N : out std_logic; -- Self trigger ADF -> SCLIF LVDS Negative SCLIF_SPARE_P : in std_logic; -- Spare wire LVDS Positive SCLIF_SPARE_N : in std_logic; -- Spare wire LVDS Negative ------------------------------------------------------------------------- -- Debug Port -- DBG_IN : in std_logic_vector(0 downto 0); -- Debug port Input pads DBG_OUT : out std_logic_vector(1 downto 0); -- Debug port Output pads ------------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Pins specific to debug implementation -- ----------------------------------------------------------------------- SCL_CLK : in std_logic -- (100 MHz clock from Evaluation Kit) ); END component; ----------------------------------------------------------------------- -- -- Miscellaneous signals -- signal RESET : std_logic := '0'; -- Register RESET ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- LED indicators -- signal LED_USER : std_logic; -- LED indicator ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Bus interface signals -- signal WE : std_logic := '0'; -- Write Enable signal CS_B : std_logic := '1'; -- Chip Select active low signal ADDR : std_logic_vector(11 downto 0) := (others => '0'); -- Address bus signal DATA : std_logic_vector(7 downto 0); -- Data bus signal WCLK : std_logic := '0'; -- Write Clock signal DTACK_B : std_logic; -- Data acknowledge active low ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Clock signals -- signal CLK_BC_PLL : std_logic; -- BC clock ouptut for board level PLL signal CLK_BC_OUT : std_logic; -- BC clock ouptut for board level distribution signal CLK_BC_IN : std_logic := '1'; -- BC clock input from board level distribution signal CLK_BC4X_IN : std_logic := '1'; -- BCX4 clock input from board level distribution ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Channel Link Deserializer interface signals -- signal RX_CLK : std_logic := '1'; -- Received clock signal RX_CLK_B : std_logic; -- Received clock inverted signal RX_DATA : std_logic_vector(35 downto 0) := (others => '0'); -- Received data ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- SCL interface cable signals -- ----------------------------------------------------------------------- signal SCLIF_CLK7_P : std_logic := '1'; -- Bunch crossing clock input LVDS Positive signal SCLIF_CLK7_N : std_logic := '0'; -- Bunch crossing clock input LVDS Negative signal SCLIF_BUSY_B_OUT_P : std_logic; -- Busy signal (active low) upstream ADF -> SCL receiver LVDS Positive signal SCLIF_BUSY_B_OUT_N : std_logic; -- Busy signal (active low) upstream ADF -> SCL receiver LVDS Negative signal SCLIF_CMDU_OUT_P : std_logic; -- Command upstream ADF's -> SCL receiver LVDS Positive signal SCLIF_CMDU_OUT_N : std_logic; -- Command upstream ADF's -> SCL receiver LVDS Negative signal SCLIF_CMDD_IN_P : std_logic := '0'; -- Command downstream ADF's <- SCL receiver LVDS Positive signal SCLIF_CMDD_IN_N : std_logic := '1'; -- Command downstream ADF's <- SCL receiver LVDS Negative signal SCLIF_ERR_B_OUT_P : std_logic; -- Error signal (active low) upstream ADF -> SCL receiver LVDS Positive signal SCLIF_ERR_B_OUT_N : std_logic; -- Error signal (active low) upstream ADF -> SCL receiver LVDS Negative signal SCLIF_STRIG_B_P : std_logic; -- Self trigger ADF -> SCLIF LVDS Positive signal SCLIF_STRIG_B_N : std_logic; -- Self trigger ADF -> SCLIF LVDS Negative signal SCLIF_SPARE_P : std_logic := '0'; -- Spare wire LVDS Positive signal SCLIF_SPARE_N : std_logic := '1'; -- Spare wire LVDS Negative ----------------------------------------------------------------------- ------------------------------------------------------------------------- -- Debug Port -- signal DBG_IN : std_logic_vector(0 downto 0) := "0"; -- Debug port Input pads signal DBG_OUT : std_logic_vector(1 downto 0); -- Debug port Output pads ------------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Pins specific to debug implementation -- ----------------------------------------------------------------------- signal SCL_CLK : std_logic := '1'; -- (100 MHz clock from Evaluation Kit) ----------------------------------------------------------------------- ------------------------------------------------------------------------- -- LFSR Signals -- signal LFSR_RESET : std_logic := '0'; -- signal LFSR_SE : std_logic := '1'; -- signal LFSR_SEED_LD : std_logic := '0'; -- signal LFSR_SEED : std_logic_vector(511 downto 0) := (others => '0'); signal LFSR_OUT : std_logic_vector(511 downto 0); signal STATE_COUNT : natural := 0; ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- Serial BX_CNT, FRAME, FR_8_10, PARITY Signal -- signal BX_CNT : std_logic; -- Bit 32 of RX data signal FR_8_10 : std_logic; -- Bit 33 of RX data signal FRAME : std_logic; -- Bit 34 of RX data signal PARITY : std_logic; -- Bit 35 of RX data ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- BX counter and FRAME shift register -- signal BX_COUNTER : std_logic_vector(7 downto 0) := (others => '0'); signal SR_FRAME : std_logic_vector(7 downto 0) := (others => '0'); ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- VME bus signals -- -- There is no VME bus actually, but to use the same software bus interface, -- signal names are fixed. We also need to adapt the 16-bit data bus to 8-bit -- create ADDR<1..0>, etc signal VME_SYSRESET_B : std_logic := '1'; signal VME_AM : std_logic_vector(5 downto 0):=(others => '0'); signal VME_ADDR : std_logic_vector(23 downto 1):=(others => '0'); signal VME_ADDR_0 : std_logic:= '0'; -- re-created from VME_DS_B signal VME_AS_B : std_logic:='1'; signal VME_DS_B : std_logic_vector(1 downto 0):=(others => '1'); signal VME_LWORD_B : std_logic:='1'; signal VME_WRITE_B : std_logic:='1'; signal VME_DATA : std_logic_vector(15 downto 0):= (others => 'Z'); -- Initial value MUST be Z for correct simulation with simulator driven by C program signal VME_DTACK_B : std_logic; ----------------------------------------------------------------------- signal RX_DATA_A : std_logic_vector(35 downto 0) := (others => '0'); -- Received data asynchronous begin -- -- The core FPGA -- FPGA : ChalinkR_FPGA port map ( ----------------------------------------------------------------------- -- -- Miscellaneous signals -- RESET => RESET, ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- LED indicators -- LED_USER => LED_USER, ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Bus interface signals -- WE => WE, CS_B => CS_B, ADDR => ADDR, DATA => DATA, WCLK => WCLK, DTACK_B => DTACK_B, ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Clock signals -- CLK_BC_PLL => CLK_BC_PLL, CLK_BC_OUT => CLK_BC_OUT, CLK_BC_IN => CLK_BC_IN, CLK_BC4X_IN => CLK_BC4X_IN, ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Channel Link Deserializer interface signals -- RX_CLK => RX_CLK, RX_DATA => RX_DATA, ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- SCL interface cable signals -- ----------------------------------------------------------------------- SCLIF_CLK7_P => SCLIF_CLK7_P, SCLIF_CLK7_N => SCLIF_CLK7_N, SCLIF_BUSY_B_OUT_P => SCLIF_BUSY_B_OUT_P, SCLIF_BUSY_B_OUT_N => SCLIF_BUSY_B_OUT_N, SCLIF_CMDU_OUT_P => SCLIF_CMDU_OUT_P, SCLIF_CMDU_OUT_N => SCLIF_CMDU_OUT_N, SCLIF_CMDD_IN_P => SCLIF_CMDD_IN_P, SCLIF_CMDD_IN_N => SCLIF_CMDD_IN_N, SCLIF_ERR_B_OUT_P => SCLIF_ERR_B_OUT_P, SCLIF_ERR_B_OUT_N => SCLIF_ERR_B_OUT_N, SCLIF_STRIG_B_P => SCLIF_STRIG_B_P, SCLIF_STRIG_B_N => SCLIF_STRIG_B_N, SCLIF_SPARE_P => SCLIF_SPARE_P, SCLIF_SPARE_N => SCLIF_SPARE_N, ------------------------------------------------------------------------- -- Debug Port -- DBG_IN => DBG_IN, DBG_OUT => DBG_OUT, ------------------------------------------------------------------------- ----------------------------------------------------------------------- -- -- Pins specific to debug implementation -- ----------------------------------------------------------------------- SCL_CLK => SCL_CLK ); -- -- Clocks and permanent signals -- WCLK <= not WCLK after H_WCLK_PERIOD; RX_CLK <= not RX_CLK after H_RX_CLK_PERIOD; RX_CLK_B <= not RX_CLK; SCL_CLK <= not SCL_CLK after H_REF_CLK_PERIOD; DTACK_B <= 'H'; -- Pullup on DTACK_B -- -- Local bus signals made from their VME counterpart. -- RESET <= VME_SYSRESET_B; -- already inverted in ChalinkR_FPGA VME_ADDR_0 <= ( ( VME_DS_B(1)) and (not VME_DS_B(0)) ); ADDR <= VME_ADDR(11 downto 1) & VME_ADDR_0; WE <= not VME_WRITE_B; VME_DTACK_B <= DTACK_B; -- -- A process to create CS_B. -- We respond from address 0x000 to 0x3FF on A24 Program and Data accesses -- CS_B_process: process(VME_AS_B, VME_ADDR(23 downto 12), VME_AM) begin if (VME_ADDR(23 downto 12)= "000000000000") and (VME_AM = "111010" or VME_AM = "111001") and (VME_AS_B = '0') then CS_B <= '0'; else CS_B <= '1'; end if; end process; -- -- A process to create CS_B. -- We respond from address 0x000 to 0x3FF on A24 Program and Data accesses -- DATA_process: process(VME_WRITE_B, VME_ADDR_0, VME_DATA, DATA, CS_B) begin if CS_B = '1' then DATA <= transport (others => 'Z') after 1 ns; VME_DATA <= (others => 'Z'); else if (VME_ADDR_0 = '0') then if VME_WRITE_B = '0' then DATA <= transport VME_DATA(15 downto 8) after 1 ns; else VME_DATA(15 downto 8) <= DATA; end if; else if VME_WRITE_B = '0' then DATA <= transport VME_DATA(7 downto 0) after 1 ns; else VME_DATA(7 downto 0) <= DATA; end if; end if; end if; end process; -- -- The LFSR array to simulate received data -- LFSR_array : for i in 31 downto 0 generate A_LFSR : lfsr port map ( RESET => LFSR_RESET, CLK => RX_CLK_B, SE => LFSR_SE, LOAD_L => LFSR_SEED_LD, LOAD_H => LFSR_SEED_LD, SEED => LFSR_SEED(((16*(i+1))-1) downto (16*i)), Q => LFSR_OUT(((16*(i+1))-1) downto (16*i)) ); LFSR_SEED(((16*(i+1))-1) downto (16*i)) <= Natural_To_Std_Logic_Vector(LFSR_SEEDS(i), 16); RX_DATA_A(i) <= LFSR_OUT(16*i); end generate; LFSR_RESET <= '0' after 0 ns , '1' after (H_RX_CLK_PERIOD), '0' after (2*H_RX_CLK_PERIOD); LFSR_SE <= '0' after 0 ns , '1' after (400 * H_RX_CLK_PERIOD); LFSR_SEED_LD <= '0' after 0 ns , '1' after (10 * H_RX_CLK_PERIOD), '0' after (12 * H_RX_CLK_PERIOD); -- -- BX counter -- Count_BX : process (LFSR_RESET, RX_CLK_B) variable index : NATURAL := 0; variable bx_bit : std_logic; begin if LFSR_RESET = '1' then BX_COUNTER <= "00000001"; BX_CNT <= '1'; elsif RX_CLK_B'event and RX_CLK_B = '1' then if LFSR_SE = '1' then index := (index + 1) mod 8; if index = 7 then if BX_COUNTER /= 159 then BX_COUNTER <= BX_COUNTER + 1; else BX_COUNTER <= "00000001"; end if; end if; end if; BX_CNT <= BX_COUNTER(index); end if; end process; RX_DATA_A(32) <= BX_CNT; -- -- FR_8_10 generation -- FR_8_10 <= '0'; RX_DATA_A(33) <= FR_8_10; -- -- Frame generation logic -- Make_Frame : process (LFSR_RESET, RX_CLK_B) begin if LFSR_RESET = '1' then SR_FRAME <= "00000001"; elsif RX_CLK_B'event and RX_CLK_B = '1' then if LFSR_SE = '1' then SR_FRAME <= SR_FRAME(0) & SR_FRAME(7 downto 1); end if; end if; end process; FRAME <= SR_FRAME(0); RX_DATA_A(34) <= FRAME; -- -- Parity generation Logic -- Make_Parity : process (LFSR_RESET, RX_CLK_B) variable tmp : std_logic := '0'; begin if LFSR_RESET = '1' then PARITY <= '0'; elsif RX_CLK_B'event and RX_CLK_B = '1' then for i in 35 downto 0 loop if i = 35 then tmp := '0'; else tmp := tmp xor RX_DATA_A(i); end if; end loop; PARITY <= tmp; end if; end process; RX_DATA_A(35) <= PARITY; RX_DATA(35) <= PARITY; -- -- Make RX_DATA -- Synchronous logic is needed because PARITY calculation takes -- time and would generate glitches with asynchronous logic -- Make_Rx_data : process(LFSR_RESET, RX_CLK_B) begin if LFSR_RESET = '1' then RX_DATA(34 downto 0) <= (others => '0'); elsif RX_CLK_B'event and RX_CLK_B = '1' then RX_DATA(34 downto 0) <= RX_DATA_A(34 downto 0); end if; end process; -- -- Counting states of LFSR -- Cnt_State : process (LFSR_RESET, RX_CLK_B) begin if LFSR_RESET = '1' then STATE_COUNT <= 0; elsif RX_CLK_B'event and RX_CLK_B = '1' then if LFSR_SE = '1' then STATE_COUNT <= STATE_COUNT + 1; end if; end if; end process; end behavior;