---------------------------------------------------------------------------
-- File           : ea_patt_gen_mux.vhd
-- Author(s)      : Nikola Avramovic
-- Created        : March 16th, 2019
---------------------------------------------------------------------------
-- Description    : Pattern multiplexer
---------------------------------------------------------------------------

---------------------------------------------------------------------------
library ieee; 
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;
   use work.p_parameters_and_constants.all;
   use work.p_patt_gen_interface.all;
   use work.PCK_CRC32_D8.all;

entity ea_patt_gen_mux is 
   port( clk             : in  std_logic;
         reset           : in  std_logic;
         -- from control pattern
         control_patti   : in  TYPE_CTRL_PATTERN_TO_PATTERN_MUX;
         control_patto   : out TYPE_PATTERN_MUX_TO_CTRL_PATTERN;
         -- from lfsr genertor
         lfsri           : in  TYPE_LFSR_GEN_TO_PATTERN_MUX;
         -- from linear generator
         lineari         : in  TYPE_LINEAR_GEN_TO_PATTERN_MUX;
         -- to fifo avalon stream
         fifo_avalon_sto : out TYPE_PATT_MUX_TO_FIFO_AVALON
   );
end ea_patt_gen_mux;

architecture rtl of ea_patt_gen_mux is  

   type TYPE_STATE is (IDLE, SENDING, LAST_BYTE);
   
   type TYPE_REGS is record
      req              : boolean;
      mux_error        : boolean;
      sending_crc32    : boolean;
      start_of_packet  : boolean;
      end_of_packet    : boolean;
      crc_count        : natural;
      data8            : std_logic_vector(C_AVALON_ST_DATA_WIDTH-1 downto 0);
      data_crc32       : std_logic_vector(C_CRC32_DATA_WIDTH-1 downto 0);
   end record;
   
   constant CONST_REGS_RESET : TYPE_REGS := (
      req              => false,
      mux_error        => false,
      sending_crc32    => false,
      start_of_packet  => false,
      end_of_packet    => false,
      crc_count        => 0,
      data8            => (others => '0'),
      data_crc32       => (others => '0')
   ); 
   
   signal r            : TYPE_REGS := CONST_REGS_RESET;

--TODO: add logic which will check error states; BIST for MUX 

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;
         s.req                    := false;

         case control_patti.mux_sel is
 
            when LFSR_DATA =>
               s.data8            := lfsri.rand_data;
               s.sending_crc32    := false;
               s.crc_count        := 0;
               s.req              := lfsri.req;
               s.start_of_packet  := lfsri.first_byte;

            when INCREMENT_DATA =>
               s.data8            := lineari.data;
               s.sending_crc32    := false;
               s.crc_count        := 0;
               s.start_of_packet  := lineari.first_byte;
               s.req              := lineari.req;

            when CRC32_DATA  =>
               s.sending_crc32    := true;
               s.crc_count        := r.crc_count + 1;
               s.end_of_packet    := false;
               s.req              := true;
               
               if r.crc_count <= C_CRC32_NO_OF_BYTS then
                  s.data8         := s.data_crc32(r.crc_count*C_AVALON_ST_DATA_WIDTH+C_AVALON_ST_DATA_WIDTH-1 downto r.crc_count*C_AVALON_ST_DATA_WIDTH);

                  if r.crc_count = C_CRC32_NO_OF_BYTS then
                     s.end_of_packet := true;

                  end if;

               else
                  s.sending_crc32 := false;
                  s.req           := false;

               end if;

            when others  =>
               NULL;

         end case;

         -- count crc32
         s.data_crc32             := nextCRC32_D8(r.data8, r.data_crc32);


         -- Assign the register record -------------------------------------------
         r                     <= s;
      end if;  
   end process;

   fifo_avalon_sto <= (req             => r.req,
                       start_of_packet => r.start_of_packet,
                       end_of_packet   => r.end_of_packet,
                       data            => r.data8);
   
   control_patto   <= (busy            => r.sending_crc32);

end architecture rtl;      