From 132301fbf5ac1b966656b4201e426b0fd2150af5 Mon Sep 17 00:00:00 2001
From: Reinier van der Walle <walle@astron.nl>
Date: Tue, 4 May 2021 12:56:48 +0200
Subject: [PATCH] inital commit of st_xsq

---
 libraries/dsp/st/hdllib.cfg          |   1 +
 libraries/dsp/st/src/vhdl/st_xsq.vhd | 225 +++++++++++++++++++++++++++
 2 files changed, 226 insertions(+)
 create mode 100644 libraries/dsp/st/src/vhdl/st_xsq.vhd

diff --git a/libraries/dsp/st/hdllib.cfg b/libraries/dsp/st/hdllib.cfg
index 3617a5976a..959d269f23 100644
--- a/libraries/dsp/st/hdllib.cfg
+++ b/libraries/dsp/st/hdllib.cfg
@@ -9,6 +9,7 @@ synth_files =
     src/vhdl/st_ctrl.vhd 
     src/vhdl/st_calc.vhd 
     src/vhdl/st_sst.vhd 
+    src/vhdl/st_xsq.vhd 
 #    src/vhdl/st_top.vhd 
     src/vhdl/st_histogram.vhd
     src/vhdl/st_histogram_reg.vhd
diff --git a/libraries/dsp/st/src/vhdl/st_xsq.vhd b/libraries/dsp/st/src/vhdl/st_xsq.vhd
new file mode 100644
index 0000000000..b151affbd5
--- /dev/null
+++ b/libraries/dsp/st/src/vhdl/st_xsq.vhd
@@ -0,0 +1,225 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- 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 : R. vd Walle
+-- Purpose:
+--   Store the (auto)power statistics of a complex input stream with
+--   blocks of g_nof_crosslets * g_nof_signal_inputs**2 multiplexed subbands into a MM register.
+-- Description:                                                          
+--
+--   After each sync the MM register gets updated with the (auto) power statistics
+--   of the previous sync interval. The length of the sync interval determines
+--   the nof accumlations per statistic, hence the integration time. See st_calc
+--   for more details.
+-- Remarks:
+-- . The in_sync is assumed to be a pulse an interpreted directly.
+-- . The MM register is single page RAM to save memory resources. Therefore
+--   just after the sync its contents is undefined when it gets written, but
+--   after that its contents remains stable for the rest of the sync interval.
+--   Therefore it is not necessary to use a dual page register that swaps at
+--   the sync. 
+-- . The minimum c_nof_statistics = 8. Lower values lead to simulation errors. This is
+--   due to the read latency of 2 of the accumulation memory in the st_calc entity. 
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+ENTITY st_xsq IS
+  GENERIC (
+    g_technology        : NATURAL := c_tech_select_default;
+    g_nof_signal_inputs : NATURAL := 2;
+    g_nof_crosslets     : NATURAL := 1;
+    g_in_data_w         : NATURAL := 18;    -- width of the data to be accumulated
+    g_stat_data_w       : NATURAL := 54;    -- statistics accumulator width
+    g_stat_data_sz      : NATURAL := 2      -- statistics word width >= statistics accumulator width and fit in a power of 2 multiple 32b MM words
+  );                
+  PORT (            
+    mm_rst          : IN  STD_LOGIC;
+    mm_clk          : IN  STD_LOGIC;
+    dp_rst          : IN  STD_LOGIC;
+    dp_clk          : IN  STD_LOGIC;
+                    
+    -- Streaming    
+    in_a      : IN  t_dp_sosi;   -- Complex input data
+    in_b      : IN  t_dp_sosi;   -- Complex input data
+    
+    -- Memory Mapped
+    ram_st_xsq_mosi : IN  t_mem_mosi;  
+    ram_st_xsq_miso : OUT t_mem_miso
+  );
+END st_xsq;
+
+ARCHITECTURE str OF st_xsq IS
+
+  CONSTANT c_xsq : NATURAL := g_nof_signal_inputs * g_nof_signal_inputs;
+  CONSTANT c_nof_statistics : NATURAL := g_nof_crosslets * c_xsq;
+  
+  CONSTANT c_nof_stat_w   : NATURAL := ceil_log2(c_nof_statistics);
+  CONSTANT c_nof_word     : NATURAL := g_stat_data_sz*c_nof_statistics;
+  CONSTANT c_nof_word_w   : NATURAL := ceil_log2(c_nof_word);
+  CONSTANT c_stat_word_w  : NATURAL := g_stat_data_sz*c_word_w;
+  
+  -- Statistics register
+  CONSTANT c_mm_ram       : t_c_mem := (latency  => 1,
+                                        adr_w    => c_nof_word_w,
+                                        dat_w    => c_word_w,
+                                        nof_dat  => c_nof_word,
+                                        init_sl  => '0');           -- MM side : sla_in, sla_out
+  CONSTANT c_stat_ram     : t_c_mem := (latency  => 1,
+                                        adr_w    => c_nof_stat_w,
+                                        dat_w    => c_stat_word_w,
+                                        nof_dat  => c_nof_statistics,
+                                        init_sl  => '0');           -- ST side : stat_mosi
+  
+  
+  SIGNAL stat_data_re : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0);  
+  SIGNAL stat_data_im : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0);  
+  
+  SIGNAL wrdata_re    : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0);
+  SIGNAL wrdata_im    : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0);
+  
+  SIGNAL stat_mosi    : t_mem_mosi;
+
+  SIGNAL ram_st_xsq_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst);
+  SIGNAL ram_st_xsq_miso_arr : t_mem_miso_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst);
+  SIGNAL remapped_ram_st_xsq_mosi : t_mem_mosi;  
+    
+BEGIN
+  -- accumulators
+  st_calc : ENTITY work.st_calc 
+  GENERIC MAP (
+    g_technology   => g_technology,
+    g_nof_mux      => 1,
+    g_nof_stat     => c_nof_statistics,
+    g_in_dat_w     => g_in_data_w,
+    g_out_dat_w    => g_stat_data_w,
+    g_out_adr_w    => c_nof_stat_w,
+    g_complex      => TRUE
+  )
+  PORT MAP (
+    rst            => dp_rst,
+    clk            => dp_clk,
+    in_ar          => in_a.re(g_in_data_w-1 DOWNTO 0),
+    in_ai          => in_a.im(g_in_data_w-1 DOWNTO 0),
+    in_br          => in_b.re(g_in_data_w-1 DOWNTO 0),
+    in_bi          => in_b.im(g_in_data_w-1 DOWNTO 0),
+    in_val         => in_a.valid,
+    in_sync        => in_a.sync,
+    out_adr        => stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0),
+    out_re         => stat_data_re,
+    out_im         => stat_data_im,
+    out_val        => stat_mosi.wr,
+    out_val_m      => OPEN
+  );
+  
+  wrdata_re <= RESIZE_MEM_UDATA(stat_data_re);
+  wrdata_im <= RESIZE_MEM_UDATA(stat_data_im);
+  
+  ---------------------------------------------------------------
+  -- COMBINE MEMORY MAPPED INTERFACES
+  ---------------------------------------------------------------
+  -- Translate incoming MM interface [N_crosslets][S_pn A][S_pn B][N_complex] to
+  -- [N_complex][N_crosslets][S_pn A][S_pn B]
+  p_remap : PROCESS(ram_st_xsq_mosi)
+  BEGIN
+    remapped_ram_st_xsq_mosi <= ram_st_xsq_mosi;
+    remapped_ram_st_xsq_mosi.address(ceil_log2(c_nof_complex)+c_nof_word_w -1 DOWNTO c_nof_word_w) <= ram_st_xsq_mosi.address(ceil_log2(c_nof_complex)-1 DOWNTO 0);
+    remapped_ram_st_xsq_mosi.address(c_nof_word_w -1 DOWNTO 0) <= ram_st_xsq_mosi.address(ceil_log2(c_nof_complex)+c_nof_word_w -1 DOWNTO ceil_log2(c_nof_complex));
+  END PROCESS;
+
+  -- Combine the internal array of mm interfaces for both real
+  -- and imaginary part. 
+  u_mem_mux_select : entity common_lib.common_mem_mux
+  generic map (    
+    g_nof_mosi    => c_nof_complex,
+    g_mult_addr_w => c_nof_word_w
+  )
+  port map (
+    mosi     => remapped_ram_st_xsq_mosi,
+    miso     => ram_st_xsq_miso,
+    mosi_arr => ram_st_xsq_mosi_arr,
+    miso_arr => ram_st_xsq_miso_arr
+  );
+ 
+  -- ram for real values 
+  stat_reg_re : ENTITY common_lib.common_ram_crw_crw_ratio
+  GENERIC MAP (
+    g_technology => g_technology,
+    g_ram_a      => c_mm_ram,
+    g_ram_b      => c_stat_ram,
+    g_init_file  => "UNUSED"
+  )
+  PORT MAP (
+    rst_a     => mm_rst,
+    clk_a     => mm_clk,
+    
+    rst_b     => dp_rst,
+    clk_b     => dp_clk,
+    
+    wr_en_a   => ram_st_xsq_mosi_arr(0).wr,  -- only for diagnostic purposes, typically statistics are read only
+    wr_dat_a  => ram_st_xsq_mosi_arr(0).wrdata(c_mm_ram.dat_w-1 DOWNTO 0),
+    adr_a     => ram_st_xsq_mosi_arr(0).address(c_mm_ram.adr_w-1 DOWNTO 0),
+    rd_en_a   => ram_st_xsq_mosi_arr(0).rd,
+    rd_dat_a  => ram_st_xsq_miso_arr(0).rddata(c_mm_ram.dat_w-1 DOWNTO 0),
+    rd_val_a  => ram_st_xsq_miso_arr(0).rdval,
+    
+    wr_en_b   => stat_mosi.wr,
+    wr_dat_b  => wrdata_re(c_stat_ram.dat_w-1 DOWNTO 0),
+    adr_b     => stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0),
+    rd_en_b   => '0',
+    rd_dat_b  => OPEN,
+    rd_val_b  => OPEN
+  );                                   
+ 
+  -- ram for imaginary values
+  stat_reg_im : ENTITY common_lib.common_ram_crw_crw_ratio
+  GENERIC MAP (
+    g_technology => g_technology,
+    g_ram_a      => c_mm_ram,
+    g_ram_b      => c_stat_ram,
+    g_init_file  => "UNUSED"
+  )
+  PORT MAP (
+    rst_a     => mm_rst,
+    clk_a     => mm_clk,
+    
+    rst_b     => dp_rst,
+    clk_b     => dp_clk,
+    
+    wr_en_a   => ram_st_xsq_mosi_arr(1).wr,  -- only for diagnostic purposes, typically statistics are read only
+    wr_dat_a  => ram_st_xsq_mosi_arr(1).wrdata(c_mm_ram.dat_w-1 DOWNTO 0),
+    adr_a     => ram_st_xsq_mosi_arr(1).address(c_mm_ram.adr_w-1 DOWNTO 0),
+    rd_en_a   => ram_st_xsq_mosi_arr(1).rd,
+    rd_dat_a  => ram_st_xsq_miso_arr(1).rddata(c_mm_ram.dat_w-1 DOWNTO 0),
+    rd_val_a  => ram_st_xsq_miso_arr(1).rdval,
+    
+    wr_en_b   => stat_mosi.wr,
+    wr_dat_b  => wrdata_im(c_stat_ram.dat_w-1 DOWNTO 0),
+    adr_b     => stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0),
+    rd_en_b   => '0',
+    rd_dat_b  => OPEN,
+    rd_val_b  => OPEN
+  );     
+  
+END str;
-- 
GitLab