Select Git revision
t_reservations.sh
-
Roy de Goei authored
TMSS-668: Move retrieving of active station reservations function from dynamic scheduler to separate reservations module. Add unittests for reservations module. Add stop_time in Reservations model, and calculate duration (it was visa versa)
Roy de Goei authoredTMSS-668: Move retrieving of active station reservations function from dynamic scheduler to separate reservations module. Add unittests for reservations module. Add stop_time in Reservations model, and calculate duration (it was visa versa)
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
st_sst.vhd 13.17 KiB
-------------------------------------------------------------------------------
--
-- Copyright (C) 2011
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
--
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.math_real.ALL; -- for sim only
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;
-- Purpose:
-- Store the (auto)power statistics of a complex input stream with
-- blocks of nof_stat multiplexed subbands into a MM register.
-- Description:
--
-- When the treshold register is set to 0 the statistics will be auto-
-- correlations.
-- In case the treshold register is set to a non-zero value, it allows
-- to create a sample & hold function for the a-input of the multiplier.
-- The a-input of the multiplier is updated every "treshold" clockcycle.
-- Thereby cross statistics can be created.
--
-- 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.
--
-- View wrdata_power and stat_bin in Wave window to see the stat power
-- values series.
--
-- 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 g_nof_stat = 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.
ENTITY st_sst IS
GENERIC (
g_technology : NATURAL := c_tech_select_default;
g_nof_stat : NATURAL := 512; -- total nof accumulators
g_xst_enable : BOOLEAN := FALSE; -- when set to true, an extra memory is instantiated to hold the imaginary part of the cross-correlation results
g_in_data_w : NATURAL := 18; -- width o dth edata 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
g_stat_multiplex: NATURAL := 2 -- number of accumulators per stat_bin, for debug purposes with view in Wave window
);
PORT (
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
-- Streaming
in_complex : IN t_dp_sosi; -- Complex input data
-- Memory Mapped
ram_st_sst_mosi : IN t_mem_mosi;
ram_st_sst_miso : OUT t_mem_miso;
reg_st_sst_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_st_sst_miso : OUT t_mem_miso := c_mem_miso_rst
);
END st_sst;
ARCHITECTURE str OF st_sst IS
CONSTANT c_nof_stat_w : NATURAL := ceil_log2(g_nof_stat);
CONSTANT c_nof_word : NATURAL := g_stat_data_sz*g_nof_stat;
CONSTANT c_nof_word_w : NATURAL := ceil_log2(c_nof_word);
CONSTANT g_stat_word_w : NATURAL := g_stat_data_sz*c_word_w;
CONSTANT zeros : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0) := (OTHERS => '0');
-- 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 => g_stat_word_w,
nof_dat => g_nof_stat,
init_sl => '0'); -- ST side : stat_mosi
CONSTANT c_field_arr : t_common_field_arr(0 DOWNTO 0) := (0=> ( field_name_pad("treshold"), "RW", c_nof_stat_w, field_default(0) ));
SIGNAL mm_fields_out : STD_LOGIC_VECTOR(field_slv_out_len(c_field_arr)-1 DOWNTO 0);
SIGNAL treshold : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0);
TYPE reg_type IS RECORD
in_sosi_reg : t_dp_sosi;
in_a_re : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO 0);
in_a_im : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO 0);
END RECORD;
SIGNAL r, rin : reg_type;
SIGNAL in_sync : STD_LOGIC;
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);
-- Sim only signals for observing wrdata_power with indices in Wave window
SIGNAL wrdata_power : REAL;
SIGNAL stat_bin : NATURAL;
SIGNAL stat_mosi : t_mem_mosi := c_mem_mosi_rst;
SIGNAL treshold_count : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0);
SIGNAL ram_st_sst_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst);
SIGNAL ram_st_sst_miso_arr : t_mem_miso_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst);
BEGIN
------------------------------------------------------------------------------
-- Register map for the treshold register
------------------------------------------------------------------------------
register_map : ENTITY mm_lib.mm_fields
GENERIC MAP(
g_cross_clock_domain => TRUE,
g_field_arr => c_field_arr
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
mm_mosi => reg_st_sst_mosi,
mm_miso => reg_st_sst_miso,
slv_rst => dp_rst,
slv_clk => dp_clk,
slv_out => mm_fields_out
);
treshold <= mm_fields_out(field_hi(c_field_arr, "treshold") DOWNTO field_lo(c_field_arr, "treshold"));
------------------------------------------------------------------------------
-- Input registers and preparation of the input data for the multiplier.
------------------------------------------------------------------------------
comb : PROCESS(r, dp_rst, in_complex, treshold_count, treshold)
VARIABLE v : reg_type;
BEGIN
v := r;
v.in_sosi_reg := in_complex;
IF treshold_count = zeros OR treshold = zeros THEN
v.in_a_re := in_complex.re(g_in_data_w-1 DOWNTO 0);
v.in_a_im := in_complex.im(g_in_data_w-1 DOWNTO 0);
END IF;
IF dp_rst = '1' THEN
v.in_a_re := (OTHERS => '0');
v.in_a_im := (OTHERS => '0');
END IF;
rin <= v;
END PROCESS comb;
regs : PROCESS(dp_clk)
BEGIN
IF rising_edge(dp_clk) THEN
r <= rin;
END IF;
END PROCESS;
------------------------------------------------------------------------------
-- Counter used to detect when treshold is reached in order to load new
-- input vlaues for the multiplier.
------------------------------------------------------------------------------
treshold_cnt : ENTITY common_lib.common_counter
GENERIC MAP(
g_latency => 1,
g_init => 0,
g_width => c_nof_stat_w,
g_max => 0,
g_step_size => 1
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
cnt_clr => in_complex.eop,
cnt_en => in_complex.valid,
cnt_max => treshold,
count => treshold_count
);
in_sync <= in_complex.sync;
st_calc : ENTITY work.st_calc
GENERIC MAP (
g_technology => g_technology,
g_nof_mux => 1,
g_nof_stat => g_nof_stat,
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 => g_xst_enable
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
in_ar => r.in_a_re,
in_ai => r.in_a_im,
in_br => r.in_sosi_reg.re(g_in_data_w-1 DOWNTO 0),
in_bi => r.in_sosi_reg.im(g_in_data_w-1 DOWNTO 0),
in_val => r.in_sosi_reg.valid,
in_sync => in_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
);
-- Auto correlations are unsigned value, cross correlations are signed values
wrdata_re <= RESIZE_MEM_UDATA(stat_data_re) WHEN g_xst_enable=FALSE ELSE RESIZE_MEM_SDATA(stat_data_re);
wrdata_im <= RESIZE_MEM_UDATA(stat_data_im) WHEN g_xst_enable=FALSE ELSE RESIZE_MEM_SDATA(stat_data_im);
-- synthesis translate_off
-- View SST or XST power values in wave window (stat_data_im = 0 for SST)
wrdata_power <= COMPLEX_RADIUS(TO_SREAL(stat_data_re), TO_SREAL(stat_data_im)) ** 2.0;
stat_bin <= TO_UINT(stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0)) / g_stat_multiplex;
-- synthesis translate_on
-- For SST or for real part of XST
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_sst_mosi_arr(0).wr, -- only for diagnostic purposes, typically statistics are read only
wr_dat_a => ram_st_sst_mosi_arr(0).wrdata(c_mm_ram.dat_w-1 DOWNTO 0),
adr_a => ram_st_sst_mosi_arr(0).address(c_mm_ram.adr_w-1 DOWNTO 0),
rd_en_a => ram_st_sst_mosi_arr(0).rd,
rd_dat_a => ram_st_sst_miso_arr(0).rddata(c_mm_ram.dat_w-1 DOWNTO 0),
rd_val_a => ram_st_sst_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
);
gen_sst: IF g_xst_enable=FALSE GENERATE
ram_st_sst_mosi_arr(0) <= ram_st_sst_mosi;
ram_st_sst_miso <= ram_st_sst_miso_arr(0);
END GENERATE;
gen_xst: IF g_xst_enable=TRUE GENERATE
---------------------------------------------------------------
-- COMBINE MEMORY MAPPED INTERFACES
---------------------------------------------------------------
-- 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 => ram_st_sst_mosi,
miso => ram_st_sst_miso,
mosi_arr => ram_st_sst_mosi_arr,
miso_arr => ram_st_sst_miso_arr
);
-- For imaginary part of XST
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_sst_mosi_arr(1).wr, -- only for diagnostic purposes, typically statistics are read only
wr_dat_a => ram_st_sst_mosi_arr(1).wrdata(c_mm_ram.dat_w-1 DOWNTO 0),
adr_a => ram_st_sst_mosi_arr(1).address(c_mm_ram.adr_w-1 DOWNTO 0),
rd_en_a => ram_st_sst_mosi_arr(1).rd,
rd_dat_a => ram_st_sst_miso_arr(1).rddata(c_mm_ram.dat_w-1 DOWNTO 0),
rd_val_a => ram_st_sst_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 GENERATE;
END str;