]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
MBS-Recv(+Billboard): Introduced optional Timestamps and Regio-Master
authorManuel Penschuck <manuel.penschuck@stud.uni-frankfurt.de>
Mon, 3 Nov 2014 09:02:24 +0000 (10:02 +0100)
committerManuel Penschuck <manuel.penschuck@stud.uni-frankfurt.de>
Mon, 3 Nov 2014 09:02:24 +0000 (10:02 +0100)
billboard/trb3_periph_billboard.vhd
billboard/trb3_periph_billboard_constraints.lpf
cts/source/mbs_vulom_recv.vhd

index 34f12957737f4b672101fa25ebb130dd55a7ce63..87dd87e0d3fdea42344d049cd65c06ff7bd4f7eb 100644 (file)
@@ -358,6 +358,10 @@ end generate;
    );
    
    THE_MBS_RECV: entity work.mbs_vulom_recv
+   generic map (
+      INCL_RDO_TIMESTAMP => c_YES,
+      INCL_REGIO => c_YES
+   )
    port map (
       CLK        => clk_100_i , -- in std_logic;  -- e.g. 100 MHz
       RESET_IN   => reset_i, -- in std_logic;  -- could be used after busy_release to make sure entity is in correct state
@@ -370,6 +374,10 @@ end generate;
       TRG_ASYNC_OUT  => open, -- out std_logic;  -- asynchronous rising edge, length varying, here=> , -- approx. 110 ns
       TRG_SYNC_OUT   => mbs_trg_sync_i, -- out std_logic;  -- sync. to CLK
 
+      TRG_NUMBER_IN  => readout_rx.trg_number,
+      TRG_CODE_IN    => readout_rx.trg_code,
+      TIMING_TRG_IN  => TRIGGER_LEFT,     
+      
       --data output for read-out
       TRIGGER_IN   => readout_rx.data_valid, -- in  std_logic;
       DATA_OUT     => readout_tx(0).data , -- out std_logic_vector(31 downto 0);
@@ -378,28 +386,15 @@ end generate;
       FINISHED_OUT => readout_tx(0).data_finished, -- out std_logic;
 
       --Registers / Debug    
-      CONTROL_REG_IN => mbs_ctrl_i,   -- in  std_logic_vector(31 downto 0);
-      STATUS_REG_OUT => mbs_status_i, -- out std_logic_vector(31 downto 0) => , --= (others => '0');
+      REGIO_IN => regio_mbs_rx,
+      REGIO_OUT => regio_mbs_tx,
+      
+      CONTROL_REG_IN => (others => '0'),   -- in  std_logic_vector(31 downto 0);
+      STATUS_REG_OUT => open, -- out std_logic_vector(31 downto 0) => , --= (others => '0');
       HEADER_REG_OUT => open, -- out std_logic_vector(1 downto 0);
       DEBUG          => open  -- out std_logic_vector(31 downto 0)    
    );
    readout_tx(0).busy_release <= readout_tx(0).data_finished;
-
-   THE_MBS_REGIO: process is
-   begin
-      wait until rising_edge(clk_100_i);
-      
-      regio_mbs_tx.wack <= regio_mbs_rx.write;
-      regio_mbs_tx.rack <= regio_mbs_rx.read;
-      regio_mbs_tx.nack <= '0';
-      regio_mbs_tx.unknown <= '0';
-      
-      if regio_mbs_rx.write='1' then
-         mbs_ctrl_i <= regio_mbs_rx.data;
-      end if;
-      
-      regio_mbs_tx.data <= mbs_status_i;
-   end process;
    
    FPGA5_COMM(10 downto 7) <= "00" & mbs_trg_sync_i & mbs_trg_async_i;
     
@@ -410,7 +405,7 @@ end generate;
    generic map(
       PORT_NUMBER      => 3,
       PORT_ADDRESSES   => (0 => x"d000", 1 => x"b000", 2 => x"b800", others => x"0000"),
-      PORT_ADDR_MASK   => (0 => 9,       1 => 9,       2 => 1,  others => 0),
+      PORT_ADDR_MASK   => (0 => 9,       1 => 9,       2 => 2,  others => 0),
       PORT_MASK_ENABLE => 1
    )
    port map(
index 8918e647182f1a183e2b2339e4febb8b85d190ae..bf5af315181113d47bfd7ff1a1b35fde44648ce9 100644 (file)
@@ -28,7 +28,9 @@ LOCATE COMP          "THE_MEDIA_UPLINK/gen_serdes_1_200_THE_SERDES/PCSD_INST" SI
 REGION               "MEDIA_UPLINK" "R102C95D" 13 25;
 LOCATE UGROUP        "THE_MEDIA_UPLINK/media_interface_group" REGION "MEDIA_UPLINK" ;
 
-MULTICYCLE TO CELL  "THE_SPI_RELOAD_THE_SPI_MASTER_THE_SPI_SLIM_tx_sreg_oregio*" 20 ns;
+MULTICYCLE TO CELL "THE_SPI_RELOAD_THE_SPI_MASTER_THE_SPI_SLIM_tx_sreg_oregio*" 20 ns;
+MULTICYCLE TO CELL "THE_MBS_RECV/PROC_REG_INFO.error_reg" 2X;
+
 
 #################################################################
 # Clocks
index 96d53d179c50a9fd250e683ba0d22ac0b3541fc3..0b41ebd02612af2d9e8d415d2836131694ef61e9 100644 (file)
@@ -4,41 +4,55 @@ use ieee.numeric_std.all;
 
 library work;
 use work.trb_net_std.all;
+use work.trb_net_components.all;
 use work.trb3_components.all;
 
 
 entity mbs_vulom_recv is
-  port(
-    CLK        : in std_logic;  -- e.g. 100 MHz
-    RESET_IN   : in std_logic;  -- could be used after busy_release to make sure entity is in correct state
-
-    --Module inputs
-    MBS_IN     : in std_logic;  -- raw input
-    CLK_200    : in std_logic;  -- internal sampling clock
-    
-    --trigger outputs
-    TRG_ASYNC_OUT  : out std_logic;  -- asynchronous rising edge, length varying, here: approx. 110 ns
-    TRG_SYNC_OUT   : out std_logic;  -- sync. to CLK
-
-    --data output for read-out
-    TRIGGER_IN   : in  std_logic;
-    DATA_OUT     : out std_logic_vector(31 downto 0);
-    WRITE_OUT    : out std_logic;
-    STATUSBIT_OUT: out std_logic_vector(31 downto 0) := (others => '0');
-    FINISHED_OUT : out std_logic;
-    
-    --Registers / Debug    
-    CONTROL_REG_IN : in  std_logic_vector(31 downto 0);
-    STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0');
-    HEADER_REG_OUT : out std_logic_vector(1 downto 0);
-    DEBUG          : out std_logic_vector(31 downto 0)    
-    );
-
-    attribute syn_useioff : boolean;
-    --no IO-FF for MBS input
-    attribute syn_useioff of MBS_IN    : signal is false;
-
+   generic (
+      INCL_RDO_TIMESTAMP : integer range c_NO to c_YES := c_NO; -- will yield an unexpected rdo length (2 words instead the signalled 1 word)
+                                                               -- if used as an ETM for the CTS
+      INCL_REGIO : integer range c_NO to c_YES := c_NO                                                        
+   );
+   port(
+      CLK        : in std_logic;  -- e.g. 100 MHz
+      RESET_IN   : in std_logic;  -- could be used after busy_release to make sure entity is in correct state
+
+      --Module inputs
+      MBS_IN     : in std_logic;  -- raw input
+      CLK_200    : in std_logic;  -- internal sampling clock
+
+      --trigger outputs
+      TRG_ASYNC_OUT  : out std_logic;  -- asynchronous rising edge, length varying, here: approx. 110 ns
+      TRG_SYNC_OUT   : out std_logic;  -- sync. to CLK
+
+      --data output for read-out
+      TRIGGER_IN     : in  std_logic;
+      TRG_NUMBER_IN  : in  std_logic_vector (15 downto 0);
+      TRG_CODE_IN    : in  std_logic_vector (7  downto 0);     
+      TIMING_TRG_IN : in std_logic := '0';
 
+      
+      DATA_OUT     : out std_logic_vector(31 downto 0);
+      WRITE_OUT    : out std_logic;
+      STATUSBIT_OUT: out std_logic_vector(31 downto 0) := (others => '0');
+      FINISHED_OUT : out std_logic;
+
+      --Registers / Debug    
+      REGIO_IN  : in  CTRLBUS_RX := (data => x"00000000", addr => x"0000", others => '0');
+      REGIO_OUT : out CTRLBUS_TX;
+      
+      
+      -- Ctrl and Status registers are only in use, if INCL_REGIO = c_NO ("ETM" mode)
+      CONTROL_REG_IN : in  std_logic_vector(31 downto 0);
+      STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0');
+      HEADER_REG_OUT : out std_logic_vector(1 downto 0);
+      DEBUG          : out std_logic_vector(31 downto 0)    
+   );
+
+   attribute syn_useioff : boolean;
+   --no IO-FF for MBS input
+   attribute syn_useioff of MBS_IN    : signal is false;
 end entity;
 
 --MBS format
@@ -61,145 +75,343 @@ end entity;
 architecture mbs_vulom_recv_arch of mbs_vulom_recv is
 
 
-signal bitcnt : integer range 0 to 37;
-signal shift_reg : std_logic_vector(36 downto 0);
-
-signal first_bits_fast : std_logic;
-signal first_bits_slow : std_logic;
-signal reg_MBS_IN      : std_logic;
-signal done            : std_logic;
-signal done_slow       : std_logic;
-
-signal number_reg      : std_logic_vector(23 downto 0);
-signal status_reg      : std_logic_vector(1 downto 0);
-signal error_reg       : std_logic;
-
-signal trg_async       : std_logic;
-signal trg_sync        : std_logic;
-
-type state_t is (IDLE, WAIT1,WAIT2,WAIT3,WAIT4, FINISH);
-signal state           : state_t;
-
-type rdo_state_t is (RDO_IDLE, RDO_WAIT, RDO_WRITE, RDO_FINISH);
-signal rdostate        : rdo_state_t;
-
-signal config_rdo_disable_i : std_logic;
-
+   signal bitcnt : integer range 0 to 37;
+   signal shift_reg : std_logic_vector(36 downto 0);
+
+   signal first_bits_fast : std_logic;
+   signal first_bits_slow : std_logic;
+   signal reg_MBS_IN      : std_logic;
+   signal reg_MBS_DELAY   : std_logic;
+   signal done            : std_logic;
+   signal done_slow       : std_logic;
+
+   signal number_reg      : std_logic_vector(23 downto 0);
+   signal status_reg      : std_logic_vector(1 downto 0);
+   signal error_reg       : std_logic;
+
+   signal trg_async       : std_logic;
+   signal trg_sync        : std_logic;
+   signal trg_sync200     : std_logic;
+
+   type state_t is (IDLE, WAIT1,WAIT2,WAIT3,WAIT4, FINISH);
+   signal state           : state_t;
+
+   type rdo_state_t is (RDO_IDLE, RDO_WAIT, RDO_WRITE, RDO_TIMESTAMP, RDO_LVL1_ID, RDO_FINISH);
+   signal rdostate        : rdo_state_t;
+
+   signal config_rdo_disable_i : std_logic;
+   signal config_invert_input_i : std_logic;
+
+   signal rec_counter_i  : unsigned(31 downto 0) := (others => '0');
+   signal act_counter_i : unsigned(31 downto 0) := (others => '0');
+   signal high_counter_i : unsigned(31 downto 0) := (others => '0');
+   
+-- timestamp
+   signal timing_trg_i : std_logic;
+   signal lvl1_trg_i   : std_logic;
+   
+   signal timestamp_i        : unsigned(31 downto 0); -- time since last timing trigger with lvl1 received (200 MHz)
+   signal timestamp_fresh_i  : unsigned(31 downto 0); -- time since last timing trigger (200 MHz)
+   signal lvl1_id_i          : std_logic_vector(23 downto 0); -- TRG-NUM + CODE
+   
+   signal rec_timestamp_i : std_logic_vector(31 downto 0); -- time trg_sync200 was asserted
+   signal rec_lvl1_id_i   : std_logic_vector(23 downto 0); -- lvl1 info for timestamp
+   
+   signal rdo_buf_rec_timestamp_i : std_logic_vector(31 downto 0); -- read-out buffer for the above
+   signal rdo_buf_rec_lvl1_id_i   : std_logic_vector(23 downto 0); -- read-out buffer for the above
 begin
-
--- we tell the CTS that we send one word of over DATA_OUT
-HEADER_REG_OUT <= b"01"; 
-
-reg_MBS_IN <= MBS_IN when rising_edge(CLK_200);
-
-PROC_FIRST_BITS : process begin
-  wait until rising_edge(CLK_200);
-  if bitcnt > 32 and RESET_IN = '0' then
-    first_bits_fast <= '1';
-  else
-    first_bits_fast <= '0';
-  end if;
-end process;
-  
-first_bits_slow <= first_bits_fast when rising_edge(CLK);
-
-trg_async     <= (not MBS_IN or trg_async) when first_bits_fast = '1' else '0';
-trg_sync      <= (not reg_MBS_IN or trg_sync) and first_bits_slow when rising_edge(CLK);
-
-TRG_ASYNC_OUT <= trg_async;
-TRG_SYNC_OUT  <= trg_sync when rising_edge(CLK);
-
-PROC_FSM: process begin
-  wait until rising_edge(CLK_200);
-
-  case state is
-    when IDLE =>
-      bitcnt <= 37;
-      done <= '1';
-      if reg_MBS_IN = '0' then
-        done  <= '0';
-        state <= WAIT1;
-      end if;
-      
-    when WAIT1 =>
-      state <= WAIT2;
-      
-    when WAIT2 =>
-      bitcnt <= bitcnt - 1;
-      shift_reg <= shift_reg(shift_reg'high - 1 downto 0) & reg_MBS_IN;
-      state <= WAIT3;
-      
-    when WAIT3 =>
-      if bitcnt = 0 then
-        state <= FINISH;
+   HEADER_REG_OUT <= b"01"; -- we tell the CTS that we send one word of over DATA_OUT
+   
+   reg_MBS_IN <= MBS_IN xor config_invert_input_i when rising_edge(CLK_200);
+   reg_MBS_DELAY <= reg_MBS_IN when rising_edge(CLK_200);
+
+   PROC_FIRST_BITS : process begin
+   wait until rising_edge(CLK_200);
+   if bitcnt > 32 and RESET_IN = '0' then
+      first_bits_fast <= '1';
+   else
+      first_bits_fast <= '0';
+   end if;
+   end process;
+   
+   first_bits_slow <= first_bits_fast when rising_edge(CLK);
+
+   trg_async     <= (not MBS_IN or trg_async) when first_bits_fast = '1' else '0';
+   trg_sync      <= (not reg_MBS_IN or trg_sync) and first_bits_slow when rising_edge(CLK);
+
+   TRG_ASYNC_OUT <= trg_async;
+   TRG_SYNC_OUT  <= trg_sync when rising_edge(CLK);
+
+   PROC_FSM: process begin
+   wait until rising_edge(CLK_200);
+
+   case state is
+      when IDLE =>
+         bitcnt <= 37;
+         done <= '1';
+         if reg_MBS_IN = '0' then
+         done  <= '0';
+         state <= WAIT1;
+         end if;
+         
+      when WAIT1 =>
+         state <= WAIT2;
+         
+      when WAIT2 =>
+         bitcnt <= bitcnt - 1;
+         shift_reg <= shift_reg(shift_reg'high - 1 downto 0) & reg_MBS_IN;
+         state <= WAIT3;
+         
+      when WAIT3 =>
+         if bitcnt = 0 then
+         state <= FINISH;
+         else
+         state <= WAIT4;
+         end if;
+         
+      when WAIT4 =>
+         state <= WAIT1;
+         
+      when FINISH =>
+         if reg_MBS_IN = '1' then
+         state <= IDLE;
+         end if;
+         done <= '1';
+   end case;
+   if RESET_IN = '1' then
+      state <= IDLE;
+      done <= '0';
+   end if;
+   end process;
+
+   done_slow <= done when rising_edge(CLK);
+
+   PROC_REG_INFO : process begin
+   wait until rising_edge(CLK);
+   if done_slow = '1' then
+      number_reg <= shift_reg(31 downto 8);
+      status_reg <= shift_reg(7 downto 6);
+
+      if shift_reg(36 downto 32) = "01010" and shift_reg(4 downto 0) = "10101" and xor_all(shift_reg(31 downto 5)) = '0' then
+         error_reg <= '0';
       else
-        state <= WAIT4;
+         error_reg <= '1';
       end if;
+   end if;
+   end process;
+
+
+   PROC_RDO : process
+      variable incl_timestamp_v : std_logic;
+   begin
+   wait until rising_edge(CLK);
+   WRITE_OUT     <= '0';
+   FINISHED_OUT  <= config_rdo_disable_i;
+   incl_timestamp_v := '0';
+   case rdostate is
+      when RDO_IDLE =>
+         if TRIGGER_IN = '1' and config_rdo_disable_i = '0' then
+         if done_slow = '0' then
+            rdostate <= RDO_WAIT;
+         else
+            rdostate <= RDO_WRITE;
+         end if;
+         end if;
+      when RDO_WAIT =>
+         if done_slow = '1' then
+         rdostate <= RDO_WRITE;
+         end if;
+         
+      when RDO_WRITE =>
+         if INCL_RDO_TIMESTAMP=c_YES then
+            rdostate <= RDO_TIMESTAMP;
+            incl_timestamp_v := '1';
+         else
+            rdostate <= RDO_FINISH;
+         end if;
+         
+         DATA_OUT <= error_reg & status_reg & "0000" & incl_timestamp_v & number_reg;
+         WRITE_OUT <= '1';
       
-    when WAIT4 =>
-      state <= WAIT1;
+      when RDO_TIMESTAMP =>
+         DATA_OUT <= rdo_buf_rec_timestamp_i;
+         WRITE_OUT <= '1';
+         rdostate <= RDO_LVL1_ID;
+         
+      when RDO_LVL1_ID =>
+         DATA_OUT <= x"00" & rdo_buf_rec_lvl1_id_i;
+         WRITE_OUT <= '1';
+         rdostate <= RDO_FINISH;
       
-    when FINISH =>
-      if reg_MBS_IN = '1' then
-        state <= IDLE;
+      when RDO_FINISH =>
+         FINISHED_OUT <= '1';
+         rdostate     <= RDO_IDLE;
+   end case;
+   end process;
+
+   STATUSBIT_OUT(23) <= error_reg when rising_edge(CLK);
+   STATUS_REG_OUT <= error_reg & MBS_IN & "000000" & number_reg;
+   DEBUG <= x"00000000"; -- & done & '0' & shift_reg(13 downto 0);
+
+   
+   -- when timing trigger arives first we reset a temporary timestamp, that will
+   -- be not used until we know the corresponding lvl1 id ...
+   PROC_TIME_BASE: process is
+      variable timing_trg_delay : std_logic;
+      variable lvl1_trg_delay : std_logic;
+   begin
+      wait until rising_edge(CLK_200);
+
+      timestamp_fresh_i <= timestamp_fresh_i + 1;
+      if timing_trg_i='1' and timing_trg_delay='0' then
+         timestamp_fresh_i <= (others => '0');
       end if;
-      done <= '1';
-  end case;
-  if RESET_IN = '1' then
-    state <= IDLE;
-    done <= '0';
-  end if;
-end process;
-
-done_slow <= done when rising_edge(CLK);
-
-PROC_REG_INFO : process begin
-  wait until rising_edge(CLK);
-  if done_slow = '1' then
-    number_reg <= shift_reg(31 downto 8);
-    status_reg <= shift_reg(7 downto 6);
-
-    if shift_reg(36 downto 32) = "01010" and shift_reg(4 downto 0) = "10101" and xor_all(shift_reg(31 downto 5)) = '0' then
-      error_reg <= '0';
-    else
-      error_reg <= '1';
-    end if;
-  end if;
-end process;
-
-
-PROC_RDO : process begin
-  wait until rising_edge(CLK);
-  WRITE_OUT     <= '0';
-  FINISHED_OUT  <= config_rdo_disable_i;
-  case rdostate is
-    when RDO_IDLE =>
-      if TRIGGER_IN = '1' and config_rdo_disable_i = '0' then
-        if done_slow = '0' then
-          rdostate <= RDO_WAIT;
-        else
-          rdostate <= RDO_WRITE;
-        end if;
+      
+      timestamp_i <= timestamp_i + 1;
+      if lvl1_trg_i='1' and lvl1_trg_delay='0' then
+         timestamp_i <= timestamp_fresh_i + 1;
+         lvl1_id_i <= TRG_CODE_IN & TRG_NUMBER_IN; -- no sync necessary, as signal should be stable until now
       end if;
-    when RDO_WAIT =>
-      if done_slow = '1' then
-        rdostate <= RDO_WRITE;
+      
+      lvl1_trg_delay := lvl1_trg_i;
+      timing_trg_delay := timing_trg_i;
+   end process;
+   
+   
+   PROC_TIMESTAMP_EVENT: process is
+      variable trg_sync200_delay : std_logic;
+      variable lvl1_trg_delay : std_logic;
+   begin
+      wait until rising_edge(CLK_200);
+
+      if trg_sync200='1' and trg_sync200_delay='0' then
+         rec_timestamp_i <= timestamp_i;
+         rec_lvl1_id_i <= lvl1_id_i;
       end if;
-    when RDO_WRITE =>
-      rdostate <= RDO_FINISH;
-      DATA_OUT <= error_reg & status_reg & "00000" & number_reg;
-      WRITE_OUT <= '1';
-    
-    when RDO_FINISH =>
-      FINISHED_OUT <= '1';
-      rdostate     <= RDO_IDLE;
-  end case;
-end process;
-
-config_rdo_disable_i <= CONTROL_REG_IN(0);
-
-STATUSBIT_OUT(23) <= error_reg when rising_edge(CLK);
-STATUS_REG_OUT <= error_reg & "0000000" & number_reg;
-DEBUG <= x"00000000"; -- & done & '0' & shift_reg(13 downto 0);
 
+      if lvl1_trg_i='1' and lvl1_trg_delay='0' then
+         rdo_buf_rec_timestamp_i <= rec_timestamp_i;
+         rdo_buf_rec_lvl1_id_i <= rec_lvl1_id_i;
+      end if;
+      
+      lvl1_trg_delay := lvl1_trg_i;
+      trg_sync200_delay := trg_sync200;
+   end process;
+   
+   -- SYNC EXTERNAL SIGNALS FOR TIMESTAMPING
+   THE_TMG_TRG_SYNC: signal_sync
+   generic map (WIDTH => 1, DEPTH => 3)
+   port map (
+      RESET => RESET_IN,
+      CLK0 => CLK,
+      CLK1 => CLK_200,
+      D_IN(0) =>  TIMING_TRG_IN,
+      D_OUT(0) => timing_trg_i
+   );
+   
+   THE_LVL1_SYNC: signal_sync
+   generic map (WIDTH => 1, DEPTH => 3)
+   port map (
+      RESET => RESET_IN,
+      CLK0 => CLK,
+      CLK1 => CLK_200,
+      D_IN(0) =>  TRIGGER_IN,
+      D_OUT(0) => lvl1_trg_i
+   );
+   
+   THE_REC_SYNC: signal_sync
+   generic map (WIDTH => 1, DEPTH => 3)
+   port map (
+      RESET => RESET_IN,
+      CLK0 => CLK_200,
+      CLK1 => CLK_200,
+      D_IN(0) =>  trg_async,
+      D_OUT(0) => trg_sync200
+   );
+   
+-- REGIO
+   GEN_REGIO: if INCL_REGIO = c_YES generate
+      proc_regio: process is
+         variable addr : integer range 0 to 3;
+      begin
+         wait until rising_edge(CLK);
+         
+         addr := to_integer(UNSIGNED(REGIO_IN.addr(1 downto 0)));
+         REGIO_OUT.rack <= REGIO_IN.read;
+         REGIO_OUT.wack <= REGIO_IN.write;
+         REGIO_OUT.nack <= '0';
+         REGIO_OUT.unknown <= '0';
+         REGIO_OUT.data <= (others => '0');
+         
+         case addr is
+            when 0 => 
+               REGIO_OUT.data(1 downto 0) <= config_invert_input_i & (not config_rdo_disable_i);
+               if INCL_RDO_TIMESTAMP=c_YES then
+                  REGIO_OUT.data(2) <= '1';
+               end if;
+               REGIO_OUT.data(7) <= error_reg;
+               REGIO_OUT.data(31 downto 8) <= number_reg;
+
+            when 1 => 
+               REGIO_OUT.data <= std_logic_vector(rec_counter_i);
+               
+            when 2 =>
+               REGIO_OUT.data <= std_logic_vector(act_counter_i);
+            
+            when 3 =>
+               REGIO_OUT.data <= std_logic_vector(high_counter_i);
+            
+         end case;
+         
+         if REGIO_IN.write='1' then
+            if addr=0 then
+               config_rdo_disable_i <= not REGIO_IN.data(0);
+               config_invert_input_i <= REGIO_IN.data(1);
+            else
+               REGIO_OUT.unknown <= '1';
+            end if;
+         end if;
+         
+         if RESET_IN = '1' then
+            config_rdo_disable_i <= '0';
+            config_invert_input_i <= '0';
+         end if;
+      end process;
+      
+      proc_stats: process is
+         variable this_mbs : std_logic;
+         variable last_mbs : std_logic;
+         variable last_trg_sync : std_logic;
+      begin
+         wait until rising_edge(CLK);
+         
+         this_mbs := reg_MBS_IN or reg_MBS_DELAY;
+         
+         if this_mbs = '1' then
+            high_counter_i <= high_counter_i + 1;
+         end if;
+         
+         if trg_sync = '1' and last_trg_sync='0' then
+            rec_counter_i <= rec_counter_i + 1;
+         end if;
+         
+         if this_mbs /= last_mbs then
+            act_counter_i <= act_counter_i + 1;
+         end if;
+         
+         if RESET_IN='1' then
+            high_counter_i <= (others => '0');
+            rec_counter_i  <= (others => '0');
+            act_counter_i  <= (others => '0');
+         end if;
+         
+         last_trg_sync := trg_sync;
+         last_mbs := this_mbs;
+      end process;
+   end generate;
+
+   GEN_NO_REGIO: if INCL_REGIO /= c_YES generate
+      config_rdo_disable_i <= CONTROL_REG_IN(0);
+      REGIO_OUT.unknown <= REGIO_IN.read or REGIO_IN.write;
+   end generate;
 end architecture;