---------------------------------------------------------------------------
-- File           : ea_control_port_mon.vhd
-- Author(s)      : Nikola Avramovic
-- Created        : April 16th, 2019
---------------------------------------------------------------------------
-- Description    : This module is used to write commands into proper register
---------------------------------------------------------------------------
--
-- Commands for this module:- PRIORITY_OUTPUT
--                          - SET_FRAG       
--                          - NO_OF_FARGMENT 
--                          - PACKET_CRC_EN  
--                          - PREAMBLE_LENGTH
--                          - SFD            
--                          - SMD_I          
--                          - SMD_C          
--                          - TERMINATED     
---------------------------------------------------------------------------

library ieee; 
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;
   use work.p_parameters_and_constants.all;
   use work.p_monitor_interface.all;
   use work.p_port_mon_interface.all;

entity ea_control_port_mon is 
   generic(
      G_PORT_MON_NO    : natural
      );
   port (clk           : in std_logic;
         reset         : in std_logic;
         -- to/from input command module
         cmd_decoderi  : in  TYPE_CMD_DECODER_TO_PORT_MON;
         cmd_decodero  : out TYPE_PORT_MON_TO_CMD_DECODER;
         -- to/from fragmentation multiplexer
         cami          : in  TYPE_CAM_TO_CONTROL_PORT;
         camo          : out TYPE_CONTROL_PORT_TO_CAM;
         -- to ethernet output
         header_checki : in  TYPE_HEADER_CHECK_TO_CONTROL_PORT;
         header_checko : out TYPE_CONTROL_PORT_TO_HEADER_CHECK;
         -- to status object
         statusi       : in  TYPE_STATUS_TO_PORT_MON;
         statuso       : out TYPE_PORT_MON_TO_STATUS

   );
end ea_control_port_mon;


architecture rtl of ea_control_port_mon is  
 
   type TYPE_REGS is record   
      busy                 : boolean;
      ready                : boolean;
      init_port            : natural;
      set_frag             : boolean;
      priority_output      : natural;
      no_of_fragment       : natural;
      packet_crc_en        : boolean;
      preamble_length      : natural;
      terminated           : std_logic_vector(C_BYTE_LENGTH-1 downto 0);
      sfd                  : std_logic_vector(C_BYTE_LENGTH-1 downto 0);
      smd_i                : std_logic_vector(C_BYTE_LENGTH-1 downto 0);
      smd_c                : std_logic_vector(C_BYTE_LENGTH-1 downto 0);
   end record;
   
   constant CONST_REGS_RESET : TYPE_REGS := (
      busy                 => false,
      ready                => false,
      init_port            => 0,
      set_frag             => true,
      priority_output      => 0,
      no_of_fragment       => 0,
      packet_crc_en        => true, 
      preamble_length      => 7,
      terminated           => X"FD",
      sfd                  => X"AB",
      smd_i                => X"E7",
      smd_c                => X"E6"
   ); 
   
   signal r :        TYPE_REGS := CONST_REGS_RESET;
   
begin
   sync: process (reset, clk) 
      variable s        : TYPE_REGS;
   begin
      if reset = '1' then
         r                         <= CONST_REGS_RESET;

      elsif rising_edge(clk) then
         -- initialize the variables
         s                         := r;

         if cmd_decoderi.init_port = G_PORT_MON_NO then
            --s.busy                 := true;
            s.ready                := true;
            s.set_frag             := cmd_decoderi.set_frag;
            s.priority_output      := cmd_decoderi.priority_output;
            s.no_of_fragment       := cmd_decoderi.no_of_fragment;
            s.packet_crc_en        := cmd_decoderi.packet_crc_en;
            s.preamble_length      := cmd_decoderi.preamble_length;
            s.sfd                  := cmd_decoderi.sfd;
            s.smd_i                := cmd_decoderi.smd_i;
            s.smd_c                := cmd_decoderi.smd_c;
            s.terminated           := cmd_decoderi.terminated;
         else
            --s.busy                 := false;
            s.ready                := false;

         end if;

         -- Assign the register record -------------------------------------------
         r                         <= s;

      end if;  
   end process;

   cmd_decodero <= (busy           => r.busy);

   camo                        <= (ready                     => r.ready,
                                   priority_output           => r.priority_output,
                                   sfd                       => r.sfd,
                                   packet_crc_en             => r.packet_crc_en,
                                   terminated                => r.terminated,
                                   no_of_fragment            => r.no_of_fragment);
                  
   header_checko               <= (ready                     => r.ready,
                                   preamble_length           => r.preamble_length,
                                   sfd                       => r.sfd,
                                   no_of_fragment            => r.no_of_fragment,
                                   corr_crc_pck_read         => statusi.corr_crc_pck_read,
                                   smd_i_read                => statusi.smd_i_read,
                                   smd_c_read                => statusi.smd_c_read,
                                   crc_packet_read           => statusi.crc_packet_read,
                                   frag_no_read              => statusi.frag_no_read,
                                   preamble_length_read      => statusi.preamble_length_read);

   statuso                     <= (-- errors per frame
                                   idle_error                => header_checki.idle_error,
                                   preamble_error            => header_checki.preamble_error,
                                   sfd_error                 => header_checki.sfd_error,
                                   -- errors per frame
                                   correct_crc_pck_counter   => header_checki.correct_crc_pck_counter,
                                   smd_i_err_count           => header_checki.smd_i_err_count,
                                   smd_c_err_count           => header_checki.smd_c_err_count,
                                   crc_packet_err_count      => header_checki.crc_packet_err_count,
                                   frag_no_err_count         => header_checki.frag_no_err_count,
                                   preamble_length_err_count => header_checki.preamble_length_err_count,
                                   -- fatal errors for this module
                                   patt_not_ready            => cami.patt_not_ready,
                                   cam_error                 => cami.cam_error);



end architecture rtl;