library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;



entity dds_control is
  -- used in pts to control dds output
  -- it enables changeing singal amplitude 
  -- and selecting between dds singal and constant value
  generic(
    data_len_g          : natural := 16 
    );
  port(

    -- Clocks & resets
    clk_i               : in std_logic;
    rst_n_i             : in std_logic;

    -- 01 means that scaled sine will be outputed
      -- out <= ampl*in
    -- 00 means that will output constant singnal
      -- out <= ampl
    -- 10 means that will output square singnal will be outputed
      -- out <= 999 when ampl > max/2 else 0
    type_i              : in std_logic_vector( 1 downto 0);
    
    -- enable/disable output signal
    output_enable_i    : in std_logic;

    -- ampitude value
    -- ffff = 1, ffff/x =1/x
    amplitude_i        : in std_logic_vector( data_len_g - 1 downto 0 );

    -- dds signal input
    input0_i            : in std_logic_vector( data_len_g - 1 downto 0 );
    input1_i            : in std_logic_vector( data_len_g - 1 downto 0 );
    input2_i            : in std_logic_vector( data_len_g - 1 downto 0 );
    input3_i            : in std_logic_vector( data_len_g - 1 downto 0 );

    -- scaled singal output
    output0_o           : out std_logic_vector( data_len_g - 1 downto 0 );
    output1_o           : out std_logic_vector( data_len_g - 1 downto 0 );
    output2_o           : out std_logic_vector( data_len_g - 1 downto 0 );
    output3_o           : out std_logic_vector( data_len_g - 1 downto 0 )

  );
end dds_control;

architecture arch of dds_control is 
  
  type arr_t is array (0 to 3) of unsigned(data_len_g - 1 downto 0); 

  signal data_arr_i       : arr_t; 
  
  signal data_scaled_r    : arr_t;
  signal data_final_r     : arr_t; 
  
  signal amplitude_r      : unsigned( data_len_g - 1 downto 0 );
  signal type_r           : std_logic_vector( 1 downto 0 );
  signal output_enable_r  : std_logic;

begin

  -- type conversions
  -- array creation (to simplify code)
  data_arr_i( 0 )     <= unsigned( input0_i );
  data_arr_i( 1 )     <= unsigned( input1_i );
  data_arr_i( 2 )     <= unsigned( input2_i );
  data_arr_i( 3 )     <= unsigned( input3_i );


  -- convert to unsigned
  -- makeing shure ampliture is latched with correct clock
  conf_reg_sp : process( clk_i )
  begin
    if rising_edge( clk_i ) then
      amplitude_r   <= unsigned( amplitude_i );
      type_r        <= type_i;
      output_enable_r <= output_enable_i;
    end if;
  end process;

  -- scaleing of sine data
  chanel_mult_gen: for i in 0 to 3 generate
  begin

    mult_sp: process( clk_i )
    begin
      if rising_edge( clk_i ) then
        -- amplitude ffff should give signal value decremented by 1
        -- amplitude ffff/2 sould give singal value divded by 2 decremented by 1
        data_scaled_r( i )    <= resize( shift_right( data_arr_i( i ) * amplitude_r, data_len_g ), data_len_g ) ;

      end if;
    end process;

    mux_sp: process( clk_i )
    begin
      if rising_edge( clk_i ) then
        if output_enable_r = '0' then
          data_final_r(i)        <= ( others => '0' );

        elsif type_r = "10" then
        -- scaling error correction
          data_final_r(i)        <= data_scaled_r(i) + 1;

        elsif type_r = "11" then
          if data_arr_i(i)( data_len_g-1 ) = '1' then
            data_final_r(i)        <= amplitude_r;
          else
            data_final_r(i)        <= (others => '0' );
          end if;
        else
          data_final_r(i)        <= amplitude_r;
        
        end if;
      end if;
    end process;

  end generate;

  -- type conversions
  output0_o <= std_logic_vector( data_final_r(0) );
  output1_o <= std_logic_vector( data_final_r(1) );
  output2_o <= std_logic_vector( data_final_r(2) );
  output3_o <= std_logic_vector( data_final_r(3) );

end arch;