Skip to content
Snippets Groups Projects
Select Git revision
  • fixedIP
  • master default protected
  • cbm_master
  • updated_ecp5_serdes
  • GbeLargeSctrl
  • dirich5s1_new_reset_cdr_fix
  • blackcat
  • deepsea
  • cbm_rich
  • trb5_GbE
  • retransmission
  • syncTRB
  • update
  • newGBE
  • oldGBE
15 results

trb_net16_hub_ipu_logic.vhd

Blame
  • trb_net16_hub_ipu_logic.vhd 55.35 KiB
    LIBRARY ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    library work;
    use work.trb_net_std.all;
    use work.trb_net_components.all;
    
    
    entity trb_net16_hub_ipu_logic is
      generic (
      --media interfaces
        POINT_NUMBER        : integer range 1 to 17 := 16
        );
      port (
        CLK    : in std_logic;
        RESET  : in std_logic;
        CLK_EN : in std_logic;
    
        --Internal interfaces to IOBufs
        INIT_DATAREADY_IN     : in  std_logic_vector (POINT_NUMBER-1 downto 0);
        INIT_DATA_IN          : in  std_logic_vector (c_DATA_WIDTH*POINT_NUMBER-1 downto 0);
        INIT_PACKET_NUM_IN    : in  std_logic_vector (c_NUM_WIDTH*POINT_NUMBER-1 downto 0);
        INIT_READ_OUT         : out std_logic_vector (POINT_NUMBER-1 downto 0);
    
        INIT_DATAREADY_OUT    : out std_logic_vector (POINT_NUMBER-1 downto 0);
        INIT_DATA_OUT         : out std_logic_vector (c_DATA_WIDTH*POINT_NUMBER-1 downto 0);
        INIT_PACKET_NUM_OUT   : out std_logic_vector (c_NUM_WIDTH*POINT_NUMBER-1 downto 0);
        INIT_READ_IN          : in  std_logic_vector (POINT_NUMBER-1 downto 0);
    
        REPLY_DATAREADY_IN    : in  std_logic_vector (POINT_NUMBER-1 downto 0);
        REPLY_DATA_IN         : in  std_logic_vector (c_DATA_WIDTH*POINT_NUMBER-1 downto 0);
        REPLY_PACKET_NUM_IN   : in  std_logic_vector (c_NUM_WIDTH*POINT_NUMBER-1 downto 0);
        REPLY_READ_OUT        : out std_logic_vector (POINT_NUMBER-1 downto 0);
    
        REPLY_DATAREADY_OUT   : out std_logic_vector (POINT_NUMBER-1 downto 0);
        REPLY_DATA_OUT        : out std_logic_vector (c_DATA_WIDTH*POINT_NUMBER-1 downto 0);
        REPLY_PACKET_NUM_OUT  : out std_logic_vector (c_NUM_WIDTH*POINT_NUMBER-1 downto 0);
        REPLY_READ_IN         : in  std_logic_vector (POINT_NUMBER-1 downto 0);
    
        MY_ADDRESS_IN         : in  std_logic_vector (15 downto 0);
        --Status ports
        STAT_DEBUG         : out std_logic_vector (31 downto 0);
        STAT_locked        : out std_logic;
        STAT_POINTS_locked : out std_logic_vector (31 downto 0);
        STAT_TIMEOUT       : out std_logic_vector (31 downto 0);
        STAT_ERRORBITS     : out std_logic_vector (31 downto 0);
        STAT_ALL_ERRORBITS : out std_logic_vector (16*32-1 downto 0);
        STAT_FSM           : out std_logic_vector (31 downto 0);
        STAT_MISMATCH      : out std_logic_vector (31 downto 0);
        CTRL_TIMEOUT_TIME  : in  std_logic_vector (15 downto 0);
        CTRL_activepoints  : in  std_logic_vector (31 downto 0) := (others => '1');
        CTRL_DISABLED_PORTS   : in  std_logic_vector (31 downto 0) := (others => '0');
        CTRL_TIMER_TICK    : in  std_logic_vector (1 downto 0)
        );
    end entity;
    
    architecture trb_net16_hub_ipu_logic_arch of trb_net16_hub_ipu_logic is
      -- Placer Directives
      attribute HGROUP : string;
      -- for whole architecture
      attribute HGROUP of trb_net16_hub_ipu_logic_arch : architecture  is "HUBIPULOGIC_group";
    
      constant DISABLE_PACKING : integer := 0;
    
    --signals init_pool
      signal INIT_POOL_DATAREADY                 : std_logic;
      signal INIT_POOL_READ                      : std_logic;
      signal INIT_POOL_DATA                      : std_logic_vector(c_DATA_WIDTH-1 downto 0);
      signal INIT_POOL_PACKET_NUM                : std_logic_vector(c_NUM_WIDTH-1  downto 0);
      signal init_has_read_from_pool             : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal saved_INIT_TYPE, current_INIT_TYPE  : std_logic_vector(2 downto 0);
    
      signal buf_INIT_READ_OUT                     : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal buf_REPLY_READ_OUT                    : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal REPLY_POOL_DATAREADY                  : std_logic;
      signal REPLY_POOL_READ                       : std_logic;
      signal REPLY_POOL_DATA                       : std_logic_vector(c_DATA_WIDTH-1 downto 0);
      signal REPLY_POOL_PACKET_NUM                 : std_logic_vector(c_NUM_WIDTH-1  downto 0);
    
      signal current_reply_packet_type : std_logic_vector(POINT_NUMBER*3-1 downto 0);
      signal saved_reply_packet_type   : std_logic_vector(POINT_NUMBER*3-1 downto 0);
      signal last_reply_packet_type    : std_logic_vector(POINT_NUMBER*3-1 downto 0);
      signal last_reply_packet_number  : std_logic_vector(POINT_NUMBER*3-1 downto 0);
      signal reply_reading_H0          : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reply_reading_F0          : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reply_reading_F1          : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reply_reading_F2          : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reply_reading_F3          : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reply_combined_trm_F1     : std_logic_vector(c_DATA_WIDTH-1  downto 0);
      signal reply_combined_trm_F2     : std_logic_vector(c_DATA_WIDTH-1  downto 0);
      signal reply_combined_trm_F3     : std_logic_vector(c_DATA_WIDTH-1  downto 0);
      signal real_activepoints         : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal hdrram_write_enable       : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal hdrram_address            : std_logic_vector(3*POINT_NUMBER-1 downto 0);
    --   signal current_waiting_for_reply : std_logic_vector(POINT_NUMBER-1 downto 0);
    --   signal next_current_waiting_for_reply : std_logic_vector(POINT_NUMBER-1 downto 0);
    
      signal current_reply_reading_trm             : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal current_reply_reading_DHDR            : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal current_REPLY_reading_hdr             : std_logic_vector(POINT_NUMBER-1  downto 0);
    --   signal current_muxed_reading_DAT             : std_logic;
    
      signal reg_current_reply_reading_trm         : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reg_current_REPLY_reading_hdr         : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reg_current_reply_reading_DHDR        : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal reg_current_reply_auto_reading_DHDR   : std_logic_vector(POINT_NUMBER-1  downto 0);
    --general signals
      signal locked, next_locked                 : std_logic;
      signal get_locked, release_locked          : std_logic;
      signal got_trm                             : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal locking_point, next_locking_point   : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal send_reply_trm                      : std_logic;
    
      signal init_locked, next_init_locked       : std_logic;
      signal get_init_locked, release_init_locked: std_logic;
    
      signal REPLY_MUX_reading                   : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal reply_arbiter_result                : std_logic_vector(POINT_NUMBER-1 downto 0);
    
      type state_type is (IDLE, WAIT_FOR_REPLY, CHECK_EVENT_INFO, WAIT_FOR_HDR_DATA, GEN_LENGTH,
                          CHECK_DHDR, SENDING_DATA, SENDING_REPLY_TRM, SEND_PADDING,
                          WAITING_FOR_INIT, WAIT_FOR_END_OF_DHDR, ARBITER_ACTIVE);
      signal current_state, next_state           : state_type;
      signal packet_counter                      : std_logic_vector(c_NUM_WIDTH-1 downto 0);
      signal reply_data_counter                  : unsigned(15 downto 0);
      signal reply_data_counter_reset            : std_logic;
      signal next_reply_data_counter_reset       : std_logic;
      signal comb_REPLY_POOL_DATAREADY           : std_logic;
      signal comb_REPLY_POOL_DATA                : std_logic_vector(c_DATA_WIDTH-1 downto 0);
      signal comb_REPLY_POOL_PACKET_NUM          : std_logic_vector(c_NUM_WIDTH-1 downto 0);
      signal REPLY_POOL_next_read                : std_logic;
      signal comb_REPLY_POOL_next_read           : std_logic;
    
      signal evt_random_code : std_logic_vector(7 downto 0);
      signal evt_number      : std_logic_vector(15 downto 0);
      signal evt_dtype       : std_logic_vector(3 downto 0);
      signal evt_seqnr       : std_logic_vector(7 downto 0);
    
      signal comb_REPLY_muxed_DATAREADY           : std_logic;
      signal comb_REPLY_muxed_DATA                : std_logic_vector(c_DATA_WIDTH-1 downto 0);
      signal comb_REPLY_muxed_PACKET_NUM          : std_logic_vector(c_NUM_WIDTH-1 downto 0);
    
      signal init_arbiter_CLK_EN                  : std_logic;
      signal init_arbiter_ENABLE                  : std_logic;
      signal init_arbiter_read_out                : std_logic_vector(POINT_NUMBER-1 downto 0);
    
      signal reply_arbiter_input                  : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal reply_arbiter_enable                 : std_logic;
      signal reply_arbiter_CLK_EN                 : std_logic;
      signal reply_arbiter_reset                  : std_logic;
    
      signal INIT_muxed_DATAREADY            : std_logic;
      signal INIT_muxed_DATA                 : std_logic_vector(c_DATA_WIDTH-1 downto 0);
      signal INIT_muxed_PACKET_NUM           : std_logic_vector(c_NUM_WIDTH-1 downto 0);
      signal INIT_muxed_READ                 : std_logic;
      signal comb_INIT_next_read             : std_logic;
      signal reply_fsm_state                 : std_logic_vector(7 downto 0);
    
    --  signal waiting_for_init_finish, next_waiting_for_init_finish : std_logic;
    
      signal waiting_for_DHDR_word           : std_logic_vector(POINT_NUMBER-1  downto 0);
      signal next_waiting_for_DHDR_word      : std_logic_vector(POINT_NUMBER-1  downto 0);
    
      signal reply_adder_input        : std_logic_vector(17*16-1 downto 0);
      signal reply_adder_start        : std_logic;
      signal reg_reply_adder_start    : std_logic;
      signal reply_adder_overflow     : std_logic;
      signal reply_adder_ready        : std_logic;
      signal reply_adder_val_enable   : std_logic_vector(17-1 downto 0);
      signal reply_adder_result       : std_logic_vector(15 downto 0);
      signal next_reply_adder_start   : std_logic;
      signal next_reply_compare_start : std_logic;
    
      signal reply_compare_start      : std_logic;
      signal reg_reply_compare_start  : std_logic;
      signal reply_compare_finished   : std_logic;
      --signal reply_compare_result     : std_logic_vector(17-1 downto 0);
      --signal reply_compare_flag       : std_logic;
      --signal reply_compare_input      : std_logic_vector(17-1 downto 0);
    
      signal dhdr_addr        : std_logic_vector(2 downto 0);
      signal dhdr_data        : std_logic_vector(16*POINT_NUMBER-1 downto 0);
      signal next_dhdr_data   : std_logic_vector(16*POINT_NUMBER-1 downto 0);
    
      signal current_point_length  : unsigned(15 downto 0);
      signal start_read_padding    : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal saved_reading_padding : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal reading_padding       : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal got_all_DHDR          : std_logic;
    --   signal got_all_reply_starts  : std_logic;
      signal not_reading_HDR       : std_logic;
      signal number_of_replies     : unsigned(4 downto 0);
      signal expected_replies      : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal reply_adder_final_result : std_logic_vector(15 downto 0);
      signal next_reply_adder_final_result : std_logic_vector(15 downto 0);
      signal last_reply_adder_ready: std_logic;
    
      signal enable_reply_data_counter : std_logic;
      signal evt_code_mismatch   : std_logic;
      signal evt_number_mismatch : std_logic;
      signal enable_packing      : std_logic;
    
    
      type timeout_counter_t is array (POINT_NUMBER-1 downto 0) of unsigned(15 downto 0);
      signal timeout_counter : timeout_counter_t;
    --   signal timeout_counter_reset : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal connection_timed_out  : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal timeout_found   : std_logic;
      signal reg_CTRL_TIMEOUT_TIME : unsigned(15 downto 0);
    
      signal timer_us_tick : std_logic;
      signal timer_ms_tick : std_logic;
    
      signal saved_auto_reading_DHDR      : std_logic_vector(POINT_NUMBER-1 downto 0);
      signal last_REPLY_PACKET_NUM_IN     : std_logic_vector(POINT_NUMBER*3-1 downto 0);
    
      signal reply_fsm_statebits          : std_logic_vector(3 downto 0);
      signal last_locked                  : std_logic;
      signal mismatch_pattern             : std_logic_vector(31 downto 0);
    begin
    
    ----------------------------------
    --Arbiter choosing init point
    ----------------------------------
    
      INIT_ARBITER: trb_net_priority_arbiter
        generic map (WIDTH => POINT_NUMBER)
        port map (
          CLK   => CLK,
          RESET  => RESET,
          CLK_EN  => init_arbiter_CLK_EN,
          INPUT_IN  => INIT_DATAREADY_IN,
          RESULT_OUT => init_arbiter_read_out,
          ENABLE  => init_arbiter_ENABLE,
          CTRL => (others => '0')
          );
      init_arbiter_CLK_EN <= not locked;
      init_arbiter_ENABLE <= not init_locked;
    
    ----------------------------------
    --Datapool for Init-Channel
    ----------------------------------
      INIT_muxed_DATAREADY <= or_all(INIT_DATAREADY_IN and buf_INIT_READ_OUT) and not init_locked and INIT_muxed_READ;
      INIT_POOL_READ <= and_all(INIT_READ_IN or init_has_read_from_pool or locking_point or not real_activepoints);
      INIT_READ_OUT <= buf_INIT_READ_OUT;
    
      gen_iro : for i in 0 to POINT_NUMBER-1 generate
        buf_INIT_READ_OUT(i) <= init_arbiter_read_out(i) and not init_locked and INIT_muxed_READ;
      end generate;
    
      gen_init_pool_data0: for i in 0 to c_DATA_WIDTH-1 generate
        process(INIT_DATA_IN, buf_INIT_READ_OUT)
          variable VAR_INIT_POOL_DATA : std_logic;
          begin
            VAR_INIT_POOL_DATA := '0';
            gen_init_pool_data1 : for j in 0 to POINT_NUMBER-1 loop
              VAR_INIT_POOL_DATA := VAR_INIT_POOL_DATA or (INIT_DATA_IN(j*c_DATA_WIDTH+i) and buf_INIT_READ_OUT(j));
            end loop;
            INIT_muxed_DATA(i) <= VAR_INIT_POOL_DATA;
          end process;
      end generate;
    
      gen_init_pool_data2: for i in 0 to c_NUM_WIDTH-1 generate
        process(INIT_PACKET_NUM_IN, buf_INIT_READ_OUT)
          variable VAR_INIT_POOL_PACKET_NUM : std_logic;
          begin
            VAR_INIT_POOL_PACKET_NUM := '0';
            gen_init_pool_data3 : for j in 0 to POINT_NUMBER-1 loop
              VAR_INIT_POOL_PACKET_NUM := VAR_INIT_POOL_PACKET_NUM or (INIT_PACKET_NUM_IN(j*c_NUM_WIDTH+i) and buf_INIT_READ_OUT(j));
            end loop;
            INIT_muxed_PACKET_NUM(i) <= VAR_INIT_POOL_PACKET_NUM;
          end process;
      end generate;
    
    
    ----------------------------------
    --Data Pool on Init Channel
    ----------------------------------
      INIT_POOL_SBUF: trb_net16_sbuf
        generic map (
          Version => std_SBUF_VERSION
          )
        port map (
          CLK   => CLK,
          RESET  => RESET,
          CLK_EN => CLK_EN,
          COMB_DATAREADY_IN => INIT_muxed_DATAREADY,
          COMB_next_READ_OUT => comb_INIT_next_read,
          COMB_READ_IN => INIT_muxed_READ,
          COMB_DATA_IN => INIT_muxed_DATA,
          COMB_PACKET_NUM_IN => INIT_muxed_PACKET_NUM,
          SYN_DATAREADY_OUT => INIT_POOL_DATAREADY,
          SYN_DATA_OUT => INIT_POOL_DATA,
          SYN_PACKET_NUM_OUT => INIT_POOL_PACKET_NUM,
          SYN_READ_IN => INIT_POOL_READ
          );
    
      process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' then
              INIT_muxed_READ <= '0';
            else
              INIT_muxed_READ <= comb_INIT_next_read;
            end if;
          end if;
        end process;
    
    
    --init_has_read signal
      gen_hasread: for i in 0 to POINT_NUMBER-1 generate
        process(CLK)
          begin
            if rising_edge(CLK) then
              if RESET = '1' or INIT_POOL_READ = '1' then
                init_has_read_from_pool(i) <= '0';
              elsif INIT_POOL_DATAREADY = '1' and INIT_READ_IN(i) = '1' then
                init_has_read_from_pool(i) <= '1';
              end if;
            end if;
          end process;
      end generate;
    
    ----------------------------------
    --Data Output to init Obufs
    ----------------------------------
      gen_init_data_out: for i in 0 to POINT_NUMBER-1 generate
        INIT_DATAREADY_OUT(i) <= INIT_POOL_DATAREADY and not init_has_read_from_pool(i) and real_activepoints(i) and not locking_point(i);
        INIT_DATA_OUT((i+1)*c_DATA_WIDTH-1 downto i*c_DATA_WIDTH) <= INIT_POOL_DATA;
        INIT_PACKET_NUM_OUT((i+1)*c_NUM_WIDTH-1 downto i*c_NUM_WIDTH) <= INIT_POOL_PACKET_NUM;
      end generate;
    
    
    ----------------------------------
    --Hub Locks - locked while a transfer is running, init_locked after trm on init has been received
    ----------------------------------
    
      get_locked     <= INIT_muxed_DATAREADY;
      next_locked    <= (get_locked or locked) and not release_locked;
      next_locking_point <= (INIT_DATAREADY_IN) when (locked = '0' and REPLY_POOL_DATAREADY = '0') else locking_point;
                           --buf_INIT_READ_OUT and
    
      get_init_locked     <= '1' when saved_INIT_TYPE = TYPE_TRM and INIT_muxed_PACKET_NUM = c_F3 else '0';
      release_init_locked <= release_locked;
      next_init_locked    <= (get_init_locked or init_locked) and not release_init_locked;
    
    
      process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' then
              locked <= '0';
              locking_point <= (others => '0');
              init_locked <= '0';
            else
              locked <= next_locked;
              locking_point <= next_locking_point;
              init_locked <= next_init_locked;
            end if;
          end if;
        end process;
    
    ----------------------------------
    --Save current packet type on init channel
    ----------------------------------
    
      save_INIT_TYPE : process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1'  or (INIT_muxed_DATAREADY = '1' and INIT_muxed_PACKET_NUM = c_F3) then
              saved_INIT_TYPE <= TYPE_ILLEGAL;
            elsif INIT_muxed_DATAREADY = '1' and INIT_muxed_PACKET_NUM = c_H0 then
              saved_INIT_TYPE <= INIT_muxed_DATA(2 downto 0);
            end if;
          end if;
        end process;
      current_INIT_TYPE <= INIT_muxed_DATA(2 downto 0) when INIT_muxed_DATAREADY = '1' and INIT_muxed_PACKET_NUM = c_H0
                           else saved_INIT_TYPE;
    
    
    ----------------------------------
    --save event information
    ----------------------------------
    
      save_INIT_PACKET : process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' then
            elsif INIT_POOL_DATAREADY = '1' then
              case INIT_POOL_PACKET_NUM is
                when c_F0 => null;
                when c_F1 => evt_random_code <= INIT_POOL_DATA(7 downto 0);
                when c_F2 => evt_number <= INIT_POOL_DATA;
                when c_F3 => evt_dtype <= INIT_POOL_DATA(3 downto 0);
                             evt_seqnr <= INIT_POOL_DATA(11 downto 4);
                when others => null;
              end case;
            end if;
          end if;
        end process;
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    ------------------------------
    --REPLY-----------------------
    ------------------------------
    
      gen_read_out : for i in 0 to POINT_NUMBER-1 generate
        buf_REPLY_READ_OUT(i) <= reg_current_reply_reading_TRM(i) --current_reply_reading_TRM(i)
                              or reg_current_reply_reading_HDR(i) --current_reply_reading_HDR(i)
                              or reg_current_reply_auto_reading_DHDR(i)
                              or saved_reading_padding(i)
                              or (reply_mux_reading(i) and REPLY_POOL_next_read and not packet_counter(2))
                              or not locked;
    --                           or (reply_fsm_state(4) and reply_reading_H0(i));
    
    
      end generate;
      REPLY_READ_OUT <= buf_REPLY_READ_OUT;
    
    
    
    
    
    
    ----------------------------------
    --save current packet type & set markers for special words
    ----------------------------------------------------------
    
      gen_reading_Fn : for i in 0 to POINT_NUMBER-1 generate
        reply_reading_H0(i) <= not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+1) and not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH)
                         and REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2) and REPLY_DATAREADY_IN(i);
        reply_reading_F0(i) <= not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+1) and not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH)
                         and not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2) and REPLY_DATAREADY_IN(i);
        reply_reading_F1(i) <= not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+1) and REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH)
                         and not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2) and REPLY_DATAREADY_IN(i);
        reply_reading_F2(i) <= REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+1) and not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH)
                         and not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2) and REPLY_DATAREADY_IN(i);
        reply_reading_F3(i) <= REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+1) and REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH)
                         and not REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2) and REPLY_DATAREADY_IN(i);
    
        process(CLK)
          begin
            if rising_edge(CLK) then
              if RESET = '1' then
                saved_reply_packet_type((i+1)*3-1 downto i*3) <= TYPE_ILLEGAL;
                last_reply_packet_type ((i+1)*3-1 downto i*3)  <= TYPE_ILLEGAL;
                last_reply_packet_number((i+1)*3-1 downto i*3)  <= c_F3;
              elsif REPLY_DATAREADY_IN(i) = '1' then
                last_reply_packet_number((i+1)*3-1 downto i*3) <= REPLY_PACKET_NUM_IN((i+1)*c_NUM_WIDTH-1 downto i*c_NUM_WIDTH);
                if REPLY_PACKET_NUM_IN((i+1)*c_NUM_WIDTH-1 downto i*c_NUM_WIDTH) = c_H0 then
                  saved_reply_packet_type((i+1)*3-1 downto i*3)  <= REPLY_DATA_IN(i*c_DATA_WIDTH+2 downto i*c_DATA_WIDTH);
                  if last_reply_packet_number((i+1)*3-1 downto i*3) /= c_H0 then
                    last_reply_packet_type ((i+1)*3-1 downto i*3)  <= saved_reply_packet_type((i+1)*3-1 downto i*3);
                  end if;
                end if;
              end if;
            end if;
          end process;
    
        current_reply_packet_type((i+1)*3-1 downto i*3) <= REPLY_DATA_IN(i*c_DATA_WIDTH+2 downto i*c_DATA_WIDTH)
                      when (REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2 downto i*c_NUM_WIDTH) = c_H0 and REPLY_DATAREADY_IN(i) = '1')
                      else saved_reply_packet_type((i+1)*3-1 downto i*3);
    
        current_reply_reading_HDR(i)  <= '1' when current_reply_packet_type((i+1)*3-1 downto i*3) = TYPE_HDR else '0';
        current_reply_reading_DHDR(i) <= '1' when current_reply_packet_type((i+1)*3-1 downto i*3) = TYPE_DAT
                                                 and last_reply_packet_type((i+1)*3-1 downto i*3) = TYPE_HDR else '0';
        current_reply_reading_TRM(i)  <= '1' when current_reply_packet_type((i+1)*3-1 downto i*3) = TYPE_TRM else '0';
    
    
        PROC_reading_signals : process(CLK)
          begin
            if rising_edge(CLK) then
              reg_current_reply_reading_TRM(i)  <= current_reply_reading_TRM(i);
              reg_current_reply_reading_HDR(i)  <= current_reply_reading_HDR(i);
              reg_current_reply_reading_DHDR(i) <= current_reply_reading_DHDR(i);
            end if;
          end process;
    
    
    
        PROC_last_reply_packet_num : process(CLK)
          begin
            if rising_edge(CLK) then
              if REPLY_DATAREADY_IN(i) = '1' and buf_REPLY_READ_OUT(i) = '1' then
                last_REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2 downto i*c_NUM_WIDTH) <= REPLY_PACKET_NUM_IN(i*c_NUM_WIDTH+2 downto i*c_NUM_WIDTH);
              end if;
            end if;
          end process;
    
    
        PROC_save_auto_reading_DHDR : process(CLK)
          begin
            if rising_edge(CLK) then
              saved_auto_reading_DHDR(i) <= reg_current_reply_auto_reading_DHDR(i);
            end if;
          end process;
    
    
        PROC_auto_read_DHDR : process(reg_current_reply_reading_HDR, enable_packing,
                                      last_REPLY_PACKET_NUM_IN,reg_current_reply_reading_dhdr)
          begin
            reg_current_reply_auto_reading_DHDR(i) <= '0';
            if reg_current_reply_reading_HDR(i) = '1' then
              reg_current_reply_auto_reading_DHDR(i) <= '1';
            elsif reg_current_reply_reading_DHDR(i) = '1' then
              if enable_packing = '0' or DISABLE_PACKING = 1 then
                if    last_REPLY_PACKET_NUM_IN(i*3+2 downto i*3) = c_F1
                   or last_REPLY_PACKET_NUM_IN(i*3+2 downto i*3) = c_F2
                   or last_REPLY_PACKET_NUM_IN(i*3+2 downto i*3) = c_F3 then
                  reg_current_reply_auto_reading_DHDR(i) <= '0';
                else
                  reg_current_reply_auto_reading_DHDR(i) <= '1';
                end if;
              else
                if last_REPLY_PACKET_NUM_IN(i*3+2 downto i*3) = c_F3 then
                  reg_current_reply_auto_reading_DHDR(i) <= '0';
                else
                  reg_current_reply_auto_reading_DHDR(i) <= '1';
                end if;
              end if;
            end if;
          end process;
    
      end generate;
    
    
      reg_timer_ticks : process(CLK)
        begin
          if rising_edge(CLK) then
            timer_us_tick <= CTRL_TIMER_TICK(0);
            timer_ms_tick <= CTRL_TIMER_TICK(1);
          end if;
        end process;
    
    ----------------------------------
    --Check for Timeouts
    ----------------------------------
    
    --   gen_timeout_counters : for i in 0 to POINT_NUMBER-1 generate
    --     proc_timeout_counters : process (CLK)
    --       begin
    --         if rising_edge(CLK) then
    --           connection_timed_out(i) <= '0';
    --           reg_CTRL_TIMEOUT_TIME <= CTRL_TIMEOUT_TIME;
    --           timeout_found <= or_all(connection_timed_out);
    --           if REPLY_DATAREADY_IN(i) = '1' or real_activepoints(i) = '0' or locked = '0' or locking_point(i) = '1'  or reg_CTRL_TIMEOUT_TIME = x"F" then
    --             timeout_counter(i) <= (others => '0');
    --           elsif timeout_counter(i)(to_integer(unsigned(reg_CTRL_TIMEOUT_TIME(2 downto 0)&'1'))) = '1' then
    --             connection_timed_out(i) <= '1';
    --           elsif timer_ms_tick = '1' then
    --             timeout_counter(i) <= timeout_counter(i) + to_unsigned(1,1);
    --           end if;
    --         end if;
    --       end process;
    --   end generate;
    
    
      proc_reg_setting : process (CLK)
        begin
          if rising_edge(CLK) then
            reg_CTRL_TIMEOUT_TIME   <= unsigned(CTRL_TIMEOUT_TIME);
            timeout_found           <= or_all(connection_timed_out);
          end if;
        end process;
    
      gen_timeout_counters : for i in 0 to POINT_NUMBER-1 generate
        proc_ack_timeout_counters : process (CLK)
          begin
            if rising_edge(CLK) then
              connection_timed_out(i) <= '0';
              if REPLY_DATAREADY_IN(i) = '1' or real_activepoints(i) = '0' or locked = '0' or got_trm(i) = '1'
                                                or locking_point(i) = '1'  or reg_CTRL_TIMEOUT_TIME = 0 then
                timeout_counter(i) <= (others => '0');
              elsif timeout_counter(i) = reg_CTRL_TIMEOUT_TIME then
                connection_timed_out(i) <= '1';
              elsif timer_ms_tick = '1' and  got_trm(i) = '0' then
                timeout_counter(i) <= timeout_counter(i) + to_unsigned(1,1);
              end if;
            end if;
          end process;
      end generate;
    
    
    ----------------------------------
    --saving (D)HDR
    ----------------------------------
      gen_saving_dhdr : for i in 0 to POINT_NUMBER-1 generate
        hdrram_write_enable(i) <= (reg_current_reply_reading_HDR(i) or reg_current_reply_reading_DHDR(i)) and not reply_reading_H0(i) and REPLY_DATAREADY_IN(i);
        hdrram_address(i*3+1 downto i*3) <= REPLY_PACKET_NUM_IN((i)*c_NUM_WIDTH+1 downto i*c_NUM_WIDTH);
        hdrram_address(i*3+2) <= '1' when current_reply_reading_DHDR(i)='1' else '0';
    
        the_last_HDR_RAM : ram_dp_rw
          generic map(
            depth => 3,
            width => 16
            )
          port map(
            CLK     => CLK,
            wr1     => hdrram_write_enable(i),
            a1      => hdrram_address(i*3+2 downto i*3),
            din1    => REPLY_DATA_IN((i+1)*c_DATA_WIDTH-1 downto i*c_DATA_WIDTH),
            a2      => dhdr_addr,
            dout2   => next_dhdr_data((i+1)*c_DATA_WIDTH-1 downto i*c_DATA_WIDTH)
            );
      end generate;
    
    
      PROC_dhdr_data_reg : process(CLK)
        begin
          if rising_edge(CLK) then
            dhdr_data <= next_dhdr_data;
            if RESET = '1' then
              reply_adder_start   <= '0';
              reply_compare_start <= '0';
            else
              reg_reply_adder_start   <= next_reply_adder_start;
              reg_reply_compare_start <= next_reply_compare_start;
              reply_adder_start       <= reg_reply_adder_start;
              reply_compare_start     <= reg_reply_compare_start;
            end if;
          end if;
        end process;
    
      the_ram_output_adder : wide_adder_17x16
        generic map(
          SIZE => 16,
          WORDS => 17
          )
        port map(
          CLK          => CLK,
          CLK_EN       => CLK_EN,
          RESET        => RESET,
          INPUT_IN     => reply_adder_input,
          VAL_ENABLE_IN=> reply_adder_val_enable,
          START_IN     => reply_adder_start,
          RESULT_OUT   => reply_adder_result,
          OVERFLOW_OUT => reply_adder_overflow,
          READY_OUT    => reply_adder_ready
          );
    
          reply_adder_val_enable(POINT_NUMBER-1 downto 0) <= (not locking_point and real_activepoints);
          gen_other_bits : if POINT_NUMBER < 17 generate
            reply_adder_val_enable(reply_adder_val_enable'left downto POINT_NUMBER) <= (others => '0');
          end generate;
    
      reply_adder_input(POINT_NUMBER*16-1 downto 0) <= dhdr_data;
      gen_spare_bits : if POINT_NUMBER < 17 generate
        reply_adder_input(reply_adder_input'left downto POINT_NUMBER*16) <= (others => '0');
      end generate;
    
      process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' then
              current_point_length <= (others => '0');
            else
              gen_current_length : for i in 0 to POINT_NUMBER-1 loop
                if reply_arbiter_result(i) = '1' then
                  current_point_length <= unsigned(dhdr_data((i)*c_DATA_WIDTH+c_DATA_WIDTH-1 downto i*c_DATA_WIDTH));
                end if;
              end loop;
            end if;
          end if;
        end process;
    
    
    
    ----------------------------------
    --reading and merging TRM
    ----------------------------------
      gen_combining_trm : for j in 0 to c_DATA_WIDTH-1 generate
        process(CLK)
          variable tmpF1, tmpF2, tmpF3 : std_logic;
          begin
            if rising_edge(CLK) then
              if RESET = '1' or locked = '0' then
                reply_combined_trm_F1(j) <= '0';
                reply_combined_trm_F2(j) <= '0';
                reply_combined_trm_F3(j) <= '0';
              else
                tmpF1 := '0';
                tmpF2 := '0';
                tmpF3 := '0';
                for i in 0 to POINT_NUMBER-1 loop
                  tmpF1 := tmpF1 or (REPLY_DATA_IN(i*c_DATA_WIDTH+j) and reply_reading_F1(i) and reg_current_reply_reading_TRM(i));
                  tmpF2 := tmpF2 or (REPLY_DATA_IN(i*c_DATA_WIDTH+j) and reply_reading_F2(i) and reg_current_reply_reading_TRM(i));
                  tmpF3 := tmpF3 or (REPLY_DATA_IN(i*c_DATA_WIDTH+j) and reply_reading_F3(i) and reg_current_reply_reading_TRM(i));
                end loop;
                if j = 3 then
                  reply_combined_trm_F1(j) <= reply_combined_trm_F1(j) or tmpF1 or timeout_found;
                else
                  reply_combined_trm_F1(j) <= reply_combined_trm_F1(j) or tmpF1;
                end if;
    
                reply_combined_trm_F2(j) <= reply_combined_trm_F2(j) or tmpF2;
                reply_combined_trm_F3(j) <= reply_combined_trm_F3(j) or tmpF3;
              end if;
            end if;
          end process;
      end generate;
    
      gen_monitoring_errorbits : process(CLK)
        begin
          if rising_edge(CLK) then
            for i in 0 to POINT_NUMBER-1 loop
              if (reply_reading_F1(i) and reg_current_reply_reading_TRM(i)) = '1' then
                STAT_ALL_ERRORBITS(i*32+31 downto i*32+16) <= REPLY_DATA_IN(i*16+15 downto i*16);
              end if;
              if (reply_reading_F2(i) and reg_current_reply_reading_TRM(i)) = '1' then
                STAT_ALL_ERRORBITS(i*32+15 downto i*32+0) <= REPLY_DATA_IN(i*16+15 downto i*16);
              end if;
            end loop;
          end if;
        end process;
    
      gen_other_errorbits : for i in POINT_NUMBER to 15 generate
        STAT_ALL_ERRORBITS(i*32+31 downto i*32) <= (others => '0');
      end generate;
    
    ----------------------------------
    --read overhead data
    ----------------------------------
    
      process(reg_current_reply_reading_trm, reply_reading_f0, start_read_padding,
              saved_reading_padding)
        begin
            for i in 0 to POINT_NUMBER-1 loop
              if reply_reading_F0(i) = '1' and reg_current_reply_reading_TRM(i) = '1' then
              --REPLY_DATAREADY_IN(i) = '1' and REPLY_PACKET_NUM_IN(i*3+2 downto i*3) = c_H0 and REPLY_DATA_IN(i*16+2 downto i*16) = TYPE_TRM then
                reading_padding(i) <= '0';
              elsif start_read_padding(i) = '1' then
                reading_padding(i) <= '1';
              else
                reading_padding(i) <= saved_reading_padding(i);
              end if;
            end loop;
        end process;
    
      gen_saved_padding : process (CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' or send_reply_trm = '1' or locked = '0' then
              saved_reading_padding <= (others => '0');
            else
              saved_reading_padding <= reading_padding;
            end if;
          end if;
        end process;
    
    
    
    ----------------------------------
    --real_activepoints can be set between transfers only, but can be cleared at any time
    ----------------------------------
      gen_real_activepoints : process (CLK)
        begin
          if rising_edge(CLK) then
            if locked = '0' then
              real_activepoints <= CTRL_activepoints(POINT_NUMBER-1 downto 0) and not CTRL_DISABLED_PORTS(POINT_NUMBER-1 downto 0);
            else
              real_activepoints <= real_activepoints and CTRL_activepoints(POINT_NUMBER-1 downto 0) 
                                    and not connection_timed_out and not CTRL_DISABLED_PORTS(POINT_NUMBER-1 downto 0);
            end if;
          end if;
        end process;
    
    
    ----------------------------------
    --count received TRM
    ----------------------------------
      gen_got_trm : process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' or locked = '0' then
              got_trm <= (others => '0');
            else
              got_trm <= got_trm or locking_point or (reply_reading_F3 and reg_current_reply_reading_TRM)
                                 or not real_activepoints or connection_timed_out;
            end if;
          end if;
        end process;
    
      send_reply_trm <= and_all(got_trm);
    
    
      gen_got_dhdr : process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' or locked = '0' then
              got_all_DHDR <= '0';
            else
              got_all_DHDR <= not or_all(waiting_for_DHDR_word);
            end if;
          end if;
        end process;
    
    
    ----------------------------------
    --REPLY Counters
    ----------------------------------
    --counter for 16bit words
      gen_packet_counter : process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' or locked = '0' then
              packet_counter <= c_H0;
            elsif comb_REPLY_POOL_DATAREADY = '1' then
              if packet_counter = c_max_word_number then
                packet_counter <= (others => '0');
              else
                packet_counter <= std_logic_vector(to_unsigned(to_integer(unsigned(packet_counter)) + 1 ,packet_counter'length ));
              end if;
            end if;
          end if;
        end process;
    
    --counts 32bit data words
      gen_data_counter : process(CLK)
        begin
          if rising_edge(CLK) then
            if reply_data_counter_reset = '1' then
              if enable_packing = '0' or DISABLE_PACKING = 1 then
                reply_data_counter <= (others => '0');
              else
                reply_data_counter <= (0 => '1', others => '0');
              end if;
            elsif enable_reply_data_counter = '1'  then
              reply_data_counter <= reply_data_counter + 1;
            end if;
          end if;
        end process;
    
      PROC_REG_COMB_DATAREADY : process(CLK)
        begin
          if rising_edge(CLK) then
            enable_reply_data_counter <= comb_REPLY_POOL_DATAREADY and packet_counter(0); --F1 or F3
            reply_data_counter_reset  <= next_reply_data_counter_reset or RESET;
          end if;
        end process;
    
    ----------------------------------
    --REPLY select input
    ----------------------------------
      REPLY_ARBITER: trb_net_priority_arbiter
        generic map (
          WIDTH => POINT_NUMBER
          )
        port map (
          CLK   => CLK,
          RESET  => reply_arbiter_reset,
          CLK_EN  => reply_arbiter_CLK_EN,
          INPUT_IN  => reply_arbiter_input,
          RESULT_OUT => reply_arbiter_result,
          ENABLE  => reply_arbiter_enable,  --switched off during DHDR
          CTRL => (others => '0')
          );
    
      reply_arbiter_reset  <= RESET or not locked;
      reply_arbiter_input  <= REPLY_DATAREADY_IN and not current_reply_reading_TRM and not saved_reading_padding;
      --and current_reply_reading_DHDR
    --  reply_arbiter_CLK_EN <= not next_point_lock;
      REPLY_MUX_reading <= reply_arbiter_result;
    
    
    
    ----------------------------------
    --Muxing Reply data
    ----------------------------------
      gen_reply_mux1 : for i in 0 to c_DATA_WIDTH-1 generate
        data_mux : process(REPLY_DATA_IN, REPLY_MUX_reading)
          variable tmp_data : std_logic;
          begin
            tmp_data := '0';
            gen_data_mux : for j in 0 to POINT_NUMBER-1 loop
              tmp_data := tmp_data or (REPLY_DATA_IN(j*c_DATA_WIDTH+i) and REPLY_MUX_reading(j));
            end loop;
            comb_REPLY_muxed_DATA(i) <= tmp_data;
          end process;
      end generate;
    
      gen_reply_mux2 : for i in 0 to c_NUM_WIDTH-1 generate
        packet_num_mux : process(REPLY_PACKET_NUM_IN, REPLY_MUX_reading)
          variable tmp_pm : std_logic;
          begin
            tmp_pm := '0';
            gen_pm_mux : for j in 0 to POINT_NUMBER-1 loop
              tmp_pm := tmp_pm or (REPLY_PACKET_NUM_IN(j*c_NUM_WIDTH+i) and REPLY_MUX_reading(j));
            end loop;
            comb_REPLY_muxed_PACKET_NUM(i) <= tmp_pm;
          end process;
      end generate;
    
    
    --Muxed data is ready, when the selected port has data, and this is neither padding, H0, padding nor termination.
    --
      comb_REPLY_muxed_DATAREADY <= or_all(reply_arbiter_result and REPLY_DATAREADY_IN and not reg_current_reply_reading_trm
                                           and not reply_reading_H0 and not saved_reading_padding)
                                      and REPLY_POOL_next_read;
    
    
    
    ----------------------------------
    --Compare Event Information
    ----------------------------------
    
    
      PROC_COMPARE : process(CLK)
        variable tmp_code, tmp_number, tmp_pack : std_logic;
        begin
          if rising_edge(CLK) then
            reply_compare_finished <= reply_compare_finished and not REPLY_POOL_next_read;
            tmp_code   := '0';
            tmp_pack   := '1';
            tmp_number := '0';
            if reply_compare_start = '1' then
              if dhdr_addr = "100" then --upper part
                mismatch_pattern(31 downto 16) <= (others => '0');
                for i in 0 to POINT_NUMBER-1 loop
                  if dhdr_data(i*16+12) = '0' and reply_adder_val_enable(i) = '1' then
                    tmp_pack := '0';
                  end if;
                  if dhdr_data(i*16+7 downto i*16) /= evt_random_code and reply_adder_val_enable(i) = '1' then
                    tmp_code := '1';
                    mismatch_pattern(i+16) <= '1';
                  end if;
                end loop;
                enable_packing    <= tmp_pack;
                evt_code_mismatch <= tmp_code;
                reply_compare_finished <= '1';
              elsif dhdr_addr = "101" then
                mismatch_pattern(15 downto 0) <= (others => '0');
                for i in 0 to POINT_NUMBER-1 loop
                  if dhdr_data(i*16+15 downto i*16) /= evt_number and reply_adder_val_enable(i) = '1' then
                    tmp_number := '1';
                    mismatch_pattern(i) <= '1';
                  end if;
                end loop;
                evt_number_mismatch <= tmp_number;
                reply_compare_finished <= '1';
              end if;
            elsif locked = '0' then
              evt_code_mismatch   <= '0';
              enable_packing      <= '0';
              evt_number_mismatch <= '0';
            end if;
          end if;
        end process;
    
    ----------------------------------
    --REPLY POOL state machine
    ----------------------------------
      reply_state_machine : process(REPLY_POOL_next_READ, current_state, packet_counter, timeout_found,
                                    send_reply_trm, REPLY_combined_trm_F1, REPLY_combined_trm_F2, got_all_DHDR,
                                    comb_REPLY_muxed_DATAREADY, comb_REPLY_muxed_DATA, init_locked,
                                    waiting_for_DHDR_word, locking_point, last_reply_adder_ready,
                                    real_activepoints, locked, MY_ADDRESS_IN, reply_adder_result, evt_code_mismatch,
                                    reply_combined_trm_F3, reply_compare_finished, reg_current_reply_auto_reading_dhdr,
                                    reply_adder_final_result, reg_current_reply_reading_dhdr, evt_number_mismatch,
                                    evt_seqnr, evt_dtype, evt_random_code, evt_number, number_of_replies,
                                    reply_data_counter, current_point_length, enable_packing, reply_arbiter_input,
                                    reply_arbiter_result, reply_reading_f2,current_reply_reading_trm)
        begin
          release_locked <= '0';
          next_state <= current_state;
          comb_REPLY_POOL_DATAREADY <= '0';
          comb_REPLY_POOL_PACKET_NUM <= packet_counter;
          comb_REPLY_POOL_DATA <= (others => '0');
          next_waiting_for_DHDR_word <= waiting_for_DHDR_word and real_activepoints
                                            and not (reg_current_reply_reading_DHDR and reply_reading_F2);
          dhdr_addr <= "000";
    --       next_current_waiting_for_reply <= current_waiting_for_reply and not reg_current_reply_reading_HDR  and real_activepoints;
          next_reply_adder_start <= '0';
          reply_arbiter_enable <= '0';
          next_reply_compare_start <= '0';
          reply_arbiter_CLK_EN <= '0';
          next_reply_data_counter_reset <= '0';
          start_read_padding <= (others => '0');
          next_reply_adder_final_result <= reply_adder_final_result;
    
          case current_state is
            when IDLE =>  --wait for init transfer
              next_waiting_for_DHDR_word <= not (locking_point or not real_activepoints);
    --           next_current_waiting_for_reply <= not (locking_point or not real_activepoints);
              if locked = '1' then
                next_state <= WAIT_FOR_REPLY;
              end if;
    
            when WAIT_FOR_REPLY =>
              if got_all_DHDR = '1'  then  --got_all_reply_starts = '1'
                next_state <= WAIT_FOR_HDR_DATA;
              end if;
    
            when WAIT_FOR_HDR_DATA =>  --start writing HDR when first reply is received, stop waiting for length
              dhdr_addr <= "100";
              case packet_counter is
                when c_H0 =>
                  comb_REPLY_POOL_DATA <= (others => '0');
                  comb_REPLY_POOL_DATA(2 downto 0) <= TYPE_HDR;
                  comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                when c_F0 =>
                  comb_REPLY_POOL_DATA <= MY_ADDRESS_IN;
                  comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                when c_F1 =>
                  comb_REPLY_POOL_DATA <= x"FFFF";
                  comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                when c_F2 =>
                  comb_REPLY_POOL_DATAREADY <= '0';
                  next_reply_compare_start <= '1';
    --              if not_reading_HDR = '1' and got_all_DHDR = '1' then --implicit not waiting_for_reply
                  next_state <= CHECK_EVENT_INFO;
    --              end if;
                when others => null;
              end case;
    
            when CHECK_EVENT_INFO =>
              dhdr_addr <= "100";
              if reply_compare_finished = '1' then
                dhdr_addr <= "010";
                next_state <= GEN_LENGTH;
              end if;
    
    
            when GEN_LENGTH =>  --now, all HDR are stored, calc sum of HDR lengths
              next_reply_adder_start <= '1';
              dhdr_addr <= "010";
              if enable_packing = '0' or DISABLE_PACKING = 1 then
                next_reply_adder_final_result <= std_logic_vector(unsigned(reply_adder_result) - number_of_replies + 2);
              else
                next_reply_adder_final_result <= std_logic_vector(unsigned(reply_adder_result) - number_of_replies - number_of_replies + 2);
              end if;
    
              case packet_counter is
                when c_F2 =>
                  comb_REPLY_POOL_DATA <= reply_adder_final_result;
                  comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read and last_reply_adder_ready;
                when c_F3 =>
                  dhdr_addr <= "100";
                  comb_REPLY_POOL_DATA <= "0000" & evt_seqnr & evt_dtype;
                  if REPLY_POOL_next_read = '1' then
                    comb_REPLY_POOL_DATAREADY <= '1';
                    next_state <= WAIT_FOR_END_OF_DHDR;
                  end if;
                when others => null;
              end case;
    
            when WAIT_FOR_END_OF_DHDR =>
              if or_all(reg_current_reply_auto_reading_DHDR) = '0' then
                next_state <= CHECK_DHDR;
              end if;
    
            when CHECK_DHDR =>
              comb_REPLY_POOL_DATAREADY <= '0';
              case packet_counter is
                when c_H0 =>
                  comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                  comb_REPLY_POOL_DATA(2 downto 0) <= TYPE_DAT;
                  comb_REPLY_POOL_DATA(c_DATA_WIDTH-1 downto 3) <= (others => '0');
                  dhdr_addr <= "100";
                  --next_reply_compare_start <= REPLY_POOL_next_read and got_all_DHDR;
                when c_F0 =>
                  dhdr_addr <= "100";
                  comb_REPLY_POOL_DATA <= "0001" & evt_dtype & evt_random_code;
                  --if reply_compare_finished = '1' then
                    next_reply_compare_start <= REPLY_POOL_next_read;
                    comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                    dhdr_addr <= "101";
                  --end if;
                when c_F1 =>
                  dhdr_addr <= "101";
                  comb_REPLY_POOL_DATA <= evt_number;
                  if reply_compare_finished = '1' then
                    comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                    next_reply_adder_start <= REPLY_POOL_next_read;
                    dhdr_addr <= "110";
                  end if;
                when c_F2 =>
                  dhdr_addr <= "110";
                  if enable_packing = '0' or DISABLE_PACKING = 1 then
                    next_reply_adder_final_result <= std_logic_vector(unsigned(reply_adder_result) + number_of_replies);
                  else
                    next_reply_adder_final_result <= std_logic_vector(unsigned(reply_adder_result));
                  end if;
                  if last_reply_adder_ready = '1' then
                    comb_REPLY_POOL_DATA <= reply_adder_final_result;
                    comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                  end if;
                when others => --c_F3
                  comb_REPLY_POOL_DATA <= MY_ADDRESS_IN;
                  comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
                  if REPLY_POOL_next_read = '1' then -- and or_all(reply_arbiter_input) = '1'
                    if or_all(reply_arbiter_input) = '1' then
                      next_state <= SENDING_DATA;
                    else
                      next_state <= ARBITER_ACTIVE;
                    end if;
                    reply_arbiter_CLK_EN <= '1';
                    reply_arbiter_enable <= '1';
                    dhdr_addr <= "110";
                    next_reply_data_counter_reset <= '1';
                  end if;
              end case;
    
            when ARBITER_ACTIVE =>
              reply_arbiter_CLK_EN <= '1';
              reply_arbiter_enable <= '1';
              dhdr_addr <= "110";
              if or_all(reply_arbiter_input) = '1' then
                next_state <= SENDING_DATA;
              elsif send_reply_trm = '1'  then
                if packet_counter /= c_H0 then
                  next_state <= SEND_PADDING;
                else
                  next_state <= SENDING_REPLY_TRM;
                end if;
              end if;
    
            when SENDING_DATA =>
              reply_arbiter_enable <= '1';
              dhdr_addr <= "110"; --length
    
              if packet_counter = c_H0 then --sending new H0 without checking for reading_DAT seems to be fine
                comb_REPLY_POOL_DATAREADY         <= REPLY_POOL_next_read;
                comb_REPLY_POOL_DATA(2 downto 0)  <= TYPE_DAT;
                comb_REPLY_POOL_DATA(15 downto 3) <= (others => '0');
                comb_REPLY_POOL_PACKET_NUM        <= packet_counter;
              else
                comb_REPLY_POOL_DATAREADY  <= comb_REPLY_muxed_DATAREADY;
                comb_REPLY_POOL_DATA       <= comb_REPLY_muxed_DATA;
                comb_REPLY_POOL_PACKET_NUM <= packet_counter;
              end if;
    
              --if number of announced words is reached and F1 or F3 is written, then care about padding
              if (reply_data_counter = current_point_length and packet_counter(0) = '1' and comb_REPLY_muxed_DATAREADY = '1')
                  or or_all(current_reply_reading_TRM and reply_arbiter_result) = '1' then
                next_reply_data_counter_reset <= '1';
                --either padding or trm follows. So: start reading in any case.
                start_read_padding <= reply_arbiter_result;
                next_state <= ARBITER_ACTIVE;
              end if;
    
              if send_reply_trm = '1'  then
                if packet_counter /= c_H0 then
                  next_state <= SEND_PADDING;
                else
                  comb_REPLY_POOL_DATAREADY <= '0';
                  next_state <= SENDING_REPLY_TRM;
                end if;
              end if;
    
            when SEND_PADDING =>
              comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
              comb_REPLY_POOL_DATA <= (1 => '1', others => '0');
              if packet_counter = c_F3 and REPLY_POOL_next_read = '1' then
                next_state <= SENDING_REPLY_TRM;
              end if;
    
            when SENDING_REPLY_TRM =>
              comb_REPLY_POOL_DATAREADY <= REPLY_POOL_next_read;
              case packet_counter is
                when c_F0 =>
                  comb_REPLY_POOL_DATA <= (others => '0');
                when c_F1 =>
                  comb_REPLY_POOL_DATA <= REPLY_combined_trm_F1;
                  comb_REPLY_POOL_DATA(0) <= REPLY_combined_trm_F1(0) or evt_number_mismatch;
                  comb_REPLY_POOL_DATA(1) <= REPLY_combined_trm_F1(1) or evt_code_mismatch;
                when c_F2 =>
                  comb_REPLY_POOL_DATA    <= REPLY_combined_trm_F2;
                  comb_REPLY_POOL_DATA(6) <= REPLY_combined_trm_F2(6) or timeout_found;
                when c_F3 =>
                  comb_REPLY_POOL_DATA <= REPLY_combined_trm_F3;
                  if REPLY_POOL_next_read = '1' and (init_locked = '1') then
                    release_locked <= '1';  --release only when init has finished too
                    next_state <= IDLE;
                  elsif REPLY_POOL_next_read = '1' and init_locked = '0' then
                    next_state <= WAITING_FOR_INIT;
                  end if;
                when others => -- | c_H0 =>
                  comb_REPLY_POOL_DATA <= (others => '0');
                  comb_REPLY_POOL_DATA(2 downto 0) <= TYPE_TRM;
                end case;
            when WAITING_FOR_INIT =>
              comb_REPLY_POOL_DATAREADY <= '0';
              if init_locked = '1' then
                release_locked <= '1';  --release only when init has finished too
                next_state <= IDLE;
              end if;
          end case;
        end process;
    
      reply_fsm_state(0) <= '1' when current_state = IDLE else '0';
      reply_fsm_state(1) <= '1' when current_state = WAIT_FOR_HDR_DATA else '0';
      reply_fsm_state(2) <= '1' when current_state = GEN_LENGTH else '0';
      reply_fsm_state(3) <= '1' when current_state = CHECK_DHDR else '0';
      reply_fsm_state(4) <= '1' when current_state = SENDING_DATA else '0';
      reply_fsm_state(5) <= '1' when current_state = SEND_PADDING else '0';
      reply_fsm_state(6) <= '1' when current_state = SENDING_REPLY_TRM else '0';
      reply_fsm_state(7) <= '1' when current_state = WAITING_FOR_INIT else '0';
    
      reply_fsm_statebits <= x"0" when current_state = IDLE else
                             x"1" when current_state = WAIT_FOR_REPLY else
                             x"2" when current_state = WAIT_FOR_HDR_DATA else
                             x"3" when current_state = CHECK_EVENT_INFO else
                             x"4" when current_state = GEN_LENGTH else
                             x"5" when current_state = WAIT_FOR_END_OF_DHDR else
                             x"6" when current_state = CHECK_DHDR else
                             x"7" when current_state = SENDING_DATA else
                             x"8" when current_state = ARBITER_ACTIVE else
                             x"9" when current_state = SEND_PADDING else
                             x"A" when current_state = SENDING_REPLY_TRM else
                             x"B" when current_state = WAITING_FOR_INIT else
    --                          x"C" when current_state = WAIT_FOR_REPLY else
    --                          x"D" when current_state = WAIT_FOR_REPLY else
    --                          x"E" when current_state = WAIT_FOR_REPLY else
                             x"F";
    
    
      process(CLK)
        begin
          if rising_edge(CLK) then
            if RESET = '1' then
              current_state <= IDLE;
              REPLY_POOL_next_read <= '0';
              waiting_for_DHDR_word <= (others => '1');
    --           current_waiting_for_reply <= (others => '1');
    --           got_all_reply_starts <= '0';
              reply_adder_final_result <= (others => '0');
              last_reply_adder_ready <= '0';
            else
              current_state <= next_state;
              REPLY_POOL_next_read <= comb_REPLY_POOL_next_read;
              waiting_for_DHDR_word <= next_waiting_for_DHDR_word;
    --           current_waiting_for_reply <= next_current_waiting_for_reply;
    --           got_all_reply_starts <= not or_all(current_waiting_for_reply);
              not_reading_HDR <= not or_all(current_reply_reading_HDR);
              number_of_replies <= to_unsigned(count_ones(expected_replies),5);
              expected_replies <= real_activepoints and not locking_point;
              reply_adder_final_result <= next_reply_adder_final_result;
              last_reply_adder_ready <= reply_adder_ready or (last_reply_adder_ready and not REPLY_POOL_next_read);
            end if;
          end if;
        end process;
    
    
    ----------------------------------
    --REPLY sbuf
    ----------------------------------
    
      REPLY_POOL_SBUF: trb_net16_sbuf
        generic map (
          Version => 0
          )
        port map (
          CLK   => CLK,
          RESET  => RESET,
          CLK_EN => CLK_EN,
          COMB_DATAREADY_IN => comb_REPLY_POOL_DATAREADY,
          COMB_next_READ_OUT => comb_REPLY_POOL_next_read,
          COMB_READ_IN => REPLY_POOL_next_read,
          COMB_DATA_IN => comb_REPLY_POOL_DATA,
          COMB_PACKET_NUM_IN => comb_REPLY_POOL_PACKET_NUM,
          SYN_DATAREADY_OUT => REPLY_POOL_DATAREADY,
          SYN_DATA_OUT => REPLY_POOL_DATA,
          SYN_PACKET_NUM_OUT => REPLY_POOL_PACKET_NUM,
          SYN_READ_IN => REPLY_POOL_READ
          );
    
    ----------------------------------
    --REPLY output
    ----------------------------------
    
      gen_reply_data_out: for i in 0 to POINT_NUMBER-1 generate
        REPLY_DATAREADY_OUT(i) <= REPLY_POOL_DATAREADY and locking_point(i);
        REPLY_DATA_OUT((i+1)*c_DATA_WIDTH-1 downto i*c_DATA_WIDTH) <= REPLY_POOL_DATA;
        REPLY_PACKET_NUM_OUT((i+1)*c_NUM_WIDTH-1 downto i*c_NUM_WIDTH) <= REPLY_POOL_PACKET_NUM;
      end generate;
      REPLY_POOL_READ <= or_all(REPLY_READ_IN and locking_point);
    
    
    
    
    ----------------------------------
    --Debugging
    ----------------------------------
    
    
      STAT_TIMEOUT(POINT_NUMBER-1 downto 0) <= connection_timed_out;
      STAT_TIMEOUT(31 downto POINT_NUMBER)  <= (others => '0');
    
    
      STAT_DEBUG(0) <= got_trm(0);
      STAT_DEBUG(1) <= got_trm(1);
      STAT_DEBUG(2) <= REPLY_POOL_DATAREADY;
      STAT_DEBUG(3) <= REPLY_DATAREADY_IN(0);
      STAT_DEBUG(4) <= buf_REPLY_READ_OUT(0);
      STAT_DEBUG(5) <= comb_REPLY_muxed_DATA(14);
    
      STAT_DEBUG(6) <= REPLY_DATA_IN(14);
      STAT_DEBUG(7) <= REPLY_DATA_IN(30);
      STAT_DEBUG(8) <= got_all_DHDR; --REPLY_DATA_IN(46);
      STAT_DEBUG(9) <= locked;
      STAT_DEBUG(10) <= '0';
      STAT_DEBUG(11) <= REPLY_POOL_next_read;
      STAT_DEBUG(15 downto 12) <= reply_fsm_statebits(3 downto 0);
    
      STAT_DEBUG(19 downto 16) <= REPLY_DATA_IN(19 downto 16);
      STAT_DEBUG(20)           <= REPLY_DATAREADY_IN(1);
      STAT_DEBUG(23 downto 21) <= REPLY_PACKET_NUM_IN(5 downto 3);
      STAT_DEBUG(24)           <= reg_current_reply_auto_reading_DHDR(1);
      STAT_DEBUG(25)           <= reg_current_reply_reading_DHDR(1);
      STAT_DEBUG(26)           <= reg_current_reply_reading_HDR(1);
      STAT_DEBUG(27)           <= got_all_DHDR;
      STAT_DEBUG(28)           <= '0'; --got_all_reply_starts;
      STAT_DEBUG(31 downto 29) <= last_REPLY_PACKET_NUM_IN(5 downto 3);
    
      --STAT(15 downto 8) <= data_counter;
    
      proc_stat_errorbits : process(CLK)
        begin
          if rising_edge(CLK) then
            last_locked <= locked;
            if locked = '1' then
              STAT_POINTS_locked(POINT_NUMBER-1 downto 0) <= not got_trm;
            else
              STAT_POINTS_locked(POINT_NUMBER-1 downto 0) <= (others => '0');
            end if;
            if current_state = SENDING_REPLY_TRM and packet_counter = c_F1 then
              STAT_ERRORBITS(31 downto 16) <= comb_REPLY_POOL_DATA;
            elsif  current_state = SENDING_REPLY_TRM and packet_counter = c_F2 then
              STAT_ERRORBITS(15 downto 0) <= comb_REPLY_POOL_DATA;
            end if;
          end if;
        end process;
    
      STAT_POINTS_locked(31 downto POINT_NUMBER)  <= (others => '0');
    
    
      STAT_FSM(3 downto 0)  <= reply_fsm_statebits;
      STAT_FSM(7 downto 4)  <= x"0";
      STAT_FSM(8)           <= reply_adder_start;
      STAT_FSM(9)           <= reply_compare_start;
      STAT_FSM(12 downto 10)<= packet_counter;
      STAT_FSM(15 downto 13)<= dhdr_addr;
      STAT_FSM(31 downto 16)<= (others => '0');
    
      STAT_locked <= locked;
      STAT_MISMATCH <= mismatch_pattern;
    
    end architecture;