-- -- data_logger.vhd -- -- Timing Signal Edge detection and multiplexing -- -- -- Version 1.0 4/1/06 A.McCormick (Alpha Data) -- -- Added state qualifier to trigger - Jeroen Belleman, July 2011 (JMB) -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; use ieee.std_logic_arith.all; use ieee.std_logic_misc.all; entity data_logger is port ( clk : in std_logic; rst : in std_logic; ten_mhz_clk : in std_logic; -- Inputs from PLL ms_pulse : in std_logic; acq : in std_logic; cycle : in std_logic_vector(31 downto 0); ctime : in std_logic_vector(31 downto 0); sigma_avg : in std_logic_vector(15 downto 0); deltax_avg : in std_logic_vector(15 downto 0); deltay_avg : in std_logic_vector(15 downto 0); avg_valid : in std_logic; init : in std_logic; bunchmean_acc : in std_logic_vector(1 downto 0); phase_table_sync : in std_Logic; hchange_sync : in std_logic; injection_sync : in std_logic; cal_start_sync : in std_logic; -- Timing Inputs (already edge detected) cycle_start_edge : in std_logic; cycle_stop_edge : in std_logic; cal_start_edge : in std_logic; cal_stop_edge : in std_logic; injection_edge : in std_logic; hchange_edge : in std_logic; -- Timing Inputs cycle_start : in std_logic; cycle_start_ten_mhz : in std_logic; cycle_stop : in std_logic; cal_start : in std_logic; cal_stop : in std_logic; injection : in std_logic; hchange : in std_logic; fref : in std_logic; -- Diagnostics from PLL diagnostics : in std_logic_vector(255 downto 0); -- Host Control Registers diag_control : in std_logic_vector(31 downto 0); diag_control_set : in std_logic; diag_delay : in std_logic_vector(31 downto 0); diag_delay_set : in std_logic; diag_trigger : in std_logic_vector(31 downto 0); diag_status : out std_logic_vector(31 downto 0); diag_irq : out std_logic; -- Write Signals to Memory sdram_addr : out std_logic_vector(24 downto 0); sdram_data : out std_logic_vector(63 downto 0); sdram_write : out std_logic; timing_addr : out std_logic_vector(11 downto 0); timing_data : out std_logic_vector(63 downto 0); timing_write : out std_logic; info_addr : out std_logic_vector(5 downto 0); info_data : out std_logic_vector(63 downto 0); info_write : out std_logic; diagnostics_data : out std_logic_vector(63 downto 0); diagnostics_addr : out std_logic_vector(11 downto 0); diagnostics_write : out std_logic; bunchmean0_data : out std_logic_vector(63 downto 0); bunchmean0_addr : out std_logic_vector(11 downto 0); bunchmean0_write : out std_logic; bunchmean1_data : out std_logic_vector(63 downto 0); bunchmean1_addr : out std_logic_vector(11 downto 0); bunchmean1_write : out std_logic); end data_logger; architecture rtl of data_logger is constant bunch_mean_base_addr : integer := 254*1024*1024/8; constant number_of_bunches : integer := 24; signal sdram_addr_i : std_logic_vector(24 downto 0); signal sdram_addr_sync : std_logic_vector(24 downto 0); signal timing_addr_i : std_logic_vector(11 downto 0); signal event_counter : std_logic_vector(3 downto 0); signal trigger,trigger1 : std_logic_vector(7 downto 0); signal analyser_data : std_logic_vector(63 downto 0); signal analyser_data1 : std_logic_vector(63 downto 0); signal analyser_data2 : std_logic_vector(63 downto 0); signal analyser_src : std_logic_vector(1 downto 0); signal store_trigger : std_logic; signal arm : std_logic; signal capturing : std_logic; signal clk_counter : std_logic_vector(16 downto 0); signal clk_count_limit : std_logic_vector(16 downto 0); signal clk_count_strb : std_logic; signal clk_select : std_logic_vector(4 downto 0); signal trig_and : std_logic; signal trig_or : std_logic; signal trig_or_match : std_logic; -- JMB signal data_and : std_logic; signal data_or : std_logic; signal wait_clk : std_logic; signal capture_count : std_logic_vector(11 downto 0); signal sample_clk : std_logic; signal state_match : std_logic; -- JMB signal state_match_en : std_logic; -- JMB signal diagnostics_r1 : std_logic_vector(255 downto 0); signal fref_reg : std_logic; signal trig_delay : std_logic_vector(31 downto 0); signal trig_delayed : std_logic; signal info_clear_count : std_logic_vector(3 downto 0); -- BRAM based bunch mean average system signal bma_s0 : std_logic_vector(15 downto 0); signal bma_dx0 : std_logic_vector(15 downto 0); signal bma_dy0 : std_logic_vector(15 downto 0); signal bma_s1 : std_logic_vector(15 downto 0); signal bma_dx1 : std_logic_vector(15 downto 0); signal bma_dy1 : std_logic_vector(15 downto 0); signal bma_counter2 : std_logic_vector(15 downto 0); signal bma_counter3 : std_logic_vector(15 downto 0); signal bma_s2 : std_logic_vector(27 downto 0); signal bma_dx2 : std_logic_vector(27 downto 0); signal bma_dy2 : std_logic_vector(27 downto 0); signal bma_s3 : std_logic_vector(27 downto 0); signal bma_dx3 : std_logic_vector(27 downto 0); signal bma_dy3 : std_logic_vector(27 downto 0); -- SDRAM based bunch mean average system type bunch_mean_array is array (natural range <>) of std_logic_vector(31 downto 0); signal sigma_averages,deltax_averages,deltay_averages,counts : bunch_mean_array(0 to number_of_bunches); signal bunch_one_hot : std_logic_vector(number_of_bunches-1 downto 0); signal bunch_mean_acc_valid : std_logic_vector(number_of_bunches downto 0); component bunch_mean_acc port ( clk : in std_logic; acc : in std_logic; clr : in std_logic; sigma : in std_logic_vector(15 downto 0); deltax : in std_logic_vector(15 downto 0); deltay : in std_logic_vector(15 downto 0); sum_sigma : out std_logic_vector(31 downto 0); sum_deltax : out std_logic_vector(31 downto 0); sum_deltay : out std_logic_vector(31 downto 0); count : out std_logic_vector(31 downto 0)); end component; signal bunch_writing : std_logic; signal ms_pulse_reg : std_logic; signal bunch_write_state,next_bunch_write_state : std_logic_vector(5 downto 0); signal bunch_sdram_data : std_logic_vector(63 downto 0); signal timing_addr_bunch : std_logic_vector(11 downto 0); signal bunch_sdram_addr : std_logic_vector(24 downto 0); begin -- rtl -- -- Data logging for normal operation -- log_data: process (clk, rst) begin -- process log_data if rst = '1' then -- asynchronous reset sdram_addr_i <= (others => '0'); timing_addr_i <= (others => '0'); event_counter <= (others => '0'); sdram_addr_sync <= (others => '0'); fref_reg <= '0'; elsif clk'event and clk = '1' then -- rising clock edge fref_reg <= fref; if init = '1' then sdram_addr_i <= (others => '0'); timing_addr_i <= (others => '0'); event_counter <= (others => '0'); else if avg_valid = '1' and acq = '1' then if sdram_addr_i = CONV_STD_LOGIC_VECTOR(bunch_mean_base_addr-1,25) then sdram_addr_i <= (others => '0'); else sdram_addr_i <= sdram_addr_i+1; end if; end if; if ms_pulse = '1' and acq = '1' then timing_addr_i <= timing_addr_i +1; end if; if (hchange_sync or injection_sync or cal_stop_edge or cal_start_sync) = '1' then event_counter <= event_counter +1; elsif cycle_stop_edge = '1' then event_counter <= (others => '0'); elsif cycle_start_edge = '1' then event_counter <= "0001"; end if; end if; if phase_table_sync = '1' then sdram_addr_sync <= sdram_addr_i; end if; if avg_valid = '1' then -- Store individual bunch position data (notwithstanding the naming!) sdram_addr <= sdram_addr_i; sdram_data <= ctime(15 downto 0) & deltay_avg & deltax_avg & sigma_avg; else -- Store bunch averaged position data sdram_addr <= bunch_sdram_addr; sdram_data <= bunch_sdram_data; end if; sdram_write <= (avg_valid or bunch_writing) and acq; timing_addr <= timing_addr_i; timing_data <= EXT(sdram_addr_sync,32) & ctime; timing_write <= ms_pulse and acq; if cycle_start_edge = '0' then if info_clear_count = "0000" then info_write <= (hchange_sync or injection_sync or cal_stop_edge or cal_start_sync or cycle_stop_edge or cycle_start_edge); info_data <= EXT(sdram_addr_i,32) & EXT(hchange_sync & injection_sync & cal_stop_edge & cal_start_sync & cycle_stop_edge & cycle_start_edge,8) & EXT(timing_addr_i,24); info_addr <= cycle(1 downto 0) & event_counter; else info_data <= (others => '0'); info_write <= '1'; info_clear_count <= info_clear_count+1; info_addr <= cycle(1 downto 0) & info_clear_count; end if; else info_write <= '1'; info_data <= EXT(sdram_addr_i,32) & EXT(hchange_sync & injection_sync & cal_stop_edge & cal_start_edge & cycle_stop_edge & cycle_start_edge,8) & EXT(timing_addr_i,24); info_addr <= cycle(1 downto 0) & "0000"; info_clear_count <= "0001"; end if; end if; end process log_data; state_match_en <= diag_control(13); -- -- Built in Logic Analyser -- analyser0: process (clk, rst) variable trig_valid : std_logic; begin -- process analyser0 if rst = '1' then -- asynchronous reset arm <= '0'; capturing <= '0'; analyser_src <= "00"; store_trigger <= '0'; clk_counter <= (others => '0'); clk_count_limit <= (others => '0'); clk_count_strb <= '0'; capture_count <= (others => '0'); diagnostics_data <= (others => '0'); diagnostics_addr <= (others => '0'); diagnostics_write <= '0'; diag_status <= (others => '0'); sample_clk <= '0'; diag_irq <= '0'; diagnostics_r1 <= (others => '0'); trigger1 <= (others => '0'); trig_delay <= (others => '0'); trig_delayed <= '0'; elsif clk'event and clk = '1' then -- rising clock edge diagnostics_r1 <= diagnostics; -- Select Trigger source and AND/OR mask operation case (diag_control(13) & diag_control(6 downto 5)) is when "000" => trig_valid := trig_or; when "001" => trig_valid := trig_and; when "010" => trig_valid := data_or; when "011" => trig_valid := data_and; when "100" => trig_valid := trig_or_match; -- Trigger with state matching. JMB when others => trig_valid := '0'; end case; -- Compare fsm0 state with diagnostic trigger state field. -- JMB state_match <= not OR_reduce(analyser_data(47 downto 44) xor diag_trigger(11 downto 8)); -- JMB if diag_control_set = '1' then arm <= diag_control(0); wait_clk <= diag_control(7); capturing <= '0'; analyser_src <= diag_control(3 downto 2); store_trigger <= diag_control(4); clk_counter <= (others => '0'); clk_count_strb <= '0'; clk_select <= diag_control(12 downto 8); capture_count <= (others => '0'); case diag_control(12 downto 8) is when "00000" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(0,17); when "00001" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(1,17); when "00010" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(4,17); when "00011" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(9,17); when "00100" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(19,17); when "00101" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(49,17); when "00110" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(99,17); when "00111" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(199,17); when "01000" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(499,17); when "01001" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(999,17); when "01010" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(1999,17); when "01011" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(4999,17); when "01100" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(9999,17); when "01101" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(19999,17); when "01110" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(49999,17); when "01111" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(99999,17); when others => clk_count_limit <= CONV_STD_LOGIC_VECTOR(0,17); end case; sample_clk <= '0'; diag_irq <= '0'; if diag_control(7) = '0' then trig_delay <= diag_delay; else trig_delay <= (others => '0'); end if; else if clk_counter = clk_count_limit then clk_counter <= (others => '0'); clk_count_strb <= '1'; else clk_count_strb <= '0'; clk_counter <= clk_counter+1; end if; if clk_select(4) = '1' then if clk_select(0) = '0' then sample_clk <= ms_pulse; else sample_clk <= fref and not fref_reg; end if; else sample_clk <= clk_count_strb; end if; if ctime(15 downto 0) = diag_control(31 downto 16) then wait_clk <= '0'; end if; if capturing = '0' then if wait_clk = '0' and arm = '1' and (trig_valid = '1' or trig_delayed = '1') then if OR_reduce(trig_delay) = '1' then trig_delay <= trig_delay -1; trig_delayed <= '1'; else trig_delayed <= '0'; capturing <= '1'; arm <= '0'; end if; capture_count <= (others => '0'); end if; diag_irq <= '0'; else if sample_clk = '1' then if AND_reduce(capture_count) = '1' then capturing <= '0'; diag_irq <= '1'; else diag_irq <= '0'; end if; capture_count <= capture_count+1; else diag_irq <= '0'; end if; end if; end if; case analyser_src is when "00" => analyser_data <= diagnostics_r1(63 downto 0); when "01" => analyser_data <= diagnostics_r1(127 downto 64); when "10" => analyser_data <= diagnostics_r1(191 downto 128); when "11" => analyser_data <= diagnostics_r1(255 downto 192); when others => analyser_data <= (others => '0'); end case; -- trigger1 <= fref & hchange & injection & cal_stop & cal_start & cycle_stop & cycle_start & ten_mhz_clk; trigger1 <= fref & hchange_edge & injection_edge & cal_stop_edge & cal_start_edge & cycle_stop_edge & cycle_start_edge & ten_mhz_clk; -- JMB trigger <= trigger1; if store_trigger = '1' then analyser_data1 <= analyser_data(63 downto 8) & trigger; else analyser_data1 <= analyser_data; end if; trig_and <= not AND_reduce(trigger or diag_trigger(7 downto 0)); trig_or <= OR_reduce(trigger and diag_trigger(7 downto 0)); data_and <= not AND_reduce(analyser_data(31 downto 0) or diag_trigger); data_or <= OR_reduce(analyser_data(31 downto 0) and diag_trigger); trig_or_match <= OR_reduce(trigger and diag_trigger(7 downto 0)) and state_match; analyser_data2 <= analyser_data1; diagnostics_data <= analyser_data2; diagnostics_addr <= capture_count; diagnostics_write <= sample_clk and capturing; diag_status <= diag_control(31 downto 2) & capturing & arm; end if; end process analyser0; -- -- Bunch Mean Averaging -- -- Use IIR filter y[n] = x[n] + 0.75 y[n-1] -- bunchmean_avg0: process (clk, rst) -- begin -- process bunchmean_avg0 -- if rst = '1' then -- asynchronous reset -- bma_s0 <= (others => '0'); -- bma_dx0 <= (others => '0'); -- bma_dy0 <= (others => '0'); -- bma_s1 <= (others => '0'); -- bma_dx1 <= (others => '0'); -- bma_dy1 <= (others => '0'); -- elsif clk'event and clk = '1' then -- rising clock edge -- if bunchmean_acc(0) = '1' then -- bma_s0 <= sigma_avg + SXT(bma_s0(15 downto 1),16) + SXT(bma_s0(15 downto 2),16); -- bma_dx0 <= deltax_avg + SXT(bma_dx0(15 downto 1),16) + SXT(bma_dx0(15 downto 2),16); -- bma_dy0 <= deltay_avg + SXT(bma_dy0(15 downto 1),16) + SXT(bma_dy0(15 downto 2),16); -- end if; -- bunchmean0_data <= EXT(bma_dy0 & bma_dx0 & bma_s0,64); -- bunchmean0_addr <= timing_addr_i; -- bunchmean0_write <= ms_pulse and acq; -- if bunchmean_acc(1) = '1' then -- bma_s1 <= sigma_avg + SXT(bma_s1(15 downto 1),16) + SXT(bma_s1(15 downto 2),16); -- bma_dx1 <= deltax_avg + SXT(bma_dx1(15 downto 1),16) + SXT(bma_dx1(15 downto 2),16); -- bma_dy1 <= deltay_avg + SXT(bma_dy1(15 downto 1),16) + SXT(bma_dy1(15 downto 2),16); -- end if; -- bunchmean1_data <= EXT(bma_dy1 & bma_dx1 & bma_s1,64); -- bunchmean1_addr <= timing_addr_i; -- bunchmean1_write <= ms_pulse and acq; -- end if; -- end process bunchmean_avg0; -- Bunch mean averaging -- Old system using block RAM bunchmean_avg0: process (clk, rst) begin -- process bunchmean_avg0 if rst = '1' then -- asynchronous reset bma_s2 <= (others => '0'); bma_dx2 <= (others => '0'); bma_dy2 <= (others => '0'); bma_s3 <= (others => '0'); bma_dx3 <= (others => '0'); bma_dy3 <= (others => '0'); bma_counter2 <= (others => '0'); bma_counter3 <= (others => '0'); elsif clk'event and clk = '1' then -- rising clock edge if ms_pulse = '1' then bma_s2 <= (others => '0'); bma_dx2 <= (others => '0'); bma_dy2 <= (others => '0'); bma_s3 <= (others => '0'); bma_dx3 <= (others => '0'); bma_dy3 <= (others => '0'); bma_counter2 <= (others => '0'); bma_counter3 <= (others => '0'); else if bunchmean_acc(0) = '1' then bma_s2 <= SXT(sigma_avg,28) + bma_s2; bma_dx2 <= SXT(deltax_avg,28) + bma_dx2; bma_dy2 <= SXT(deltay_avg,28) + bma_dy2; bma_counter2 <= bma_counter2+1; end if; if bunchmean_acc(1) = '1' then bma_s3 <= SXT(sigma_avg,28) + bma_s3; bma_dx3 <= SXT(deltax_avg,28) + bma_dx3; bma_dy3 <= SXT(deltay_avg,28) + bma_dy3; bma_counter3 <= bma_counter3+1; end if; end if; if OR_reduce(bma_counter2(15 downto 11)) = '1' then bunchmean0_data <= bma_counter2 & bma_dy2(27 downto 12) & bma_dx2(27 downto 12) & bma_s2(27 downto 12); elsif bma_counter2(10) = '1' then bunchmean0_data <= bma_counter2 & bma_dy2(26 downto 11) & bma_dx2(26 downto 11) & bma_s2(26 downto 11); elsif bma_counter2(9) = '1' then bunchmean0_data <= bma_counter2 & bma_dy2(25 downto 10) & bma_dx2(25 downto 10) & bma_s2(25 downto 10); elsif bma_counter2(8) = '1' then bunchmean0_data <= bma_counter2 & bma_dy2(24 downto 9) & bma_dx2(24 downto 9) & bma_s2(24 downto 9); else bunchmean0_data <= bma_counter2 & bma_dy2(23 downto 8) & bma_dx2(23 downto 8) & bma_s2(23 downto 8); end if; --bunchmean0_data <= bma_counter2 & bma_dy2(23 downto 8) & bma_dx2(23 downto 8) & bma_s2(23 downto 8); bunchmean0_addr <= timing_addr_i; bunchmean0_write <= ms_pulse and acq; if OR_reduce(bma_counter3(15 downto 11)) = '1' then bunchmean1_data <= bma_counter3 & bma_dy3(27 downto 12) & bma_dx3(27 downto 12) & bma_s3(27 downto 12); elsif bma_counter3(10) = '1' then bunchmean1_data <= bma_counter3 & bma_dy3(26 downto 11) & bma_dx3(26 downto 11) & bma_s3(26 downto 11); elsif bma_counter3(9) = '1' then bunchmean1_data <= bma_counter3 & bma_dy3(25 downto 10) & bma_dx3(25 downto 10) & bma_s3(25 downto 10); elsif bma_counter3(8) = '1' then bunchmean1_data <= bma_counter3 & bma_dy3(24 downto 9) & bma_dx3(24 downto 9) & bma_s3(24 downto 9); else bunchmean1_data <= bma_counter3 & bma_dy3(23 downto 8) & bma_dx3(23 downto 8) & bma_s3(23 downto 8); end if; --bunchmean1_data <= bma_counter3 & bma_dy3(23 downto 8) & bma_dx3(23 downto 8) & bma_s3(23 downto 8); bunchmean1_addr <= timing_addr_i; bunchmean1_write <= ms_pulse and acq; end if; end process bunchmean_avg0; -- Bunch Mean averaging -- New system using upper 2MB of SDRAM gen_bma_accs: for i in 0 to number_of_bunches generate bma0: bunch_mean_acc port map ( clk => clk, acc => bunch_mean_acc_valid(i), clr => ms_pulse, sigma => sigma_avg, deltax => deltax_avg, deltay => deltay_avg, sum_sigma => sigma_averages(i), sum_deltax => deltax_averages(i), sum_deltay => deltay_averages(i), count => counts(i)); end generate gen_bma_accs; bunch_mean_acc_valid(0) <= bunchmean_acc(0); gen_bma_accs_v: for i in 1 to number_of_bunches-1 generate bunch_mean_acc_valid(i) <= bunchmean_acc(0) and bunch_one_hot(i-1); end generate gen_bma_accs_v; bunch_mean_logic0: process (clk, rst) begin -- process bunch_mean_logic0 if rst = '1' then -- asynchronous reset (active low) bunch_one_hot <= (others => '0'); bunch_writing <= '0'; bunch_write_state <= (others => '0'); next_bunch_write_state <= (others => '0'); ms_pulse_reg <= '0'; bunch_sdram_data <= (others => '0'); timing_addr_bunch <= (others => '0'); elsif clk'event and clk = '1' then -- rising clock edge -- Write bunches 1 to 30 into averages 1 to 30 if phase_table_sync = '1' then bunch_one_hot(0) <= '1'; bunch_one_hot(number_of_bunches-1 downto 1) <= (others => '0'); elsif bunchmean_acc(0) = '1' then bunch_one_hot <= bunch_one_hot(number_of_bunches-2 downto 0) & '0'; end if; -- Write out data after ms_pulse ms_pulse_reg <= ms_pulse; if ms_pulse = '1' then timing_addr_bunch <= timing_addr_i; end if; if ms_pulse_reg = '1' then bunch_writing <= '1'; bunch_write_state <= (others => '0'); next_bunch_write_state <= CONV_STD_LOGIC_VECTOR(1,6); bunch_sdram_data <=deltax_averages(0) & sigma_averages(0); else if bunch_writing = '1' and avg_valid = '0' then bunch_write_state <= next_bunch_write_state; next_bunch_write_state <= next_bunch_write_state+1; if bunch_write_state = CONV_STD_LOGIC_VECTOR(number_of_bunches*2-1,6) then bunch_writing <= '0'; end if; if next_bunch_write_state(0) = '0' then bunch_sdram_data <= deltax_averages(CONV_INTEGER(next_bunch_write_state(5 downto 1))) & sigma_averages(CONV_INTEGER(next_bunch_write_state(5 downto 1))); else bunch_sdram_data <= counts(CONV_INTEGER(next_bunch_write_state(5 downto 1))) & deltay_averages(CONV_INTEGER(next_bunch_write_state(5 downto 1))); end if; end if; end if; end if; end process bunch_mean_logic0; bunch_sdram_addr <= "1111111" & bunch_write_state(5 downto 1) & timing_addr_bunch & bunch_write_state(0); end rtl;