--====================================================================== -- Slowly growing TCDS2 partition manager. --====================================================================== library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.ipbus.all; use work.ipbus_reg_types.all; use work.ipbus_decode_partition_manager.all; use work.tcds2_link_pkg.all; use work.tcds2_bx_and_orbit_pkg.all; use work.tcds2_streams_pkg.all; --================================================== entity partition_manager is generic ( G_PARTITION_MANAGER_ID : integer range 0 to 1; G_NUM_PARTITIONS : positive ); port ( clk_ipb : in std_logic; rst_ipb : in std_logic; ipb_in : in ipb_wbus; ipb_out : out ipb_rbus; clk_40 : in std_logic; ttc2_o : out tcds2_ttc2; tts2_i : in tcds2_tts2_value_array(G_NUM_PARTITIONS - 1 downto 0) ); end partition_manager; --================================================== architecture arch of partition_manager is -- IPBus read/write buses. signal ipbw : ipb_wbus_array(N_SLAVES - 1 downto 0); signal ipbr : ipb_rbus_array(N_SLAVES - 1 downto 0); -- CSR signals. signal ctrl_main : ipb_reg_v(0 downto 0); signal stat_main : ipb_reg_v(4 downto 0); signal ctrl_tts2 : ipb_reg_v(0 downto 0); signal stat_tts2 : ipb_reg_v(G_NUM_PARTITIONS - 1 downto 0); signal tts2_enable : std_logic_vector(G_NUM_PARTITIONS - 1 downto 0); signal tts2_masked : tcds2_tts2_value_array(G_NUM_PARTITIONS - 1 downto 0); -- Some test and debugging signals. -- NOTE: Bit 0 of tcds_test_counter will be fixed to G_PARTITION_MANAGER_ID. signal tcds_test_counter : std_logic_vector(C_TCDS2_TTC2_RESERVED_WIDTH - 2 downto 0); constant COUNT_MAX : integer := 2 ** tcds_test_counter'length; signal tcds_test_cnt : integer range 0 to COUNT_MAX - 1; -- signal tcds_test_frame_tx : std_logic_vector(C_TCDS2_FRAME_WIDTH - 1 downto 0); signal reset_all : std_logic; signal rst_ticker : std_logic; signal en_ticker : std_logic; signal ticker : std_logic; signal bx_number : bx_num; signal orbit_number : orbit_num; signal orbit_strobe : std_logic; signal first_orbit_detected : std_logic; signal missed_orbit_detected : std_logic; signal early_orbit_detected : std_logic; signal missed_orbit_count : std_logic_vector(31 downto 0); signal early_orbit_count : std_logic_vector(31 downto 0); signal ttc2 : tcds2_ttc2; signal tts2 : tcds2_tts2_value_array(G_NUM_PARTITIONS - 1 downto 0); begin ------------------------------------------ -- IPBus address decoder. ------------------------------------------ fabric : entity work.ipbus_fabric_sel generic map ( NSLV => N_SLAVES, SEL_WIDTH => IPBUS_SEL_WIDTH ) port map ( ipb_in => ipb_in, ipb_out => ipb_out, sel => ipbus_sel_partition_manager(ipb_in.ipb_addr), ipb_to_slaves => ipbw, ipb_from_slaves => ipbr ); ------------------------------------------ -- Control and status register (main/misc.). ------------------------------------------ csr_main : entity work.ipbus_ctrlreg_v generic map ( N_CTRL => ctrl_main'length, N_STAT => stat_main'length ) port map ( clk => clk_ipb, reset => rst_ipb, ipbus_in => ipbw(N_SLV_CSR_MAIN), ipbus_out => ipbr(N_SLV_CSR_MAIN), q => ctrl_main, d => stat_main ); reset_all <= ctrl_main(0)(0); en_ticker <= ctrl_main(0)(1); rst_ticker <= ctrl_main(0)(2); stat_main(0)(C_ORBIT_NUM_WIDTH - 1 downto 0) <= std_logic_vector(orbit_number); stat_main(1)(C_BX_NUM_WIDTH - 1 downto 0) <= std_logic_vector(to_unsigned(bx_number, C_BX_NUM_WIDTH)); stat_main(2)(0) <= first_orbit_detected; stat_main(2)(1) <= missed_orbit_detected; stat_main(2)(2) <= early_orbit_detected; stat_main(3)(missed_orbit_count'range) <= missed_orbit_count; stat_main(4)(early_orbit_count'range) <= early_orbit_count; ------------------------------------------ -- Control and status register for TTS2. ------------------------------------------ csr_tts2 : entity work.ipbus_ctrlreg_v generic map ( N_CTRL => ctrl_tts2'length, N_STAT => stat_tts2'length ) port map ( clk => clk_ipb, reset => rst_ipb, ipbus_in => ipbw(N_SLV_CSR_TTS2), ipbus_out => ipbr(N_SLV_CSR_TTS2), q => ctrl_tts2, d => stat_tts2 ); tts2_enable <= ctrl_tts2(0)(tts2_enable'range); generate_stat_tts2_assignment : for i in 0 to G_NUM_PARTITIONS - 1 generate -- Raw value. stat_tts2(i)(C_TCDS2_TTS2_VALUE_WIDTH - 1 downto 0) <= std_logic_vector(to_unsigned(tts2_i(i), C_TCDS2_TTS2_VALUE_WIDTH)); -- Masked value. stat_tts2(i)(2 * C_TCDS2_TTS2_VALUE_WIDTH - 1 downto C_TCDS2_TTS2_VALUE_WIDTH) <= std_logic_vector(to_unsigned(tts2_masked(i), C_TCDS2_TTS2_VALUE_WIDTH)); end generate; ------------------------------------------ -- TTS2 ignore mask to mask the disabled partitions. ------------------------------------------ tts2_mask_local_0 : entity work.tts2_ignore_mask generic map ( G_NUMBER_OF_INPUTS => G_NUM_PARTITIONS ) port map ( tts2_in_enable => tts2_enable, tts2_in => tts2_i, tts2_out => tts2_masked ); ------------------------------------------ -- Clock divider etc. to generate some test counters. ------------------------------------------ ticker_div : entity work.ipbus_clock_div port map ( clk => clk_40, d7 => open, d17 => open, d25 => ticker, d28 => open ); test_counter : process(clk_40) variable ticker_delayed : std_logic; begin if rising_edge(clk_40) then if rst_ticker = '1' then tcds_test_cnt <= 0; ticker_delayed := '0'; else if en_ticker = '1' then if ticker = '1' and ticker_delayed = '0' then tcds_test_cnt <= (tcds_test_cnt + 1) mod COUNT_MAX; else tcds_test_cnt <= tcds_test_cnt; end if; else tcds_test_cnt <= tcds_test_cnt; end if; ticker_delayed := ticker; end if; end if; end process; tcds_test_counter <= std_logic_vector(to_unsigned(tcds_test_cnt, tcds_test_counter'length)); ------------------------------------------ -- BX and orbit generator. ------------------------------------------ bx_and_orbit_gen : entity work.orbit_strobe_generator port map ( reset_i => reset_all, bunch_clock_i => clk_40, orbit_strobe_i => '0', expected_strobe_bx_i => to_bx("001"), desired_strobe_bx_i => to_bx("001"), bx_number_o => bx_number, orbit_number_o => orbit_number, orbit_strobe_o => orbit_strobe ); ------------------------------------------ -- Orbit monitor. ------------------------------------------ orbit_mon : entity work.orbit_monitor port map ( reset_i => reset_all, bunch_clock_i => clk_40, orbit_strobe_i => orbit_strobe, first_strobe_detected_o => first_orbit_detected, missed_strobe_detected_o => missed_orbit_detected, early_strobe_detected_o => early_orbit_detected, missed_strobe_count_o => missed_orbit_count, early_strobe_count_o => early_orbit_count ); ------------------------------------------ -- Creation of the TTC2 stream. ------------------------------------------ ttc2.l1a_types <= C_TCDS2_TTC2_NULL.l1a_types; ttc2.physics_l1a_subtypes <= C_TCDS2_TTC2_NULL.physics_l1a_subtypes; ttc2.bril_trigger_data <= C_TCDS2_TTC2_NULL.bril_trigger_data; -- DEBUG DEBUG DEBUG -- Quick-and-dirty orbit marker. ttc2.sync_flags_and_commands <= (0 => orbit_strobe, others => '0'); -- DEBUG DEBUG DEBUG end ttc2.status <= C_TCDS2_TTC2_NULL.status; -- DEBUG DEBUG DEBUG -- An annotated counter in the reserved bits. ttc2.reserved <= tcds_test_counter & std_logic_vector(to_unsigned(G_PARTITION_MANAGER_ID, ttc2.reserved'length - tcds_test_counter'length)); -- DEBUG DEBUG DEBUG end ------------------------------------------ -- Spy access to the TTC2 and TTS2 streams. ------------------------------------------ spy_ttc2 : entity work.tcds2_ttc2_spy port map ( clk_ipb => clk_ipb, rst_ipb => rst_ipb, ipb_in => ipbw(N_SLV_SPY_TTC2), ipb_out => ipbr(N_SLV_SPY_TTC2), stream_i => ttc2 ); spy_tts2 : entity work.tcds2_tts2_spy port map ( clk_ipb => clk_ipb, rst_ipb => rst_ipb, ipb_in => ipbw(N_SLV_SPY_TTS2), ipb_out => ipbr(N_SLV_SPY_TTS2), stream_i => tts2 ); ------------------------------------------ ttc2_o <= ttc2; tts2 <= tts2_i; end arch; --======================================================================