---------------------------------------------------------------------------
-- File           : p_functions.vhd
-- Author(s)      : Nikola Avramovic
-- Created        : March 16th, 2019
---------------------------------------------------------------------------
-- Description    : Global functions
---------------------------------------------------------------------------

---------------------------------------------------------------------------

library ieee, work;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;
   use work.p_commands.all;
   use work.p_parameters_and_constants.all;

package p_functions is

   type TYPE_CMD_GEN_STATE is (IDLE, START, INIT_PATTERN_GEN, INIT_PORT_GEN, -- start and modules states
                           -- pattern states
                           FRAME_NO, FRAME_LEN, FRAME_SEED, RANDOM_DATA, NON_RANDOM_DATA, CRC_EN, SEED_INCREMENT,
                           -- port states
                           SET_FRAG, PRIORITY_INPUT, NO_OF_FARGMENT, PACKET_CRC_EN, FRAME_WAIT_PRIORITY, 
                           FRAME_WAIT_FRAG, PREAMBLE_LENGTH, SFD, SMD_I, SMD_C, TERMINATED, 
                           -- end state
                           END_CMD, NONE);

   type TYPE_CMD_MON_STATE is (IDLE, START, INIT_PATTERN_MON, INIT_PORT_MON, -- start and modules states
                           -- pattern states
                           FRAME_NO, FRAME_LEN, FRAME_SEED, RANDOM_DATA, NON_RANDOM_DATA, CRC_EN, SEED_INCREMENT,
                           SCOREBOARD_EN,
                           -- port states
                           SET_FRAG, PRIORITY_OUTPUT, NO_OF_FARGMENT, PACKET_CRC_EN, PREAMBLE_LENGTH, SFD, SMD_I, 
                           SMD_C, TERMINATED, 
                           -- end state
                           END_CMD, NONE);

   -- convert boolean to std_logic
   pure function boolean_to_stdlogic(b: boolean ) return std_logic;

   -- choose next command
   pure function choose_gen_command(cmd_word : std_logic_vector (C_WORD_LENGTH-1 downto 0)) return  TYPE_CMD_GEN_STATE;

   -- choose wheather command
   -- In this desing is not allowed to use constants which is same as commands 
   pure function choose_mon_command(cmd_word : std_logic_vector(C_WORD_LENGTH-1 downto 0)) return TYPE_CMD_MON_STATE;

   -- add proper constant for frament number
   pure function frag_no_const(frag_no : natural range 0 to C_PREEMPTABLE_NO-1) return std_logic_vector;

   -- add proper constant for preemptable packet start
   pure function smd_i_const(smd_i : natural range 0 to C_PREEMPTABLE_NO-1) return std_logic_vector;

   -- add proper constant for start mframe delimeter continue fragment 
   pure function smd_c_const(smd_c : natural range 0 to C_PREEMPTABLE_NO-1) return std_logic_vector;

end package;

package body p_functions is

   -- convert boolean to std_logic
   pure function boolean_to_stdlogic(b: boolean ) return std_logic is
   begin
      if b then return '1';
      else      return '0';
      end if;
   end function;

   -- choose wheather command
   -- In this desing is not allowed to use constants which is same as commands 
   pure function choose_gen_command(cmd_word : std_logic_vector(C_WORD_LENGTH-1 downto 0)) return TYPE_CMD_GEN_STATE is
   begin

      case cmd_word is
         -- start command
         when C_GEN_CMD_START              => return START;
         -- pattern/port command
         when C_GEN_CMD_INIT_PATTERN_GEN   => return INIT_PATTERN_GEN;
         when C_GEN_CMD_INIT_PORT_GEN      => return INIT_PORT_GEN;
         -- pattern commands
         when C_GEN_CMD_IDLE               => return IDLE;
         when C_GEN_CMD_FRAME_NO           => return FRAME_NO;
         when C_GEN_CMD_FRAME_LENGTH       => return FRAME_LEN;
         when C_GEN_CMD_FRAME_SEED         => return FRAME_SEED;
         when C_GEN_CMD_SEED_INCREMENT     => return SEED_INCREMENT;
         when C_GEN_CMD_RANDOM_DATA        => return RANDOM_DATA;
         when C_GEN_CMD_LINEAR_DATA        => return NON_RANDOM_DATA;
         when C_GEN_CMD_CRC_EN             => return CRC_EN;
         -- port commands
         when C_GEN_CMD_SET_FRAG           => return SET_FRAG;
         when C_GEN_CMD_PRIORITY_INPUT     => return PRIORITY_INPUT;
         when C_GEN_CMD_NO_OF_FARGMENT     => return NO_OF_FARGMENT;
         when C_GEN_CMD_PACKET_CRC_EN      => return PACKET_CRC_EN;
         when C_GEN_CMD_FRAME_WAIT_PRIORITY=> return FRAME_WAIT_PRIORITY;
         when C_GEN_CMD_FRAME_WAIT_FRAG    => return FRAME_WAIT_FRAG;
         when C_GEN_CMD_PREAMBLE_LENGTH    => return PREAMBLE_LENGTH;
         when C_GEN_CMD_SFD                => return SFD;
         when C_GEN_CMD_SMD_I              => return SMD_I;
         when C_GEN_CMD_SMD_C              => return SMD_C;
         when C_GEN_CMD_TERMINATED         => return TERMINATED;
         -- end command
         when C_GEN_CMD_END                => return END_CMD;
         when others                       => return NONE;

      end case;
   end function;


   -- choose wheather command
   -- In this desing is not allowed to use constants which is same as commands 
   pure function choose_mon_command(cmd_word : std_logic_vector(C_WORD_LENGTH-1 downto 0)) return TYPE_CMD_MON_STATE is
   begin

      case cmd_word is
         -- start command
         when C_MON_CMD_START              => return START;
         -- pattern/port command
         when C_MON_CMD_INIT_PATTERN_MON   => return INIT_PATTERN_MON;
         when C_MON_CMD_INIT_PORT_MON      => return INIT_PORT_MON;
         -- pattern commands
         when C_MON_CMD_IDLE               => return IDLE;
         when C_MON_CMD_FRAME_NO           => return FRAME_NO;
         when C_MON_CMD_FRAME_LENGTH       => return FRAME_LEN;
         when C_MON_CMD_FRAME_SEED         => return FRAME_SEED;
         when C_MON_CMD_SEED_INCREMENT     => return SEED_INCREMENT;
         when C_MON_CMD_RANDOM_DATA        => return RANDOM_DATA;
         when C_MON_CMD_LINEAR_DATA        => return NON_RANDOM_DATA;
         when C_MON_CMD_CRC_EN             => return CRC_EN;
         when C_MON_CMD_SCOREBOARD_EN      => return SCOREBOARD_EN;
         -- port commands
         when C_MON_CMD_SET_FRAG           => return SET_FRAG;
         when C_MON_CMD_PRIORITY_OUTPUT    => return PRIORITY_OUTPUT;
         when C_MON_CMD_NO_OF_FARGMENT     => return NO_OF_FARGMENT;
         when C_MON_CMD_PACKET_CRC_EN      => return PACKET_CRC_EN;
         when C_MON_CMD_PREAMBLE_LENGTH    => return PREAMBLE_LENGTH;
         when C_MON_CMD_SFD                => return SFD;
         when C_MON_CMD_SMD_I              => return SMD_I;
         when C_MON_CMD_SMD_C              => return SMD_C;
         when C_MON_CMD_TERMINATED         => return TERMINATED;
         -- end command
         when C_MON_CMD_END                => return END_CMD;
         when others                       => return NONE;

      end case;
   end function;


   -- add proper constant for framen number
   pure function frag_no_const(frag_no : natural range 0 to C_PREEMPTABLE_NO-1) return std_logic_vector is --(C_BYTE_LENGTH-1 downto 0) is
   begin

      case frag_no is
         when 0 => return C_FRAG_NO_0;
         when 1 => return C_FRAG_NO_1;
         when 2 => return C_FRAG_NO_2;
         when 3 => return C_FRAG_NO_3;

      end case;
   end function;


   -- add proper constant for preemptable packet start
   pure function smd_i_const(smd_i : natural range 0 to C_PREEMPTABLE_NO-1) return std_logic_vector is
   begin

      case smd_i is
         when 0 => return C_SMD_S_0;
         when 1 => return C_SMD_S_1;
         when 2 => return C_SMD_S_2;
         when 3 => return C_SMD_S_3;

      end case;
   end function;

   -- add proper constant for start mframe delimeter continue fragment 
   pure function smd_c_const(smd_c : natural range 0 to C_PREEMPTABLE_NO-1) return std_logic_vector is
   begin

      case smd_c is
         when 0 => return C_SMD_C_0;
         when 1 => return C_SMD_C_1;
         when 2 => return C_SMD_C_2;
         when 3 => return C_SMD_C_3;

      end case;
   end function;

end package body;