--******************************************************************************
--* @short   12 bit BX counter with delay for bx reset configurable by VME
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv5.cern.ch>
--* @date    $Date: 2004/12/17 09:30:37 $
--* @version $Revision: 1.4 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_std.all;
-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.all;
-- pragma translate_on


entity BXCounter is
  generic (
    reg_addr                  : integer;   -- address of VME readout reg
    bcreset_delay_reg_default : std_logic_vector(15 downto 0));
  port (
    iBCReset          : in std_logic;   -- from input FF (decoded)

    oPreBCReset       : out std_logic;
    oBCReset          : out std_logic;  -- delayed

    oBXCounter  : out std_logic_vector(11 downto 0);

    -- VME port (for latency delay register)
    vme_addr       : in    std_logic_vector;
    vme_data       : in    std_logic_vector;
    vme_en         : in    std_logic;
    vme_wr         : in    std_logic;

    vme_data_out   : out   std_logic_vector(15 downto 0);
    vme_en_out     : out   std_logic;

    -- Clock, control
    clk            : in    std_logic;
    reset          : in    std_logic
    );  

end entity BXCounter;


architecture behavioral of BXCounter is

  component SRL16
-- synthesis translate_off
    generic (
      INIT: bit_vector:= X"0001");
-- synthesis translate_on
    port (Q : out STD_ULOGIC;
          A0 : in STD_ULOGIC;
          A1 : in STD_ULOGIC;
          A2 : in STD_ULOGIC;
          A3 : in STD_ULOGIC;
          CLK : in STD_ULOGIC;
          D : in STD_ULOGIC);
  end component;

  signal sReadoutSync_Reg : std_logic_vector(15 downto 0);
  signal bcres_delayed : std_logic;
  signal bcres_srl : std_logic;
  signal bcres_d1 : std_logic;
  signal bcres_d2 : std_logic;
  
begin  -- architecture behavioral

  -----------------------------------------------------------------------------
  --  Configuration Registers
  -----------------------------------------------------------------------------
  --
  -- 0   0   0   0  |  0   0   0   0   |  0   0   0   0   |  0   0   0   0
  -- |   |   |   |  |                  |              |   |  bcres delay
  -- |   |   |                                        |
  -- |   |   |                                        +==== use bcres delay
  
  readout_sync_reg: entity work.VMEReg
    generic map (
      init_val            => bcreset_delay_reg_default,
      my_vme_base_address => reg_addr )
    port map (
      data         => sReadoutSync_Reg,        
      reset        => reset,
      
      vme_addr     => vme_addr,
      vme_data     => vme_data,
      vme_en       => vme_en,
      vme_wr       => vme_wr,
      vme_data_out => vme_data_out,
      vme_en_out   => vme_en_out,
      vme_clk      => clk);

  -----------------------------------------------------------------------------
  -- BC reset delay shift register
  -----------------------------------------------------------------------------
  
  bcres_delay_block: SRL16
    port map (
      D   => iBCReset,
      Q   => bcres_srl,
      A0  => sReadoutSync_Reg(0),
      A1  => sReadoutSync_Reg(1),
      A2  => sReadoutSync_Reg(2),
      A3  => sReadoutSync_Reg(3),
      CLK => clk);

  -- do the delay?
  bcres_delayed <= bcres_srl when sReadoutSync_Reg(4) = '1' else iBCReset;

  oPreBCReset <= bcres_delayed;

  -----------------------------------------------------------------------------
  -- additional delays
  -----------------------------------------------------------------------------

  -- oPreBCReset output is for bcresest of simulation RAM counter (if used)
  -- oBCReset output is for bcresest of main BXCounter

  
  delay_more: process (clk, reset) is
  begin  -- process delay_more
    if reset = '1' then
      bcres_d1 <= '0';
      bcres_d2 <= '0';
    elsif clk'event and clk = '1' then  -- rising clock edge
      bcres_d1 <= bcres_delayed;
      bcres_d2 <= bcres_d1;
    end if;
  end process delay_more;

  oBCReset <= bcres_d2;

  -----------------------------------------------------------------------------
  -- main BX counter
  -----------------------------------------------------------------------------
  bx_counter: process (clk, reset) is
    variable counter : std_logic_vector(11 downto 0) := "000000000000";
                            
  begin
    if reset = '1' then
      counter := "000000000000";
      oBXCounter <= "000000000000";
    elsif clk'event and clk = '1' then
      if bcres_d2 = '1' then
        counter := "000000000000";
      else
        counter := std_logic_vector(TO_UNSIGNED(TO_INTEGER(UNSIGNED(counter))+1,12));
      end if;      
    end if;
    oBXCounter <= counter;
  end process bx_counter;

end architecture behavioral;