-------------------------------------------------------------------------------
--
-- Copyright 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Author: Job van Wee
-- Purpose: Folding a stream of data into a mm data configuration so it can be
-- stored in a DDR RAM-stick.
--
-- Description:
--  First the data from the sosi array gets collected into one data vector.
--  After that this data vector gets resized to the right size data vector in 
--  order to make it storable in a DDR RAM-stick.
--  After that a address gets assigned to the data so the data can be found back.
--
-- Remark:
--  Use VHDL coding template from:
--  https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding
--  The maximum value of the address is determend by g_tech_ddr.

LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE technology_lib.technology_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;


ENTITY ddrctrl_output IS
  GENERIC (
    g_tech_ddr        : t_c_tech_ddr;                                   -- type of memory
    g_sim_model       : BOOLEAN       := TRUE;                          -- determens if this is a simulation
    g_in_data_w       : NATURAL       := 576;                           
    g_nof_streams     : NATURAL       := 12;                            -- number of input streams
    g_data_w          : NATURAL       := 14                             -- data with of input data vectors
  );
  PORT (
    clk               : IN  STD_LOGIC := '0';
    rst               : IN  STD_LOGIC;
    in_data           : IN  STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0);   -- input data
    in_of             : IN  NATURAL;                                    -- amount of internal overflow this output
    in_bsn            : IN  STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- bsn corresponding to the data at in_data[in_of]
    out_sosi_arr      : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init) -- output data
  );
END ddrctrl_output;


ARCHITECTURE str OF ddrctrl_output IS

  -- constant for readability
  CONSTANT  c_out_data_w : NATURAL    := g_nof_streams*g_data_w;        -- the input data with for ddrctrl_repack 168

  -- signals for connecting the components
  SIGNAL    sosi                   : t_dp_sosi  := c_dp_sosi_init;

BEGIN

  -- makes one data vector out of all the data from the t_dp_sosi_arr
  u_ddrctrl_output_pack : ENTITY work.ddrctrl_output_unpack
  GENERIC MAP(
    g_tech_ddr        => g_tech_ddr,
    g_in_data_w       => g_in_data_w,
    g_out_data_w      => c_out_data_w
  )
  PORT MAP(
    clk               => clk,
    rst               => rst,
    in_data           => in_data,                                       -- input data
    in_of             => in_of,
    in_bsn            => in_bsn,
    out_sosi          => sosi                                           -- output data
  );

  -- resizes the input data vector so that the output data vector can be stored into the ddr memory
  u_ddrctrl_output_repack : ENTITY work.ddrctrl_output_repack
  GENERIC MAP(
  g_nof_streams       => g_nof_streams,
  g_data_w            => g_data_w
  )
  PORT MAP(
    in_sosi           => sosi,
    out_sosi_arr      => out_sosi_arr
  );

END str;