----------------------------------------------------------------------------------
--
-- Copyright CERN 2011.
-- 
-- This documentation describes Open Hardware and is licensed under the
-- CERN OHL v. 1.1.
--
-- You may redistribute and modify this documentation under the terms of the CERN
-- OHL v.1.1. (http://ohwr.org/cernohl).
--
-- This documentation is distributed WITHOUT
-- ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY
-- QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL v.1.1 for
-- applicable conditions.
--
----------------------------------------------------------------------------------
--
-- Company:        CERN, BE-CO-HT 
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    11:03:11 06/19/2012 
-- Design Name:     
-- Module Name:    trigger_pkg - Behavioral 
-- Project Name:   CTDAH/SVEC
-- Target Devices: Spartan 6
-- Tool versions:  Xilinx ISE 13.4
-- Description:    Package providing all the register configurations for the
--                  SPI core.
--
-- Dependencies: 
--
-- Revision: 0.1
--   0.01          + File Created
--   0.1           - Alpha version. Able to write and output data correctly at
--                   different configurations.
-- Additional Comments: 
--
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;

package trigger_pkg is

   -------------------------------------
   -- Clocking for deglitch and pulse length                          
   -------------------------------------
   --! System clock @ 20MHz, hence 50 ns
   constant c_CLOCK_PERIOD          : NATURAL := 50;
   constant c_MAX_GLITCH_STAGES     : INTEGER := 6;
   constant c_DEFAULT_GLITCH_MASK   : UNSIGNED(c_MAX_GLITCH_STAGES-1 downto 0)
   --! Every pulse below this threshold will be notified
   constant c_MIN_PULSE_LENGTH      : NATURAL :=  600/c_CLOCK_PERIOD;
   constant c_DEFAULT_PULSE_LENGTH  : NATURAL := 1000/c_CLOCK_PERIOD;
   --! Every pulse above this threshold will be notified
   constant c_MAX_PULSE_LENGTH      : NATURAL := 1400/c_CLOCK_PERIOD;

   constant c_LED_PERIOD            : NATURAL := 500000000/c_CLOCK_PERIOD;


   -------------------------------------
   -- Timetagging RAM parameters
   -------------------------------------
   constant c_RAM_ADDR_BITS         : INTEGER := 8;      --! Upto 256 pulses
                                                         --! per channel
   constant c_RAMTT_DATA_WIDTH      : INTEGER := 96/8;   --! In bytes  
   constant c_RAMID_DATA_WIDTH      : INTEGER := 32/8;   --! In bytes 

   attribute a_length : NATURAL;

  -------------------------------------
  -- CTR0 register
  -------------------------------------
  -- 32 bits
  -- Wishbone access: Read-write
  ------------------------------------
  -- BIT       NAME      Description
  --  0         EN        General ENable
  --  1         AH        Active High pulse (otherwise is low) 
  --  2         EN_TT     ENable Time-Tagging
  --  3         CLR_TT    CLeaR Time-Tagging
  --  4         EMPTY     RAM empty flag
  --  5         FULL      RAM full flag
  --  6         WA        RAM wrapped around
  --  8-7       RDM       time-tagging ReaD Mode
  --  15-9      CGM       Current Glitch Mask
  --  31-16     CPL       Current output Pulse Length
  -------------------------------------
  type r_CTR0 is
    record
       EN      : STD_LOGIC;  
       AH      : STD_LOGIC;  
       EN_TT   : STD_LOGIC;  
       CLR_TT  : STD_LOGIC; 
       EMPTY   : STD_LOGIC; 
       FULL    : STD_LOGIC; 
       WA      : STD_LOGIC; 
       RDM     : STD_LOGIC_VECTOR (8  downto 7);
       CGM     : STD_LOGIC_VECTOR (15 downto 9);
       CPL     : STD_LOGIC_VECTOR (31 downto 16);
    end record;

  attribute a_length of r_CTR0 : type is 32;

  -------------------------------------
  -- CTR1 register
  -------------------------------------
  -- 32 bits
  -- Wishbone access: Read-write
  -------------------------------------
  -- BIT       NAME      Description
  --  15-0      MinPL     Minimum input Pulse Length Threshold 
  --  31-16     MaxPL     Maximum input Pulse Length Threshold 
  -------------------------------------
  type r_CTR1 is
    record
       MinPL  : UNSIGNED (15 downto 0);
       MaxPL  : UNSIGNED (31 downto 16);
    end record;

  attribute a_length of r_CTR1 : type is 32;

  -------------------------------------
  -- CTR2 register
  -------------------------------------
  -- 24 bits
  -- Wishbone access: Read-write
  -------------------------------------
  -- BIT       NAME      Description
  --  15-0      PET       input Pulse Elapsed Time 
  --  16        SPF       Short Pulse Flag 
  --  17        LPF       Long  Pulse Flag
  --  18        EPF       End   Pulse Flag
  --  23-19     x         Reserved
  -------------------------------------
  type r_CTR2 is
     record
        PET   : UNSIGNED (15 downto 0);
        SPF   : STD_LOGIC; 
        LPF   : STD_LOGIC; 
        EPF   : STD_LOGIC;
        x     : STD_LOGIC_VECTOR(23 downto 19);
     end record;

  attribute a_length of r_CTR2 : type is 24;
  -------------------------------------
  -- RAM0 register
  -------------------------------------
  -- 8 bits
  -- Wishbone access: Read-write
  -------------------------------------
  -- BIT       NAME      Description
  --  0         WER       Write Enable into RAM
  --  2-1       RDM       time-tagging ReaD Mode
  --  3         RQT       ReQuesT read
  --- 7-4       x         Reserved
  -------------------------------------
  type r_RAM0 is
    record
       WER    : STD_LOGIC;
       RDM    : STD_LOGIC_VECTOR(2 downto 1);
       RQT    : STD_LOGIC;
       x      : STD_LOGIC_VECTOR(7 downto 4);
    end record;

  attribute a_length of r_RAM0 : type is 8;

  -------------------------------------
  -- RAM1 register
  -------------------------------------
  -- 32 bits
  -- Wishbone access: Read-only
  -------------------------------------
  -- BIT       NAME      Description
  --  15-0      CRA        Current Read Address   
  --  31-16     CWA        Current Write Address
  -------------------------------------
  type r_RAM1 is
    record
       CRA : UNSIGNED(15 downto  0); 
       CWA : UNSIGNED(31 downto 16); 
    end record;

  attribute a_length of r_RAM1 : type is 32;

  -------------------------------------
  -- RAM2 register
  -------------------------------------
  -- 32 bits
  -- Wishbone access: Read-write
  -------------------------------------
  -- BIT       NAME      Description
  --  15-0      SA        Starting read Address        
  --  31-16     EA        Ending read Address
  -------------------------------------
  type r_RAM2 is
    record
       SA : STD_LOGIC_VECTOR(15 downto 0);
       EA : STD_LOGIC_VECTOR(31 downto 16); 
    end record;

  attribute a_length of r_RAM2 : type is 32;


  constant c_CTR0_default  : r_CTR0 := (
                               EN     => '1', 
                               CLR    => '1', 
                               EN_TT  => '1', 
                               CLR_TT => '1', 
                               EMPTY  => '1', 
                               FULL   => '0', 
                               WA     => '0',
                               RDM    => (others => '0'),
                               CGM    => (others => '1'),
           -- TIP: the lenght of the repeated pulse must be 1us by default.
           --      Considering that wb period is 50 ns (20 MHz) a value of
           --      30 jiffies should be set by default.
                               CPL    => STD_LOGIC_VECTOR(TO_UNSIGNED(
                                           c_DEFAULT_PULSE_LENGTH, 16)));

  constant c_CTR1_default  : r_CTR1 := (
                           MinPL => to_unsigned(c_MIN_PULSE_LENGTH, 16), 
                           MaxPL => to_unsigned(c_MAX_PULSE_LENGTH, 16));

  constant c_CTR2_default  : r_CTR2 := (PET => (others => '0'), 
                                        SPF => '0', 
                                        LPF => '0', 
                                        EPF => '0', 
                                        x   => (others => '0'));

  constant c_RAM0_default  : r_RAM0 := (RDM => (others => '0'),
                                        RQT => '0');

  constant c_RAM1_default  : r_RAM1 := (CRA => to_unsigned(0, 16),
                                        CWA => to_unsigned(0, 16));

  constant c_RAM2_default  : r_RAM2 := (SA => (others => '0'),
                                        EA => (others => '0'));


  -------------------------------------
  -- Memory mapping
  -------------------------------------
  constant CTR0_addr    : STD_LOGIC_VECTOR (2 downto 0) := "001"; 
  constant CTR1_addr    : STD_LOGIC_VECTOR (2 downto 0) := "010";
  constant CTR2_addr    : STD_LOGIC_VECTOR (2 downto 0) := "011";
  constant RAM0_addr    : STD_LOGIC_VECTOR (2 downto 0) := "101";
  constant RAM1_addr    : STD_LOGIC_VECTOR (2 downto 0) := "110";
  constant RAM2_addr    : STD_LOGIC_VECTOR (2 downto 0) := "111";


  function f_CTR0  (
              r_register_slv: STD_LOGIC_VECTOR(r_CTR0'a_length   - 1 downto 0))
                                                                 return r_CTR0;
  function f_CTR1  (
              r_register_slv: STD_LOGIC_VECTOR(r_CTR1'a_length   - 1 downto 0))
                                                                 return r_CTR1;
  function f_CTR2  (
              r_register_slv: STD_LOGIC_VECTOR(r_CTR1'a_length   - 1 downto 0))
                                                                 return r_CTR2;
  function f_RAM0  (
              r_register_slv: STD_LOGIC_VECTOR(r_RAM0'a_length   - 1 downto 0))
                                                                 return r_RAM0;
  function f_RAM1  (
              r_register_slv: STD_LOGIC_VECTOR(r_RAM1'a_length   - 1 downto 0))
                                                                 return r_RAM1;
  function f_RAM2  (
              r_register_slv: STD_LOGIC_VECTOR(r_RAM2'a_length   - 1 downto 0))
                                                                 return r_RAM2;

  function f_STD_LOGIC_VECTOR(r_register : r_CTR0) return STD_LOGIC_VECTOR;
  function f_STD_LOGIC_VECTOR(r_register : r_CTR1) return STD_LOGIC_VECTOR;
  function f_STD_LOGIC_VECTOR(r_register : r_CTR2) return STD_LOGIC_VECTOR;
  function f_STD_LOGIC_VECTOR(r_register : r_RAM0) return STD_LOGIC_VECTOR;
  function f_STD_LOGIC_VECTOR(r_register : r_RAM1) return STD_LOGIC_VECTOR;
  function f_STD_LOGIC_VECTOR(r_register : r_RAM2) return STD_LOGIC_VECTOR;


   component trigger_core is
      port (
              pulse_i    : in  STD_LOGIC;
              pulse_o    : out STD_LOGIC;

              led_o      : out STD_LOGIC;

              wb_clk_i   : in  STD_LOGIC;
              wb_rst_i   : in  STD_LOGIC;

              write_tt_o : out STD_LOGIC;

              CTR0_i     : in  r_CTR0;
              CTR1_i     : in  r_CTR1;
              CTR2_o     : out r_CTR2
           );
   end component;
end trigger_pkg;

package body trigger_pkg is



  function f_CTR0  (
              r_register_slv: STD_LOGIC_VECTOR(r_CTR0'a_length   - 1 downto 0))
                                                               return r_CTR0 is
     variable v_CTR0  : r_CTR0;
  begin
     v_CTR0.EN     := r_register_slv(0);
     v_CTR0.AH     := r_register_slv(1);
     v_CTR0.EN_TT  := r_register_slv(2);
     v_CTR0.CLR_TT := r_register_slv(3);
     v_CTR0.EMPTY  := r_register_slv(4);
     v_CTR0.FULL   := r_register_slv(5);
     v_CTR0.WA     := r_register_slv(6);
     v_CTR0.RDM    := r_register_slv(8 downto  7);
     v_CTR0.CGM    := r_register_slv(r_CTR0'a_length - 1 downto 9);
  end functiCPL   on f_CTR0;


  function f_CTR1  (
              r_register_slv: STD_LOGIC_VECTOR(r_CTR1'a_length   - 1 downto 0))
                                                               return r_CTR1 is
     variable v_CTR1  : r_CTR1;
  begin
     v_CTR1.MinPL := UNSIGNED(r_register_slv(15 downto 0));
     v_CTR1.MaxPL := UNSIGNED(r_register_slv(r_CTR1'a_length - 1 downto 16));
  end function f_CTR1;


  function f_CTR2  (
              r_register_slv: STD_LOGIC_VECTOR(r_CTR1'a_length   - 1 downto 0))
                                                               return r_CTR2 is
     variable v_CTR2  : r_CTR2;
  begin
     v_CTR2.PET := UNSIGNED(r_register_slv(15 downto 0));
     v_CTR2.SPF := r_register_slv(16);
     v_CTR2.LPF := r_register_slv(17);
     v_CTR2.EPF := r_register_slv(18);
     v_CTR2.x   := r_register_slv(r_CTR2'a_length - 1 downto 19);
  end function f_CTR2;


  function f_RAM0  (
              r_register_slv: STD_LOGIC_VECTOR(r_RAM0'a_length   - 1 downto 0))
                                                               return r_RAM0 is
     variable v_RAM0  : r_RAM0;
  begin
     v_RAM0.WER := r_register_slv(0)
     v_RAM0.RDM := r_register_slv(2 downto 1);
     v_RAM0.RQT := r_register_slv(3);
     v_RAM0.x   := r_register_slv(r_RAM0'a_length - 1 downto 4);
  end function f_RAM0;


  function f_RAM1  (
              r_register_slv: STD_LOGIC_VECTOR(r_RAM1'a_length   - 1 downto 0))
                                                               return r_RAM1 is
     variable v_RAM1  : r_RAM1;
  begin
     v_RAM1.CRA := UNSIGNED(r_register_slv(15 downto 0));
     v_RAM1.CWA := UNSIGNED(r_register_slv(r_RAM1'a_length - 1 downto 16));
  end function f_RAM1;


  function f_RAM2  (
              r_register_slv: STD_LOGIC_VECTOR(r_RAM2'a_length   - 1 downto 0))
                                                               return r_RAM2 is
     variable v_RAM2  : r_RAM2;
  begin
     v_RAM2.SA := r_register_slv(15 downto  0);
     v_RAM2.EA := r_register_slv(r_RAM2'a_length - 1 downto 16);
  end function f_RAM2;




   function f_STD_LOGIC_VECTOR(r_register : r_CTR0) return STD_LOGIC_VECTOR is
      variable v_return  : STD_LOGIC_VECTOR(r_CTR0'a_length - 1 downto 0);
   begin
       v_return(0)            := r_register.EN;
       v_return(1)            := r_register.AH;
       v_return(2)            := r_register.EN_TT;
       v_return(3)            := r_register.CLR_TT;
       v_return(4)            := r_register.EMPTY;
       v_return(5)            := r_register.FULL;
       v_return(6)            := r_register.WA;
       v_return(8  downto 7)  := r_register.RDM;
       v_return(15 downto 9)  := r_register.CGM;
       v_return(31 downto 16) := r_register.CPL;
       return v_return;
   end function f_STD_LOGIC_VECTOR;


   function f_STD_LOGIC_VECTOR(r_register : r_CTR1) return STD_LOGIC_VECTOR is
      variable v_return  : STD_LOGIC_VECTOR(r_CTR1'a_length - 1 downto 0);
   begin
      v_return(15 downto 0) := STD_LOGIC_VECTOR(r_register.MinPL); 
      v_return(r_CTR1'a_length - 1 downto 16)
                            := STD_LOGIC_VECTOR(r_register.MaxPL); 
      return v_return;
   end function f_STD_LOGIC_VECTOR;


   function f_STD_LOGIC_VECTOR(r_register : r_CTR2) return STD_LOGIC_VECTOR is
      variable v_return  : STD_LOGIC_VECTOR(r_CTR2'a_length - 1 downto 0);
   begin
      v_return(15 downto 0)                   := STD_LOGIC_VECTOR(r_register.PET);
      v_return(16)                            := r_register.SPF;
      v_return(17)                            := r_register.LPF;
      v_return(18)                            := r_register.EPF;
      v_return(r_CTR2'a_length - 1 downto 19) := r_register.x;
      return v_return;
   end function f_STD_LOGIC_VECTOR;


   function f_STD_LOGIC_VECTOR(r_register : r_RAM0) return STD_LOGIC_VECTOR is
      variable v_return  : STD_LOGIC_VECTOR(r_RAM0'a_length - 1 downto 0);
   begin
      v_return(0)                             := r_register.WER;
      v_return(2 downto 1)                    := r_register.RDM;
      v_return(3)                             := r_register.RQT;
      v_return(r_RAM0'a_length - 1  downto 4) := r_register.x;
      return v_return;
   end function f_STD_LOGIC_VECTOR;


   function f_STD_LOGIC_VECTOR(r_register : r_RAM1) return STD_LOGIC_VECTOR is
      variable v_return  : STD_LOGIC_VECTOR(r_RAM1'a_length - 1 downto 0);
   begin
      v_return(15 downto 0)                   := r_register.CRA;
      v_return(r_RAM1'a_length - 1 downto 16) := r_register.CWA;
      return v_return;
   end function f_STD_LOGIC_VECTOR;


   function f_STD_LOGIC_VECTOR(r_register : r_RAM2) return STD_LOGIC_VECTOR is
      variable v_return  : STD_LOGIC_VECTOR(r_RAM2'a_length - 1 downto 0);
   begin
      v_return(15 downto 0)                   := r_register.SA;
      v_return(r_RAM2'a_length - 1 downto 16) := r_register.EA;
      return v_return;
   end function f_STD_LOGIC_VECTOR;


end trigger_pkg;
