RSS Git Download  Clone
Raw Blame History
--
-- 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;