Skip to content
Snippets Groups Projects
Select Git revision
  • 855c682d56cadfd8d1e8b260b9c05d500cdcde86
  • master default protected
  • L2SDP-1131
  • L2SDP-LIFT
  • L2SDP-1137
  • HPR-158
6 results

reorder_transpose.vhd

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    reorder_transpose.vhd 20.16 KiB
    --------------------------------------------------------------------------------
    --
    -- Copyright (C) 2011
    -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
    -- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
    -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
    --
    -- This program is free software: you can redistribute it and/or modify
    -- it under the terms of the GNU General Public License as published by
    -- the Free Software Foundation, either version 3 of the License, or
    -- (at your option) any later version.
    --
    -- This program is distributed in the hope that it will be useful,
    -- but WITHOUT ANY WARRANTY; without even the implied warranty of
    -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    -- GNU General Public License for more details.
    --
    -- You should have received a copy of the GNU General Public License
    -- along with this program.  If not, see <http://www.gnu.org/licenses/>.
    --
    --------------------------------------------------------------------------------
    
    -- Purpose: Performing a transpose (reordering data) on one or more streaming 
    --          inputs using external memory.
    --
    -- Description:
    --   The input of multiple streams (g_nof_streams) is concatenated into a 
    --   single stream. Either the data field or the complex fields can be 
    --   used, based on the g_use_complex generic.
    -- 
    --   Data on this single stream is than transposed according to the settings 
    --   of g_frame_size_in and g_reorder_seq. 
    --   The actual transpose is divided in two stages. The first stage (pre_transpose) 
    --   is done using a subband select module (reorder_col in RadioHDL).
    --   The second stage is done in external memory (DDR3, DDR4,...). 
    --  
    --   Stage 1: Pre Transpose 
    --   This stage is used to reorder data with a resolution as high as a single 
    --   sample, because the second stage (if using DDR3 for instance) has a resolution
    --   of 16 or more samples. The ss_ss_transp mm interface can be used to specify
    --   the desired reordering for the pre transpose. 
    --
    --   Stage 2: Reorder Sequencer
    --   After the pre transpose the data is send to the external memory 
    --   interface (to_mem_src_out). The reorder sequencer module provides the address
    --   and control signals for the external memory. Writing and reading is done in a 
    --   alternating way. Data from the external memory is received via the 
    --   from_mem_snk_in interface. The sequencers rhythm is based on the settings of 
    --   the g_reorder_seq generic.  
    -- 
    --   At the output the data from the single stream is split up in the original 
    --   g_nof_streams again. A block_gen module is used to generate the SYNC, SOP and EOP 
    --   signals. 
    --  
    --   SYNC and BSN
    --   At the input the BSN number at every SYNC is written to a fifo. This BSN number
    --   is inserted in the output data again when a SYNC is applied at the output. 
    -- 
    --   SYNC Period
    --   The SYNC period (the number of blocks per sync interval) is monitored with a counter.
    --   In case the number of blocks within a syncperiod is not equal to the specified 
    --   g_reorder_seq.nof_blocks the sequencer will reset and start again when the number of 
    --   received blocksdoes match the g_reorder_seq.nof_blocks. 
    --
    --   Complex or real data:
    --   The the width of snk_in.data, re, im is g_in_dat_w. When g_use_complex = FALSE then
    --   snk_in.data is passed on internally, so then the internal sosi.data width is also
    --   g_in_dat_w. When g_use_complex = TRUE then snk_in.im and snk_in.re are concatenated
    --   into an internal sosi.data that has then width 2*g_in_dat_w. The g_nof_streams are
    --   also concatenated into the sosi.data.
    --   . g_use_complex = FALSE : sosi.data =  data[g_nof_streams-1] & ... &  data[1] &  data[0]
    --   . g_use_complex =  TRUE : sosi.data = im&re[g_nof_streams-1] & ... & im&re[1] & im&re[0]
    --   Hence:
    --   . g_use_complex = FALSE : c_data_w = g_nof_streams*g_in_dat_w
    --   . g_use_complex =  TRUE : c_data_w = g_nof_streams*g_in_dat_w*c_nof_complex
    -- Remarks:
    
    LIBRARY IEEE, common_lib, technology_lib, dp_lib;                   
    USE IEEE.STD_LOGIC_1164.ALL;    
    USE IEEE.numeric_std.ALL;
    USE common_lib.common_pkg.ALL;
    USE common_lib.common_mem_pkg.ALL;
    USE dp_lib.dp_stream_pkg.ALL;
    USE work.reorder_pkg.ALL;
    USE technology_lib.technology_select_pkg.ALL;
    
    ENTITY reorder_transpose IS
      GENERIC(
        g_technology     : NATURAL := c_tech_select_default;
        g_nof_streams    : NATURAL := 4;
        g_in_dat_w       : NATURAL := 8;
        g_frame_size_in  : NATURAL := 256;
        g_frame_size_out : NATURAL := 256;
        g_use_complex    : BOOLEAN := TRUE;
        g_mem_dat_w      : NATURAL := 256;       -- The data width to the attached memory. 
        g_ena_pre_transp : BOOLEAN := TRUE;
        g_reorder_seq    : t_reorder_seq := c_reorder_seq;
        g_select_file    : STRING := "UNUSED"
      );                      
      PORT (
        mm_rst                   : IN  STD_LOGIC;  -- reset synchronous with mm_clk
        mm_clk                   : IN  STD_LOGIC;  -- memory-mapped bus clock                       
        dp_clk                   : IN  STD_LOGIC;
        dp_rst                   : IN  STD_LOGIC;
                                 
        -- ST sinks              
        snk_out_arr              : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
        snk_in_arr               : IN  t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
        -- ST source             
        src_in_arr               : IN  t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
        src_out_arr              : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
        
        -- Memory Mapped                                           
        ram_ss_ss_transp_mosi    : IN  t_mem_mosi;  -- channel select control
        ram_ss_ss_transp_miso    : OUT t_mem_miso;  
        reg_dp_sync_checker_mosi : IN  t_mem_mosi;                                              
        reg_dp_sync_checker_miso : OUT t_mem_miso;                  
    
        -- Control interface to the external memory
        dvr_miso                 : IN  t_mem_ctlr_miso;   
        dvr_mosi                 : OUT t_mem_ctlr_mosi;   
        
        -- Data interface to the external memory
        to_mem_src_out           : OUT t_dp_sosi;        
        to_mem_src_in            : IN  t_dp_siso;
                                 
        from_mem_snk_in          : IN  t_dp_sosi;
        from_mem_snk_out         : OUT t_dp_siso := c_dp_siso_rdy
       );
    END reorder_transpose;
    
    
    ARCHITECTURE str OF reorder_transpose IS  
      
      CONSTANT c_blocksize        : POSITIVE := g_reorder_seq.wr_chunksize + g_reorder_seq.gapsize;
      CONSTANT c_pagesize         : POSITIVE := g_reorder_seq.nof_blocks * c_blocksize;  
      CONSTANT c_mem_size         : POSITIVE := 2*c_pagesize;
      CONSTANT c_mem_size_w       : POSITIVE := ceil_log2(c_mem_size);
     
      CONSTANT c_total_data_w     : NATURAL  := g_nof_streams*g_in_dat_w;
      CONSTANT c_complex_data_w   : NATURAL  := c_total_data_w*c_nof_complex;
      CONSTANT c_data_w           : NATURAL  := sel_a_b(g_use_complex, c_complex_data_w, c_total_data_w);
      CONSTANT c_data_w_pre       : NATURAL  := sel_a_b(g_use_complex, c_total_data_w, c_total_data_w/2);  -- Datawidth for pre-transpose defines Re or Im part.
      CONSTANT c_sdata_w          : NATURAL  := c_data_w / g_nof_streams;
                                               
      CONSTANT c_nof_ch_in        : NATURAL  := g_frame_size_in*g_reorder_seq.rd_chunksize;
      CONSTANT c_nof_ch_sel       : NATURAL  := g_reorder_seq.wr_chunksize*g_reorder_seq.rd_chunksize;
                                             
      CONSTANT c_data_w_ratio     : POSITIVE := g_mem_dat_w/c_data_w;
    
      SIGNAL sync_check_in_sosi   : t_dp_sosi;          
      SIGNAL sync_check_in_siso   : t_dp_siso := c_dp_siso_rdy;          
      
      SIGNAL packet_merge_in_sosi : t_dp_sosi;          
      SIGNAL packet_merge_in_siso : t_dp_siso; 
                                  
      SIGNAL ss_in_sosi           : t_dp_sosi;          
      SIGNAL ss_in_siso           : t_dp_siso := c_dp_siso_rdy;          
      
      -- ctrl & status DDR3 driver
      SIGNAL dvr_done             : STD_LOGIC;
      SIGNAL dvr_en               : STD_LOGIC;
      SIGNAL dvr_wr_not_rd        : STD_LOGIC;
      SIGNAL dvr_start_address    : STD_LOGIC_VECTOR(c_mem_size_w-1 DOWNTO 0); 
      SIGNAL dvr_nof_data         : STD_LOGIC_VECTOR(c_mem_size_w-1 DOWNTO 0);
      SIGNAL dvr_wr_flush_en      : STD_LOGIC;
      
      SIGNAL i_to_mem_src_out     : t_dp_sosi;    
                                  
      SIGNAL block_gen_out_sosi   : t_dp_sosi;
      SIGNAL pipeline_out_sosi    : t_dp_sosi;  
      
      SIGNAL sync_bsn             : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
      SIGNAL wr_req               : STD_LOGIC;
      SIGNAL rd_req_i             : STD_LOGIC;
      SIGNAL rd_dat_i             : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
      SIGNAL rd_val_i             : STD_LOGIC;
         
      SIGNAL i_src_out_arr        : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
      
      -- debug signals
      -- . g_use_complex = FALSE : view sosi.data
      SIGNAL dbg_snk_in_data_concat           : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_to_mem_src_out_data_concat   : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_from_mem_snk_in_data_concat  : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_src_out_data_concat          : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      -- . g_use_complex = TRUE : view sosi.re and sosi.im
      SIGNAL dbg_snk_in                       : t_dp_sosi;
      SIGNAL dbg_snk_in_re_concat             : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_snk_in_im_concat             : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_to_mem_src_out               : t_dp_sosi;
      SIGNAL dbg_to_mem_src_out_re_concat     : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_to_mem_src_out_im_concat     : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_from_mem_snk_in              : t_dp_sosi;
      SIGNAL dbg_from_mem_snk_in_re_concat    : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_from_mem_snk_in_im_concat    : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_src_out                      : t_dp_sosi;
      SIGNAL dbg_src_out_re_concat            : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      SIGNAL dbg_src_out_im_concat            : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0);
      
    BEGIN
    
      to_mem_src_out <= i_to_mem_src_out;  
      src_out_arr <= i_src_out_arr;
    
      -- Internal transport is done via sosi.data, for debug view sosi.data or view sosi.re and sosi.im dependent on g_use_complex
      dbg_snk_in          <= snk_in_arr(0);
      dbg_to_mem_src_out  <= i_to_mem_src_out;
      dbg_from_mem_snk_in <= from_mem_snk_in;
      dbg_src_out         <= i_src_out_arr(0);
      gen_debug : FOR I IN 0 TO g_nof_streams-1 GENERATE
        -- g_use_complex = FALSE : view sosi.data
        dbg_snk_in_data_concat(         (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <=    snk_in_arr(I).data(      g_in_dat_w-1 DOWNTO 0);
        dbg_to_mem_src_out_data_concat( (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= i_to_mem_src_out.data((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w);
        dbg_from_mem_snk_in_data_concat((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <=  from_mem_snk_in.data((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w);
        dbg_src_out_data_concat(        (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= i_src_out_arr(I).data(      g_in_dat_w-1 DOWNTO 0);
        
        -- g_use_complex = TRUE : view sosi.re and sosi.im (transported via sosi.data, factor 2 = c_nof_complex)
        dbg_snk_in_re_concat(         (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <=    snk_in_arr(I).re(          g_in_dat_w-1 DOWNTO 0);
        dbg_snk_in_im_concat(         (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <=    snk_in_arr(I).im(          g_in_dat_w-1 DOWNTO 0);
        dbg_to_mem_src_out_re_concat( (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= i_to_mem_src_out.data((2*I+1)*g_in_dat_w-1 DOWNTO (2*I+0)*g_in_dat_w);
        dbg_to_mem_src_out_im_concat( (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= i_to_mem_src_out.data((2*I+2)*g_in_dat_w-1 DOWNTO (2*I+1)*g_in_dat_w);
        dbg_from_mem_snk_in_re_concat((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <=  from_mem_snk_in.data((2*I+1)*g_in_dat_w-1 DOWNTO (2*I+0)*g_in_dat_w);
        dbg_from_mem_snk_in_im_concat((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <=  from_mem_snk_in.data((2*I+2)*g_in_dat_w-1 DOWNTO (2*I+1)*g_in_dat_w);
        dbg_src_out_re_concat(        (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= i_src_out_arr(I).re(          g_in_dat_w-1 DOWNTO 0);
        dbg_src_out_im_concat(        (I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= i_src_out_arr(I).im(          g_in_dat_w-1 DOWNTO 0);
      END GENERATE;
    
      g_merge_in_complex : IF g_use_complex = TRUE GENERATE 
        PROCESS(snk_in_arr)
        BEGIN 
          sync_check_in_sosi <= snk_in_arr(0);
          FOR i IN 0 TO g_nof_streams-1 LOOP
            sync_check_in_sosi.data((2*i+1)*g_in_dat_w-1 DOWNTO 2*i*g_in_dat_w)     <= snk_in_arr(i).re(g_in_dat_w-1 DOWNTO 0);
            sync_check_in_sosi.data((2*i+2)*g_in_dat_w-1 DOWNTO (2*i+1)*g_in_dat_w) <= snk_in_arr(i).im(g_in_dat_w-1 DOWNTO 0);
          END LOOP;
        END PROCESS;     
      END GENERATE;
        
      g_merge_in_data : IF g_use_complex = FALSE GENERATE 
        PROCESS(snk_in_arr)
        BEGIN 
          sync_check_in_sosi <= snk_in_arr(0);
          FOR i IN 0 TO g_nof_streams-1 LOOP
            sync_check_in_sosi.data((i+1)*g_in_dat_w-1 DOWNTO i*g_in_dat_w) <= snk_in_arr(i).data(g_in_dat_w-1 DOWNTO 0);
          END LOOP;
        END PROCESS;     
      END GENERATE;  
      
      g_siso : FOR J IN 0 TO g_nof_streams-1 GENERATE
        snk_out_arr(J) <= sync_check_in_siso;
      END GENERATE;
    
      u_sync_check_and_restore : ENTITY dp_lib.mms_dp_sync_checker 
      GENERIC MAP(     
        g_cross_clock_domain => TRUE,
        g_nof_blk_per_sync   => g_reorder_seq.nof_blocks
      )                      
      PORT MAP(
        mm_rst  => mm_rst,                 
        mm_clk  => mm_clk,                 
        dp_rst  => dp_rst,                               
        dp_clk  => dp_clk,                               
        snk_out => sync_check_in_siso,    
        snk_in  => sync_check_in_sosi,    
        src_in  => packet_merge_in_siso,  
        src_out => packet_merge_in_sosi,   
        reg_dp_sync_checker_mosi => reg_dp_sync_checker_mosi,
        reg_dp_sync_checker_miso => reg_dp_sync_checker_miso 
      );
      
      --u_sync_check_and_restore : ENTITY dp_lib.dp_sync_checker
      --GENERIC MAP (
      --  g_nof_blk_per_sync => g_reorder_seq.nof_blocks
      --)
      --PORT MAP (
      --  dp_rst  => dp_rst,
      --  dp_clk  => dp_clk,
      --  snk_out => sync_check_in_siso,     
      --  snk_in  => sync_check_in_sosi,
      --  src_in  => packet_merge_in_siso,    
      --  src_out => packet_merge_in_sosi
      --);
      
      gen_pre_transpose : IF g_ena_pre_transp = TRUE GENERATE 
        -- Packet merge is required for reorder_col. 
        u_dp_packet_merge : ENTITY dp_lib.dp_packet_merge
        GENERIC MAP (
          g_nof_pkt => g_reorder_seq.rd_chunksize
        )
        PORT MAP (
          rst         => dp_rst,
          clk         => dp_clk,
        
          snk_out     => packet_merge_in_siso,
          snk_in      => packet_merge_in_sosi,
        
          src_in      => ss_in_siso,
          src_out     => ss_in_sosi
        );
     
        u_single_ss : ENTITY work.reorder_col
        GENERIC MAP (
          g_technology         => g_technology,
          g_dsp_data_w         => c_data_w_pre,
          g_nof_ch_in          => c_nof_ch_in,
          g_nof_ch_sel         => c_nof_ch_sel,
          g_select_file_name   => g_select_file,
          g_use_complex        => FALSE
        )
        PORT MAP (
          mm_rst         => mm_rst,
          mm_clk         => mm_clk,
          dp_rst         => dp_rst,
          dp_clk         => dp_clk,
          
          -- Memory Mapped
          ram_ss_ss_mosi => ram_ss_ss_transp_mosi,
          ram_ss_ss_miso => ram_ss_ss_transp_miso,
          
          -- Streaming
          input_sosi     => ss_in_sosi,
          input_siso     => OPEN,                  -- Don't allow backpressure. 
                         
          output_sosi    => i_to_mem_src_out,
          output_siso    => to_mem_src_in
        );
        
      END GENERATE;  
      
      gen_not_pre_transpose : IF g_ena_pre_transp = FALSE GENERATE
        i_to_mem_src_out     <= packet_merge_in_sosi;
        packet_merge_in_siso <= to_mem_src_in;
      END GENERATE;  
       
      -- Map original dvr interface signals to t_mem_ctlr_mosi/miso
      dvr_done            <= dvr_miso.done;           -- Requested wr or rd sequence is done
      dvr_mosi.burstbegin <= dvr_en;
      dvr_mosi.wr         <= dvr_wr_not_rd;           -- No need to use dvr_mosi.rd
      dvr_mosi.address    <= RESIZE_MEM_CTLR_ADDRESS(dvr_start_address);
      dvr_mosi.burstsize  <= RESIZE_MEM_CTLR_BURSTSIZE(dvr_nof_data);
      dvr_mosi.flush      <= dvr_wr_flush_en;
      dvr_wr_flush_en     <= '0';
      
      u_ddr_sequencer: ENTITY work.reorder_sequencer
      GENERIC MAP(
        g_reorder_seq  => g_reorder_seq,
        g_data_w_ratio => c_data_w_ratio
      )                      
      PORT MAP (       
        dp_rst    => dp_rst,
        dp_clk    => dp_clk,
                  
        en_evt    => dvr_en, 
        wr_not_rd => dvr_wr_not_rd,
                  
        address   => dvr_start_address,
        burstsize => dvr_nof_data,
                  
        done      => dvr_done
      );
        
      ---------------------------------------------------------------
      -- FIFO FOR SYNC-BSN
      ---------------------------------------------------------------   
      wr_req <= snk_in_arr(0).sync;
      
      u_sync_bsn_fifo : ENTITY common_lib.common_fifo_sc 
      GENERIC MAP (
        g_technology => g_technology,
        g_use_lut   => TRUE,   -- Make this FIFO in logic, since it's only 2 words deep. 
        g_reset     => FALSE,
        g_init      => FALSE,
        g_dat_w     => c_dp_stream_bsn_w,
        g_nof_words => 16
      )
      PORT MAP (
        rst     => dp_rst,
        clk     => dp_clk,
        wr_dat  => snk_in_arr(0).bsn,
        wr_req  => wr_req,
        wr_ful  => OPEN ,
        rd_dat  => rd_dat_i,
        rd_req  => rd_req_i,
        rd_emp  => open,
        rd_val  => rd_val_i, 
        usedw   => OPEN
      );  
      
      ---------------------------------------------------------------
      -- CREATE READ-AHEAD FIFO INTERFACE FOR SYNC-BSN
      ---------------------------------------------------------------
      u_fifo_adapter : ENTITY common_lib.common_fifo_rd
      GENERIC MAP (
        g_dat_w => c_dp_stream_bsn_w
      )
      PORT MAP(
        rst        => dp_rst, 
        clk        => dp_clk, 
        -- ST sink: RL = 1
        fifo_req   => rd_req_i,
        fifo_dat   => rd_dat_i,
        fifo_val   => rd_val_i,
        -- ST source: RL = 0
        rd_req     => block_gen_out_sosi.sync,
        rd_dat     => sync_bsn,
        rd_val     => OPEN
      );
      
      -----------------------
      -- Pipeline
      -----------------------
      u_dp_pipeline : ENTITY dp_lib.dp_pipeline
      GENERIC MAP(
        g_pipeline => 1
      )
      PORT MAP (
        rst          => dp_rst,
        clk          => dp_clk,
        -- ST sink
        snk_out      => OPEN,
        snk_in       => from_mem_snk_in,
        -- ST source
        src_in       => OPEN,
        src_out      => pipeline_out_sosi
      );
      
      --------------------
      -- DP BLOCK GEN (providing sop/eop)
      --------------------
      u_dp_block_gen : ENTITY dp_lib.dp_block_gen
      GENERIC MAP( 
        g_use_src_in       => FALSE,
        g_nof_data         => g_frame_size_out,
        g_nof_blk_per_sync => g_reorder_seq.nof_blocks,
        g_empty            => 0,
        g_channel          => 0,
        g_error            => 0
      )
      PORT MAP(
        rst        => dp_rst,
        clk        => dp_clk,
        snk_in     => from_mem_snk_in,
        
        -- Use incoming data to generate more data  
        src_in     => c_dp_siso_rdy,
        src_out    => block_gen_out_sosi,
        en         => '1'
      ); 
      
      from_mem_snk_out <= src_in_arr(0);
      
      g_merge_out_complex : IF g_use_complex = TRUE GENERATE 
        gen_merge_out : PROCESS(block_gen_out_sosi, pipeline_out_sosi, sync_bsn)
        BEGIN 
          FOR i IN 0 TO g_nof_streams-1 LOOP
            i_src_out_arr(i)       <= block_gen_out_sosi; 
            i_src_out_arr(i).valid <= pipeline_out_sosi.valid; 
            i_src_out_arr(i).re    <= RESIZE_DP_DSP_DATA(pipeline_out_sosi.data((2*i+1)*g_in_dat_w-1 DOWNTO 2*i*g_in_dat_w));
            i_src_out_arr(i).im    <= RESIZE_DP_DSP_DATA(pipeline_out_sosi.data((2*i+2)*g_in_dat_w-1 DOWNTO (2*i+1)*g_in_dat_w));
            IF (block_gen_out_sosi.sync = '1') THEN 
              i_src_out_arr(i).bsn <= sync_bsn;
            END IF; 
          END LOOP;
        END PROCESS;
      END GENERATE;
      
      g_merge_out_data : IF g_use_complex = FALSE GENERATE 
        gen_merge_out : PROCESS(block_gen_out_sosi, pipeline_out_sosi)
        BEGIN
          FOR i IN 0 TO g_nof_streams-1 LOOP
            i_src_out_arr(i)       <= block_gen_out_sosi; 
            i_src_out_arr(i).valid <= pipeline_out_sosi.valid; 
            i_src_out_arr(i).data  <= RESIZE_DP_DATA(pipeline_out_sosi.data((i+1)*g_in_dat_w-1 DOWNTO i*g_in_dat_w));
            IF (block_gen_out_sosi.sync = '1') THEN 
              i_src_out_arr(i).bsn <= sync_bsn;
            END IF; 
          END LOOP;  
        END PROCESS;        
      END GENERATE;
                  
    END str;