diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index 56fe01aa18d5d1a42d08a5d17271a9d79bde5c04..0076348213e60bd7b7c36df9bb11a49d8e7faf3b 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -1,3 +1,74 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- 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: J.W.E. Oudman +-- Purpose: Create a histogram from the input data and present it to the MM bus +-- Description: +-- The histogram component separates it's input samples in counter bins based +-- on the value of the MSbits of the input. These bins are adresses on a RAM +-- block that is swapped with another RAM block at every sync pulse plus 2 +-- cycles. While one RAM block is used to count the input samples, the other +-- is read by the MM bus through a fifo. +-- +-- +-- ram_pointer ram_pointer +-- | | +-- | /o--- RAM_0 ---o | +-- |/ | +-- / | +-- snk_in ----o/ | /o----- FIFO to MM ---- MM +-- |/ +-- / +-- o--- RAM_1 ---o/ +-- +-- +-- The input data is a dp stream which obviously uses a dp_clk. Because the +-- RAM is swapped after every sync both RAM blocks need to use the dp_clk. +-- Because the MM bus needs to access one RAM block but can't use it's mm_clk +-- on it a FIFO is used. +-- +-- Remarks: +-- . Because the values of the generics g_nof_bins depends on g_in_data_w +-- (you should not have more bins than data values) an assert is made to +-- warn in the simulation when the maximum value of g_nof_bins is reached. +-- If exceeded the simulator will throw fatal error ("...Port length (#) does +-- not match actual length (#)...") +-- +-- . when an adress is determined it takes 1 cycle to receive it's value and +-- another cycle before the calculated value can be written into that RAM +-- adress. There is also the limitation of not being able to read and write +-- on the same adress at the same time. These limitations cause the following +-- complications in the implementation: +-- . repeating samples of the same adress have to be counted first till +-- another adress appears before written (as you would miss the second and +-- further consecutive samples and have the read/write limitation) +-- . If adresses are toggling at every cycle (e.g. adress 0; 1; 0; 1) you +-- have to remember the data to be written and increment it as you have the +-- read/write limitation and writing takes priority in this case +-- . When a sync signal appears the RAM has to be swapped 2 cycles later so +-- the first 2 cycles may not be read from the old RAM block +-- +------------------------------------------------------------------------------- + LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; USE IEEE.std_logic_1164.ALL; USE common_lib.common_pkg.ALL; @@ -7,10 +78,10 @@ USE technology_lib.technology_select_pkg.ALL; ENTITY st_histogram IS GENERIC ( - g_in_data_w : NATURAL := 18; --(waarde 18 komt van st_sst) >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768) - g_nof_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span - g_nof_data : NATURAL; - g_str : STRING := "histogram" -- to select output to MM bus ("frequency" or "histogram") + g_in_data_w : NATURAL := 14; -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768) + g_nof_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span; max. 512 + g_nof_data : NATURAL; -- any use? + g_str : STRING := "freq.density" -- to select output to MM bus ("frequency" or "freq.density") ); PORT ( mm_rst : IN STD_LOGIC; @@ -30,15 +101,15 @@ END st_histogram; ARCHITECTURE str OF st_histogram IS - CONSTANT c_data_span : NATURAL := pow2(g_in_data_w); - CONSTANT c_bin_w : NATURAL := ceil_log2(g_nof_data); + CONSTANT c_data_span : NATURAL := pow2(g_in_data_w); -- any use? + CONSTANT c_bin_w : NATURAL := ceil_log2(g_nof_data); -- any use? CONSTANT c_adr_w : NATURAL := ceil_log2(g_nof_bins); CONSTANT c_adr_low_calc : INTEGER := g_in_data_w-c_adr_w; -- Calculation might yield a negative number CONSTANT c_adr_low : NATURAL := largest(0, c_adr_low_calc); -- Override any negative value of c_adr_low_calc CONSTANT c_ram : t_c_mem := (latency => 1, adr_w => c_adr_w, -- 9 bits needed to adress/select 512 adresses - dat_w => c_word_w, -- 32bit, def. in common_pkg + dat_w => c_word_w, -- 32bit, def. in common_pkg; >= c_bin_w nof_dat => g_nof_bins, -- 512 adresses with 32 bit words, so 512 init_sl => '0'); -- MM side : sla_in, sla_out @@ -89,9 +160,25 @@ BEGIN ASSERT c_adr_low_calc>0 REPORT "ceil_log2(g_nof_bins) is as large as g_in_data_w, don't increase g_nof_bins" SEVERITY WARNING; ----------------------------------------------------------------------------- - -- Assign inputs of dual page RAM: + -- Assign inputs of RAM: -- . Determine address based on input data - -- . Read out current counter value from RAM, write back incremented value + -- . Compare adress with the two previous adresses and if: + -- . it is the same as the last adress increase a counter + -- . it is the same as 2 cycles back but not the last copy the data to be + -- written directly into the counter instead of trying to read (ask) it + -- back from RAM at the same clock cycle (which is impossible) + -- . it is not the same enable the nxt_wr_dat_a data to be written + -- at the next cycle by making nxt_wr_en_a high + -- . Write the wr_dat_a data to the RAM + -- . At the snk_in.sync pulse: + -- . let first 2 cycles start counting from 0 again + -- . (plus 2 cycles) let counting depend on values in RAM (which should + -- be 0) + -- . Restart or pause counting when a snk_in.valid = '0' appears: + -- . pause when adress is the same as the previous adress + -- . restart from 0 when adress is not the same as previous adress + -- . restart from 0 when also a sync appears + -- ---------------------------------------------------------------------------- p_bin_cnt_switch : PROCESS(snk_in) IS @@ -113,10 +200,7 @@ BEGIN rd_en_b <= '1'; END IF; END PROCESS; --- rd_en_b <= snk_in.valid; -- WHEN snk_in.valid='1'; -- AND dp_rst='0'; --- adr_a <= adr_b; --- wr_dat_a <= INCR_UVEC(rd_dat_b, adr_b_cnt_dly) WHEN rising_edge(dp_clk) AND rd_val_b='1' ELSE (OTHERS =>'1'); --- wr_en_a <= '1' WHEN rising_edge(dp_clk) AND rd_val_b='1' ELSE '0'; + p_nxt_wr_dat : PROCESS(rd_dat_b, adr_b_cnt, rd_val_b, dp_pipeline_src_out_p.sync, dp_pipeline_src_out_pp.sync, wr_en_a) IS BEGIN nxt_wr_dat_a <= (OTHERS => '0'); @@ -144,9 +228,6 @@ BEGIN nxt_wr_en_a <= '1'; END IF; END PROCESS; - --- nxt_wr_dat_a <= INCR_UVEC(rd_dat_b, adr_b_cnt) WHEN rd_val_b='1' ELSE (OTHERS =>'0'); -- adr_b_cnt_dly ?? --- nxt_wr_en_a <= rd_val_b WHEN adr_b /= prev_adr_b ELSE '0'; p_prev_adr_cnt : PROCESS(adr_a, adr_b, prev_adr_b, adr_b_cnt, snk_in.sync, snk_in.valid, dp_pipeline_src_out_p.valid, dp_pipeline_src_out_p.sync) IS BEGIN @@ -200,7 +281,6 @@ BEGIN -- RAM selector ----------------------------------------------------------------------------- - -- p_ram_pointer : PROCESS(ram_pointer, dp_rst, dp_clk, wr_en_a, wr_dat_a, adr_a, adr_b, rd_en_b, ram_0_rd_dat_b, ram_0_rd_val_b) IS BEGIN -- Default / init values @@ -262,7 +342,7 @@ BEGIN ----------------------------------------------------------------------------- -- Pipeline for adress - ---------------------------------------------------------------------------- + ----------------------------------------------------------------------------- u_common_pipeline_adr : ENTITY common_lib.common_pipeline GENERIC MAP ( @@ -278,6 +358,15 @@ BEGIN out_dat => adr_a ); + + + + + + ----------------------------------------------------------------------------- + -- Pipeline for toggle issue + ----------------------------------------------------------------------------- + u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl GENERIC MAP( g_pipeline => 1 -- 0 for wires, > 0 for registers, @@ -295,7 +384,7 @@ BEGIN ----------------------------------------------------------------------------- -- Pipeline for adresscounter - ---------------------------------------------------------------------------- + ----------------------------------------------------------------------------- u_common_pipeline_adr_cnt : ENTITY common_lib.common_pipeline GENERIC MAP ( @@ -317,8 +406,8 @@ BEGIN ----------------------------------------------------------------------------- - -- Pipeline for cycle after sync - ---------------------------------------------------------------------------- + -- Pipeline for cycles after sync + ----------------------------------------------------------------------------- u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline GENERIC MAP ( @@ -348,8 +437,8 @@ BEGIN ----------------------------------------------------------------------------- - -- Dual page RAM instace - ---------------------------------------------------------------------------- + -- Dual swapped RAM instance + ----------------------------------------------------------------------------- ram_0: ENTITY common_lib.common_ram_r_w GENERIC MAP ( @@ -360,7 +449,7 @@ BEGIN PORT MAP ( rst => dp_rst, clk => dp_clk, - clken => '1', + clken => '1', -- only necessary for Stratix iv wr_en => ram_0_wr_en_a, wr_adr => ram_0_adr_a, wr_dat => ram_0_wr_dat_a, @@ -430,8 +519,8 @@ BEGIN ----------------------------------------------------------------------------- - -- Connect MM interface to DUAL page RAM read out histogram statistics - ---------------------------------------------------------------------------- + -- Connect MM interface to DUAL swapped RAM read out histogram statistics + ----------------------------------------------------------------------------- diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd index fa6f771dbc8a93c06dc470545b0db841f937aba7..2e699fcd0f21d9d9ad78389e421580946163c349 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd @@ -11,9 +11,9 @@ ENTITY tb_st_histogram IS g_data_w : NATURAL := 4; g_nof_bins : NATURAL := 8; g_nof_data : NATURAL := 200; - g_str : STRING := "histogram"; + g_str : STRING := "freq.density"; g_valid_gap : BOOLEAN := TRUE; - g_snk_in_data_sim_type : STRING := "toggle" -- "counter" of "toggle" + g_snk_in_data_sim_type : STRING := "toggle" -- "counter" or "toggle" ); END tb_st_histogram;